Crystal
Components

CrystalProvider & Hooks

Theme provider context and utility hooks for the Crystal Design System.

CrystalProvider

The root provider that manages Crystal's two-axis customization system: theme (color identity) and crystallization (personality preset).

import { CrystalProvider } from '@artasce/crystal-ui';

export default function Layout({ children }) {
  return (
    <CrystalProvider defaultTheme="onyx" defaultCrystallization="edge">
      {children}
    </CrystalProvider>
  );
}

CrystalProvider Props

TokenVariableValue
children
ReactNode(required)
theme
CrystalTheme
defaultTheme
CrystalTheme'diamond'
crystallization
CrystalCrystallization
defaultCrystallization
CrystalCrystallization'clean'

Values update live with theme changes. Click any row to copy the CSS variable.

What It Renders

A wrapper <div> with data attributes that activate CSS tokens:

<div class="crystal-root" data-crystal="onyx" data-crystallization="edge">
  ...children
</div>

CrystalProvider vs data-crystal Attribute

For apps that only need a single, static theme (like the showcase app), you can skip CrystalProvider entirely and set data-crystal directly on <html>:

<html data-crystal="tanzanite">

Use CrystalProvider when you need runtime theme switching or the useCrystalTheme hook.


Hooks

useCrystalTheme

Access and update theme/crystallization from any component inside CrystalProvider.

import { useCrystalTheme } from '@artasce/crystal-ui';

function ThemeSwitcher() {
  const { theme, setTheme, crystallization, setCrystallization } = useCrystalTheme();

  return (
    <select value={theme} onChange={(e) => setTheme(e.target.value)}>
      <option value="diamond">Diamond</option>
      <option value="onyx">Onyx</option>
      <option value="tanzanite">Tanzanite</option>
    </select>
  );
}

useCrystalScale

Fibonacci-based tile scale utilities.

import { useCrystalScale } from '@artasce/crystal-ui';

function Component() {
  const { getSize, getNextScale, scales } = useCrystalScale();

  console.log(getSize('card'));      // 104
  console.log(getNextScale('card')); // 'panel'
  console.log(scales);              // { dot: 4, micro: 8, icon: 16, ... }
}
ScaleSizeUse Case
dot4pxStatus indicators
micro8pxSpacing, icons
icon16pxSmall icons
icon-plus24pxMedium icons
chip40pxChips, tags
mini-card64pxCompact cards
card104pxStandard cards
panel168pxPanels, sidebars
detail272pxDetail views
full440pxFull sections

useCrystallization

Convenience hook to get the current crystallization preset.

import { useCrystallization } from '@artasce/crystal-ui';

const crystallization = useCrystallization(); // 'clean' | 'dream' | 'edge' | 'luxe' | 'bold'

usePrefersReducedMotion

Detects and tracks the user's reduced motion OS preference. Updates reactively when the preference changes.

import { usePrefersReducedMotion } from '@artasce/crystal-ui';

function AnimatedComponent() {
  const prefersReduced = usePrefersReducedMotion();

  if (prefersReduced) {
    return <div>Static content</div>;
  }

  return <div className="animate-bounce">Animated content</div>;
}