Skip to content

Styling hooks

The data attributes and CSS variables you can target from your own CSS, which ones are Youj's, and which are private.

Write selectors and overrides against the names on this page. Anything else, in particular a CSS variable that starts with --ui--, is private and can change in any release. A rename of a name on this page is a breaking change.

One prefix rule

Youj's own attributes all start with data-yj-. Attributes from Base UI, shadcn/ui and next-themes keep their own names and are not prefixed.

AttributeSet byValuesMeaning
data-yj-themeYoujProvider with a themethe theme idMarks a subtree whose derived tokens are recomputed.
data-yj-lookYoujProviderbezel, classicThe look of the components.
data-yj-motionYoujProvider with a themeprecise, calm, livelyThe theme's motion personality.
data-yj-scopeYoujProvider, ThemeScope, useYoujScope()emptyMarks an element that carries Speed (--yj-time-scale) and reduced motion (--yj-motion); the duration tokens resolve again on it.
data-yj-reducedYoujProvider with reducedMotion="always"emptyForces reduced motion in the subtree, whatever the OS says.
data-yj-scalingYoujProvider with scaling75 to 120The interface scale, in percent.
data-yj-densityYoujProvider with densityroomy, compactThe layout room.
data-yj-deviceYoujProvidertouch, pointerThe input device the components size for.
data-yj-toneYou, on a surfacechrome, overlay, inverseRe-derives the color roles for that surface.
data-yj-triggerYou, on a parentemptyPlays the icons inside it on hover and keyboard focus.

The page color mode is data-theme, with light or dark. It keeps that name because next-themes sets it. The preset is data-yj-theme.

Standard attributes

These come from Base UI and shadcn/ui, and the components pass them through unchanged: data-slot (every component part), data-state, data-open, data-closed, data-checked, data-unchecked, data-disabled, data-highlighted, data-selected, data-pressed, data-orientation, data-side, data-align, data-starting-style, data-ending-style, data-popup-open, data-variant, data-size, data-tone, data-status and data-loading.

CSS variables

Variables that you may read or set:

  • The color roles, as --color-<role> (--color-canvas, --color-fg, --color-accent…).
  • The theme contract, as --yj-*.
  • The shadow scale --ui-shadow-xs, --ui-shadow-sm, --ui-shadow-md and --ui-shadow-lg, the skeleton --ui-shimmer color, and the scrollbar thumb colors --ui-scrollbar-thumb, --ui-scrollbar-thumb-hover and --ui-scrollbar-thumb-active.

Variables that start with --ui-- (the panel padding, the press depth, the compact switch…) are internal to the components. Don't read or set them.

pnpm check:api records both lists in api/youj-surface.md, so a change to a public name shows up in review.

Canvas, WebGL and Lottie

Code that draws with token colors resolves them once, so it has to hear about theme changes. Youj's backgrounds and players already do. For your own canvas code, observeThemeChange(element, callback) calls back whenever the theme above element changes: a light/dark switch, a preset, or a changed theme on a scope.

import { observeThemeChange } from '@youj/core'

// Tokens are formulas, so let the browser resolve one: read the color back
// from an element inside the same scope that uses it.
const probe = document.createElement('span')
probe.hidden = true
probe.style.color = 'var(--color-accent)'
canvas.after(probe)

const paint = () => redraw(getComputedStyle(probe).color)
paint()
const stop = observeThemeChange(canvas, paint) // call stop() on teardown