Skip to content

Commit f00ca90

Browse files
committed
Keep landing deep-slate brightness and keep docs more readable.
1 parent 1a12f62 commit f00ca90

4 files changed

Lines changed: 132 additions & 9 deletions

File tree

‎frontend/README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ page, cards, inset surfaces, and controls, plus border strength, saturation, and
8282
shadow density. Dark presets range from crisp slate to a brighter warm studio.
8383
Documentation derives its colors from these same roles, so its code panels and
8484
copy controls keep their own layers instead of sharing one flat reading surface.
85+
`theme/studioLandingColors.ts` keeps the landing page's original light-paper and
86+
deep-slate brightness while applying the selected color family's hues. Its
87+
palette overrides stay within the studio template; documentation retains each
88+
preset's distinct layer contrast. The initial background style uses the same
89+
template-specific palette before the full stylesheets load.
8590
`studioColorStyles.ts` emits the changed palette variables and documentation
8691
color variables. A tiny inline startup script before the
8792
stylesheet links restores `purestack-site-color` from local storage. The picker

‎frontend/theme/studioColorHead.ts‎

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { PageHeadTemplate } from '@purestack/ts-common'
22
import { Style } from '@purestack/ts-css'
33
import { h } from '@purestack/ts-html'
4+
import { createStudioLandingPalette } from './studioLandingColors'
45
import { createStudioDarkPalette } from './studioSkinDark'
56
import { createStudioLightPalette } from './studioSkinLight'
67
import {
@@ -15,17 +16,23 @@ export function buildSiteColorInitScript() {
1516
return `(()=>{let c=${JSON.stringify(DEFAULT_SITE_COLOR)};try{let s=localStorage.getItem(${JSON.stringify(SITE_COLOR_STORAGE_KEY)});if(${ids}.includes(s))c=s}catch{}document.documentElement.setAttribute("data-site-color",c)})();`
1617
}
1718

18-
let criticalStyle: string | undefined
19+
const criticalStyles = new Map<boolean, string>()
1920

20-
function buildSiteColorCriticalStyle() {
21-
if (criticalStyle) return criticalStyle
21+
function buildSiteColorCriticalStyle(landing: boolean) {
22+
const cached = criticalStyles.get(landing)
23+
if (cached) return cached
2224
const root = new Style()
25+
if (landing) registerLandingInitialColors(root)
2326
for (const preset of studioColorPresets) {
24-
const light = createStudioLightPalette(preset, preset.layers.light)
25-
const dark = createStudioDarkPalette(preset, preset.layers.dark)
27+
const light = landing
28+
? createStudioLandingPalette('light', preset)
29+
: createStudioLightPalette(preset, preset.layers.light)
30+
const dark = landing
31+
? createStudioLandingPalette('dark', preset)
32+
: createStudioDarkPalette(preset, preset.layers.dark)
2633
const lightCanvas = light.semanticTone.neutral.canvas
2734
const darkCanvas = dark.semanticTone.neutral.canvas
28-
const selector = `html[data-site-color="${preset.id}"]`
35+
const selector = `html:root[data-site-color="${preset.id}"]`
2936
root.select(selector).background(lightCanvas)
3037
root
3138
.media('prefers-color-scheme: dark')
@@ -34,19 +41,34 @@ function buildSiteColorCriticalStyle() {
3441
root.select(`${selector}[data-theme="light"]`).background(lightCanvas)
3542
root.select(`${selector}[data-theme="dark"]`).background(darkCanvas)
3643
}
37-
criticalStyle = root.toCSS()
44+
const criticalStyle = root.toCSS()
45+
criticalStyles.set(landing, criticalStyle)
3846
return criticalStyle
3947
}
4048

41-
export const renderStudioColorHead: PageHeadTemplate = ({ head }) => {
49+
function registerLandingInitialColors(root: Style) {
50+
const light = createStudioLandingPalette('light').semanticTone.neutral
51+
const dark = createStudioLandingPalette('dark').semanticTone.neutral
52+
root.select('html, body').background(light.canvas).color(light.text.default)
53+
root
54+
.media('prefers-color-scheme: dark')
55+
.select('html, body')
56+
.background(dark.canvas)
57+
.color(dark.text.default)
58+
}
59+
60+
export const renderStudioColorHead: PageHeadTemplate = ({
61+
head,
62+
templateName,
63+
}) => {
4264
const startup = h('script')
4365
.attr({ 'data-site-color-init': '' })
4466
.raw(buildSiteColorInitScript())
4567
if (!head.insertBefore('link', startup, { rel: 'stylesheet' }))
4668
head.push(startup)
4769
const critical = h('style')
4870
.attr({ 'data-site-color-critical': '' })
49-
.raw(buildSiteColorCriticalStyle())
71+
.raw(buildSiteColorCriticalStyle(templateName === 'studio'))
5072
if (!head.insertBefore('link', critical, { rel: 'stylesheet' }))
5173
head.push(critical)
5274
return head

‎frontend/theme/studioColorStyles.ts‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import type { Style } from '@purestack/ts-css'
12
import {
23
listThemePaletteVarEntries,
34
styleBuilder,
45
themes,
6+
type ThemeMode,
57
type ThemePalette,
68
} from '@purestack/ts-style'
79
import { studioColorPresets } from './studioColorPresets'
10+
import { createStudioLandingPalette } from './studioLandingColors'
811
import { createStudioDarkPalette } from './studioSkinDark'
912
import { createStudioLightPalette } from './studioSkinLight'
1013

@@ -36,9 +39,58 @@ export function registerStudioColorStyles() {
3639
root.set(token.name, token.value)
3740
}
3841
}
42+
registerLandingColorStyles(theme, defaults)
3943
})
4044
}
4145

46+
function registerLandingColorStyles(
47+
theme: ThemeMode,
48+
defaults: Map<string, string>,
49+
) {
50+
const landingScope =
51+
':is(:root:has(> body.studio), body.studio, body.studio *)'
52+
const landing = styleBuilder
53+
.get(theme)
54+
.select(
55+
`:scope${landingScope}:not(:where([data-site-color], [data-site-color] *))`,
56+
)
57+
setChangedPaletteVariables(
58+
landing,
59+
createStudioLandingPalette(theme),
60+
defaults,
61+
)
62+
63+
for (const preset of studioColorPresets) {
64+
const root = styleBuilder
65+
.get(theme)
66+
.select(
67+
`:scope:is([data-site-color="${preset.id}"], [data-site-color="${preset.id}"] *)${landingScope}`,
68+
)
69+
// Compare with the active preset, since its declarations also match descendants.
70+
const createPalette =
71+
theme === 'dark' ? createStudioDarkPalette : createStudioLightPalette
72+
const presetDefaults = paletteValues(
73+
createPalette(preset, preset.layers[theme]),
74+
)
75+
setChangedPaletteVariables(
76+
root,
77+
createStudioLandingPalette(theme, preset),
78+
presetDefaults,
79+
)
80+
}
81+
}
82+
83+
function setChangedPaletteVariables(
84+
root: Style,
85+
palette: ThemePalette,
86+
defaults: Map<string, string>,
87+
) {
88+
for (const token of listThemePaletteVarEntries(palette)) {
89+
if (token.value !== defaults.get(token.name))
90+
root.set(token.name, token.value)
91+
}
92+
}
93+
4294
function paletteValues(palette: ThemePalette) {
4395
return new Map(
4496
listThemePaletteVarEntries(palette).map((token) => [
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import type { ThemeMode } from '@purestack/ts-style'
2+
import type { StudioHues } from './studioSkinShared'
3+
import { createStudioDarkPalette } from './studioSkinDark'
4+
import { createStudioLightPalette } from './studioSkinLight'
5+
import type { StudioSurfaceProfile } from './studioSurfaceProfiles'
6+
7+
/** Keep the landing page's original light paper and deep slate brightness. */
8+
const landingSurfaces = {
9+
light: {
10+
canvas: 0.984,
11+
surface: 1,
12+
surfaceAlt: 0.965,
13+
control: 0.955,
14+
border: 0.86,
15+
borderSubtle: 0.92,
16+
ink: 0.24,
17+
muted: 0.5,
18+
chroma: 0.04,
19+
tint: 0.1,
20+
shadow: 1,
21+
},
22+
dark: {
23+
canvas: 0.17,
24+
surface: 0.205,
25+
surfaceAlt: 0.19,
26+
control: 0.26,
27+
border: 0.33,
28+
borderSubtle: 0.27,
29+
ink: 0.93,
30+
muted: 0.71,
31+
chroma: 0.22,
32+
tint: 0.22,
33+
shadow: 1,
34+
},
35+
} satisfies Record<ThemeMode, StudioSurfaceProfile>
36+
37+
export function createStudioLandingPalette(
38+
theme: ThemeMode,
39+
hues?: StudioHues,
40+
) {
41+
const createPalette =
42+
theme === 'dark' ? createStudioDarkPalette : createStudioLightPalette
43+
return createPalette(hues, landingSurfaces[theme])
44+
}

0 commit comments

Comments
 (0)