<p align="center">
  <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4IiByb2xlPSJpbWciIGFyaWEtbGFiZWw9IlN0cml4Ij48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9InN0cml4LW93bC1yZWQiIHgxPSIyNiIgeTE9IjMwIiB4Mj0iMTAyIiB5Mj0iOTgiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlZjIyM2EiIC8+PHN0b3Agb2Zmc2V0PSIwLjU1IiBzdG9wLWNvbG9yPSIjZGIxMzJhIiAvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2IxMGYyMyIgLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48ZyBmaWxsPSJub25lIiBzdHJva2U9InVybCgjc3RyaXgtb3dsLXJlZCkiIHN0cm9rZS13aWR0aD0iNi41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiID48cGF0aCBkPSJNMjYgNDIgSDEwMiIgLz48cGF0aCBkPSJNNDQgNDYgUTU0IDMwIDY0IDMwIFE3NCAzMCA4NCA0NiIgLz48Y2lyY2xlIGN4PSI0NCIgY3k9IjY2IiByPSIxOCIgLz48Y2lyY2xlIGN4PSI4NCIgY3k9IjY2IiByPSIxOCIgLz48Y2lyY2xlIGN4PSI0NCIgY3k9IjY2IiByPSI4IiAvPjxjaXJjbGUgY3g9Ijg0IiBjeT0iNjYiIHI9IjgiIC8+PHBhdGggZD0iTTU3IDgxIEw2NCA5OCBMNzEgODEiIC8+PC9nPjwvc3ZnPg==" width="96" height="96" alt="Strix" />
</p>

<h1 align="center">@gtmi/strix-react</h1>

<p align="center">
  Strix: an AI-native React design system.
</p>

## Installation

```bash
npm install @gtmi/strix-react
```

React is the only peer dependency — 18 or newer, with `react-dom` to match. Tailwind CSS and Base UI
come with the package, so there is nothing else to add.

## Requirements

Strix is styled with Tailwind CSS v4 and ships its token layer as source, so Tailwind has to see it.
Add this once, in the stylesheet Tailwind processes:

```css
@import 'tailwindcss';
@import '@gtmi/strix-react/tokens.css';
```

Without that import the components render unstyled — every utility they use is generated from those
tokens, so nothing resolves. **Tailwind has to come first:** `tokens.css` does not import
`tailwindcss` itself and its `@theme` block extends Tailwind's, so reversing the two produces no
error and silently missing utilities.

You do not need an `@source` line. Tailwind v4 skips `node_modules` when detecting content, so
Strix's compiled classes would never be generated — `tokens.css` therefore declares the `@source`
itself. An `@source` resolves relative to the stylesheet that declares it, which makes that one line
correct from any layout: pnpm's nested store, a monorepo at any depth, hoisted or not.

### React Server Components

Every entry ships `'use client'` except `.`, `./cn` and `./tokens`, so any component can be rendered
straight from a server component and `cn()` stays callable during a server render. On the Next.js App
Router there is nothing to configure — no `transpilePackages`, no `tsconfig` `paths`, no PostCSS
plugin.

### Testing

Strix is ESM-only. Vitest needs nothing. Jest needs a `.js` transform and a
`transformIgnorePatterns` carve-out — the exact config, and the rest of the integration surface, is
in [docs/CONSUMING.md](https://github.com/twilio-demos/strix/blob/main/docs/CONSUMING.md).

## Usage

### Components

```tsx
import { Button } from '@gtmi/strix-react/button';
import { Card } from '@gtmi/strix-react/card';

export function App() {
  return (
    <Card heading="Hello">
      <Button>Click me</Button>
    </Card>
  );
}
```

### Utilities

```tsx
import { cn } from '@gtmi/strix-react/cn';

const className = cn('px-4', { 'py-2': true });
```

### Themes

The tokens define both themes. `ThemeProvider` stamps the active one onto a `data-theme` attribute,
and `useTheme` reads or changes it:

```tsx
import { ThemeProvider, useTheme } from '@gtmi/strix-react/theme';

export function App() {
  return (
    <ThemeProvider initialTheme="dark">
      <YourApp />
    </ThemeProvider>
  );
}
```

`ThemeProvider` stamps tokens but paints no background, so give your own root a surface —
`className="bg-surface-base"` — or dark text will land on a white page.

**Dark is the default.** The dark values are declared under `:root` as well as
`[data-theme="dark"]`, so an app that renders no provider and sets no attribute is already dark.
Light is opt-in: `initialTheme="light"`, or `data-theme="light"` on your root element.
`prefers-color-scheme` is deliberately never consulted — read it yourself and pass the result as
`initialTheme` if you want to follow the OS.

Set `color-scheme: dark` on your own root too, or native UI (scrollbars, form controls, the caret)
stays light against a dark page.

### Icons

All 340 icons are individually importable, so a bundler only ever sees the ones you use:

```tsx
import { PhoneIcon } from '@gtmi/strix-react/icons/phone';
```

### Patterns

Larger compositions live under `patterns/`:

```tsx
import { ChatLog } from '@gtmi/strix-react/patterns/chat-log';
import { MetricList } from '@gtmi/strix-react/patterns/metric-list';
```

## Accessibility

Every component is measured rather than assumed. Contrast is asserted from each component's own
class output in both themes, `prefers-reduced-motion` is honoured throughout, and the browser
harnesses check the things axe cannot: focus trapping, forced-colours mode, and reflow at 320 CSS
pixels. The current state is 510 story renders with no axe violations and 61 keyboard checks with no
failures.

## Development

This package lives in a monorepo. See the [repository README](https://github.com/twilio-demos/strix)
for the full workflow; the short version:

```bash
pnpm install
pnpm build
pnpm test
pnpm storybook
```

## License

MIT
