selectors
This commit is contained in:
parent
8a4408fe22
commit
718dc3b73d
49
README.md
49
README.md
|
|
@ -111,6 +111,55 @@ console.log(<Profile pic={user.pic} bio={user.bio} />)
|
|||
console.log(<Profile size="small" pic={user.pic} bio={user.bio} />)
|
||||
```
|
||||
|
||||
### selectors
|
||||
|
||||
Use `selectors` to write custom CSS selectors. Reference the current
|
||||
element with `&` and other parts with `@PartName`:
|
||||
|
||||
```tsx
|
||||
const Checkbox = define("Checkbox", {
|
||||
parts: {
|
||||
Input: {
|
||||
base: "input[type=checkbox]",
|
||||
display: "none",
|
||||
},
|
||||
Label: {
|
||||
base: "label",
|
||||
padding: 10,
|
||||
cursor: "pointer",
|
||||
color: "gray",
|
||||
|
||||
selectors: {
|
||||
// style Label when Input is checked
|
||||
"@Input:checked + &": {
|
||||
color: "green",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
// style Label when Input is disabled
|
||||
"@Input:disabled + &": {
|
||||
opacity: 0.5,
|
||||
cursor: "not-allowed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
render({ props, parts: { Root, Input, Label } }) {
|
||||
return (
|
||||
<Root>
|
||||
<Label>
|
||||
<Input checked={props.checked} />
|
||||
{props.label}
|
||||
</Label>
|
||||
</Root>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
// Usage
|
||||
<Checkbox label="Agree to terms" checked />
|
||||
```
|
||||
|
||||
## themes
|
||||
|
||||
built-in support for CSS variables with full type safety:
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ const UserProfile = define('UserProfile', {
|
|||
maxWidth: 600,
|
||||
margin: "0 auto",
|
||||
background: theme('colors-bgElevated'),
|
||||
border: `1px solid ${theme('colors-border')}`,
|
||||
borderRadius: theme('radius-md'),
|
||||
border: theme('colors-accent'),
|
||||
|
||||
parts: {
|
||||
Header: {
|
||||
|
|
|
|||
|
|
@ -35,16 +35,9 @@ const ThemePicker = define('SpaThemePicker', {
|
|||
},
|
||||
|
||||
render({ parts: { Root, Select } }) {
|
||||
const handleChange = (e: Event) => {
|
||||
const target = e.target as HTMLSelectElement
|
||||
const themeName = target.value
|
||||
document.body.setAttribute('data-theme', themeName)
|
||||
localStorage.setItem('theme', themeName)
|
||||
}
|
||||
|
||||
return (
|
||||
<Root>
|
||||
<Select id="theme-select" onchange={handleChange}>
|
||||
<Select id="theme-select" onChange={themeChanged}>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="light">Light</option>
|
||||
</Select>
|
||||
|
|
@ -53,6 +46,13 @@ const ThemePicker = define('SpaThemePicker', {
|
|||
}
|
||||
})
|
||||
|
||||
function themeChanged(e: Event) {
|
||||
const target = e.target as HTMLSelectElement
|
||||
const themeName = target.value
|
||||
document.body.setAttribute('data-theme', themeName)
|
||||
localStorage.setItem('theme', themeName)
|
||||
}
|
||||
|
||||
export const Main = define('SpaMain', {
|
||||
base: 'div',
|
||||
|
||||
|
|
|
|||
|
|
@ -51,13 +51,12 @@ 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>> = {}
|
||||
type Theme = Record<string, string | number>
|
||||
export function createThemes<T extends Record<string, Theme>>(themes: T) {
|
||||
const registeredThemes = {} as T
|
||||
|
||||
for (const [name, values] of Object.entries(themes)) {
|
||||
registeredThemes[name] = createTheme(name, values)
|
||||
(registeredThemes as any)[name] = createTheme(name, values)
|
||||
}
|
||||
|
||||
return createThemedVar(registeredThemes)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user