Foundations

Theming and styling channels

Change what a primitive looks like with token overrides, className, and xstyle

LayerOwnsMechanism
Base UIInteraction, focus, ARIA, data attributesHeadless components
@nyte-ai/uiReusable component stylingStyleX stylex.create reading tokens
The appLayout, typography, product identity, compositesToken overrides, className, xstyle, own components

Token overrides

Override on an ancestor. The app root is the right place, and a preview container works too.

.my-app {
  color-scheme: dark;
  --nyte-color-avatar-orange-background: #5f2a06;
  --nyte-color-avatar-orange-foreground: #ffb27d;
}

Override the tokens that carry identity. Overriding --nyte-control-height-md to fix one layout is a layout problem, so solve that one with className.

The three props every styled primitive accepts

PropTypePurpose
classNamestringConsumer layout, including Tailwind utilities. Appended after the StyleX class.
styleReact.CSSPropertiesInline overrides. Spread after StyleX's inline style, so it wins.
xstyleXStyleA deliberate StyleX override. Passed as the last argument to stylex.props, so it wins by StyleX's merge rules.

XStyle accepts one compiled style, an array, or a conditional.

unstyled

Button, Input, and Textarea accept unstyled. When true the component renders the Base UI part with no StyleX class at all, keeping the interaction layer and the data-slot attribute. On Button, unstyled also forbids variant and size at the type level.

Reach for unstyled when a surface supplies a complete xstyle treatment of its own. For a slightly different button, use a token override or xstyle.

Data attributes

Every primitive sets data-slot="<part>", so you can target a part from CSS without knowing the StyleX class. Variant-bearing primitives also expose their appearance.

ComponentAttributes
Buttondata-slot="button", data-variant, data-size (omitted when unstyled)
Avatardata-slot="avatar", data-size, data-tone
AvatarImagedata-slot="avatar-image"
AvatarFallbackdata-slot="avatar-fallback"
Inputdata-slot="input"
Textareadata-slot="textarea"
DropdownMenuItemdata-slot="dropdown-menu-item", data-variant, data-inset
DropdownMenuLabeldata-inset

Base UI adds its own state attributes on top, such as data-disabled, data-popup-open, data-highlighted, and data-checked. Each component page lists them.

Headless subpaths

For anything without a styled wrapper, import the Base UI namespace from its subpath and style it in the app.

import { Popover } from "@nyte-ai/ui/popover";

Import from the subpath rather than @base-ui/react, so the Base UI version stays behind the shared package. See Components.

Dark mode

Tokens use light-dark(), so a primitive follows whichever color-scheme is in effect. The primitives have no .dark class. @nyte-ai/ui/styles.css declares @custom-variant dark (&:is(.dark *)) for Tailwind consumers who want class-based variants in their own utilities.