jamdesk 1.1.207 → 1.1.209
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.
- package/dist/__tests__/unit/vendored-sync.test.js +2 -2
- package/dist/__tests__/unit/vendored-sync.test.js.map +1 -1
- package/package.json +1 -1
- package/vendored/app/layout.tsx +3 -2
- package/vendored/components/mdx/CodeGroup.tsx +39 -3
- package/vendored/components/navigation/Header.tsx +0 -7
- package/vendored/components/navigation/Sidebar.tsx +14 -0
- package/vendored/components/navigation/ThemePreviewChips.tsx +121 -0
- package/vendored/components/theme/ThemeToggle.tsx +8 -1
- package/vendored/lib/theme-preview-client.ts +72 -0
- package/vendored/lib/theme-preview.ts +41 -31
- package/vendored/themes/jam/variables.css +9 -0
- package/vendored/themes/nebula/variables.css +19 -14
- package/vendored/themes/pulsar/variables.css +11 -2
- package/vendored/workspace-package-lock.json +3 -3
- package/vendored/components/navigation/ThemePreviewPicker.tsx +0 -197
|
@@ -42,8 +42,8 @@ const SYNCED_FILES = [
|
|
|
42
42
|
['build-service/themes/index.ts', 'cli/vendored/themes/index.ts'],
|
|
43
43
|
['build-service/components/navigation/Header.tsx', 'cli/vendored/components/navigation/Header.tsx'],
|
|
44
44
|
[
|
|
45
|
-
'build-service/components/navigation/
|
|
46
|
-
'cli/vendored/components/navigation/
|
|
45
|
+
'build-service/components/navigation/ThemePreviewChips.tsx',
|
|
46
|
+
'cli/vendored/components/navigation/ThemePreviewChips.tsx',
|
|
47
47
|
],
|
|
48
48
|
[
|
|
49
49
|
"build-service/components/navigation/Sidebar.tsx",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vendored-sync.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/vendored-sync.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vendored-sync.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/vendored-sync.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jamdesk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.209",
|
|
4
4
|
"description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jamdesk",
|
package/vendored/app/layout.tsx
CHANGED
|
@@ -190,8 +190,9 @@ async function rootLayoutImpl({
|
|
|
190
190
|
const embedTheme = (headersList.get('x-jd-embed-theme') as 'light' | 'dark' | 'auto' | null) ?? 'auto';
|
|
191
191
|
|
|
192
192
|
// Theme preview (jamdesk-docs only). Capture the project's own theme BEFORE
|
|
193
|
-
// overriding —
|
|
194
|
-
//
|
|
193
|
+
// overriding — ThemePreviewChips needs it to decide whether a preview is on
|
|
194
|
+
// (Reset and the "Previewing" label), and after the override config.theme
|
|
195
|
+
// holds the previewed value.
|
|
195
196
|
// `toThemeName`, not a cast: config.theme is an unvalidated docs.json string.
|
|
196
197
|
const defaultTheme = toThemeName(config.theme);
|
|
197
198
|
const themePreviewGate = {
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
'use client'
|
|
1
|
+
// Deliberately NOT 'use client'. CodeGroup reads its children as elements, so
|
|
2
|
+
// it must see them BEFORE React Server Components renders them. As a client
|
|
3
|
+
// component it received what MdxPreBlock (a server component) had already
|
|
4
|
+
// turned each fence into: a bare <pre> for an untitled fence, but a whole
|
|
5
|
+
// titled CodePanel for a titled one. Nothing below recognises the latter, so
|
|
6
|
+
// in production every titled fence fell out of the tab strip. Run on the
|
|
7
|
+
// server, it gets the raw MdxPreBlock elements, the same shape its tests
|
|
8
|
+
// build. The browser half lives in CodePanel, which stays a client component.
|
|
9
|
+
// Pinned by the directive test in __tests__/components/CodeGroup.test.tsx.
|
|
2
10
|
|
|
3
11
|
import { ReactNode, ReactElement, Children, Fragment, cloneElement, isValidElement, memo } from 'react';
|
|
4
12
|
import { CodePanel, CodePanelTab } from '../ui/CodePanel';
|
|
@@ -161,8 +169,10 @@ const CODE_FENCE_MARKER = 'jdCodeFenceMarker';
|
|
|
161
169
|
* the child is not a fence at all.
|
|
162
170
|
*
|
|
163
171
|
* Two layers have to be peeled, and the pre-fix filter (`child.type ===
|
|
164
|
-
* 'pre'`) saw through neither,
|
|
165
|
-
*
|
|
172
|
+
* 'pre'`) saw through neither, so no <CodeGroup> rendered a tab strip
|
|
173
|
+
* outside RSC (the editor preview, tests). Under RSC it only ever caught
|
|
174
|
+
* untitled fences, as host <pre> elements; see the note at the top of the
|
|
175
|
+
* file:
|
|
166
176
|
*
|
|
167
177
|
* 1. Compiled MDX hands each fence over wrapped in a single-child
|
|
168
178
|
* Fragment, not as the fence element directly.
|
|
@@ -194,6 +204,21 @@ function unwrapCodeFence(child: ReactNode): ReactElement | null {
|
|
|
194
204
|
return null;
|
|
195
205
|
}
|
|
196
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Whether MdxPreBlock will render this fence as its own captioned panel.
|
|
209
|
+
* Mirrors MdxPreBlock's `if (!dataTitle)` branch exactly, and only for the
|
|
210
|
+
* marked MdxPreBlock element: a hand-built host <pre> never takes that
|
|
211
|
+
* branch, whatever attributes it carries.
|
|
212
|
+
*/
|
|
213
|
+
function isTitledMdxFence(block: ReactElement): boolean {
|
|
214
|
+
const { type } = block;
|
|
215
|
+
return (
|
|
216
|
+
typeof type === 'function' &&
|
|
217
|
+
(type as unknown as Record<string, unknown>)[CODE_FENCE_MARKER] === true &&
|
|
218
|
+
Boolean((block.props as PreProps)['data-title'])
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
197
222
|
/**
|
|
198
223
|
* Children that are neither code fences nor the blank text nodes MDX emits
|
|
199
224
|
* between block children. These are rendered after the panel so a
|
|
@@ -237,6 +262,17 @@ export const CodeGroup = memo(function CodeGroup({ children }: CodeGroupProps) {
|
|
|
237
262
|
return <div>{children}</div>;
|
|
238
263
|
}
|
|
239
264
|
|
|
265
|
+
// A lone titled fence keeps the caption-only panel production has always
|
|
266
|
+
// shown for it, through the same fallback as above. While CodeGroup was a
|
|
267
|
+
// client component it never recognised a titled fence, so this is the only
|
|
268
|
+
// rendering such a group has ever had; tabbing it would add a one-tab
|
|
269
|
+
// language strip under the caption on every page that wraps a single
|
|
270
|
+
// titled fence in <CodeGroup>. Fence titles become tab labels only where
|
|
271
|
+
// there is more than one fence to switch between.
|
|
272
|
+
if (codeBlocks.length === 1 && isTitledMdxFence(codeBlocks[0])) {
|
|
273
|
+
return <div>{children}</div>;
|
|
274
|
+
}
|
|
275
|
+
|
|
240
276
|
const extras = allChildren.filter(isRenderableExtra);
|
|
241
277
|
|
|
242
278
|
// Extract title from first code block (only shown for single blocks)
|
|
@@ -13,7 +13,6 @@ import { ThemeToggle } from '@/components/theme/ThemeToggle';
|
|
|
13
13
|
import { LazySearchModal as SearchModal } from '@/components/search/LazySearchModal';
|
|
14
14
|
import { DefaultLogo } from './DefaultLogo';
|
|
15
15
|
import { LanguageSelector } from './LanguageSelector';
|
|
16
|
-
import { ThemePreviewPicker } from './ThemePreviewPicker';
|
|
17
16
|
import LogoutButton from './LogoutButton';
|
|
18
17
|
import { resolveNavigation } from '@/lib/navigation-resolver';
|
|
19
18
|
import { getIconClass } from '@/lib/icon-utils';
|
|
@@ -556,12 +555,6 @@ export function Header({ config, layout = 'header-logo', tabsPosition: tabsPosit
|
|
|
556
555
|
renders nothing until the client confirms an active session. */}
|
|
557
556
|
{config.auth?.jwt?.enabled === true && <LogoutButton />}
|
|
558
557
|
|
|
559
|
-
{/* Theme preview picker — jamdesk-docs only. The component returns
|
|
560
|
-
null unless the ThemePreviewProvider enables it, and carries its
|
|
561
|
-
own `hidden lg:block`, so there is no stray wrapper on customer
|
|
562
|
-
sites. */}
|
|
563
|
-
<ThemePreviewPicker />
|
|
564
|
-
|
|
565
558
|
{/* Theme toggle - hidden on mobile since it's in the sidebar menu.
|
|
566
559
|
Also hidden when appearance.strict pins users to the configured mode. */}
|
|
567
560
|
{!config.appearance?.strict && (
|
|
@@ -12,6 +12,7 @@ import { getTheme } from '@/themes';
|
|
|
12
12
|
import { DefaultLogo, DefaultLogoCompact } from './DefaultLogo';
|
|
13
13
|
import { LanguageSelector } from './LanguageSelector';
|
|
14
14
|
import { LazySearchModal as SearchModal } from '@/components/search/LazySearchModal';
|
|
15
|
+
import { ThemePreviewChips } from './ThemePreviewChips';
|
|
15
16
|
import { ThemeToggle, ThemeToggleCycle } from '@/components/theme/ThemeToggle';
|
|
16
17
|
import { getIconClass } from '@/lib/icon-utils';
|
|
17
18
|
import { getTabsFromConfig } from '@/lib/navigation-utils';
|
|
@@ -877,6 +878,13 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
|
|
|
877
878
|
</button>
|
|
878
879
|
</div>
|
|
879
880
|
|
|
881
|
+
{/* Theme-preview chips, header-logo layouts (Jam/Nebula/Halo) only.
|
|
882
|
+
Pinned outside the scroll area so it stays at the top of the
|
|
883
|
+
mobile drawer and desktop rail. Pulsar (sidebar-logo) renders its
|
|
884
|
+
own copy inside the scroll area below — its desktop logo lives
|
|
885
|
+
there, so a pinned row here would sit above the logo instead. */}
|
|
886
|
+
{!showLogoInSidebar && <ThemePreviewChips />}
|
|
887
|
+
|
|
880
888
|
{/* Scrollable content area - everything below mobile header scrolls */}
|
|
881
889
|
<div className="flex-1 overflow-y-auto sidebar-scroll" data-has-tabs={hasTopTabsBar ? 'true' : 'false'}>
|
|
882
890
|
|
|
@@ -929,6 +937,12 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
|
|
|
929
937
|
</div>
|
|
930
938
|
)}
|
|
931
939
|
|
|
940
|
+
{/* Theme-preview chips, sidebar-logo layout (Pulsar) only. Lives
|
|
941
|
+
inside the scroll area, right below the logo and search — Pulsar
|
|
942
|
+
hides the header entirely at >=1024px, so the pinned copy above
|
|
943
|
+
(header-logo layouts) can't reach this layout at all. */}
|
|
944
|
+
{showLogoInSidebar && <ThemePreviewChips />}
|
|
945
|
+
|
|
932
946
|
<nav className="flex-1">
|
|
933
947
|
{/* External anchors - appear at top of sidebar on all pages */}
|
|
934
948
|
{renderExternalAnchors()}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useId, useState } from 'react';
|
|
4
|
+
import { useLinkPrefix } from '@/lib/link-prefix-context';
|
|
5
|
+
import { useThemePreview } from '@/lib/theme-preview-context';
|
|
6
|
+
import { applyThemePreview, type ThemePreviewSurface } from '@/lib/theme-preview-client';
|
|
7
|
+
import { getAllThemes, type ThemeName } from '@/themes';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Jamdesk-only affordance: re-skins jamdesk.com/docs with any built-in theme
|
|
11
|
+
* so prospects (and customers) can see all four on a real docs site.
|
|
12
|
+
*
|
|
13
|
+
* Lives in the Sidebar, not the header, at every breakpoint. The header can't
|
|
14
|
+
* host it: Pulsar hides the header entirely at >=1024px, which stranded any
|
|
15
|
+
* visitor who picked Pulsar, and at 1024px in Jam/Halo a header control
|
|
16
|
+
* pushed the light/dark toggle off-screen. Every theme has a sidebar.
|
|
17
|
+
*
|
|
18
|
+
* Collapsed to a one-line toggle by default. Paying customers read these docs
|
|
19
|
+
* too, and the top of the sidebar is the most valuable navigation space, so
|
|
20
|
+
* the chips only take it when someone asks for them. The open/closed state is
|
|
21
|
+
* deliberately not persisted: every load paints the same collapsed row, so
|
|
22
|
+
* there's no layout shift and no storage. Reset sits beside the toggle rather
|
|
23
|
+
* than inside the row, so leaving a preview is always one tap.
|
|
24
|
+
*
|
|
25
|
+
* Self-guards on `enabled`: Sidebar renders for every tenant, and the context
|
|
26
|
+
* default is disabled, so customer sites render nothing.
|
|
27
|
+
*
|
|
28
|
+
* Strings are English-only by design: the only prose is "Preview a theme",
|
|
29
|
+
* "Previewing" and "Reset"; theme names are proper nouns.
|
|
30
|
+
*/
|
|
31
|
+
export function ThemePreviewChips() {
|
|
32
|
+
const { enabled, activeTheme, defaultTheme } = useThemePreview();
|
|
33
|
+
const linkPrefix = useLinkPrefix();
|
|
34
|
+
const panelId = useId();
|
|
35
|
+
const [expanded, setExpanded] = useState(false);
|
|
36
|
+
// Set on the first tap and never cleared: the page is about to reload
|
|
37
|
+
// (after up to THEME_PREVIEW_EVENT_TIMEOUT_MS). A second tap in that window
|
|
38
|
+
// would write a second cookie that races the first reload.
|
|
39
|
+
const [pending, setPending] = useState(false);
|
|
40
|
+
|
|
41
|
+
if (!enabled) return null;
|
|
42
|
+
|
|
43
|
+
function choose(name: ThemeName | null) {
|
|
44
|
+
if (pending) return;
|
|
45
|
+
setPending(true);
|
|
46
|
+
// 1024px = Tailwind `lg`, where the Sidebar stops being a drawer. Read at
|
|
47
|
+
// click time, not render time, so a resized window reports correctly.
|
|
48
|
+
const surface: ThemePreviewSurface =
|
|
49
|
+
typeof window.matchMedia === 'function' && window.matchMedia('(min-width: 1024px)').matches
|
|
50
|
+
? 'desktop'
|
|
51
|
+
: 'mobile';
|
|
52
|
+
applyThemePreview(name, { linkPrefix, surface });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const themes = getAllThemes();
|
|
56
|
+
const previewing = activeTheme !== defaultTheme;
|
|
57
|
+
const activeName = themes.find((t) => t.name === activeTheme)?.displayName ?? activeTheme;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div className="flex-shrink-0 px-4 py-1 border-b border-[var(--color-border)]">
|
|
61
|
+
<div className="flex items-center gap-2">
|
|
62
|
+
<button
|
|
63
|
+
type="button"
|
|
64
|
+
aria-expanded={expanded}
|
|
65
|
+
aria-controls={panelId}
|
|
66
|
+
onClick={() => setExpanded((open) => !open)}
|
|
67
|
+
className="flex flex-1 min-w-0 items-center gap-1.5 py-1.5 rounded text-xs font-medium text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-accent)]"
|
|
68
|
+
>
|
|
69
|
+
<i className="fa-solid fa-palette text-[12px]" aria-hidden="true" />
|
|
70
|
+
<span className="truncate">{previewing ? `Previewing ${activeName}` : 'Preview a theme'}</span>
|
|
71
|
+
<i
|
|
72
|
+
className={`fa-solid fa-chevron-right text-[8px] text-[var(--color-text-muted)] transition-transform ${expanded ? 'rotate-90' : ''}`}
|
|
73
|
+
aria-hidden="true"
|
|
74
|
+
/>
|
|
75
|
+
</button>
|
|
76
|
+
{previewing && (
|
|
77
|
+
<button
|
|
78
|
+
type="button"
|
|
79
|
+
disabled={pending}
|
|
80
|
+
onClick={() => choose(null)}
|
|
81
|
+
// Visible text stays "Reset" to fit beside "Previewing Nebula" in
|
|
82
|
+
// the narrowest sidebar; the name starts with it (WCAG 2.5.3).
|
|
83
|
+
aria-label="Reset to default theme"
|
|
84
|
+
className="flex-shrink-0 text-xs px-2 py-1.5 -mr-2 rounded text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] disabled:opacity-50"
|
|
85
|
+
>
|
|
86
|
+
Reset
|
|
87
|
+
</button>
|
|
88
|
+
)}
|
|
89
|
+
</div>
|
|
90
|
+
{/* The `hidden` wrapper carries no display utility, so nothing can
|
|
91
|
+
override it; same pattern as Sidebar's collapsible nav groups. */}
|
|
92
|
+
<div id={panelId} hidden={!expanded}>
|
|
93
|
+
<div role="group" aria-label="Preview a theme" className="flex flex-wrap gap-1.5 pt-1 pb-2">
|
|
94
|
+
{themes.map((theme) => {
|
|
95
|
+
const isActive = theme.name === activeTheme;
|
|
96
|
+
return (
|
|
97
|
+
<button
|
|
98
|
+
key={theme.name}
|
|
99
|
+
type="button"
|
|
100
|
+
aria-pressed={isActive}
|
|
101
|
+
disabled={pending}
|
|
102
|
+
// Re-selecting the active theme would reload into the same page.
|
|
103
|
+
onClick={() => { if (!isActive) choose(theme.name as ThemeName); }}
|
|
104
|
+
className={`rounded-full border px-3 py-1.5 text-xs cursor-pointer transition-colors disabled:opacity-50 ${
|
|
105
|
+
isActive
|
|
106
|
+
// accent-TEXT, not accent: raw #635BFF on Halo's light
|
|
107
|
+
// background is 4.21:1, under WCAG AA. The -text token is
|
|
108
|
+
// the primary darkened/lightened per mode for exactly this.
|
|
109
|
+
? 'border-[var(--color-accent)] text-[var(--color-accent-text)]'
|
|
110
|
+
: 'border-[var(--color-border)] text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-tertiary)]'
|
|
111
|
+
}`}
|
|
112
|
+
>
|
|
113
|
+
{theme.displayName}
|
|
114
|
+
</button>
|
|
115
|
+
);
|
|
116
|
+
})}
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
@@ -63,13 +63,16 @@ export function ThemeToggle() {
|
|
|
63
63
|
>
|
|
64
64
|
{THEMES.map(({ name, icon, title }) => {
|
|
65
65
|
const active = theme === name;
|
|
66
|
+
// The active segment is a filled --color-bg-hover chip, not a
|
|
67
|
+
// --color-bg-primary "cut-out": jam, nebula and pulsar tint the track
|
|
68
|
+
// so faintly that a page-colored segment vanished into it in light mode.
|
|
66
69
|
return (
|
|
67
70
|
<button
|
|
68
71
|
key={name}
|
|
69
72
|
onClick={() => setTheme(name)}
|
|
70
73
|
className={`${buttonClass} transition-colors ${
|
|
71
74
|
active
|
|
72
|
-
? 'bg-[var(--color-bg-
|
|
75
|
+
? 'bg-[var(--color-bg-hover)] text-[var(--color-text-primary)]'
|
|
73
76
|
: 'text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)]'
|
|
74
77
|
}`}
|
|
75
78
|
aria-label={`${title} theme`}
|
|
@@ -112,6 +115,10 @@ export function ThemeToggleCycle() {
|
|
|
112
115
|
return (
|
|
113
116
|
<button
|
|
114
117
|
onClick={cycleTheme}
|
|
118
|
+
// Hook for the jam/pulsar rule that thickens their light-weight icons.
|
|
119
|
+
// A distinct attribute, not [data-theme-toggle], so Pulsar's
|
|
120
|
+
// segmented-control sizing rules don't reach this button.
|
|
121
|
+
data-theme-toggle-cycle
|
|
115
122
|
className="p-1.5 bg-[var(--color-bg-secondary)]/50 border border-[var(--color-border)]/50 text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] rounded-md transition-colors cursor-pointer"
|
|
116
123
|
aria-label={label}
|
|
117
124
|
title={label}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { THEME_PREVIEW_COOKIE } from '@/lib/theme-preview';
|
|
2
|
+
import type { ThemeName } from '@/themes';
|
|
3
|
+
|
|
4
|
+
/** Which breakpoint the visitor chose from, for splitting desktop and mobile uptake in Plausible. */
|
|
5
|
+
export type ThemePreviewSurface = 'desktop' | 'mobile';
|
|
6
|
+
|
|
7
|
+
/** Plausible goal name — must match the goal configured in Plausible. */
|
|
8
|
+
export const THEME_PREVIEW_EVENT = 'Theme Preview';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Longest the reload waits for Plausible to confirm. The inline stub in
|
|
12
|
+
* layout-helpers' PlausibleScript defines `window.plausible` even when an
|
|
13
|
+
* ad-blocker stops the real script loading; the stub only queues, so the
|
|
14
|
+
* callback never fires and without this bound the click would do nothing.
|
|
15
|
+
*/
|
|
16
|
+
export const THEME_PREVIEW_EVENT_TIMEOUT_MS = 400;
|
|
17
|
+
|
|
18
|
+
type PlausibleFn = (
|
|
19
|
+
event: string,
|
|
20
|
+
options: { props: Record<string, string>; callback: () => void },
|
|
21
|
+
) => void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Apply (or with `null`, clear) a theme preview: write the cookie, report it
|
|
25
|
+
* to Plausible, reload. The single place a preview is applied, so the cookie
|
|
26
|
+
* contract and the event stay in one place for every caller (today,
|
|
27
|
+
* `ThemePreviewChips`).
|
|
28
|
+
*/
|
|
29
|
+
export function applyThemePreview(
|
|
30
|
+
name: ThemeName | null,
|
|
31
|
+
{ linkPrefix, surface }: { linkPrefix: string; surface: ThemePreviewSurface },
|
|
32
|
+
): void {
|
|
33
|
+
const path = linkPrefix || '/';
|
|
34
|
+
// SESSION cookie on the set path — no Max-Age, by product decision: a
|
|
35
|
+
// preview is a look at a theme, not a setting, and should not outlive the
|
|
36
|
+
// visit. The CLEAR path is the opposite and must stay explicit: `Max-Age=0`
|
|
37
|
+
// is what expires an existing cookie, and omitting it there would leave the
|
|
38
|
+
// preview in place.
|
|
39
|
+
const expiry = name === null ? '; Max-Age=0' : '';
|
|
40
|
+
// `Secure` means the browser silently DROPS this cookie over plain http, so
|
|
41
|
+
// the picker looks inert when QA'd on http://localhost — use https or a
|
|
42
|
+
// deployed host.
|
|
43
|
+
document.cookie =
|
|
44
|
+
`${THEME_PREVIEW_COOKIE}=${name ?? ''}; Path=${path}${expiry}; SameSite=Lax; Secure`;
|
|
45
|
+
|
|
46
|
+
// Full reload: the theme is applied by the server render (CSS variables,
|
|
47
|
+
// font class and layout variant all key off config.theme). Guarded because
|
|
48
|
+
// both the Plausible callback and the timeout race to call it.
|
|
49
|
+
let reloaded = false;
|
|
50
|
+
const reload = () => {
|
|
51
|
+
if (reloaded) return;
|
|
52
|
+
reloaded = true;
|
|
53
|
+
window.location.reload();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const plausible = (window as unknown as { plausible?: PlausibleFn }).plausible;
|
|
57
|
+
if (typeof plausible !== 'function') {
|
|
58
|
+
reload();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Arm the timeout BEFORE calling Plausible: a synchronous callback then
|
|
62
|
+
// still goes through the once-guard rather than racing a later timer.
|
|
63
|
+
window.setTimeout(reload, THEME_PREVIEW_EVENT_TIMEOUT_MS);
|
|
64
|
+
try {
|
|
65
|
+
plausible(THEME_PREVIEW_EVENT, {
|
|
66
|
+
props: { theme: name ?? 'reset', surface },
|
|
67
|
+
callback: reload,
|
|
68
|
+
});
|
|
69
|
+
} catch {
|
|
70
|
+
reload();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme preview gate — jamdesk-docs only.
|
|
3
3
|
*
|
|
4
|
-
* A visitor picks a theme from the
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* A visitor picks a theme from the chip row in the Sidebar
|
|
5
|
+
* (`components/navigation/ThemePreviewChips.tsx`); `lib/theme-preview-client.ts`
|
|
6
|
+
* writes a cookie and reloads, and `app/layout.tsx` applies it by overriding
|
|
7
|
+
* `config.theme` before rendering DocsChrome. Everything in this file is pure
|
|
8
|
+
* so the entire gate can be tested without rendering or touching the
|
|
9
|
+
* environment.
|
|
8
10
|
*
|
|
9
11
|
* TWO OPERATIONAL INVARIANTS live here because nothing else in the tree records
|
|
10
12
|
* them:
|
|
@@ -24,28 +26,35 @@
|
|
|
24
26
|
* with `node scripts/smoke-tenants.mjs`, never a single URL. Prefer it to a
|
|
25
27
|
* code revert, but budget for a deploy: there is no faster kill path.
|
|
26
28
|
*
|
|
27
|
-
* 2. CACHEABILITY — the response varies by the `jd_theme` cookie
|
|
28
|
-
*
|
|
29
|
-
*
|
|
29
|
+
* 2. CACHEABILITY — the response varies by the `jd_theme` cookie and carries
|
|
30
|
+
* no `Vary: Cookie`. It is safe anyway because BOTH hosts serve the docs
|
|
31
|
+
* HTML as `private, no-cache, no-store, max-age=0, must-revalidate`. That
|
|
32
|
+
* comes from the route being dynamic, which `app/[[...slug]]/page.tsx`'s
|
|
33
|
+
* `force-dynamic` guarantees — the root layout's own `headers()`/`cookies()`
|
|
34
|
+
* reads also force every docs page dynamic, so `force-dynamic` is a
|
|
35
|
+
* belt-and-suspenders guarantee, not the sole cause. This was verified
|
|
36
|
+
* 2026-09-22 with curl and a `jd_theme` cookie on both hosts:
|
|
37
|
+
* `jamdesk.com/docs/introduction` (apex, through the worker,
|
|
38
|
+
* `cf-cache-status: BYPASS`) and `jamdesk-docs.jamdesk.app/docs/introduction`
|
|
39
|
+
* (the ISR subdomain, `x-vercel-cache: MISS`). The `public, max-age=0,
|
|
40
|
+
* must-revalidate` that once looked like an exposure on
|
|
41
|
+
* `jamdesk-docs.jamdesk.app` belongs to the 308 redirect from bare paths
|
|
42
|
+
* (e.g. `/introduction`) to `/docs/...` — that redirect does not vary by
|
|
43
|
+
* cookie. The cookie itself is `Path=/docs` on both hosts.
|
|
30
44
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* if anything raises the stakes: a Cloudflare Cache Rule or `s-maxage` that
|
|
45
|
-
* makes the apex shared-cacheable, extending the preview past jamdesk-docs,
|
|
46
|
-
* or putting anything per-visitor in the response. A server component
|
|
47
|
-
* cannot set response headers, so this docblock IS the mitigation — the
|
|
48
|
-
* only thing that can go wrong with it is going stale.
|
|
45
|
+
* The invariant is that the page stays `private, no-store`, pinned on
|
|
46
|
+
* `force-dynamic` by `layout-theme-preview-wiring.test.ts` as the explicit
|
|
47
|
+
* guarantee. If anything makes the HTML shared-cacheable — removing
|
|
48
|
+
* `force-dynamic`, adding `revalidate` or `s-maxage`, or a Cloudflare
|
|
49
|
+
* Cache Rule on `/docs` — the preview leaks across visitors. If that ever
|
|
50
|
+
* needs to change, force `Cache-Control: private, no-store` for the
|
|
51
|
+
* `jamdesk-docs` slug at `proxy.ts`'s terminal `continueWith` return.
|
|
52
|
+
* `Vary: Cookie` is NOT enough: on jamdesk.com the apex worker
|
|
53
|
+
* (`cloudflare-worker/index.js`) fetches every proxied docs path with
|
|
54
|
+
* `cf: { cacheEverything: true }` and no `cf.vary`, so it caches by URL and
|
|
55
|
+
* Cloudflare ignores `Vary` unless a Cache Rule opts in — that worker would
|
|
56
|
+
* keep serving one visitor's previewed HTML to everyone else regardless of
|
|
57
|
+
* a `Vary` header.
|
|
49
58
|
*/
|
|
50
59
|
import { getAllThemes, type ThemeName } from '@/themes';
|
|
51
60
|
|
|
@@ -56,10 +65,9 @@ export const THEME_PREVIEW_COOKIE = 'jd_theme';
|
|
|
56
65
|
export const THEME_PREVIEW_SLUG = 'jamdesk-docs';
|
|
57
66
|
|
|
58
67
|
// No lifetime constant on purpose: the picker writes a SESSION cookie (no
|
|
59
|
-
// Max-Age)
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
// applyTheme.
|
|
68
|
+
// Max-Age) by product decision — a preview is a look at a theme, not a
|
|
69
|
+
// setting, and should not outlive the visit. The clear path still sends
|
|
70
|
+
// `Max-Age=0` — see theme-preview-client.ts's applyThemePreview.
|
|
63
71
|
|
|
64
72
|
// Built from the registry rather than using `isValidTheme`, which is a plain
|
|
65
73
|
// `name in themes` check and therefore also returns true for inherited Object
|
|
@@ -102,8 +110,10 @@ function parseThemeName(value: string | undefined | null): ThemeName | null {
|
|
|
102
110
|
/**
|
|
103
111
|
* A registry theme name, or `jam` for anything else. `config.theme` arrives
|
|
104
112
|
* from docs.json as an unvalidated string, so casting it straight to ThemeName
|
|
105
|
-
* would hand
|
|
106
|
-
*
|
|
113
|
+
* would hand `defaultTheme` a value that never lines up with a real chip —
|
|
114
|
+
* `ThemePreviewChips` uses it only to decide whether a preview is on
|
|
115
|
+
* (`activeTheme !== defaultTheme`), which shows Reset and the "Previewing"
|
|
116
|
+
* label.
|
|
107
117
|
*/
|
|
108
118
|
export function toThemeName(value: string | undefined | null): ThemeName {
|
|
109
119
|
return parseThemeName(value) ?? 'jam';
|
|
@@ -771,6 +771,15 @@ body[data-theme="jam"] [class*="fa-"]:not(.fa-brands) {
|
|
|
771
771
|
font-weight: 300 !important;
|
|
772
772
|
}
|
|
773
773
|
|
|
774
|
+
/* Except the theme toggles: their 12-14px icons are hairlines at light weight
|
|
775
|
+
and nearly vanish on the pale pill. A thin text stroke thickens the glyph
|
|
776
|
+
instead of switching weight: fa-regular is a separate ~333 KB webfont that
|
|
777
|
+
jam pages otherwise never load, and font-display:block would hold the icons
|
|
778
|
+
blank until it arrived. */
|
|
779
|
+
body[data-theme="jam"] :is([data-theme-toggle], [data-theme-toggle-cycle]) [class*="fa-"] {
|
|
780
|
+
-webkit-text-stroke: 0.3px currentColor;
|
|
781
|
+
}
|
|
782
|
+
|
|
774
783
|
/* ===== JAM THEME API PARAMETER STYLING ===== */
|
|
775
784
|
/* Scoped to jam theme */
|
|
776
785
|
|
|
@@ -245,25 +245,30 @@ body[data-theme="nebula"] .sidebar-tabs {
|
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
/*
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
body[data-theme="nebula"] > div > header::after {
|
|
248
|
+
/* Header divider. Targets the nav header by its data-has-tabs attribute, not a
|
|
249
|
+
child-combinator chain from <body>: the old `body > div > header` form broke
|
|
250
|
+
silently when LayoutWrapper nested the header three levels down, and Nebula
|
|
251
|
+
shipped with no divider (nebula-header-divider.test.tsx). The header is
|
|
252
|
+
sticky, which already anchors ::after, so it needs no position of its own.
|
|
253
|
+
The -1rem / -1.5rem insets span the layout column's `px-4 lg:px-6`: the line
|
|
254
|
+
runs edge to edge up to --layout-max-width without lifting the column's
|
|
255
|
+
lg:overflow-hidden, which the desktop wheel-chaining fix relies on. */
|
|
256
|
+
body[data-theme="nebula"] header[data-has-tabs]::after {
|
|
259
257
|
content: '';
|
|
260
258
|
position: absolute;
|
|
259
|
+
left: -1rem;
|
|
260
|
+
right: -1rem;
|
|
261
261
|
bottom: 0;
|
|
262
|
-
left: 50%;
|
|
263
|
-
transform: translateX(-50%);
|
|
264
|
-
width: 100vw;
|
|
265
262
|
height: 0.5px;
|
|
266
263
|
background-color: var(--color-border);
|
|
264
|
+
pointer-events: none;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
@media (min-width: 1024px) {
|
|
268
|
+
body[data-theme="nebula"] header[data-has-tabs]::after {
|
|
269
|
+
left: -1.5rem;
|
|
270
|
+
right: -1.5rem;
|
|
271
|
+
}
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
/* Add right padding to code panels sidebar on API pages */
|
|
@@ -612,6 +612,14 @@ aside {
|
|
|
612
612
|
font-weight: 300 !important;
|
|
613
613
|
}
|
|
614
614
|
|
|
615
|
+
/* Except the theme toggles: the sidebar toggle's icons shrink to 8px on
|
|
616
|
+
desktop, where light weight turns them to hairlines. A thin text stroke
|
|
617
|
+
thickens the glyph instead of switching weight: fa-regular is a separate
|
|
618
|
+
~333 KB webfont that pulsar pages otherwise never load. */
|
|
619
|
+
:is([data-theme-toggle], [data-theme-toggle-cycle]) [class*="fa-"] {
|
|
620
|
+
-webkit-text-stroke: 0.3px currentColor;
|
|
621
|
+
}
|
|
622
|
+
|
|
615
623
|
/* ===== PULSAR THEME API PARAMETER STYLING ===== */
|
|
616
624
|
|
|
617
625
|
/*
|
|
@@ -1011,8 +1019,9 @@ body[data-theme="pulsar"] header [data-theme-toggle] {
|
|
|
1011
1019
|
background-color: var(--color-bg-primary) !important;
|
|
1012
1020
|
}
|
|
1013
1021
|
|
|
1014
|
-
/* Ensure content area starts at top with no gap
|
|
1015
|
-
|
|
1022
|
+
/* Ensure content area starts at top with no gap. :not() spares the
|
|
1023
|
+
sr-only agent directive, which is also a body > div. */
|
|
1024
|
+
body[data-theme="pulsar"] > div:not([data-jd-agent-directive]) {
|
|
1016
1025
|
min-height: 100vh;
|
|
1017
1026
|
min-height: 100dvh; /* Dynamic viewport height for mobile browsers */
|
|
1018
1027
|
}
|
|
@@ -3182,9 +3182,9 @@
|
|
|
3182
3182
|
"license": "MIT"
|
|
3183
3183
|
},
|
|
3184
3184
|
"node_modules/electron-to-chromium": {
|
|
3185
|
-
"version": "1.5.
|
|
3186
|
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.
|
|
3187
|
-
"integrity": "sha512-
|
|
3185
|
+
"version": "1.5.435",
|
|
3186
|
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.435.tgz",
|
|
3187
|
+
"integrity": "sha512-hwZNgb6JmRlmQX/L0yojyu6upuvtR7iGS1hB/9nc7I9vCsvekahqh3noFeXUBRirv9+Hk7E6v/LFz4CW6FvpWA==",
|
|
3188
3188
|
"license": "ISC"
|
|
3189
3189
|
},
|
|
3190
3190
|
"node_modules/elkjs": {
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { useOnClickOutside } from '@/hooks/useOnClickOutside';
|
|
5
|
-
import { useLinkPrefix } from '@/lib/link-prefix-context';
|
|
6
|
-
import { useThemePreview } from '@/lib/theme-preview-context';
|
|
7
|
-
import { THEME_PREVIEW_COOKIE } from '@/lib/theme-preview';
|
|
8
|
-
import { getAllThemes, type ThemeName } from '@/themes';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Jamdesk-only affordance: re-skins jamdesk.com/docs with any built-in theme so
|
|
12
|
-
* prospects can see all four on a real docs site.
|
|
13
|
-
*
|
|
14
|
-
* The gate is server-side (lib/theme-preview.ts decides whether the provider is
|
|
15
|
-
* enabled); this component ALSO self-guards on `enabled` so a mistake in
|
|
16
|
-
* Header's conditional can never leak it onto a customer site.
|
|
17
|
-
*
|
|
18
|
-
* Strings are English-only by design. jamdesk-docs has fr/es locales, but the
|
|
19
|
-
* only prose here is "Reset to default" and "Default" — everything else is a
|
|
20
|
-
* proper noun — and adding entries to lib/ui-strings.ts for a sales affordance
|
|
21
|
-
* isn't worth the churn across every locale.
|
|
22
|
-
*/
|
|
23
|
-
export function ThemePreviewPicker() {
|
|
24
|
-
const { enabled, activeTheme, defaultTheme } = useThemePreview();
|
|
25
|
-
const linkPrefix = useLinkPrefix();
|
|
26
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
27
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
28
|
-
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
29
|
-
const listRef = useRef<HTMLUListElement>(null);
|
|
30
|
-
|
|
31
|
-
// Every close path but a theme selection runs through here. A click-outside
|
|
32
|
-
// would otherwise unmount the focused option and drop focus to <body>, so
|
|
33
|
-
// the visitor's next Tab restarts at the top of the document. Synchronous on
|
|
34
|
-
// purpose: this runs during the mousedown dispatch, so a click that lands on
|
|
35
|
-
// something focusable still ends up there — the browser's own focus default
|
|
36
|
-
// wins afterwards, which is what it should do.
|
|
37
|
-
function closeAndRestoreFocus() {
|
|
38
|
-
const hadFocus = !!containerRef.current?.contains(document.activeElement);
|
|
39
|
-
setIsOpen(false);
|
|
40
|
-
if (hadFocus) buttonRef.current?.focus();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
useOnClickOutside(containerRef, closeAndRestoreFocus, isOpen);
|
|
44
|
-
|
|
45
|
-
// Move focus onto the active option when the menu opens. Without this the
|
|
46
|
-
// trigger keeps focus and Tab is the only way forward — and an earlier cut of
|
|
47
|
-
// this component closed the menu on Tab (copied from LanguageSelector, where
|
|
48
|
-
// that is safe only because ArrowUp/Down have already moved focus into the
|
|
49
|
-
// list), which left the widget keyboard-inoperable: WCAG 2.1.1.
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (!isOpen) return;
|
|
52
|
-
const options = listRef.current?.querySelectorAll<HTMLElement>('[role="option"]');
|
|
53
|
-
if (!options?.length) return;
|
|
54
|
-
const active = Array.from(options).find((o) => o.getAttribute('aria-selected') === 'true');
|
|
55
|
-
(active ?? options[0]).focus();
|
|
56
|
-
}, [isOpen]);
|
|
57
|
-
|
|
58
|
-
if (!enabled) return null;
|
|
59
|
-
|
|
60
|
-
// Escape only. Arrow-key roving focus is deliberately NOT copied from
|
|
61
|
-
// LanguageSelector: its options are a customer-configurable list, whereas
|
|
62
|
-
// this is a fixed four-row Jamdesk-only affordance whose rows are ordinary
|
|
63
|
-
// buttons that Tab already walks. Escape must stay — it is the way back out
|
|
64
|
-
// of a menu focus has just been moved into.
|
|
65
|
-
function handleKeyDown(e: React.KeyboardEvent) {
|
|
66
|
-
if (e.key === 'Escape') closeAndRestoreFocus();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Tabbing past the last row leaves the widget; close behind it. This is what
|
|
70
|
-
// LanguageSelector's Tab branch achieved, without eating the Tab that is this
|
|
71
|
-
// component's only way INTO the option list.
|
|
72
|
-
function handleFocusOut(e: React.FocusEvent) {
|
|
73
|
-
// A null relatedTarget means focus landed on <body>, NOT that focus left
|
|
74
|
-
// the widget — and since the menu always opens with focus inside itself,
|
|
75
|
-
// that blur comes from inside. Safari and Firefox-on-macOS produce it on
|
|
76
|
-
// every mousedown over a <button>; Chrome produces it for a mousedown on
|
|
77
|
-
// this panel's own padding or its divider band. Closing there unmounts the
|
|
78
|
-
// row before its click can land, so no theme is ever applied. Do not
|
|
79
|
-
// "simplify" this branch away: genuine outside-pointer closes are
|
|
80
|
-
// useOnClickOutside's job, and Escape and Tab both supply a real
|
|
81
|
-
// relatedTarget. The only thing given up is close-on-window-blur.
|
|
82
|
-
if (!(e.relatedTarget instanceof Element)) return;
|
|
83
|
-
if (!e.currentTarget.contains(e.relatedTarget)) setIsOpen(false);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// `null` clears the cookie. Path mirrors the docs prefix so the cookie is
|
|
87
|
-
// scoped to /docs on jamdesk.com and to / on jamdesk-docs.jamdesk.app.
|
|
88
|
-
function applyTheme(name: ThemeName | null) {
|
|
89
|
-
const path = linkPrefix || '/';
|
|
90
|
-
// SESSION cookie on the set path — no Max-Age, so the preview dies with the
|
|
91
|
-
// browser. The picker is desktop-only (`hidden lg:block`), so a persisted
|
|
92
|
-
// preview would follow a visitor to mobile with no affordance to reset it.
|
|
93
|
-
// The CLEAR path is the opposite and must stay explicit: `Max-Age=0` is
|
|
94
|
-
// what expires an existing cookie, and omitting it there would leave the
|
|
95
|
-
// preview in place.
|
|
96
|
-
const expiry = name === null ? '; Max-Age=0' : '';
|
|
97
|
-
// `Secure` means the browser silently DROPS this cookie over plain http, so
|
|
98
|
-
// the picker looks inert when QA'd on http://localhost — use https or a
|
|
99
|
-
// deployed host.
|
|
100
|
-
document.cookie =
|
|
101
|
-
`${THEME_PREVIEW_COOKIE}=${name ?? ''}; Path=${path}${expiry}; SameSite=Lax; Secure`;
|
|
102
|
-
// Close first: the reload is not instant, and an open menu left showing the
|
|
103
|
-
// previous selection reads as a dead click.
|
|
104
|
-
setIsOpen(false);
|
|
105
|
-
// Full reload — the theme is applied by the server render (CSS variables,
|
|
106
|
-
// font class and layout variant all key off config.theme), so there is no
|
|
107
|
-
// client-side state to update.
|
|
108
|
-
window.location.reload();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const allThemes = getAllThemes();
|
|
112
|
-
const activeDisplayName = allThemes.find((t) => t.name === activeTheme)?.displayName ?? '';
|
|
113
|
-
|
|
114
|
-
return (
|
|
115
|
-
<div
|
|
116
|
-
ref={containerRef}
|
|
117
|
-
className="relative hidden lg:block"
|
|
118
|
-
onKeyDown={handleKeyDown}
|
|
119
|
-
onBlur={handleFocusOut}
|
|
120
|
-
>
|
|
121
|
-
<button
|
|
122
|
-
ref={buttonRef}
|
|
123
|
-
onClick={() => {
|
|
124
|
-
setIsOpen(!isOpen);
|
|
125
|
-
// Closing unmounts the focused option. Safari does not focus a
|
|
126
|
-
// button on mousedown, so without this focus would land on <body>.
|
|
127
|
-
// Mirrors Prompt.tsx's trigger.
|
|
128
|
-
if (isOpen) buttonRef.current?.focus();
|
|
129
|
-
}}
|
|
130
|
-
aria-expanded={isOpen}
|
|
131
|
-
aria-haspopup="listbox"
|
|
132
|
-
aria-label={`Preview a theme: ${activeDisplayName}`}
|
|
133
|
-
className="flex items-center gap-2 rounded-lg px-2 py-1.5 cursor-pointer transition-colors text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-tertiary)]"
|
|
134
|
-
>
|
|
135
|
-
<i
|
|
136
|
-
className="fa-solid fa-palette text-[12px] text-[var(--color-text-tertiary)]"
|
|
137
|
-
aria-hidden="true"
|
|
138
|
-
/>
|
|
139
|
-
<i
|
|
140
|
-
className={`fa-solid fa-chevron-down text-[10px] text-[var(--color-text-tertiary)] transition-transform ${isOpen ? 'rotate-180' : ''}`}
|
|
141
|
-
aria-hidden="true"
|
|
142
|
-
/>
|
|
143
|
-
</button>
|
|
144
|
-
|
|
145
|
-
{isOpen && (
|
|
146
|
-
<div
|
|
147
|
-
className="absolute right-0 top-full mt-1 z-50 min-w-[190px] py-1 bg-[var(--color-bg-primary)] border border-[var(--color-border)] rounded-lg"
|
|
148
|
-
style={{ boxShadow: 'var(--shadow-lg)' }}
|
|
149
|
-
>
|
|
150
|
-
<ul ref={listRef} role="listbox" aria-label="Preview a theme">
|
|
151
|
-
{allThemes.map((theme) => {
|
|
152
|
-
const isActive = theme.name === activeTheme;
|
|
153
|
-
return (
|
|
154
|
-
<li key={theme.name}>
|
|
155
|
-
<button
|
|
156
|
-
role="option"
|
|
157
|
-
aria-selected={isActive}
|
|
158
|
-
onClick={() => applyTheme(theme.name as ThemeName)}
|
|
159
|
-
className="w-full flex items-center justify-between gap-3 px-3 py-2 text-left text-sm cursor-pointer text-[var(--color-text-primary)] hover:bg-[var(--color-bg-tertiary)]"
|
|
160
|
-
>
|
|
161
|
-
<span>{theme.displayName}</span>
|
|
162
|
-
<span className="flex items-center gap-2">
|
|
163
|
-
{theme.name === defaultTheme && (
|
|
164
|
-
<span className="text-xs text-[var(--color-text-tertiary)]">Default</span>
|
|
165
|
-
)}
|
|
166
|
-
{isActive && (
|
|
167
|
-
<i
|
|
168
|
-
className="fa-solid fa-check text-[11px] text-[var(--color-accent)]"
|
|
169
|
-
aria-hidden="true"
|
|
170
|
-
/>
|
|
171
|
-
)}
|
|
172
|
-
</span>
|
|
173
|
-
</button>
|
|
174
|
-
</li>
|
|
175
|
-
);
|
|
176
|
-
})}
|
|
177
|
-
</ul>
|
|
178
|
-
|
|
179
|
-
{/* Outside the <ul>: a `role="listbox"` may only own `option` and
|
|
180
|
-
`group` children, and a reset action is neither. Nesting it as a
|
|
181
|
-
bare <li><button> would put a `listitem` inside a listbox, which
|
|
182
|
-
screen readers drop or mis-announce. LanguageSelector — the
|
|
183
|
-
pattern this component mirrors — has no extra row, so there is no
|
|
184
|
-
existing precedent to copy here. */}
|
|
185
|
-
<div className="mt-1 pt-1 border-t border-[var(--color-border)]">
|
|
186
|
-
<button
|
|
187
|
-
onClick={() => applyTheme(null)}
|
|
188
|
-
className="w-full px-3 py-2 text-left text-sm cursor-pointer text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-tertiary)]"
|
|
189
|
-
>
|
|
190
|
-
Reset to default
|
|
191
|
-
</button>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
)}
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
197
|
-
}
|