claude
This commit is contained in:
parent
890fac1afc
commit
f88eb4dc83
105
CLAUDE.md
Normal file
105
CLAUDE.md
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# Forge - Structured CSS Authoring
|
||||||
|
|
||||||
|
A typed, local, variant-driven way to author CSS. Compiles to real CSS but removes the chaos: no global conflicts, no selector gymnastics, no inline styles. Built for Hono JSX with SSR support.
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
|
||||||
|
CSS is hostile to humans at scale: global namespace, no markup-to-definition link, requires inline styles for per-instance variance, silent conflicts, selector complexity.
|
||||||
|
|
||||||
|
## The Solution
|
||||||
|
|
||||||
|
- **Local styles** - Attached via generated class names, not strings
|
||||||
|
- **Parts** - Named sub-components replace selectors (no `.Button > .Icon` nonsense)
|
||||||
|
- **Variants** - Typed parameters replace inline styles (no `style={{ color: x }}`)
|
||||||
|
- **Deterministic** - Known merge order, dev warnings for conflicts
|
||||||
|
- **Compiles to CSS** - Not a new language, not runtime CSS-in-JS, just organized CSS generation
|
||||||
|
|
||||||
|
## Core Concepts
|
||||||
|
|
||||||
|
**`define(name?, def)`** - Creates a styled component. Returns a component function.
|
||||||
|
- Accepts CSS properties in camelCase (auto-converts to kebab-case)
|
||||||
|
- Numbers auto-converted to `px` (except unitless props like `opacity`, `zIndex`)
|
||||||
|
- Generates CSS classes and registers styles globally
|
||||||
|
|
||||||
|
**Parts** - Sub-components within a component (e.g., Header, Body, Footer)
|
||||||
|
- Defined via `parts: { PartName: { ...styles } }`
|
||||||
|
- Accessible in render as `parts.PartName`
|
||||||
|
- Generate classes like `ComponentName_PartName`
|
||||||
|
|
||||||
|
**Variants** - Conditional styling based on props
|
||||||
|
- Boolean: `variants: { active: { color: 'blue' } }` → `<Component active />`
|
||||||
|
- Keyed: `variants: { size: { small: {...}, large: {...} } }` → `<Component size="small" />`
|
||||||
|
- Work on both root and parts
|
||||||
|
- Generate classes like `ComponentName.variant-key`
|
||||||
|
|
||||||
|
**States** - Pseudo-selectors like hover, focus
|
||||||
|
- `states: { hover: { background: 'blue' } }` → `.Class:hover { ... }`
|
||||||
|
|
||||||
|
**Custom Render** - Override default rendering
|
||||||
|
- `render({ props, parts }) { return <parts.Root>...</parts.Root> }`
|
||||||
|
- Compose parts manually, pass props through
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
- `src/index.tsx` - Main implementation (`define`, `Styles`, CSS generation)
|
||||||
|
- `src/types.ts` - `TagDef` type with all CSS properties, helper sets
|
||||||
|
- **`examples/`** - **REFERENCE THESE** for real-world usage patterns:
|
||||||
|
- `helpers.tsx` - Layout wrapper, reusable components (Body, Header, ThemeToggle)
|
||||||
|
- `index.tsx` - Landing page with grid, cards, parts, and custom render
|
||||||
|
- `button.tsx` - Button variants (intent, size, disabled)
|
||||||
|
- `profile.tsx` - Complex component with multiple parts and variants
|
||||||
|
- `navigation.tsx` - Tabs, pills, breadcrumbs, vertical nav patterns
|
||||||
|
- `src/tests/` - Comprehensive test suite with test helpers
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
- **Static CSS generation** - CSS created at component definition time, not runtime
|
||||||
|
- **Global styles registry** - `styles` object stores all CSS as plain objects
|
||||||
|
- **`Styles` component** - Renders `<style>` tag with all registered CSS (include in HTML `<head>`)
|
||||||
|
- **Real CSS classes** - Generates actual CSS selectors, not inline styles or CSS-in-JS
|
||||||
|
- **Class naming**:
|
||||||
|
- Root: `ComponentName`
|
||||||
|
- Parts: `ComponentName_PartName`
|
||||||
|
- Variants: `ComponentName.variant-key` or just `variant` for boolean
|
||||||
|
- States: `.ClassName:state`
|
||||||
|
- **No duplicate names** - Throws if same name registered twice
|
||||||
|
- **Anonymous components** - Auto-named `Def1`, `Def2`, etc. when name omitted
|
||||||
|
|
||||||
|
## Usage Pattern
|
||||||
|
|
||||||
|
**IMPORTANT: Check `examples/` for real-world patterns before writing new components.**
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { define } from 'forge'
|
||||||
|
|
||||||
|
export const Button = define('Button', {
|
||||||
|
base: 'button', // HTML tag (default: 'div')
|
||||||
|
padding: 20,
|
||||||
|
background: 'blue',
|
||||||
|
|
||||||
|
states: {
|
||||||
|
hover: { background: 'darkblue' }
|
||||||
|
},
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
danger: { background: 'red' }, // boolean
|
||||||
|
size: { // keyed
|
||||||
|
small: { padding: 10 },
|
||||||
|
large: { padding: 30 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// <Button>Click</Button>
|
||||||
|
// <Button danger>Danger!</Button>
|
||||||
|
// <Button size="large">Big</Button>
|
||||||
|
```
|
||||||
|
|
||||||
|
For complex patterns (parts with variants, custom render, states within variants), see:
|
||||||
|
- `examples/index.tsx` - ExampleCard with parts, custom render, nested variants
|
||||||
|
- `examples/profile.tsx` - Multi-part component with size/theme variants
|
||||||
|
- `examples/navigation.tsx` - Multiple component patterns (tabs, pills, breadcrumbs)
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Tests use Bun's test runner. Helpers in `src/tests/test_helpers.ts` for rendering JSX to HTML strings and parsing CSS.
|
||||||
Loading…
Reference in New Issue
Block a user