themes
This commit is contained in:
parent
855112ac82
commit
dafbce762b
105
README.md
105
README.md
|
|
@ -30,6 +30,24 @@ self-contained TSX components out of discrete parts.
|
|||
|
||||
## examples
|
||||
|
||||
### styles
|
||||
|
||||
```tsx
|
||||
import { define } from "forge"
|
||||
|
||||
export const Button = define("button", {
|
||||
base: "button",
|
||||
|
||||
padding: 20,
|
||||
background: "blue",
|
||||
})
|
||||
|
||||
// Usage
|
||||
<Button>Click me</Button>
|
||||
```
|
||||
|
||||
### variants
|
||||
|
||||
```tsx
|
||||
import { define } from "forge"
|
||||
|
||||
|
|
@ -51,23 +69,27 @@ export const Button = define("button", {
|
|||
<Button>Click me</Button>
|
||||
<Button status="danger">Click me carefully</Button>
|
||||
<Button status="warning">Click me?</Button>
|
||||
```
|
||||
|
||||
### parts + `render()`
|
||||
|
||||
```typescript
|
||||
export const Profile = define("div", {
|
||||
padding: 50,
|
||||
background: "red",
|
||||
|
||||
parts: {
|
||||
Header: { display: "flex" },
|
||||
Avatar: { base: 'img', width: 50 },
|
||||
Avatar: { base: "img", width: 50 },
|
||||
Bio: { color: "gray" },
|
||||
},
|
||||
|
||||
variants: {
|
||||
size: {
|
||||
small: {
|
||||
parts: { Avatar: { width: 20 }}
|
||||
}
|
||||
}
|
||||
parts: { Avatar: { width: 20 } },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
render({ props, parts: { Root, Header, Avatar, Bio } }) {
|
||||
|
|
@ -83,9 +105,80 @@ export const Profile = define("div", {
|
|||
})
|
||||
|
||||
// Usage:
|
||||
import { Profile } from './whatever'
|
||||
import { Profile } from "./whatever"
|
||||
|
||||
<Profile pic={user.pic} bio={user.bio} />
|
||||
console.log(<Profile pic={user.pic} bio={user.bio} />)
|
||||
console.log(<Profile size="small" pic={user.pic} bio={user.bio} />)
|
||||
```
|
||||
|
||||
## themes
|
||||
|
||||
built-in support for CSS variables with full type safety:
|
||||
|
||||
```tsx
|
||||
// themes.tsx - Define your themes
|
||||
import { createThemes } from "forge"
|
||||
|
||||
export const theme = createThemes({
|
||||
dark: {
|
||||
bgColor: "#0a0a0a",
|
||||
fgColor: "#00ff00",
|
||||
sm: 12,
|
||||
lg: 24,
|
||||
},
|
||||
light: {
|
||||
bgColor: "#f5f5f0",
|
||||
fgColor: "#0a0a0a",
|
||||
sm: 12,
|
||||
lg: 24,
|
||||
},
|
||||
})
|
||||
|
||||
// Use theme() in your components
|
||||
import { define } from "forge"
|
||||
import { theme } from "./themes"
|
||||
|
||||
const Button = define("Button", {
|
||||
padding: theme("spacing-sm"),
|
||||
background: theme("colors-bg"),
|
||||
color: theme("colors-fg"),
|
||||
})
|
||||
```
|
||||
|
||||
Theme switching is done via the `data-theme` attribute:
|
||||
|
||||
```tsx
|
||||
// Toggle between themes
|
||||
document.body.setAttribute("data-theme", "dark")
|
||||
document.body.setAttribute("data-theme", "light")
|
||||
```
|
||||
|
||||
The `theme()` function is fully typed based on your theme keys, giving
|
||||
you autocomplete and type checking throughout your codebase.
|
||||
|
||||
## scopes
|
||||
|
||||
Sometimes you want your parts named things like ButtonRow, ButtonCell,
|
||||
ButtonTable, etc, but all those Button's are repetitive:
|
||||
|
||||
```typescript
|
||||
const { define } = createScope("Button")
|
||||
|
||||
// css class becomes "Button"
|
||||
const Button = define("Root", {
|
||||
// becomes "Button"
|
||||
// ...
|
||||
})
|
||||
|
||||
// css class becomes "ButtonRow"
|
||||
const ButtonRow = define("Row", {
|
||||
// ...
|
||||
})
|
||||
|
||||
// css class becomes "ButtonContainer"
|
||||
const ButtonContainer = define("Container", {
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
## see it
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { createTheme, createThemedVar } from '../../src'
|
||||
import { createThemes } from '../../src'
|
||||
import darkTheme from './darkTheme'
|
||||
import lightTheme from './lightTheme'
|
||||
|
||||
// Register themes and get typed keys back
|
||||
const dark = createTheme('dark', darkTheme)
|
||||
const light = createTheme('light', lightTheme)
|
||||
|
||||
// Create a typed themeVar function
|
||||
export const theme = createThemedVar({ dark, light })
|
||||
// Register themes and get a typed theme function in one step
|
||||
export const theme = createThemes({
|
||||
dark: darkTheme,
|
||||
light: lightTheme
|
||||
})
|
||||
|
|
@ -50,6 +50,19 @@ export function createThemedVar<T extends Record<string, any>>(_themes: T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Simplified API: register multiple themes and get typed themeVar in one call
|
||||
export function createThemes<
|
||||
T extends Record<string, Record<string, string | number>>
|
||||
>(themes: T) {
|
||||
const registeredThemes: Record<string, Record<string, string>> = {}
|
||||
|
||||
for (const [name, values] of Object.entries(themes)) {
|
||||
registeredThemes[name] = createTheme(name, values)
|
||||
}
|
||||
|
||||
return createThemedVar(registeredThemes)
|
||||
}
|
||||
|
||||
// Generic themeVar (untyped fallback)
|
||||
export function themeVar(name: string): string {
|
||||
return `var(--theme-${name as string})`
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user