93 lines
2.1 KiB
Markdown
93 lines
2.1 KiB
Markdown
# Forge
|
||
|
||
## Why Forge?
|
||
|
||
CSS is powerful, but hostile.
|
||
|
||
### Problems with CSS
|
||
|
||
- Styles are **global and open** — anything can override anything.
|
||
- There’s **no link** between a class in markup and its definition.
|
||
- Inline styles exist because there’s **no structured way to vary styles per instance**.
|
||
- Overrides are silent — conflicts happen without feedback.
|
||
- Complex components require selector gymnastics and reach-in styling.
|
||
|
||
### What Forge Does Instead
|
||
|
||
- Styles are **local to components** and attached by generated handles, not strings.
|
||
- **Parts** give components named sub-targets without selectors.
|
||
- **Variants** replace inline styles with typed, declarative parameters.
|
||
- Style composition is **deterministic** (known merge order, last-wins).
|
||
- Overlapping changes are **warned about in dev**, not silently ignored.
|
||
|
||
### What Forge Is
|
||
|
||
- A typed, local, variant-driven way to author CSS.
|
||
- A system that optimizes for **people typing at a keyboard**, not selectors in a cascade.
|
||
|
||
### What Forge Is Not
|
||
|
||
- Not a new component model.
|
||
- Not a new language.
|
||
- Not a CSS replacement — it compiles _to_ CSS, but removes the chaos.
|
||
|
||
Example:
|
||
|
||
```tsx
|
||
import { define } from "forge"
|
||
|
||
export const Button = define("button", {
|
||
base: "button",
|
||
|
||
padding: 20,
|
||
background: "blue",
|
||
|
||
variants: {
|
||
kind: {
|
||
danger: { background: "red" },
|
||
warning: { background: "yellow" },
|
||
}
|
||
},
|
||
})
|
||
|
||
// Usage
|
||
<Button>Click me</Button>
|
||
<Button kind="danger">Click me carefully</Button>
|
||
<Button kind="warning">Click me?</Button>
|
||
|
||
export const Profile = define("div", {
|
||
padding: 50,
|
||
background: "red",
|
||
|
||
parts: {
|
||
Header: { display: "flex" },
|
||
Avatar: { base: 'img', width: 50 },
|
||
Bio: { color: "gray" },
|
||
},
|
||
|
||
variants: {
|
||
size: {
|
||
small: {
|
||
parts: { Avatar: { width: 20 }}
|
||
}
|
||
}
|
||
},
|
||
|
||
render({ props, parts: { Root, Header, Avatar, Bio } }) {
|
||
return (
|
||
<Root>
|
||
<Header>
|
||
<Avatar src={props.pic} />
|
||
<Bio>{props.bio}</Bio>
|
||
</Header>
|
||
</Root>
|
||
)
|
||
},
|
||
})
|
||
|
||
// Usage:
|
||
import { Profile } from './whatever'
|
||
|
||
<Profile pic={user.pic} bio={user.bio} />
|
||
```
|