@rimelight/ui 0.0.34 → 0.0.36

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.
Files changed (185) hide show
  1. package/README.md +1 -0
  2. package/package.json +19 -24
  3. package/src/components/astro/RLAAccordion.astro +94 -18
  4. package/src/components/astro/RLAAvatar.astro +135 -68
  5. package/src/components/astro/RLABadge.astro +4 -2
  6. package/src/components/astro/RLABanner.astro +138 -23
  7. package/src/components/astro/RLABreadcrumb.astro +13 -0
  8. package/src/components/astro/RLAButton.astro +8 -4
  9. package/src/components/astro/RLACallout.astro +112 -0
  10. package/src/components/astro/RLACard.astro +6 -5
  11. package/src/components/astro/RLACarousel.astro +104 -75
  12. package/src/components/astro/RLAChart.astro +4 -1
  13. package/src/components/astro/RLAChip.astro +11 -5
  14. package/src/components/astro/RLACollapsible.astro +4 -1
  15. package/src/components/astro/RLAColorArea.astro +432 -0
  16. package/src/components/astro/RLAColorField.astro +300 -0
  17. package/src/components/astro/RLAColorSlider.astro +413 -0
  18. package/src/components/astro/RLAConfirm.astro +13 -11
  19. package/src/components/astro/RLACopyMarkdown.astro +78 -0
  20. package/src/components/astro/RLADate.astro +30 -0
  21. package/src/components/astro/RLADrawer.astro +50 -3
  22. package/src/components/astro/RLADropdownMenu.astro +78 -51
  23. package/src/components/astro/RLAFieldGroup.astro +4 -1
  24. package/src/components/astro/RLAFileUpload.astro +114 -100
  25. package/src/components/astro/RLAFooter.astro +2 -1
  26. package/src/components/astro/RLAFormField.astro +10 -6
  27. package/src/components/astro/RLAGrid.astro +31 -39
  28. package/src/components/astro/RLAHead.astro +139 -39
  29. package/src/components/astro/RLAHeader.astro +2 -1
  30. package/src/components/astro/RLAImage.astro +274 -251
  31. package/src/components/astro/RLAInput.astro +14 -9
  32. package/src/components/astro/RLAInputMenu.astro +119 -83
  33. package/src/components/astro/RLAKbd.astro +5 -5
  34. package/src/components/astro/RLALayoutGrid.astro +395 -0
  35. package/src/components/astro/RLALink.astro +23 -1
  36. package/src/components/astro/RLALinkGroup.astro +99 -99
  37. package/src/components/astro/RLALocaleSelector.astro +34 -41
  38. package/src/components/astro/RLALogo.astro +117 -90
  39. package/src/components/astro/RLAModal.astro +48 -18
  40. package/src/components/astro/RLANavigationMenu.astro +381 -326
  41. package/src/components/astro/{RLADocsPackageManagers.astro → RLAPackageManagers.astro} +81 -87
  42. package/src/components/astro/RLAPageSection.astro +4 -2
  43. package/src/components/astro/RLAPopover.astro +4 -3
  44. package/src/components/astro/RLAPost.astro +11 -2
  45. package/src/components/astro/RLAScrollArea.astro +4 -1
  46. package/src/components/astro/RLAScrollToTop.astro +200 -172
  47. package/src/components/astro/RLASearch.astro +282 -0
  48. package/src/components/astro/RLASelect.astro +78 -55
  49. package/src/components/astro/RLASeparator.astro +11 -6
  50. package/src/components/astro/RLAShare.astro +60 -0
  51. package/src/components/astro/RLAShortcuts.astro +429 -0
  52. package/src/components/astro/RLASidebar.astro +158 -212
  53. package/src/components/astro/RLASlideover.astro +47 -17
  54. package/src/components/astro/RLASplitter.astro +194 -141
  55. package/src/components/astro/RLASteps.astro +118 -71
  56. package/src/components/astro/RLASurround.astro +39 -0
  57. package/src/components/astro/RLATable.astro +4 -1
  58. package/src/components/astro/RLATableOfContents.astro +109 -23
  59. package/src/components/astro/RLATabs.astro +147 -133
  60. package/src/components/astro/RLATextarea.astro +4 -1
  61. package/src/components/astro/RLAThemeSelector.astro +105 -76
  62. package/src/components/astro/RLAToast.astro +35 -21
  63. package/src/components/vue/RLVBanner.vue +230 -0
  64. package/src/components/vue/RLVButton.vue +3 -2
  65. package/src/components/vue/RLVCheckbox.vue +4 -2
  66. package/src/components/vue/RLVFooter.vue +3 -2
  67. package/src/components/vue/RLVHeader.vue +3 -2
  68. package/src/components/vue/RLVIcon.vue +4 -2
  69. package/src/components/vue/RLVInput.vue +5 -4
  70. package/src/components/vue/RLVLogo.vue +25 -3
  71. package/src/components/vue/RLVPlaceholder.vue +3 -2
  72. package/src/components/vue/RLVPost.vue +8 -2
  73. package/src/components/vue/RLVProgress.vue +60 -0
  74. package/src/components/vue/RLVScrollToTop.vue +65 -52
  75. package/src/components/vue/RLVSection.vue +14 -13
  76. package/src/components/vue/RLVToast.vue +17 -4
  77. package/src/composables/index.ts +1 -0
  78. package/src/composables/useHeaderStore.ts +1 -0
  79. package/src/composables/useShortcuts.ts +11 -0
  80. package/src/config/security.ts +43 -36
  81. package/src/config/site.config.ts +1 -0
  82. package/src/docs/components/ApiChangelog.astro +147 -0
  83. package/src/{plugins/starlightDocsApi → docs}/components/ApiEmits.astro +4 -4
  84. package/src/{plugins/starlightDocsApi → docs}/components/ApiProps.astro +4 -4
  85. package/src/{plugins/starlightDocsApi → docs}/components/ApiSlots.astro +4 -4
  86. package/src/docs/components/ApiTheme.astro +100 -0
  87. package/src/docs/extractAll.ts +94 -0
  88. package/src/docs/extractors/extractAstro.ts +69 -0
  89. package/src/docs/extractors/extractTheme.ts +56 -0
  90. package/src/{plugins/starlightDocsApi/extract-vue.ts → docs/extractors/extractVue.ts} +164 -15
  91. package/src/{plugins/starlightDocsApi → docs}/utils.ts +1 -2
  92. package/src/env.d.ts +0 -12
  93. package/src/integrations/ui.ts +35 -19
  94. package/src/middleware/security.ts +75 -19
  95. package/src/presets/index.ts +118 -293
  96. package/src/styles/index.css +0 -2
  97. package/src/themes/accordion.theme.ts +29 -3
  98. package/src/themes/aspect-ratio.theme.ts +1 -1
  99. package/src/themes/avatar-group.theme.ts +1 -1
  100. package/src/themes/avatar.theme.ts +2 -2
  101. package/src/themes/badge.theme.ts +2 -3
  102. package/src/themes/banner.theme.ts +40 -4
  103. package/src/themes/breadcrumb.theme.ts +1 -1
  104. package/src/themes/button.theme.ts +21 -22
  105. package/src/themes/{alert.theme.ts → callout.theme.ts} +12 -39
  106. package/src/themes/card.theme.ts +17 -9
  107. package/src/themes/carousel.theme.ts +1 -1
  108. package/src/themes/checkbox.theme.ts +1 -2
  109. package/src/themes/chip.theme.ts +2 -3
  110. package/src/themes/color-area.theme.ts +33 -0
  111. package/src/themes/color-field.theme.ts +32 -0
  112. package/src/themes/color-slider.theme.ts +34 -0
  113. package/src/themes/confirm.theme.ts +1 -1
  114. package/src/themes/container.theme.ts +1 -1
  115. package/src/themes/drawer.theme.ts +1 -1
  116. package/src/themes/footer.theme.ts +2 -2
  117. package/src/themes/grid.theme.ts +38 -0
  118. package/src/themes/header.theme.ts +4 -3
  119. package/src/themes/hover-card.theme.ts +1 -1
  120. package/src/themes/image.theme.ts +11 -1
  121. package/src/themes/input.theme.ts +7 -1
  122. package/src/themes/kbd.theme.ts +2 -3
  123. package/src/themes/label.theme.ts +1 -1
  124. package/src/themes/layout-grid.theme.ts +16 -0
  125. package/src/themes/link-group.theme.ts +0 -4
  126. package/src/themes/marquee.theme.ts +1 -1
  127. package/src/themes/modal.theme.ts +1 -1
  128. package/src/themes/navigation-menu.theme.ts +2 -2
  129. package/src/themes/page-section.theme.ts +4 -2
  130. package/src/themes/pagination.theme.ts +1 -1
  131. package/src/themes/pin-input.theme.ts +1 -1
  132. package/src/themes/popover.theme.ts +1 -1
  133. package/src/themes/post.theme.ts +23 -3
  134. package/src/themes/progress.theme.ts +1 -2
  135. package/src/themes/scroll-to-top.theme.ts +2 -3
  136. package/src/themes/search.theme.ts +64 -0
  137. package/src/themes/separator.theme.ts +1 -1
  138. package/src/themes/slideover.theme.ts +1 -1
  139. package/src/themes/slider.theme.ts +1 -2
  140. package/src/themes/spinner.theme.ts +1 -2
  141. package/src/themes/{megamenu.theme.ts → steps.theme.ts} +3 -3
  142. package/src/themes/sticky-surface.theme.ts +1 -1
  143. package/src/themes/switch.theme.ts +1 -2
  144. package/src/themes/table-of-contents.theme.ts +21 -2
  145. package/src/themes/timeline.theme.ts +7 -2
  146. package/src/themes/toast.theme.ts +1 -1
  147. package/src/types/components/accordion.ts +35 -2
  148. package/src/types/components/avatar.ts +16 -0
  149. package/src/types/components/banner.ts +42 -0
  150. package/src/types/components/button.ts +3 -4
  151. package/src/types/components/{alert.ts → callout.ts} +6 -6
  152. package/src/types/components/color-area.ts +19 -0
  153. package/src/types/components/color-field.ts +21 -0
  154. package/src/types/components/color-slider.ts +20 -0
  155. package/src/types/components/grid.ts +23 -0
  156. package/src/types/components/input.ts +4 -0
  157. package/src/types/components/layout-grid.ts +145 -0
  158. package/src/types/components/link-group.ts +4 -2
  159. package/src/types/components/link.ts +15 -0
  160. package/src/types/components/logo.ts +3 -3
  161. package/src/types/components/post.ts +12 -0
  162. package/src/types/components/search.ts +29 -0
  163. package/src/types/components/sidebar.ts +2 -6
  164. package/src/types/components/{megamenu.ts → steps.ts} +7 -1
  165. package/src/types/components/table-of-contents.ts +22 -0
  166. package/src/types/components/toast.ts +4 -0
  167. package/src/types/docs.ts +40 -0
  168. package/src/types/index.ts +151 -1
  169. package/src/types/theme.ts +6 -6
  170. package/src/utils/color.ts +165 -0
  171. package/src/utils/docs.ts +260 -110
  172. package/src/utils/headerStack.ts +24 -4
  173. package/src/utils/index.ts +2 -0
  174. package/src/utils/shortcuts.ts +322 -0
  175. package/src/components/TableOfContents.astro +0 -107
  176. package/src/components/astro/RLAAlert.astro +0 -93
  177. package/src/components/astro/RLAChangelog.astro +0 -23
  178. package/src/components/astro/RLAMegamenu.astro +0 -23
  179. package/src/plugins/index.ts +0 -2
  180. package/src/plugins/starlightDocsApi/components/ApiTheme.astro +0 -27
  181. package/src/plugins/starlightDocsApi/index.ts +0 -272
  182. package/src/styles/prism.css +0 -42
  183. package/src/themes/changelog.theme.ts +0 -13
  184. package/src/types/components/index.ts +0 -134
  185. /package/src/{plugins/starlightDocsApi → docs}/types.ts +0 -0
