Questions about setting the icon and accessing dark/light mode in Sanity Structure.

7 replies
Last updated: Feb 27, 2024
Hey Everyone! I managed to set the icon with the defineConfig of the sanity.config.js file, which changes the icon in the upper left corner of Sanity Structure. But my questions are:1. Is the icon required to be an SVG? That's all I could get to work.
2. Can I access if a user switches between Dark and Light mode? If the icon is a white svg, then it can't be seen in Light mode. Same if it is a dark svg in dark mode.
AI Update

Great questions about customizing the Studio icon! Let me address both:

1. Icon Format - Not Limited to SVG

The icon property in defineConfig accepts React components, which gives you flexibility beyond just SVG. While SVG is common and recommended, you can use any React component that returns JSX.

Here's how it works:

import {defineConfig} from 'sanity'

// You can use a functional component that returns an SVG
const MyIcon = () => (
  <svg viewBox="0 0 100 100">
    {/* your svg paths */}
  </svg>
)

export default defineConfig({
  projectId: '<projectId>',
  dataset: 'production',
  icon: MyIcon, // Pass the component
  // ... other config
})

You can also use icons from @sanity/icons which are SVG-based React components that integrate well with Sanity's design system.

2. Detecting Dark/Light Mode for Theme-Aware Icons

Yes, you can detect the Studio's theme! The @sanity/ui package provides usePrefersDark(), which returns whether the user prefers dark mode based on the Sanity UI theme context (not just the system preference).

Since the icon property accepts a React component, you can create a theme-aware wrapper:

import {defineConfig} from 'sanity'
import {usePrefersDark} from '@sanity/ui'

const ThemeAwareIcon = () => {
  const prefersDark = usePrefersDark()
  
  return prefersDark ? (
    <svg viewBox="0 0 100 100">
      {/* Light-colored icon for dark mode */}
    </svg>
  ) : (
    <svg viewBox="0 0 100 100">
      {/* Dark-colored icon for light mode */}
    </svg>
  )
}

export default defineConfig({
  icon: ThemeAwareIcon,
  // ... other config
})

Even Simpler: Use currentColor

The easiest approach is to use currentColor in your SVG's fill or stroke attributes. This automatically adapts to Sanity's theme without any conditional logic:

const StudioIcon = () => (
  <svg viewBox="0 0 100 100" fill="currentColor">
    {/* your svg paths */}
  </svg>
)

export default defineConfig({
  icon: StudioIcon,
  // ... other config
})

With currentColor, Sanity UI's theming system automatically applies the appropriate color - your icon will be dark in light mode and light in dark mode, perfectly matching the Studio's appearance!

user K
Did you get an answer to #2? I'm interested in the answer to that šŸ‘€
I did find this, though it doesn't help you to set specific colours, but does get you a toggle between
rgb(228, 229, 233)
(near white) and
rgb(37, 40, 55)
(near black).
There’s a
usePrefersDark
hook you could import from
@sanity/ui
that I believe should achieve this. I tried the following for a quick POC:

// sanity.config.tsx

import { usePrefersDark } from '@sanity/ui';

function StudioIcon() {
  const prefersDark = usePrefersDark();
  return prefersDark === true ? <RocketIcon /> : <AddIcon />;
}

export default defineConfig({
  name: 'default',
  title: 'Playground v3',
  icon: () => <StudioIcon />,

  // ...

});
For number 1, I tried replacing one of the icons with a simple image element (sourcing a png), and that worked fine.
For number 1, it looks like the key is to use a function. I tried the following and it worked:

export default defineConfig({
  name: 'default',
  title: 'Playground v3',
  icon: () => (
    <img
      src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAARVBMVEVHcEzyPzDxPy/wPjDwPi/wPi/xPzLxQDHwPi/wPCzwOSjzXlL3kor4oZr1f3bxSz36sqz0cGf81tTwMh/////+7Or6v7uaZRJHAAAACXRSTlMAMoO/5/9bFdR0/bLYAAABA0lEQVR4AWyRBwKDMAhFMx2ZGGLvf9RiCHZ+t4+NuqWNdd47a7T61kJA5JYPtG7+Q9v6FtH/SH+xPex8e6crf4WYMqnUwN8ceRtuPsFUYbqNOtmP2Tu9anaDHQ0gxVqPi9aR10k1mDtkKmbHyK5ck2EI/Sw4yq0kP2SUZZh674+jIpL37lmWU5J9v3Q2KB4FOuVZWPrUmW9XgR7j45y4CVVOaMB65DYMMs6wVgZLlQTEWhq5hlmQYRhJ4TKi8P2UVjQ7ZgCIeDknaI3D6nt8QDpijQmgcU73d/DZ7zJ4tXHgIiwx2z6WXUvKOZUY9rdlc03SzXPwZIIvgeFLmoQTNd7sAAAfVxYmUQgxOwAAAABJRU5ErkJggg=="
      alt="Sanity.io"
      width={24}
      height={24}
    />
  ),

  // ...

});
Ok, figured out that the
usePrefersDark
hook is designed to respond to the user's system-wide color scheme preference, and not the theme setting within the Sanity Studio. To access that, use the useTheme hook and you can drill down to find the dark/light mode info.
const theme = useTheme()

console.log(theme.sanity.v2.color._dark)
This will log true or false as you switch between dark and light. This is exactly what I was looking for.
Thanks for your help,
user A
and
user G
!
Ah, good to know! I used the light/dark emulation buttons in dev tools, but I guess those would operate on the system setting. Thanks for following up with your solution!

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?