@timmo001/groundwork-tokens 0.9.40 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2706,6 +2706,53 @@
2706
2706
  "row-padding": "var(--gw-space-3)"
2707
2707
  },
2708
2708
  "modes": {
2709
+ "light": {
2710
+ "surface-lower": "#d0d5e3",
2711
+ "surface-low": "#dadbe0",
2712
+ "surface-default": "#e1e2e7",
2713
+ "surface-raised": "#e9e9ed",
2714
+ "surface-overlay": "#e1e1e5",
2715
+ "border-quiet": "#ced2e4",
2716
+ "border-normal": "#c4c8da",
2717
+ "border-loud": "#abafc0",
2718
+ "text-strong": "#3760bf",
2719
+ "text-primary": "#3760bf",
2720
+ "text-secondary": "#6172b0",
2721
+ "text-disabled": "#6172b099",
2722
+ "fill-neutral-resting": "#dfdfe3",
2723
+ "fill-neutral-hovered": "#d5d5d9",
2724
+ "fill-neutral-pressed": "#ccccd0",
2725
+ "fill-neutral-selected": "#cfcfd3",
2726
+ "fill-neutral-disabled": "#e4e4e8",
2727
+ "fill-primary-resting": "#3760bf",
2728
+ "fill-primary-hovered": "#4772d3",
2729
+ "fill-primary-pressed": "#537fe1",
2730
+ "on-primary": "#e1e2e7",
2731
+ "accent": "#2e7de9",
2732
+ "fill-accent-resting": "#2e7de9",
2733
+ "fill-accent-hovered": "#0042a5",
2734
+ "fill-accent-pressed": "#0059c0",
2735
+ "fill-accent-quiet": "#0051b729",
2736
+ "border-accent": "#0051b780",
2737
+ "on-accent": "#ffffff",
2738
+ "focus": "#2e7de9",
2739
+ "link": "#0051b7",
2740
+ "info": "#2e7de9",
2741
+ "fill-info-quiet": "#2e7de924",
2742
+ "border-info": "#2e7de973",
2743
+ "success": "#587539",
2744
+ "fill-success-quiet": "#58753924",
2745
+ "border-success": "#58753973",
2746
+ "important": "#9854f1",
2747
+ "fill-important-quiet": "#9854f124",
2748
+ "border-important": "#9854f173",
2749
+ "warning": "#8c6c3e",
2750
+ "fill-warning-quiet": "#8c6c3e24",
2751
+ "border-warning": "#8c6c3e73",
2752
+ "danger": "#f52a65",
2753
+ "fill-danger-quiet": "#f52a6524",
2754
+ "border-danger": "#f52a6573"
2755
+ },
2709
2756
  "dark": {
2710
2757
  "surface-lower": "#16161e",
2711
2758
  "surface-low": "#171823",
@@ -2803,9 +2850,9 @@
2803
2850
  }
2804
2851
  },
