Theming

Light and dark theme system with CSS custom properties

Theme Switching

Themes are controlled via the data-theme attribute on the <html> element.

  • :root = light theme (default)
  • [data-theme="dark"] = dark theme (override)

The dark theme only overrides color and shadow tokens. Spacing, font, radius, duration, easing, and z-index are shared between light and dark.

Use the useTheme() hook for theme switching:

import { useTheme } from "@hareru/ui"

const { theme, setTheme, resolvedTheme } = useTheme()

// Switch to dark mode
setTheme("dark")

Styling Rules

All style values must use var(--hui-*) tokens. Hardcoded values are prohibited.

Adding Custom Styles

Pass a className prop to the component and reference tokens in your CSS:

.my-component {
  background-color: var(--hui-color-muted);
  padding: var(--hui-spacing-4);
  border-radius: var(--hui-radius-lg);
  font-size: var(--hui-font-size-sm);
  box-shadow: var(--hui-shadow-md);
  transition: background-color var(--hui-duration-fast) var(--hui-easing-out);
}
<Card className="my-component">
  {/* ... */}
</Card>

Correct vs Incorrect

/* Correct */
.my-section {
  padding: var(--hui-spacing-4);
  background-color: var(--hui-color-muted);
  border-radius: var(--hui-radius-lg);
}

/* Incorrect — hardcoded values */
.my-section {
  padding: 16px;
  background-color: #f5f5f5;
  border-radius: 8px;
}

Prohibited Patterns

PatternReasonCorrect Approach
color: #333Hardcoded colors break themingcolor: var(--hui-color-foreground)
z-index: 50Breaks z-index scalez-index: var(--hui-z-index-dropdown)
document.setAttribute("data-theme", ...)Causes state mismatchuseTheme().setTheme("dark")
Tailwind utilities for token valuesDual maintenanceUse var(--hui-*)

Import Rules

// Correct
import { Button, Card } from "@hareru/ui"

// Incorrect — sub-path imports don't exist
import { Button } from "@hareru/ui/components/Button"

// Incorrect — use Hareru UI wrappers instead
import { Dialog } from "@base-ui-components/react/dialog"

On this page