feat: htmx derivation home page 1:1 from react

This commit is contained in:
2026-04-23 23:05:50 -06:00
parent 72448f36d9
commit 928fdd8f75
14 changed files with 13953 additions and 7 deletions

View File

@@ -37,7 +37,10 @@ greyhaven-design-system/
│ ├── utils.ts # cn() utility
│ └── catalog.ts # Shared component catalog (used by MCP + SKILL.md)
├── scripts/
── generate-skill.ts # SKILL.md generator
── generate-skill.ts # SKILL.md generator
│ └── generate-htmx-css.ts # HTMX / framework-agnostic CSS generator
├── dist/
│ └── greyhaven.htmx.css # Auto-generated CSS for HTMX/server-rendered projects
├── app/ # Next.js showcase app (demo only)
└── style-dictionary.config.mjs
```
@@ -53,6 +56,8 @@ greyhaven-design-system/
> **Framework-agnostic**: Components have zero Next.js imports. They work with Vite, Remix, Astro, CRA, or any React framework.
> **Also works without React**: `dist/greyhaven.htmx.css` exposes every component via `data-slot` / `data-variant` / `data-size` attribute selectors. HTMX, Django, Rails, Go template, Astro SSR — any project that emits HTML can consume the visual layer. See [HTMX / server-rendered usage](#htmx--server-rendered-usage).
---
## Using the Design System with AI
@@ -244,6 +249,77 @@ pnpm build-storybook # Static build
---
## HTMX / server-rendered usage
The React components assume a React runtime. For HTMX, Django templates, Rails ERB, Go `html/template`, Astro SSR, or any other server-rendered stack, consume the design system via the auto-generated CSS layer.
### What you get
`dist/greyhaven.htmx.css` is generated from `components/ui/*.tsx` (AST walk over `cva()` configs + static `className` strings on `data-slot` elements). It contains ~300 `@layer components` rules, one per data-slot, with attribute selectors for variants and sizes.
```css
[data-slot="card"] { @apply bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm; }
[data-slot="card-header"] { @apply grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6; }
[data-slot="card-title"] { @apply leading-none font-semibold; }
[data-slot="button"] { @apply inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ; }
[data-slot="button"]:not([data-variant]),
[data-slot="button"][data-variant="default"] { @apply bg-primary text-primary-foreground hover:bg-primary/90; }
[data-slot="button"][data-variant="outline"] { @apply border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground; }
[data-slot="button"][data-size="sm"] { @apply h-8 rounded-md gap-1.5 px-3; }
```
### Install
```bash
./skill/install.sh /path/to/your/project --htmx-css
```
This copies:
- `dist/greyhaven.htmx.css``public/css/greyhaven.htmx.css`
- Aspekta fonts → `public/fonts/`
Add to your Tailwind v4 input CSS:
```css
@import "tailwindcss";
@import "./tokens-light.css";
@import "./tokens-dark.css";
@import "./greyhaven.htmx.css";
```
### Consume
```html
<div data-slot="card">
<div data-slot="card-header">
<div data-slot="card-title">Requests Over Time</div>
<div data-slot="card-description">Last 24 hours</div>
</div>
<div data-slot="card-content"></div>
</div>
<button data-slot="button" data-variant="default">Save</button>
<button data-slot="button" data-variant="outline" data-size="sm">Cancel</button>
<span data-slot="badge" data-variant="success">Active</span>
```
### Scope
- **Static visual components** (Card, Button, Badge, Input, Label, Textarea, Table, Separator, Code, Kbd, Progress, Avatar, Skeleton, Alert, Pagination, Breadcrumb, Navbar, etc.) → fully driven by CSS, no JS needed.
- **Interactive components** (Dialog, Dropdown, Popover, Select, Combobox, Accordion, Tabs, Tooltip, etc.) → CSS emits their static styles, but open/close / positioning / focus management is the consumer's responsibility. Alpine.js pairs naturally with HTMX for these.
- **Native HTML alternatives**: `<details>` covers Accordion/Collapsible, `<dialog>` covers Dialog. The CSS rules apply to those too.
### Regenerate
```bash
pnpm htmx-css:build # Regenerate dist/greyhaven.htmx.css from components/ui/*.tsx
```
Re-runs of `./skill/install.sh --htmx-css` in consumer projects refresh their copy.
---
## Adding a New Component
1. Create `components/ui/my-component.tsx` following the CVA pattern (see `button.tsx`)
@@ -264,6 +340,7 @@ pnpm build-storybook # Static build
| `pnpm build-storybook` | Static Storybook build |
| `pnpm tokens:build` | Regenerate CSS/TS/MD from token JSON files |
| `pnpm skill:build` | Regenerate skill/SKILL.md and skill/AGENTS.md from tokens + catalog |
| `pnpm htmx-css:build` | Regenerate dist/greyhaven.htmx.css from components/ui/*.tsx |
| `pnpm mcp:start` | Start the MCP server (stdio transport) |
| `pnpm mcp:build` | Type-check MCP server |
| `pnpm lint` | Run ESLint |