2805
2852
  {
2806
- "id": "tokyo-night-day",
2807
- "name": "Tokyo Night Day",
2808
- "description": "Tokyo Night Day, mapped onto the roles so it stays faithful to the Tokyo Night palette.",
2853
+ "id": "tokyo-night-moon",
2854
+ "name": "Tokyo Night Moon",
2855
+ "description": "Tokyo Night Moon, mapped onto the roles so it stays faithful to the Tokyo Night palette.",
2809
2856
  "optional": true,
2810
2857
  "family": "Tokyo Night",
2811
2858
  "examples": [],
@@ -2925,86 +2972,7 @@
2925
2972
  "danger": "#f52a65",
2926
2973
  "fill-danger-quiet": "#f52a6524",
2927
2974
  "border-danger": "#f52a6573"
2928
- }
2929
- }
2930
- },
2931
- {
2932
- "id": "tokyo-night-moon",
2933
- "name": "Tokyo Night Moon",
2934
- "description": "Tokyo Night Moon, mapped onto the roles so it stays faithful to the Tokyo Night palette.",
2935
- "optional": true,
2936
- "family": "Tokyo Night",
2937
- "examples": [],
2938
- "style": {
2939
- "font": "Mona Sans",
2940
- "mono": "Geist Mono",
2941
- "radius": {
2942
- "panel": 10,
2943
- "control": 8,
2944
- "chip": 6
2945
- },
2946
- "border": {
2947
- "width": 1,
2948
- "strength": "hairline"
2949
- },
2950
- "weights": {
2951
- "regular": 400,
2952
- "strong": 600
2953
- },
2954
- "density": "normal",
2955
- "capitals": false,
2956
- "link": {
2957
- "color": "accent",
2958
- "underline": "thin"
2959
2975
  },
2960
- "surfaceAccent": "none",
2961
- "rows": "cards"
2962
- },
2963
- "properties": {
2964
- "font-sans": "\"Mona Sans Variable\", \"Mona Sans\", system-ui, sans-serif",
2965
- "font-figures": "\"Mona Sans Variable\", \"Mona Sans\", system-ui, sans-serif",
2966
- "font-mono": "\"Geist Mono Variable\", \"Geist Mono\", ui-monospace, monospace",
2967
- "font-weight-regular": "400",
2968
- "font-weight-strong": "600",
2969
- "density": "1",
2970
- "control-scale": "1",
2971
- "space-0-5": "calc(0.125rem * var(--gw-density))",
2972
- "space-1": "calc(0.25rem * var(--gw-density))",
2973
- "space-2": "calc(0.5rem * var(--gw-density))",
2974
- "space-3": "calc(0.75rem * var(--gw-density))",
2975
- "space-4": "calc(1rem * var(--gw-density))",
2976
- "space-5": "calc(1.25rem * var(--gw-density))",
2977
- "space-6": "calc(1.5rem * var(--gw-density))",
2978
- "space-7": "calc(1.75rem * var(--gw-density))",
2979
- "space-8": "calc(2rem * var(--gw-density))",
2980
- "space-9": "calc(2.25rem * var(--gw-density))",
2981
- "space-10": "calc(2.5rem * var(--gw-density))",
2982
- "space-11": "calc(2.75rem * var(--gw-density))",
2983
- "space-12": "calc(3rem * var(--gw-density))",
2984
- "space-13": "calc(3.25rem * var(--gw-density))",
2985
- "space-14": "calc(3.5rem * var(--gw-density))",
2986
- "space-15": "calc(3.75rem * var(--gw-density))",
2987
- "space-16": "calc(4rem * var(--gw-density))",
2988
- "space-17": "calc(4.25rem * var(--gw-density))",
2989
- "space-18": "calc(4.5rem * var(--gw-density))",
2990
- "space-19": "calc(4.75rem * var(--gw-density))",
2991
- "space-20": "calc(5rem * var(--gw-density))",
2992
- "radius-panel": "10px",
2993
- "radius-control": "8px",
2994
- "radius-chip": "6px",
2995
- "border-width": "1px",
2996
- "border-color": "var(--gw-color-border-quiet)",
2997
- "label-transform": "none",
2998
- "label-tracking": "normal",
2999
- "link-color": "var(--gw-color-link)",
3000
- "link-underline": "1px",
3001
- "panel-sheen": "none",
3002
- "panel-marker": "0px",
3003
- "panel-flange": "0px",
3004
- "panel-flange-color": "var(--gw-border-color)",
3005
- "row-padding": "var(--gw-space-3)"
3006
- },
3007
- "modes": {
3008
2976
  "dark": {
3009
2977
  "surface-lower": "#1e2030",
3010
2978
  "surface-low": "#202234",
@@ -3178,6 +3146,53 @@
3178
3146
  "row-padding": "var(--gw-space-3)"
3179
3147
  },
3180
3148
  "modes": {
3149
+ "light": {
3150
+ "surface-lower": "#d0d5e3",
3151
+ "surface-low": "#dadbe0",
3152
+ "surface-default": "#e1e2e7",
3153
+ "surface-raised": "#e9e9ed",
3154
+ "surface-overlay": "#e1e1e5",
3155
+ "border-quiet": "#ced2e4",
3156
+ "border-normal": "#c4c8da",
3157
+ "border-loud": "#abafc0",
3158
+ "text-strong": "#3760bf",
3159
+ "text-primary": "#3760bf",
3160
+ "text-secondary": "#6172b0",
3161
+ "text-disabled": "#6172b099",
3162
+ "fill-neutral-resting": "#dfdfe3",
3163
+ "fill-neutral-hovered": "#d5d5d9",
3164
+ "fill-neutral-pressed": "#ccccd0",
3165
+ "fill-neutral-selected": "#cfcfd3",
3166
+ "fill-neutral-disabled": "#e4e4e8",
3167
+ "fill-primary-resting": "#3760bf",
3168
+ "fill-primary-hovered": "#4772d3",
3169
+ "fill-primary-pressed": "#537fe1",
3170
+ "on-primary": "#e1e2e7",
3171
+ "accent": "#2e7de9",
3172
+ "fill-accent-resting": "#2e7de9",
3173
+ "fill-accent-hovered": "#0042a5",
3174
+ "fill-accent-pressed": "#0059c0",
3175
+ "fill-accent-quiet": "#0051b729",
3176
+ "border-accent": "#0051b780",
3177
+ "on-accent": "#ffffff",
3178
+ "focus": "#2e7de9",
3179
+ "link": "#0051b7",
3180
+ "info": "#2e7de9",
3181
+ "fill-info-quiet": "#2e7de924",
3182
+ "border-info": "#2e7de973",
3183
+ "success": "#587539",
3184
+ "fill-success-quiet": "#58753924",
3185
+ "border-success": "#58753973",
3186
+ "important": "#9854f1",
3187
+ "fill-important-quiet": "#9854f124",
3188
+ "border-important": "#9854f173",
3189
+ "warning": "#8c6c3e",
3190
+ "fill-warning-quiet": "#8c6c3e24",
3191
+ "border-warning": "#8c6c3e73",
3192
+ "danger": "#f52a65",
3193
+ "fill-danger-quiet": "#f52a6524",
3194
+ "border-danger": "#f52a6573"
3195
+ },
3181
3196
  "dark": {
3182
3197
  "surface-lower": "#1f2335",
3183
3198
  "surface-low": "#222538",
@@ -2707,6 +2707,53 @@ export const themes = [
2707
2707
  "row-padding": "var(--gw-space-3)"
2708
2708
  },
2709
2709
  "modes": {
2710
+ "light": {
2711
+ "surface-lower": "#d0d5e3",
2712
+ "surface-low": "#dadbe0",
2713
+ "surface-default": "#e1e2e7",
2714
+ "surface-raised": "#e9e9ed",
2715
+ "surface-overlay": "#e1e1e5",
2716
+ "border-quiet": "#ced2e4",
2717
+ "border-normal": "#c4c8da",
2718
+ "border-loud": "#abafc0",
2719
+ "text-strong": "#3760bf",
2720
+ "text-primary": "#3760bf",
2721
+ "text-secondary": "#6172b0",
2722
+ "text-disabled": "#6172b099",
2723
+ "fill-neutral-resting": "#dfdfe3",
2724
+ "fill-neutral-hovered": "#d5d5d9",
2725
+ "fill-neutral-pressed": "#ccccd0",
2726
+ "fill-neutral-selected": "#cfcfd3",
2727
+ "fill-neutral-disabled": "#e4e4e8",
2728
+ "fill-primary-resting": "#3760bf",
2729
+ "fill-primary-hovered": "#4772d3",
2730
+ "fill-primary-pressed": "#537fe1",
2731
+ "on-primary": "#e1e2e7",
2732
+ "accent": "#2e7de9",
2733
+ "fill-accent-resting": "#2e7de9",
2734
+ "fill-accent-hovered": "#0042a5",
2735
+ "fill-accent-pressed": "#0059c0",
2736
+ "fill-accent-quiet": "#0051b729",
2737
+ "border-accent": "#0051b780",
2738
+ "on-accent": "#ffffff",
2739
+ "focus": "#2e7de9",
2740
+ "link": "#0051b7",
2741
+ "info": "#2e7de9",
2742
+ "fill-info-quiet": "#2e7de924",
2743
+ "border-info": "#2e7de973",
2744
+ "success": "#587539",
2745
+ "fill-success-quiet": "#58753924",
2746
+ "border-success": "#58753973",
2747
+ "important": "#9854f1",
2748
+ "fill-important-quiet": "#9854f124",
2749
+ "border-important": "#9854f173",
2750
+ "warning": "#8c6c3e",
2751
+ "fill-warning-quiet": "#8c6c3e24",
2752
+ "border-warning": "#8c6c3e73",
2753
+ "danger": "#f52a65",
2754
+ "fill-danger-quiet": "#f52a6524",
2755
+ "border-danger": "#f52a6573"
2756
+ },
2710
2757
  "dark": {
2711
2758
  "surface-lower": "#16161e",
2712
2759
  "surface-low": "#171823",
@@ -2804,9 +2851,9 @@ export const themes = [
2804
2851
  }
2805
2852
  },
2806
2853
  {
2807
- "id": "tokyo-night-day",
2808
- "name": "Tokyo Night Day",
2809
- "description": "Tokyo Night Day, mapped onto the roles so it stays faithful to the Tokyo Night palette.",
2854
+ "id": "tokyo-night-moon",
2855
+ "name": "Tokyo Night Moon",
2856
+ "description": "Tokyo Night Moon, mapped onto the roles so it stays faithful to the Tokyo Night palette.",
2810
2857
  "optional": true,
2811
2858
  "family": "Tokyo Night",
2812
2859
  "examples": [],
@@ -2926,86 +2973,7 @@ export const themes = [
2926
2973
  "danger": "#f52a65",
2927
2974
  "fill-danger-quiet": "#f52a6524",
2928
2975
  "border-danger": "#f52a6573"
2929
- }
2930
- }
2931
- },
2932
- {
2933
- "id": "tokyo-night-moon",
2934
- "name": "Tokyo Night Moon",
2935
- "description": "Tokyo Night Moon, mapped onto the roles so it stays faithful to the Tokyo Night palette.",
2936
- "optional": true,
2937
- "family": "Tokyo Night",
2938
- "examples": [],
2939
- "style": {
2940
- "font": "Mona Sans",
2941
- "mono": "Geist Mono",
2942
- "radius": {
2943
- "panel": 10,
2944
- "control": 8,
2945
- "chip": 6
2946
- },
2947
- "border": {
2948
- "width": 1,
2949
- "strength": "hairline"
2950
- },
2951
- "weights": {
2952
- "regular": 400,
2953
- "strong": 600
2954
- },
2955
- "density": "normal",
2956
- "capitals": false,
2957
- "link": {
2958
- "color": "accent",
2959
- "underline": "thin"
2960
2976
  },
2961
- "surfaceAccent": "none",
2962
- "rows": "cards"
2963
- },
2964
- "properties": {
2965
- "font-sans": "\"Mona Sans Variable\", \"Mona Sans\", system-ui, sans-serif",
2966
- "font-figures": "\"Mona Sans Variable\", \"Mona Sans\", system-ui, sans-serif",
2967
- "font-mono": "\"Geist Mono Variable\", \"Geist Mono\", ui-monospace, monospace",
2968
- "font-weight-regular": "400",
2969
- "font-weight-strong": "600",
2970
- "density": "1",
2971
- "control-scale": "1",
2972
- "space-0-5": "calc(0.125rem * var(--gw-density))",
2973
- "space-1": "calc(0.25rem * var(--gw-density))",
2974
- "space-2": "calc(0.5rem * var(--gw-density))",
2975
- "space-3": "calc(0.75rem * var(--gw-density))",
2976
- "space-4": "calc(1rem * var(--gw-density))",
2977
- "space-5": "calc(1.25rem * var(--gw-density))",
2978
- "space-6": "calc(1.5rem * var(--gw-density))",
2979
- "space-7": "calc(1.75rem * var(--gw-density))",
2980
- "space-8": "calc(2rem * var(--gw-density))",
2981
- "space-9": "calc(2.25rem * var(--gw-density))",
2982
- "space-10": "calc(2.5rem * var(--gw-density))",
2983
- "space-11": "calc(2.75rem * var(--gw-density))",
2984
- "space-12": "calc(3rem * var(--gw-density))",
2985
- "space-13": "calc(3.25rem * var(--gw-density))",
2986
- "space-14": "calc(3.5rem * var(--gw-density))",
2987
- "space-15": "calc(3.75rem * var(--gw-density))",
2988
- "space-16": "calc(4rem * var(--gw-density))",
2989
- "space-17": "calc(4.25rem * var(--gw-density))",
2990
- "space-18": "calc(4.5rem * var(--gw-density))",
2991
- "space-19": "calc(4.75rem * var(--gw-density))",
2992
- "space-20": "calc(5rem * var(--gw-density))",
2993
- "radius-panel": "10px",
2994
- "radius-control": "8px",
2995
- "radius-chip": "6px",
2996
- "border-width": "1px",
2997
- "border-color": "var(--gw-color-border-quiet)",
2998
- "label-transform": "none",
2999
- "label-tracking": "normal",
3000
- "link-color": "var(--gw-color-link)",
3001
- "link-underline": "1px",
3002
- "panel-sheen": "none",
3003
- "panel-marker": "0px",
3004
- "panel-flange": "0px",
3005
- "panel-flange-color": "var(--gw-border-color)",
3006
- "row-padding": "var(--gw-space-3)"
3007
- },
3008
- "modes": {
3009
2977
  "dark": {
3010
2978
  "surface-lower": "#1e2030",
3011
2979
  "surface-low": "#202234",
@@ -3179,6 +3147,53 @@ export const themes = [
3179
3147
  "row-padding": "var(--gw-space-3)"
3180
3148
  },
3181
3149
  "modes": {
3150
+ "light": {
3151
+ "surface-lower": "#d0d5e3",
3152
+ "surface-low": "#dadbe0",
3153
+ "surface-default": "#e1e2e7",
3154
+ "surface-raised": "#e9e9ed",
3155
+ "surface-overlay": "#e1e1e5",
3156
+ "border-quiet": "#ced2e4",
3157
+ "border-normal": "#c4c8da",
3158
+ "border-loud": "#abafc0",
3159
+ "text-strong": "#3760bf",
3160
+ "text-primary": "#3760bf",
3161
+ "text-secondary": "#6172b0",
3162
+ "text-disabled": "#6172b099",
3163
+ "fill-neutral-resting": "#dfdfe3",
3164
+ "fill-neutral-hovered": "#d5d5d9",
3165
+ "fill-neutral-pressed": "#ccccd0",
3166
+ "fill-neutral-selected": "#cfcfd3",
3167
+ "fill-neutral-disabled": "#e4e4e8",
3168
+ "fill-primary-resting": "#3760bf",
3169
+ "fill-primary-hovered": "#4772d3",
3170
+ "fill-primary-pressed": "#537fe1",
3171
+ "on-primary": "#e1e2e7",
3172
+ "accent": "#2e7de9",
3173
+ "fill-accent-resting": "#2e7de9",
3174
+ "fill-accent-hovered": "#0042a5",
3175
+ "fill-accent-pressed": "#0059c0",
3176
+ "fill-accent-quiet": "#0051b729",
3177
+ "border-accent": "#0051b780",
3178
+ "on-accent": "#ffffff",
3179
+ "focus": "#2e7de9",
3180
+ "link": "#0051b7",
3181
+ "info": "#2e7de9",
3182
+ "fill-info-quiet": "#2e7de924",
3183
+ "border-info": "#2e7de973",
3184
+ "success": "#587539",
3185
+ "fill-success-quiet": "#58753924",
3186
+ "border-success": "#58753973",
3187
+ "important": "#9854f1",
3188
+ "fill-important-quiet": "#9854f124",
3189
+ "border-important": "#9854f173",
3190
+ "warning": "#8c6c3e",
3191
+ "fill-warning-quiet": "#8c6c3e24",
3192
+ "border-warning": "#8c6c3e73",
3193
+ "danger": "#f52a65",
3194
+ "fill-danger-quiet": "#f52a6524",
3195
+ "border-danger": "#f52a6573"
3196
+ },
3182
3197
  "dark": {
3183
3198
  "surface-lower": "#1f2335",
3184
3199
  "surface-low": "#222538",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timmo001/groundwork-tokens",
3
- "version": "0.9.40",
3
+ "version": "0.10.0",
4
4
  "description": "Groundwork's design tokens: the theme schema, the OKLCH solver and every theme as CSS and JSON",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
package/src/choices.ts CHANGED
@@ -19,7 +19,6 @@ import glazing from "../themes/glazing.json" with { type: "json" };
19
19
  import slate from "../themes/slate.json" with { type: "json" };
20
20
  import snag from "../themes/snag.json" with { type: "json" };
21
21
  import survey from "../themes/survey.json" with { type: "json" };
22
- import tokyoNightDay from "../themes/tokyo-night-day.json" with { type: "json" };
23
22
  import tokyoNightMoon from "../themes/tokyo-night-moon.json" with { type: "json" };
24
23
  import tokyoNightStorm from "../themes/tokyo-night-storm.json" with { type: "json" };
25
24
  import tokyoNight from "../themes/tokyo-night.json" with { type: "json" };
@@ -44,8 +43,8 @@ export const omarchyThemeStyleId = "gw-omarchy-theme";
44
43
 
45
44
  /**
46
45
  * A theme to offer, by id and name. A `Theme` document is one. `mode` marks
47
- * a theme with only one scheme, such as Catppuccin Latte: it's offered and
48
- * kept for that scheme alone, beside a pick for the other.
46
+ * a theme with only one scheme, such as Catppuccin Latte: while it's picked,
47
+ * the page stays in that scheme.
49
48
  */
50
49
  export interface ThemeChoice {
51
50
  readonly id: string;
@@ -59,6 +58,31 @@ export interface ThemeChoice {
59
58
  export const themeCovers = (choice: ThemeChoice, scheme: ThemeScheme) =>
60
59
  choice.mode === undefined || choice.mode === scheme;
61
60
 
61
+ /**
62
+ * Whether `mode` can be used with `choice`: any for a theme with both
63
+ * schemes, and only its own for one with one. Auto could land on the other
64
+ * scheme, so it's left out too.
65
+ */
66
+ export const themeAllows = (choice: ThemeChoice, mode: ThemeMode) =>
67
+ choice.mode === undefined ||
68
+ (mode !== "auto" && themeCovers(choice, mode === "light" ? "light" : "dark"));
69
+
70
+ /**
71
+ * Choices as a picker's options, grouped: a choice's `family`, or `group`
72
+ * for those without one. Order the choices as the picker should list them,
73
+ * usually the app's own theme, then the other core themes, then the optional
74
+ * ones.
75
+ */
76
+ export const themeOptions = (
77
+ choices: readonly ThemeChoice[],
78
+ group = "Groundwork",
79
+ ) =>
80
+ choices.map(({ id, name, family }) => ({
81
+ value: id,
82
+ label: name,
83
+ group: family ?? group,
84
+ }));
85
+
62
86
  /** The core themes by id and name, in the order the docs list them. */
63
87
  export const coreThemeChoices: readonly ThemeChoice[] = [
64
88
  base,
@@ -79,7 +103,6 @@ export const optionalThemeDocuments = [
79
103
  catppuccinFrappe,
80
104
  catppuccinMacchiato,
81
105
  catppuccinMocha,
82
- tokyoNightDay,
83
106
  tokyoNight,
84
107
  tokyoNightStorm,
85
108
  tokyoNightMoon,
@@ -114,22 +137,16 @@ export interface ThemeBootOptions {
114
137
  readonly defaultTheme: string;
115
138
  /** The mode to start with. Defaults to `auto`. */
116
139
  readonly defaultMode?: ThemeMode;
117
- /**
118
- * Whether the Omarchy theme takes over while the visitor hasn't picked
119
- * one. With `false` it's only offered, and `defaultTheme` stays in use.
120
- * Defaults to `true`.
121
- */
122
- readonly followOmarchy?: boolean;
123
140
  }
124
141
 
125
142
  /** The local storage keys a pick is kept under. */
126
143
  export const themeStorageKeys = (key: string) => ({
127
144
  mode: `${key}:mode`,
128
145
  theme: `${key}:id`,
129
- dark: `${key}:id-dark`,
130
146
  document: `${key}:custom`,
131
147
  css: `${key}:custom-css`,
132
148
  name: `${key}:custom-name`,
149
+ scheme: `${key}:custom-mode`,
133
150
  });
134
151
 
135
152
  /** The Omarchy theme's cache, kept apart so a reset doesn't drop it. */
@@ -142,7 +159,8 @@ export const omarchyStorageKeys = (key: string) => ({
142
159
  /**
143
160
  * An inline script that applies the stored mode, theme and any custom or
144
161
  * Omarchy theme's cached CSS before the first paint. Takes the same key and
145
- * defaults as `pageTheme`.
162
+ * defaults as `pageTheme`. Picking a theme stores the mode it needs, so the
163
+ * two stay in step.
146
164
  */
147
165
  export const themeBootScript = (options: ThemeBootOptions) => {
148
166
  const config = JSON.stringify({
@@ -150,14 +168,13 @@ export const themeBootScript = (options: ThemeBootOptions) => {
150
168
  omarchy: omarchyStorageKeys(options.key),
151
169
  theme: options.defaultTheme,
152
170
  mode: options.defaultMode ?? "auto",
153
- follow: options.followOmarchy !== false,
154
171
  custom: customThemeId,
155
172
  style: customThemeStyleId,
156
173
  omarchyId: omarchyThemeId,
157
174
  omarchyStyle: omarchyThemeStyleId,
158
175
  });
159
176
 
160
- // With nothing picked, a cached Omarchy theme for the scheme is the
161
- // default, unless it's only offered
162
- return `(()=>{const c=${config};let s;try{s=localStorage}catch{}const g=(k)=>{try{return s?.getItem(k)??null}catch{return null}};const r=document.documentElement;const a=(id,css)=>{const e=document.createElement("style");e.id=id;e.textContent=css;document.head.append(e)};const m=g(c.keys.mode)??c.mode;const d=m==="dark"||m==="darker"||(m==="auto"&&matchMedia("(prefers-color-scheme: dark)").matches);const o=g(c.omarchy.css);let t=(d?g(c.keys.dark):null)??g(c.keys.theme)??(c.follow&&o&&g(c.omarchy.mode)===(d?"dark":"light")?c.omarchyId:c.theme);if(t===c.custom){const css=g(c.keys.css);if(css)a(c.style,css);else t=c.theme}else if(t===c.omarchyId){if(o)a(c.omarchyStyle,o);else t=c.theme}r.setAttribute("data-gw-theme",t);if(m==="auto")r.removeAttribute("data-gw-mode");else r.setAttribute("data-gw-mode",m)})();`;
177
+ // An imported or Omarchy theme only applies once it's been picked, and
178
+ // falls back to the default when its CSS has gone
179
+ return `(()=>{const c=${config};let s;try{s=localStorage}catch{}const g=(k)=>{try{return s?.getItem(k)??null}catch{return null}};const r=document.documentElement;const a=(id,css)=>{const e=document.createElement("style");e.id=id;e.textContent=css;document.head.append(e)};let m=g(c.keys.mode)??c.mode;let t=g(c.keys.theme)??c.theme;const o=t===c.custom?g(c.keys.css):t===c.omarchyId?g(c.omarchy.css):null;if(t===c.custom||t===c.omarchyId){if(o)a(t===c.custom?c.style:c.omarchyStyle,o);else{t=c.theme;m=c.mode}}r.setAttribute("data-gw-theme",t);if(m==="auto")r.removeAttribute("data-gw-mode");else r.setAttribute("data-gw-mode",m)})();`;
163
180
  };
package/src/generate.ts CHANGED
@@ -536,17 +536,17 @@ export const blumeTheme = (theme: ResolvedTheme) =>
536
536
  ].join("\n\n") + "\n";
537
537
 
538
538
  /**
539
- * Every core theme as Blume's tokens, each under `data-gw-docs-theme`, for a
540
- * site that lets readers pick one with the theme picker.
539
+ * Every theme, core and optional, as Blume's tokens, each under
540
+ * `data-gw-docs-theme`, for a site that lets readers pick one with the theme
541
+ * picker. An optional theme with one scheme has rules for that scheme only;
542
+ * the picker keeps the page in it.
541
543
  */
542
544
  export const blumeThemes = (themes: readonly ResolvedTheme[]) =>
543
545
  [
544
546
  `/* ${header} */`,
545
- ...themes
546
- .filter((theme) => !theme.optional)
547
- .flatMap((theme) =>
548
- blumeRules(theme, `:root[data-gw-docs-theme="${theme.id}"]`),
549
- ),
547
+ ...themes.flatMap((theme) =>
548
+ blumeRules(theme, `:root[data-gw-docs-theme="${theme.id}"]`),
549
+ ),
550
550
  ].join("\n\n") + "\n";
551
551
 
552
552
  const hexRoles = (roles: Roles) =>
@@ -761,7 +761,7 @@ export const optionalPage = (themes: readonly ResolvedTheme[]) => {
761
761
  "",
762
762
  `{/* ${header} */}`,
763
763
  "",
764
- "Most flavors are one mode of their palette, and GitHub's cover both light and dark. Each is mapped straight onto the roles rather than solved, so it looks the way the palette's authors intended. They take Base's style. The [contrast report](/themes/contrast) shows where a palette sits below the core targets.",
764
+ "Catppuccin's flavors are one mode each, so an app in one stays in its scheme. GitHub's cover both light and dark, and so do Tokyo Night's, each taking Day as its light side. Each is mapped straight onto the roles rather than solved, so it looks the way the palette's authors intended. They take Base's style. The [contrast report](/themes/contrast) shows where a palette sits below the core targets.",
765
765
  "",
766
766
  ...families.flatMap((family) => [
767
767
  `## ${family}`,