Skip to content

Commit 1a2fe2a

Browse files
committed
Add states to the spotlight and glass variants.
1 parent d8001c4 commit 1a2fe2a

3 files changed

Lines changed: 42 additions & 14 deletions

File tree

‎frontend/purestack.studio/guides/semantic-tones.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ A tone contains more than one background and text color. These samples all selec
121121

122122
Keep fill, border, and text from the same role when you need a ready-made combination. Each role's colors are designed as a set within the active theme. The direct `tone-fill`, `tone-border`, and `tone-text` classes use the tone color itself; they are useful for accents, but they are not the same as a complete surface or button treatment.
123123

124-
`spotlight` is for large areas such as feature bands, callouts, and showcase panels. It is a calm field with a soft light, without the gloss and edge shading of surfaces and buttons, so it stays calm at any size. It has no interaction states and pairs with the alternate surface border and text classes. Components accept it as `variant="spotlight"`, for example `<Panel tone="accent" variant="spotlight">`.
124+
`spotlight` is for large areas such as feature bands, callouts, and showcase panels. It is a calm field with a soft light, without the gloss and edge shading of surfaces and buttons, so it stays calm at any size. It pairs with the alternate surface border and text classes. Like every fill it has `-hover`, `-active`, `-disabled`, and `-all` forms: the light reaches further on hover and press, and goes out when disabled. Components accept it as `variant="spotlight"`, for example `<Panel tone="accent" variant="spotlight">`.
125125

126126
Keep spotlights rare: one or two per page, for the pieces a visitor should notice first. Most surfaces should be quiet. `tone-fill-flat`, `tone-fill-flat-alt`, and `tone-fill-flat-solid` paint a role's single color without the gradient chrome, with the same `-hover`, `-active`, `-disabled`, and `-all` forms as the gradient fills. Components accept them as `variant="flat"`, `variant="flatAlt"`, and `variant="flatSolid"`:
127127

@@ -138,7 +138,7 @@ The skin sets the field and the light color; the page decides where the light fa
138138
</Panel>
139139
```
140140

141-
Cards placed on a spotlight should not repeat its field. `tone-fill-glass` lets the field show through, lifted by a faint veil and lit by the same light, so a card reads as a lighter pane rather than a second color. The light follows the nearest `spotlight-from-*`, so cards and their spotlight are lit from the same side. Components accept it as `variant="glass"`. A different tone on a glass card tints it without breaking the field:
141+
Cards placed on a spotlight should not repeat its field. `tone-fill-glass` lets the field show through, lifted by a faint veil and lit by the same light, so a card reads as a lighter pane rather than a second color. The light follows the nearest `spotlight-from-*`, so cards and their spotlight are lit from the same side. Its veil thickens on hover and press, and thins without the light when disabled. Components accept it as `variant="glass"`. A different tone on a glass card tints it without breaking the field:
142142

143143
<div class="tone--accent tone-fill-spotlight tone-border-surface-alt tone-text-surface-alt b-1 rounded-lg p-3 spotlight-from-top-right">
144144
<Grid columns="1" columnsSm="2" class="gap-3">

‎packages/ts-components/src/standard/componentVariant.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ const STATELESS_COMPONENT_VARIANT_CLASSES: Record<ComponentVariant, string> = {
6666
}
6767

6868
const STATEFUL_COMPONENT_VARIANT_CLASSES = {
69+
spotlight:
70+
'tone-fill-spotlight-hover tone-fill-spotlight-active tone-border-surface-alt-hover tone-border-surface-alt-active tone-text-surface-alt-hover tone-text-surface-alt-active',
71+
glass:
72+
'tone-fill-glass-hover tone-fill-glass-active tone-border-surface-alt-hover tone-border-surface-alt-active tone-text-surface-alt-hover tone-text-surface-alt-active',
6973
flat: 'tone-fill-flat-hover tone-fill-flat-active tone-border-surface-hover tone-border-surface-active tone-text-surface-hover tone-text-surface-active',
7074
flatAlt:
7175
'tone-fill-flat-alt-hover tone-fill-flat-alt-active tone-border-surface-alt-hover tone-border-surface-alt-active tone-text-surface-alt-hover tone-text-surface-alt-active',

‎packages/ts-style/src/semanticPresets.ts‎

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,40 @@ function flatFill(role: ThemePaletteCurrent['surface']): States {
5252
}
5353
}
5454

55-
function glass(current: ThemePaletteCurrent) {
56-
const veil = `color-mix(in srgb, ${current.spotlight.light} 45%, transparent)`
57-
return `${spotlightLight(current, '75%')}, linear-gradient(${veil}, ${veil})`
55+
/**
56+
* The spotlight answers a pointer by letting its light reach further, and
57+
* goes dark, leaving only the field, when disabled.
58+
*/
59+
function spotlightFill(current: ThemePaletteCurrent): States {
60+
const lit = (reach: string) =>
61+
`${spotlightLight(current, reach)}, ${current.spotlight.field}`
62+
return {
63+
all: true,
64+
rest: { background: lit('46%') },
65+
hover: { background: lit('60%') },
66+
active: { background: lit('72%') },
67+
disabled: { background: current.spotlight.field },
68+
}
69+
}
70+
71+
/**
72+
* Glass answers a pointer by thickening its veil, and loses its light and
73+
* most of its veil when disabled.
74+
*/
75+
function glassFill(current: ThemePaletteCurrent): States {
76+
const veil = (strength: string) => {
77+
const color = `color-mix(in srgb, ${current.spotlight.light} ${strength}, transparent)`
78+
return `linear-gradient(${color}, ${color})`
79+
}
80+
const lit = (strength: string) =>
81+
`${spotlightLight(current, '75%')}, ${veil(strength)}`
82+
return {
83+
all: true,
84+
rest: { background: lit('45%') },
85+
hover: { background: lit('58%') },
86+
active: { background: lit('70%') },
87+
disabled: { background: veil('25%') },
88+
}
5889
}
5990

6091
function createSpotlightOrigins(styleBuilder: StyleBuilder, theme: string) {
@@ -203,17 +234,10 @@ function createFills(
203234
background: current.canvas,
204235
},
205236
},
206-
'tone-fill-spotlight': {
207-
rest: {
208-
background: `${spotlightLight(current, '46%')}, ${current.spotlight.field}`,
209-
},
210-
},
237+
'tone-fill-spotlight': spotlightFill(current),
211238
// Glass lets the field behind show through, lifted by a veil and lit by
212239
// the same light, so cards sit on a spotlight without a second color.
213-
'tone-fill-glass': {
214-
rest: { background: glass(current) },
215-
hover: { background: glass(current) },
216-
},
240+
'tone-fill-glass': glassFill(current),
217241
// Flat fills paint each role's single color, without the gradient
218242
// chrome, for the many quiet surfaces around a few spotlights.
219243
'tone-fill-flat': flatFill(current.surface),

0 commit comments

Comments
 (0)