Theme the comment components
Change how the comment components look through the Sanity UI theme, a few typed props, and composition.
The comment components are built on Sanity UI and take their look from its theme. There are three supported ways to change it: the theme, a few typed props, and composition. Try them in that order. Each one later in the list takes more code.
Prerequisites:
- A working comments panel. See Get started.
Import the Sanity UI stylesheet
Sanity UI v4 ships its static styles as a plain stylesheet, and none of the theming below shows without it. Import it once, wherever your app loads global CSS:
import '@sanity/ui/styles.css'Change the Sanity UI theme
The comment components ship no theme of their own. They use the Sanity UI theme above them. Wrap your app in ThemeProvider and build a theme:
import {ThemeProvider} from '@sanity/ui'
import {buildTheme} from '@sanity/ui/theme'
// Your own component that renders the comments panel
import {Panel} from './Panel'
const theme = buildTheme()
export function Root() {
return (
<ThemeProvider theme={theme}>
<Panel />
</ThemeProvider>
)
}buildTheme takes a config. Leave a key out and its default stays.
What each theme value changes
Each theme value changes these parts of the components:
Theme value | What it changes |
|---|---|
| The primary hue: focus ring, selected outline, mention chip, links and buttons |
| Borders, dividers, muted text, and the tabs |
| The corners of cards and inputs |
| Insets and gaps |
| Avatar sizes, and with them how far the message indents |
| Text |
| Light or dark |
Use a brand palette
Sanity UI names its hues after colors, and the primary tone uses blue. To make the primary hue purple, swap the ramp. The ramps come from @sanity/color. Install it as a dependency of your app to import them:
import * as colors from '@sanity/color'
import {buildTheme} from '@sanity/ui/theme'
const theme = buildTheme({
palette: {...colors, blue: colors.purple},
})Swap gray the same way for warmer or cooler neutrals.
Increase corner radius and spacing
radius and space are arrays, indexed by the numbers the components pass to Sanity UI. Larger values give rounder corners and more air:
const theme = buildTheme({
radius: [0, 3, 6, 10, 14, 18, 24],
space: [0, 5, 10, 15, 24, 36, 56, 88, 140, 220],
})Use the dark color scheme
The scheme is a prop on ThemeProvider, not part of the theme:
<ThemeProvider scheme="dark" theme={theme}>
<Card style={{minHeight: '100vh'}}>
<Panel />
</Card>
</ThemeProvider>Sanity UI paints no background of its own, so if the page behind the panel is not already dark, put the panel in a Card, as above, and give it the height of the page so the dark background reaches the bottom of the window. The browser's default margin on body still shows around the Card as a light frame. Remove it in your global CSS:
body {
margin: 0;
}Each of these is a live story in Theming in the reference.
Restyle the inline highlight
The inline comment highlight is a fixed yellow. The palette doesn't change it; only the scheme does, pale on light and deep on dark. To give it your own look, replace the mark with renderHighlight. It receives the comment and its state, (comment, state), and returns a function that the editor calls to wrap the words, (props) => element. The editor calls that function directly rather than mounting it as a component, so it must not use hooks:
import {SDKPortableTextComments} from '@sanity/collaboration/sdk'
// `handle` is the document handle, `threads` what useCommentThreads returns
<SDKPortableTextComments
{...handle}
path="body"
threads={threads}
renderHighlight={(comment, {selected, onSelect}) =>
(props) => (
<mark
data-comment-id={comment.id}
className={selected ? 'note note-active' : 'note'}
onClick={onSelect}
>
{props.children}
</mark>
)}
/>renderPendingHighlight does the same for the comment being written. More in Draw your own highlight.
Adjust appearance with props
A few props cover what the theme does not.
actions on Comment and CommentThread. 'hover', the default, reveals the action row on hover and focus. 'always' shows it all the time:
<CommentThread actions="always" thread={thread} />In a CommentsPanel or SDKCommentsPanel, pass it through threadProps, which both panels take and which takes a function: threadProps={() => ({actions: 'always'})}.
className and style on each component's root, to place it in your layout: width, margin, a minimum width, the root's opacity. They apply to the root element only. Use them for placement, not to reach the elements inside.
Value | Default | How to change it |
|---|---|---|
How far a resolved or retrying comment fades |
|
|
Where a comment stops shrinking |
|
|
labels rewords the text the components render. See Translate the UI text.
Compose a different layout
When you need a different arrangement rather than a different look, build it from the parts:
- A card of your own, from the primitives: Build a custom comment.
- A different inline highlight:
renderHighlight. See Draw your own highlight.
Unsupported styling approaches
The comment components don't support these styling approaches:
- CSS selectors on the components'
data-*attributes or class names. - Styling elements inside a component, through
style,className, or a global stylesheet.
The DOM is internal. The attributes and the structure can change in any release, without notice. If the theme and the props don't reach what you need, compose.
The one exception is identity. data-thread-id on a thread and data-comment-id on a comment or a highlight say which node is which, so you can find one to scroll to it. They are not for styling.
Next steps
- Each theme in this guide, live: Theming.
- To rearrange a comment rather than theme it: Build a custom comment.
- What a studio already provides: Use comments in Sanity Studio.
Was this page helpful?
Feedback submitted, thanks for helping us improve the docs. Have you tried these alternatives?