@@ -15,7 +15,7 @@ export const uiSrcGlob = join(pathDirname, "../**/*.{js,ts,jsx,tsx,vue,svelte,as
15
15
  export const uiFilesystemGlob = join(pathDirname, "../**/*")
16
16
 
17
17
  type ColorShades = Record<string, string>
18
- type ColorModeShades = { light?: ColorShades; dark?: ColorShades; flat?: ColorShades }
18
+ type ColorModeShades = { light?: ColorShades; dark?: ColorShades }
19
19
  export type ColorConfigValue = ColorShades | ColorModeShades
20
20
 
21
21
  function generateLightShade(shade: string, value: string): string {
@@ -35,7 +35,7 @@ function generateDarkShade(shade: string, value: string): string {
35
35
  function resolveColorModes(
36
36
  entry: ColorConfigValue,
37
37
  autogenerate?: boolean
38
- ): { light: Record<string, string>; dark: Record<string, string>; flat: Record<string, string> } {
38
+ ): { light: Record<string, string>; dark: Record<string, string> } {
39
39
  const raw = entry as Record<string, unknown>
40
40
 
41
41
  const modeLight =
@@ -46,12 +46,8 @@ function resolveColorModes(
46
46
  typeof raw.dark === "object" && raw.dark !== null
47
47
  ? ({ ...raw.dark } as ColorShades)
48
48
  : ({} as ColorShades)
49
- const modeFlat =
50
- typeof raw.flat === "object" && raw.flat !== null
51
- ? ({ ...raw.flat } as ColorShades)
52
- : ({} as ColorShades)
53
49
 
54
- const modeKeys = new Set(["light", "dark", "flat"])
50
+ const modeKeys = new Set(["light", "dark"])
55
51
  const flatShades: ColorShades = {}
56
52
  for (const [k, v] of Object.entries(raw)) {
57
53
  if (!modeKeys.has(k) && typeof v === "string") {
@@ -60,24 +56,19 @@ function resolveColorModes(
60
56
  }
61
57
 
62
58
  const allShades = [
63
- ...new Set([
64
- ...Object.keys(modeLight),
65
- ...Object.keys(modeDark),
66
- ...Object.keys(modeFlat),
67
- ...Object.keys(flatShades)
68
- ])
59
+ ...new Set([...Object.keys(modeLight), ...Object.keys(modeDark), ...Object.keys(flatShades)])
69
60
  ]
70
61
 
71
62
  if (autogenerate) {
72
63
  if (Object.keys(modeLight).length === 0) {
73
64
  for (const shade of allShades) {
74
- const value = flatShades[shade] ?? modeFlat[shade] ?? modeDark[shade]
65
+ const value = flatShades[shade] ?? modeDark[shade]
75
66
  if (value) modeLight[shade] = generateLightShade(shade, value)
76
67
  }
77
68
  }
78
69
  if (Object.keys(modeDark).length === 0) {
79
70
  for (const shade of allShades) {
80
- const value = flatShades[shade] ?? modeFlat[shade] ?? modeLight[shade]
71
+ const value = flatShades[shade] ?? modeLight[shade]
81
72
  if (value) modeDark[shade] = generateDarkShade(shade, value)
82
73
  }
83
74
  }
@@ -85,34 +76,23 @@ function resolveColorModes(
85
76
 
86
77
  const light: ColorShades = {}
87
78
  const dark: ColorShades = {}
88
- const flat: ColorShades = {}
89
79
 
90
80
  for (const shade of allShades) {
91
- const lv = modeLight[shade] ?? flatShades[shade] ?? modeFlat[shade] ?? modeDark[shade]
81
+ const lv = modeLight[shade] ?? flatShades[shade] ?? modeDark[shade]
92
82
  if (lv !== undefined) light[shade] = lv
93
83
 
94
- const dv = modeDark[shade] ?? flatShades[shade] ?? modeFlat[shade] ?? modeLight[shade]
84
+ const dv = modeDark[shade] ?? flatShades[shade] ?? modeLight[shade]
95
85
  if (dv !== undefined) dark[shade] = dv
96
-
97
- const fv = modeFlat[shade] ?? flatShades[shade] ?? modeLight[shade] ?? modeDark[shade]
98
- if (fv !== undefined) flat[shade] = fv
99
86
  }
100
87
 
101
- return { light, dark, flat }
88
+ return { light, dark }
102
89
  }
103
90
 
104
91
  const createScale = (colorName: string, shadeKeys: string[]) => ({
105
92
  DEFAULT: `var(--${colorName})`,
106
93
  foreground: `var(--${colorName}-foreground)`,
107
94
  accent: `var(--${colorName}-accent)`,
108
- ...Object.fromEntries(
109
- shadeKeys.flatMap((shade) => [
110
- [shade, `var(--color-${colorName}-${shade})`],
111
- [`${shade}-f`, `var(--color-${colorName}-${shade}-f)`],
112
- [`${shade}-l`, `var(--color-${colorName}-${shade}-l)`],
113
- [`${shade}-d`, `var(--color-${colorName}-${shade}-d)`]
114
- ])
115
- )
95
+ ...Object.fromEntries(shadeKeys.map((shade) => [shade, `var(--color-${colorName}-${shade})`]))
116
96
  })
117
97
 
118
98
  export interface RimelightPresetOptions {
@@ -184,7 +164,7 @@ export default definePreset((options?: RimelightPresetOptions) => {
184
164
  },
185
165
 
186
166
  shortcuts: {
187
- "container": "mx-auto w-full max-w-90rem px-md",
167
+ "container": "mx-auto w-full max-w-[1440px] px-xs sm:px-md md:px-xl lg:px-xl",
188
168
  "sr-only":
189
169
  "absolute w-px h-px p-0 m-0 overflow-hidden clip-rect-1-1-1-1 whitespace-nowrap border-0"
190
170
  },
@@ -200,63 +180,27 @@ export default definePreset((options?: RimelightPresetOptions) => {
200
180
  "--rl-bg-hover": `var(--color-${color}-600)`,
201
181
  "--rl-text": `var(--color-${color}-600)`,
202
182
  "--rl-ring": `var(--color-${color}-500)`,
203
- "--rl-border": `var(--color-${color}-500)`,
204
- "--rl-bg-f": `var(--color-${color}-500-f)`,
205
- "--rl-bg-hover-f": `var(--color-${color}-600-f)`,
206
- "--rl-text-f": `var(--color-${color}-600-f)`,
207
- "--rl-ring-f": `var(--color-${color}-500-f)`,
208
- "--rl-border-f": `var(--color-${color}-500-f)`,
209
- "--rl-bg-l": `var(--color-${color}-500-l)`,
210
- "--rl-bg-hover-l": `var(--color-${color}-600-l)`,
211
- "--rl-text-l": `var(--color-${color}-600-l)`,
212
- "--rl-ring-l": `var(--color-${color}-500-l)`,
213
- "--rl-border-l": `var(--color-${color}-500-l)`,
214
- "--rl-bg-d": `var(--color-${color}-500-d)`,
215
- "--rl-bg-hover-d": `var(--color-${color}-600-d)`,
216
- "--rl-text-d": `var(--color-${color}-600-d)`,
217
- "--rl-ring-d": `var(--color-${color}-500-d)`,
218
- "--rl-border-d": `var(--color-${color}-500-d)`
183
+ "--rl-border": `var(--color-${color}-500)`
219
184
  })
220
185
  ],
186
+ // Pins the element's color-scheme to light — light-dark() resolves to light values.
187
+ // Also sets color so plain text children inherit the correct foreground without needing
188
+ // an explicit utility class on every element.
189
+ ["rl-light", { "color-scheme": "light", "color": "var(--foreground)" }],
190
+ // Pins the element's color-scheme to dark — light-dark() resolves to dark values.
191
+ ["rl-dark", { "color-scheme": "dark", "color": "var(--foreground)" }],
192
+ // Resets color-scheme back to reactive — follows the page-level preference
193
+ // (i.e. whatever is set on <html>). Use inside a pinned wrapper to opt a subtree back out.
194
+ ["rl-auto", { "color-scheme": "light dark", "color": "var(--foreground)" }],
221
195
  [
222
- "rl-flat",
223
- {
224
- "--rl-bg": "var(--rl-bg-f)",
225
- "--rl-bg-hover": "var(--rl-bg-hover-f)",
226
- "--rl-text": "var(--rl-text-f)",
227
- "--rl-ring": "var(--rl-ring-f)",
228
- "--rl-border": "var(--rl-border-f)"
229
- }
230
- ],
231
- [
232
- "rl-light",
233
- {
234
- "--rl-bg": "var(--rl-bg-l, var(--rl-bg-f))",
235
- "--rl-bg-hover": "var(--rl-bg-hover-l, var(--rl-bg-hover-f))",
236
- "--rl-text": "var(--rl-text-l, var(--rl-text-f))",
237
- "--rl-ring": "var(--rl-ring-l, var(--rl-ring-f))",
238
- "--rl-border": "var(--rl-border-l, var(--rl-border-f))"
239
- }
240
- ],
241
- [
242
- "rl-dark",
243
- {
244
- "--rl-bg": "var(--rl-bg-d, var(--rl-bg-f))",
245
- "--rl-bg-hover": "var(--rl-bg-hover-d, var(--rl-bg-hover-f))",
246
- "--rl-text": "var(--rl-text-d, var(--rl-text-f))",
247
- "--rl-ring": "var(--rl-ring-d, var(--rl-ring-f))",
248
- "--rl-border": "var(--rl-border-d, var(--rl-border-f))"
249
- }
250
- ],
251
- [
252
- /^(text)-(default|inverted)(?:\/(\d+))?$/,
196
+ /^(text)-(default|inverted|muted|dimmed|toned|highlighted)(?:\/(\d+))?$/,
253
197
  ([, , name, opacity]) =>
254
198
  opacity
255
199
  ? { color: `color-mix(in srgb, var(--text-color-${name}) ${opacity}%, transparent)` }
256
200
  : { color: `var(--text-color-${name})` }
257
201
  ],
258
202
  [
259
- /^(bg)-(default|inverted)(?:\/(\d+))?$/,
203
+ /^(bg)-(default|inverted|muted|elevated|accented)(?:\/(\d+))?$/,
260
204
  ([, , name, opacity]) =>
261
205
  opacity
262
206
  ? {
@@ -265,7 +209,7 @@ export default definePreset((options?: RimelightPresetOptions) => {
265
209
  : { "background-color": `var(--background-color-${name})` }
266
210
  ],
267
211
  [
268
- /^(ring)-(default|inverted)(?:\/(\d+))?$/,
212
+ /^(ring)-(default|inverted|muted|accented)(?:\/(\d+))?$/,
269
213
  ([, , name, opacity]) =>
270
214
  opacity
271
215
  ? {
@@ -274,16 +218,7 @@ export default definePreset((options?: RimelightPresetOptions) => {
274
218
  : { "--un-ring-color": `var(--ring-color-${name})` }
275
219
  ],
276
220
  [
277
- /^(divide)-(default)(?:\/(\d+))?$/,
278
- ([, , name, opacity]) =>
279
- opacity
280
- ? {
281
- "border-color": `color-mix(in srgb, var(--divide-color-${name}) ${opacity}%, transparent)`
282
- }
283
- : { "border-color": `var(--divide-color-${name})` }
284
- ],
285
- [
286
- /^(border)-(default)(?:\/(\d+))?$/,
221
+ /^(border)-(default|inverted|muted|accented)(?:\/(\d+))?$/,
287
222
  ([, , name, opacity]) =>
288
223
  opacity
289
224
  ? {
@@ -334,9 +269,7 @@ export default definePreset((options?: RimelightPresetOptions) => {
334
269
  ...Object.fromEntries(
335
270
  allColors.map((color) => {
336
271
  const m = resolvedColors[color]!
337
- const shadeKeys = [
338
- ...new Set([...Object.keys(m.light), ...Object.keys(m.dark), ...Object.keys(m.flat)])
339
- ]
272
+ const shadeKeys = [...new Set([...Object.keys(m.light), ...Object.keys(m.dark)])]
340
273
  return [color, createScale(color, shadeKeys)]
341
274
  })
342
275
  ),
@@ -425,144 +358,121 @@ export default definePreset((options?: RimelightPresetOptions) => {
425
358
  preflights: [
426
359
  {
427
360
  getCSS: () => {
428
- const lightLines = Object.entries(resolvedColors)
429
- .flatMap(([color, modes]) =>
430
- Object.entries(modes.light).map(
431
- ([shade, value]) => ` --color-${color}-${shade}: ${value};`
432
- )
433
- )
434
- .join("\n")
435
-
436
- const flatLines = Object.entries(resolvedColors)
437
- .flatMap(([color, modes]) => {
438
- const u = modes.flat
439
- return Object.entries(u).map(
440
- ([shade, value]) => ` --color-${color}-${shade}-f: ${value};`
441
- )
442
- })
443
- .join("\n")
444
-
445
- const lightPinnedLines = Object.entries(resolvedColors)
446
- .flatMap(([color, modes]) =>
447
- Object.entries(modes.light)
448
- .filter(([shade, value]) => value !== modes.flat[shade])
449
- .map(([shade, value]) => ` --color-${color}-${shade}-l: ${value};`)
450
- )
451
- .join("\n")
452
-
453
- const darkPinnedLines = Object.entries(resolvedColors)
361
+ // Single pass: emit light-dark() for every color shade.
362
+ // The browser resolves each call based on the element's inherited color-scheme.
363
+ const lightDarkLines = Object.entries(resolvedColors)
454
364
  .flatMap(([color, modes]) =>
455
- Object.entries(modes.dark)
456
- .filter(([shade, value]) => value !== modes.flat[shade])
457
- .map(([shade, value]) => ` --color-${color}-${shade}-d: ${value};`)
458
- )
459
- .join("\n")
460
-
461
- const darkLines = Object.entries(resolvedColors)
462
- .flatMap(([color, modes]) =>
463
- Object.entries(modes.dark)
464
- .filter(([shade, value]) => modes.light[shade] !== value)
465
- .map(([shade, value]) => ` --color-${color}-${shade}: ${value};`)
365
+ Object.keys(modes.light).map((shade) => {
366
+ const l = modes.light[shade]
367
+ const d = modes.dark[shade] ?? modes.light[shade]
368
+ return ` --color-${color}-${shade}: light-dark(${l}, ${d});`
369
+ })
466
370
  )
467
371
  .join("\n")
468
372
 
469
373
  return `
470
374
  :root {
471
- --background: #ffffff;
472
- --foreground: #030712;
473
- --card: #ffffff;
474
- --card-foreground: #030712;
475
- --popover: #ffffff;
476
- --popover-foreground: #030712;
477
- --primary: #0064d7;
375
+ color-scheme: light dark;
376
+
377
+ /* Semantic tokens — each resolves to its light or dark value based on color-scheme */
378
+ --background: light-dark(#ffffff, #030712);
379
+ --foreground: light-dark(#030712, #f9fafb);
380
+ --card: light-dark(#ffffff, #111827);
381
+ --card-foreground: light-dark(#030712, #f9fafb);
382
+ --popover: light-dark(#ffffff, #1f2937);
383
+ --popover-foreground: light-dark(#030712, #f9fafb);
384
+ --primary: light-dark(#0064d7, #3b82f6);
478
385
  --primary-foreground: #ffffff;
479
- --primary-accent: #0050ac;
386
+ --primary-accent: light-dark(#0050ac, #60a5fa);
480
387
  --secondary: #8b5cf6;
481
388
  --secondary-foreground: #f9fafb;
482
- --secondary-accent: #7c3aed;
483
- --muted: #f3f4f6;
484
- --muted-foreground: #4b5563;
485
- --accent: #f3f4f6;
486
- --accent-foreground: #111827;
389
+ --secondary-accent: light-dark(#7c3aed, #a78bfa);
390
+ --muted: light-dark(#f3f4f6, #1f2937);
391
+ --muted-foreground: light-dark(#4b5563, #9ca3af);
392
+ --accent: light-dark(#f3f4f6, #374151);
393
+ --accent-foreground: light-dark(#111827, #f3f4f6);
487
394
  --info: #3b82f6;
488
395
  --info-foreground: #ffffff;
489
- --info-accent: #2563eb;
396
+ --info-accent: light-dark(#2563eb, #60a5fa);
490
397
  --success: #22c55e;
491
398
  --success-foreground: #ffffff;
492
- --success-accent: #16a34a;
399
+ --success-accent: light-dark(#16a34a, #4ade80);
493
400
  --warning: #f59e0b;
494
401
  --warning-foreground: #000000;
495
- --warning-accent: #d97706;
402
+ --warning-accent: light-dark(#d97706, #fbbf24);
496
403
  --error: #ef4444;
497
404
  --error-foreground: #f9fafb;
498
- --error-accent: #dc2626;
499
- --commentary: #ec4899;
500
- --commentary-foreground: #f9fafb;
501
- --commentary-accent: #db2777;
502
- --ideation: #8b5cf6;
503
- --ideation-foreground: #f9fafb;
504
- --ideation-accent: #7c3aed;
505
- --source: #38bdf8;
405
+ --error-accent: light-dark(#dc2626, #f87171);
406
+ --commentary: light-dark(#ec4899, #f472b6);
407
+ --commentary-foreground: light-dark(#f9fafb, #0f172a);
408
+ --commentary-accent: light-dark(#db2777, #f9a8d4);
409
+ --ideation: light-dark(#8b5cf6, #a78bfa);
410
+ --ideation-foreground: light-dark(#f9fafb, #0f172a);
411
+ --ideation-accent: light-dark(#7c3aed, #c4b5fd);
412
+ --source: light-dark(#38bdf8, #7dd3fc);
506
413
  --source-foreground: #0f172a;
507
- --source-accent: #0284c7;
508
- --border: #e5e7eb;
509
- --input: #e5e7eb;
510
- --outline: #9ca3af;
511
- --ring: #9ca3af;
414
+ --source-accent: light-dark(#0284c7, #bae6fd);
415
+ --border: light-dark(#e5e7eb, rgba(249, 250, 251, 0.1));
416
+ --input: light-dark(#e5e7eb, rgba(249, 250, 251, 0.15));
417
+ --outline: light-dark(#9ca3af, #6b7280);
418
+ --ring: light-dark(#9ca3af, #6b7280);
512
419
  --radius: 0.625rem;
513
- --sidebar: #f9fafb;
514
- --sidebar-foreground: #030712;
420
+ --sidebar: light-dark(#f9fafb, #111827);
421
+ --sidebar-foreground: light-dark(#030712, #f9fafb);
515
422
  --sidebar-primary: #1d4ed8;
516
423
  --sidebar-primary-foreground: #f9fafb;
517
- --sidebar-accent: #f3f4f6;
518
- --sidebar-accent-foreground: #111827;
519
- --sidebar-border: #e5e7eb;
520
- --sidebar-ring: #9ca3af;
521
- --chart-1: #3b82f6;
522
- --chart-2: #6366f1;
523
- --chart-3: #8b5cf6;
524
- --chart-4: #a855f7;
525
- --chart-5: #ec4899;
526
- --destructive: #ef4444;
527
- --color-surface: #ffffff;
528
- --color-muted-strong: #e5e7eb;
529
- --color-foreground-secondary: #4b5563;
530
- --color-foreground-tertiary: #6b7280;
531
- --color-placeholder: #9ca3af;
532
- --color-input-border: #d1d5db;
533
- --color-hover: #f3f4f6;
534
- --color-destructive-subtle: #fef2f2;
535
- --color-accent-subtle: #eff6ff;
424
+ --sidebar-accent: light-dark(#f3f4f6, #1f2937);
425
+ --sidebar-accent-foreground: light-dark(#111827, #f3f4f6);
426
+ --sidebar-border: light-dark(#e5e7eb, #1f2937);
427
+ --sidebar-ring: light-dark(#9ca3af, #6b7280);
428
+ --chart-1: light-dark(#3b82f6, #60a5fa);
429
+ --chart-2: light-dark(#6366f1, #818cf8);
430
+ --chart-3: light-dark(#8b5cf6, #a78bfa);
431
+ --chart-4: light-dark(#a855f7, #c084fc);
432
+ --chart-5: light-dark(#ec4899, #f472b6);
433
+ --destructive: light-dark(#ef4444, #f87171);
434
+ --color-surface: light-dark(#ffffff, #1f2937);
435
+ --color-muted-strong: light-dark(#e5e7eb, #374151);
436
+ --color-foreground-secondary: light-dark(#4b5563, #d1d5db);
437
+ --color-foreground-tertiary: light-dark(#6b7280, #9ca3af);
438
+ --color-placeholder: light-dark(#9ca3af, #6b7280);
439
+ --color-input-border: light-dark(#d1d5db, #4b5563);
440
+ --color-hover: light-dark(#f3f4f6, #374151);
441
+ --color-destructive-subtle: light-dark(#fef2f2, #451a1a);
442
+ --color-accent-subtle: light-dark(#eff6ff, #1e293b);
536
443
  --font-sans: "Noto Sans", sans-serif;
537
444
  --font-serif: "Noto Serif", serif;
538
445
  --font-mono: "Noto Sans Mono", monospace;
539
446
 
540
447
  --ui-header-height: 4rem;
541
448
  --ui-container: 80rem;
449
+ --rl-container: 1440px;
450
+
451
+ /* Text / background / border / ring semantic tokens using responsive neutral variables */
542
452
  --text-color-default: var(--color-neutral-700);
543
453
  --text-color-muted: var(--color-neutral-500);
544
454
  --text-color-dimmed: var(--color-neutral-400);
545
455
  --text-color-toned: var(--color-neutral-600);
546
- --text-color-highlighted: var(--color-neutral-900);
547
- --text-color-inverted: #ffffff;
548
- --background-color-default: #ffffff;
549
- --background-color-muted: var(--color-neutral-50);
550
- --background-color-elevated: var(--color-neutral-100);
551
- --background-color-accented: var(--color-neutral-200);
552
- --background-color-inverted: var(--color-neutral-900);
456
+ --text-color-highlighted: var(--color-neutral-950);
457
+ --text-color-inverted: light-dark(#ffffff, var(--color-neutral-50));
458
+ --background-color-default: light-dark(#ffffff, var(--color-neutral-50));
459
+ --background-color-muted: var(--color-neutral-100);
460
+ --background-color-elevated: var(--color-neutral-200);
461
+ --background-color-accented: var(--color-neutral-300);
462
+ --background-color-inverted: var(--color-neutral-950);
553
463
  --border-color-default: var(--color-neutral-200);
554
- --border-color-muted: var(--color-neutral-200);
464
+ --border-color-muted: var(--color-neutral-100);
555
465
  --border-color-accented: var(--color-neutral-300);
556
- --border-color-inverted: var(--color-neutral-900);
466
+ --border-color-inverted: var(--color-neutral-950);
557
467
  --ring-color-default: var(--color-neutral-200);
558
- --ring-color-muted: var(--color-neutral-200);
468
+ --ring-color-muted: var(--color-neutral-100);
559
469
  --ring-color-accented: var(--color-neutral-300);
560
- --ring-color-inverted: var(--color-neutral-900);
470
+ --ring-color-inverted: var(--color-neutral-950);
561
471
  --divide-color-default: var(--color-neutral-200);
562
- ${lightLines}
563
- ${flatLines}
564
- ${lightPinnedLines}
565
- ${darkPinnedLines}
472
+ --divide-color-inverted: var(--color-neutral-950);
473
+
474
+ /* Color scales — light-dark() resolves based on inherited color-scheme */
475
+ ${lightDarkLines}
566
476
 
567
477
  /* Shiki / Expressive Code */
568
478
  --shiki-foreground: #e1e4e8;
@@ -575,105 +485,20 @@ ${darkPinnedLines}
575
485
  --shiki-token-parameter: #ffab70;
576
486
  --shiki-token-punctuation: #e1e4e8;
577
487
  }
578
-
488
+ /* Re-declare color on semantic text elements so light-dark() re-evaluates
489
+ against each element's own inherited color-scheme. Without this, plain
490
+ text inherits a pre-computed color from body and ignores rl-dark/rl-light
491
+ wrappers. All rules are overridable by any utility class. */
492
+ p, h1, h2, h3, h4, h5, h6,
493
+ li, blockquote, figcaption, caption,
494
+ label, legend, dt, dd {
495
+ color: var(--foreground);
496
+ }
579
497
  .dark {
580
- --background: #030712;
581
- --foreground: #f9fafb;
582
- --card: #111827;
583
- --card-foreground: #f9fafb;
584
- --popover: #1f2937;
585
- --popover-foreground: #f9fafb;
586
- --primary: #3b82f6;
587
- --primary-foreground: #ffffff;
588
- --primary-accent: #60a5fa;
589
- --secondary: #8b5cf6;
590
- --secondary-foreground: #f9fafb;
591
- --secondary-accent: #a78bfa;
592
- --muted: #1f2937;
593
- --muted-foreground: #9ca3af;
594
- --accent: #374151;
595
- --accent-foreground: #f3f4f6;
596
- --info: #3b82f6;
597
- --info-foreground: #ffffff;
598
- --info-accent: #60a5fa;
599
- --success: #22c55e;
600
- --success-foreground: #ffffff;
601
- --success-accent: #4ade80;
602
- --warning: #f59e0b;
603
- --warning-foreground: #000000;
604
- --warning-accent: #fbbf24;
605
- --error: #ef4444;
606
- --error-foreground: #f9fafb;
607
- --error-accent: #f87171;
608
- --commentary: #f472b6;
609
- --commentary-foreground: #0f172a;
610
- --commentary-accent: #f9a8d4;
611
- --ideation: #a78bfa;
612
- --ideation-foreground: #0f172a;
613
- --ideation-accent: #c4b5fd;
614
- --source: #7dd3fc;
615
- --source-foreground: #0f172a;
616
- --source-accent: #bae6fd;
617
- --border: rgba(249, 250, 251, 0.1);
618
- --input: rgba(249, 250, 251, 0.15);
619
- --outline: #6b7280;
620
- --ring: #6b7280;
621
- --sidebar: #111827;
622
- --sidebar-foreground: #f9fafb;
623
- --sidebar-primary: #1d4ed8;
624
- --sidebar-primary-foreground: #f9fafb;
625
- --sidebar-accent: #1f2937;
626
- --sidebar-accent-foreground: #f3f4f6;
627
- --sidebar-border: #1f2937;
628
- --sidebar-ring: #6b7280;
629
- --chart-1: #60a5fa;
630
- --chart-2: #818cf8;
631
- --chart-3: #a78bfa;
632
- --chart-4: #c084fc;
633
- --chart-5: #f472b6;
634
- --destructive: #f87171;
635
- --color-surface: #1f2937;
636
- --color-muted-strong: #374151;
637
- --color-foreground-secondary: #d1d5db;
638
- --color-foreground-tertiary: #9ca3af;
639
- --color-placeholder: #6b7280;
640
- --color-input-border: #4b5563;
641
- --color-hover: #374151;
642
- --color-destructive-subtle: #451a1a;
643
- --color-accent-subtle: #1e293b;
644
-
645
- --text-color-default: var(--color-neutral-200);
646
- --text-color-muted: var(--color-neutral-400);
647
- --text-color-dimmed: var(--color-neutral-500);
648
- --text-color-toned: var(--color-neutral-300);
649
- --text-color-highlighted: #ffffff;
650
- --text-color-inverted: #030712;
651
- --background-color-default: var(--color-neutral-900);
652
- --background-color-muted: var(--color-neutral-800);
653
- --background-color-elevated: var(--color-neutral-800);
654
- --background-color-accented: var(--color-neutral-700);
655
- --background-color-inverted: #ffffff;
656
- --border-color-default: var(--color-neutral-800);
657
- --border-color-muted: var(--color-neutral-700);
658
- --border-color-accented: var(--color-neutral-700);
659
- --border-color-inverted: #ffffff;
660
- --ring-color-default: var(--color-neutral-800);
661
- --ring-color-muted: var(--color-neutral-700);
662
- --ring-color-accented: var(--color-neutral-700);
663
- --ring-color-inverted: #ffffff;
664
- --divide-color-default: var(--color-neutral-800);
665
- ${darkLines}
666
-
667
- /* Shiki / Expressive Code */
668
- --shiki-foreground: #e1e4e8;
669
- --shiki-background: #1f2428;
670
- --shiki-token-keyword: #f97583;
671
- --shiki-token-string: #9ecbff;
672
- --shiki-token-comment: #6a737d;
673
- --shiki-token-function: #b392f0;
674
- --shiki-token-constant: #79b8ff;
675
- --shiki-token-parameter: #ffab70;
676
- --shiki-token-punctuation: #e1e4e8;
498
+ color-scheme: dark;
499
+ }
500
+ .light {
501
+ color-scheme: light;
677
502
  }
678
503
  `
679
504
  }
@@ -1,5 +1,3 @@
1
- @import "./prism.css";
2
-
3
1
  body {
4
2
  background-color: var(--background);
5
3
  color: var(--foreground);
@@ -2,11 +2,37 @@ import { defineTheme } from "../utils/defineTheme"
2
2
 
3
3
  export const createAccordionTheme = () =>
4
4
  defineTheme({
5
- slots: ["root"],
5
+ slots: [
6
+ "root",
7
+ "item",
8
+ "header",
9
+ "trigger",
10
+ "content",
11
+ "body",
12
+ "leadingIcon",
13
+ "trailingIcon",
14
+ "label"
15
+ ],
6
16
  base: {
7
- root: ""
17
+ root: "w-full",
18
+ item: "border-b border-default last:border-b-0",
19
+ header: "flex",
20
+ trigger:
21
+ "group flex w-full flex-1 items-center gap-1.5 font-medium text-sm py-3.5 px-4 focus-visible:outline-primary min-w-0 cursor-pointer list-none [&::-webkit-details-marker]:hidden",
22
+ content: "overflow-hidden focus:outline-none pt-1 px-4",
23
+ body: "text-sm pb-3.5 text-astro-gray-200",
24
+ leadingIcon: "shrink-0 size-5 text-astro-gray-300",
25
+ trailingIcon:
26
+ "shrink-0 size-5 ms-auto rotate-0 transition-transform duration-200 group-open:rotate-180 text-astro-gray-300",
27
+ label: "text-start break-words text-astro-gray-100"
28
+ },
29
+ variants: {
30
+ disabled: {
31
+ true: {
32
+ trigger: "cursor-not-allowed opacity-50 select-none"
33
+ }
34
+ }
8
35
  },
9
- variants: {},
10
36
  defaultVariants: {}
11
37
  })
12
38
 
@@ -1,7 +1,7 @@
1
1
  import { defaultColors } from "../presets/defaults"
2
2
  import { defineTheme } from "../utils/defineTheme"
3
3
 
4
- export const createAspectRatioTheme = (colors: string[] = defaultColors) =>
4
+ export const createAspectRatioTheme = (_colors: readonly string[] = defaultColors) =>
5
5
  defineTheme({
6
6
  slots: ["root", "content"],
7
7
  base: {
@@ -1,7 +1,7 @@
1
1
  import { defaultColors } from "../presets/defaults"
2
2
  import { defineTheme } from "../utils/defineTheme"
3
3
 
4
- export const createAvatarGroupTheme = (colors: string[] = defaultColors) =>
4
+ export const createAvatarGroupTheme = (_colors: readonly string[] = defaultColors) =>
5
5
  defineTheme({
6
6
  slots: ["root"],
7
7
  base: {
@@ -1,7 +1,7 @@
1
1
  import { defaultColors } from "../presets/defaults"
2
2
  import { defineTheme } from "../utils/defineTheme"
3
3
 
4
- export const createAvatarTheme = (colors: string[] = defaultColors) =>
4
+ export const createAvatarTheme = (colors: readonly string[] = defaultColors) =>
5
5
  defineTheme({
6
6
  slots: ["root", "image", "fallback", "icon", "badge"],
7
7
  base: {
@@ -25,7 +25,7 @@ export const createAvatarTheme = (colors: string[] = defaultColors) =>
25
25
  ),
26
26
  neutral: {
27
27
  root: "bg-elevated",
28
- fallback: "text-muted",
28
+ fallback: "text-foreground",
29
29
  icon: "text-muted"
30
30
  }
31
31
  },