Profile picture
Profile picture
Go to top
Top bar profile picture
Use .bf-nav-profile on a profile image to get a circular, bordered picture.
<img className="bf-nav-profile" src="..." />
Use it with <Nav.Group> to create a dropdown
button.
<Nav.Group name={<img className="bf-nav-profile" src="..." alt="Profile menu" />} > [dropdown content...] </Nav.Group>
Then place it as the last sibling in the top prop of your <Nav>.
<Nav top={ <> [other top bar items, if any...] <Nav.Group ... /> </> }>
Profile dropdown content
Inside <Nav.Group> you can use <section> to get spacing around sections of items, and <hr> for a horizontal line separator.
Also see <Nav> and useApplyColorMode() docs.
import useLocalStorageState from "use-local-storage-state"; import React, { useState } from "react"; import { faUser, faSignOutAlt } from "@fortawesome/free-solid-svg-icons"; import Nav from "@intility/bifrost-react/Nav"; import Checkbox from "@intility/bifrost-react/Checkbox"; import useApplyColorMode from "@intility/bifrost-react/hooks/useApplyColorMode"; import type { ColorMode } from "@intility/bifrost-react"; // Can be replaced by the component from the next example const ProfilePicture = () => ( <img className="bf-nav-profile" src="https://picsum.photos/id/152/100/100" alt="" /> ); export default function ProfilePictureDropdownDemo() { const [lang, setLang] = useState("English"); // persist color mode state in local storage. // you might want to use a cookie or a database instead? const [colorMode, setColorMode] = useLocalStorageState<ColorMode>( "colorMode", // local storage key { defaultValue: "system", }, ); // keep document color mode in sync with state useApplyColorMode(colorMode); // If you're using create.intility.app template (@azure/msal-browser) //import instance from '~/auth' //const logout = () => instance.logoutRedirect() return ( <div className="page-demo"> <Nav logo="Demo App" top={ <Nav.Group name={<ProfilePicture />}> <a href="#path"> <Nav.Item icon={faUser}>My profile</Nav.Item> </a> <hr /> <section> <Nav.Header>Language</Nav.Header> <Checkbox type="radio" label="English" name="language" checked={lang === "English"} onChange={() => setLang("English")} /> <Checkbox type="radio" label="Norsk" name="language" checked={lang === "Norsk"} onChange={() => setLang("Norsk")} /> </section> <section> <Nav.Header>Color mode</Nav.Header> <Checkbox type="radio" label="Light" name="color-mode" checked={colorMode === "light"} onChange={() => setColorMode("light")} /> <Checkbox type="radio" label="Dark" name="color-mode" checked={colorMode === "dark"} onChange={() => setColorMode("dark")} /> <Checkbox type="radio" label="System" name="color-mode" checked={colorMode === "system"} onChange={() => setColorMode("system")} /> </section> <hr /> <button type="button" onClick={() => { // logout() // from useAuth hook or msal instance }} > <Nav.Item icon={faSignOutAlt}>Sign out</Nav.Item> </button> </Nav.Group> } > Click the profile picture to show a dropdown with user-specific links, global app settings and a log out button. </Nav> </div> ); }
Authenticated user
The following code will fetch the current user's photo from Microsoft Graph, with a faUser icon as fallback.
You can use this custom <ProfilePicture> component in the name prop of the <Nav.Group>, as shown in the example above.
import useSWRImmutable from "swr/immutable"; // if you're using /src/auth/fetch.ts from create.intility.app template import { authorizedFetch } from "~/auth"; import { faUser } from "@fortawesome/pro-solid-svg-icons"; import Icon from "@intility/bifrost-react/Icon"; const fetcher = (url: string) => authorizedFetch(url) .then((r) => { if (!r.ok) throw new Error("Could not fetch photo from graph"); return r.blob(); }) // createObjectURL creates a DOMString containing a URL representing the blob .then(URL.createObjectURL); const ProfilePicture = () => { // The profile picture will rarely change between refreshes // https://swr.vercel.app/docs/revalidation#disable-automatic-revalidations const { data, error } = useSWRImmutable( "https://graph.microsoft.com/v1.0/me/photos/48x48/$value", fetcher, ); if (!data || error) return <Icon icon={faUser} />; return <img className="bf-nav-profile" src={data} alt="Profile picture" />; }; export default ProfilePicture;