Skip to main content
/
/
/
/
Profile picture

Profile picture

Top bar profile picture

Use .bf-nav-profile on a profile image to get a circular, bordered picture.

<img className="bf-nav-profile" src="..." />
<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>
<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 ... /> </> }>
<Nav top={ <> [other top bar items, if any...] <Nav.Group ... /> </> }>
Skip to main content
[dropdown content...]

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;
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;