@adea-ai/ui 0.97.1 → 0.97.3

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 (37) hide show
  1. package/dist/components/composites/about-dialog/about-dialog.d.ts.map +1 -1
  2. package/dist/components/composites/about-dialog/about-dialog.js +2 -1
  3. package/dist/components/composites/about-dialog/about-dialog.js.map +1 -1
  4. package/dist/components/composites/account-menu/account-menu.d.ts.map +1 -1
  5. package/dist/components/composites/account-menu/account-menu.js +95 -99
  6. package/dist/components/composites/account-menu/account-menu.js.map +1 -1
  7. package/dist/components/composites/appearance-editor/appearance-choices.d.ts.map +1 -1
  8. package/dist/components/composites/appearance-editor/appearance-choices.js +44 -42
  9. package/dist/components/composites/appearance-editor/appearance-choices.js.map +1 -1
  10. package/dist/components/composites/appearance-editor/appearance-editor.d.ts.map +1 -1
  11. package/dist/components/composites/appearance-editor/appearance-editor.js +23 -1
  12. package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
  13. package/dist/components/composites/appearance-editor/appearance-rows.d.ts +22 -5
  14. package/dist/components/composites/appearance-editor/appearance-rows.d.ts.map +1 -1
  15. package/dist/components/composites/appearance-editor/appearance-rows.js +249 -152
  16. package/dist/components/composites/appearance-editor/appearance-rows.js.map +1 -1
  17. package/dist/components/composites/appearance-editor/appearance-types.d.ts +7 -0
  18. package/dist/components/composites/appearance-editor/appearance-types.d.ts.map +1 -1
  19. package/dist/components/composites/appearance-editor/theme-preview.d.ts +10 -0
  20. package/dist/components/composites/appearance-editor/theme-preview.d.ts.map +1 -1
  21. package/dist/components/composites/appearance-editor/theme-preview.js +61 -12
  22. package/dist/components/composites/appearance-editor/theme-preview.js.map +1 -1
  23. package/dist/r/src/components/composites/about-dialog/about-dialog.tsx +6 -1
  24. package/dist/r/src/components/composites/account-menu/account-menu.tsx +2 -1
  25. package/dist/r/src/components/composites/appearance-editor/appearance-choices.tsx +19 -14
  26. package/dist/r/src/components/composites/appearance-editor/appearance-editor.tsx +13 -1
  27. package/dist/r/src/components/composites/appearance-editor/appearance-rows.tsx +270 -160
  28. package/dist/r/src/components/composites/appearance-editor/appearance-types.ts +7 -0
  29. package/dist/r/src/components/composites/appearance-editor/theme-preview.tsx +58 -0
  30. package/package.json +1 -1
  31. package/src/components/composites/about-dialog/about-dialog.tsx +6 -1
  32. package/src/components/composites/account-menu/account-menu.tsx +2 -1
  33. package/src/components/composites/appearance-editor/appearance-choices.tsx +19 -14
  34. package/src/components/composites/appearance-editor/appearance-editor.tsx +13 -1
  35. package/src/components/composites/appearance-editor/appearance-rows.tsx +270 -160
  36. package/src/components/composites/appearance-editor/appearance-types.ts +7 -0
  37. package/src/components/composites/appearance-editor/theme-preview.tsx +58 -0
@@ -1 +1 @@
1
- {"version":3,"file":"appearance-rows.js","names":["AdeaTheme","AdeaThemeRecord","For","Show","createMemo","createSignal","onCleanup","JSX","ChevronDown","Palette","cn","Button","DropdownMenu","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuTrigger","PalettePreview","POINTER_FOCUS_TARGET_SELECTOR","isTabStop","element","HTMLElement","tabIndex","matches","hasAttribute","getAttribute","closest","getClientRects","length","SettingsRow","props","title","icon","Element","description","stacked","children","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$7","_$insert","_$createComponent","when","_el$6","_tmpl$","_$effect","_p$","_v$","_v$2","e","_$className","t","undefined","ThemeRow","appearance","selectedId","preview","themes","disabled","onSelect","id","portalMount","setPortalMount","HTMLDivElement","triggerElement","setTriggerElement","HTMLButtonElement","menuOpen","setMenuOpen","focusOutsideTarget","setFocusOutsideTarget","restoreTriggerFocus","setRestoreTriggerFocus","focusTargetAfterTab","focusLifecycleVersion","options","filter","theme","selected","find","label","closeMenu","moveFocusOnTab","event","KeyboardEvent","key","isComposing","trigger","parentDialog","focusScope","ownerDocument","body","focusStops","Array","from","querySelectorAll","orderedFocusStops","toSorted","a","b","triggerIndex","indexOf","direction","shiftKey","adjacent","at","stopPropagation","preventDefault","focus","preventScroll","_el$8","_tmpl$4","_$use","modal","open","onOpenChange","ref","as","variant","size","aria-label","_el$9","_tmpl$3","_el$0","name","onInteractOutside","detail","originalEvent","type","target","contains","focusTarget","onFocusOutside","onEscapeKeyDown","onCloseAutoFocus","lifecycleVersion","shouldRestore","isConnected","queueMicrotask","activeElement","document","isMenuFocus","isTriggerFocus","value","onChange","each","textValue","closeOnSelect","_el$1","_tmpl$5","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/appearance-rows.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n// Retains the compact divided row and palette-preview selector from the pinned\n// Zeron/Adea composition; Kobalte owns option navigation and nested dismissal.\nimport type { AdeaTheme, AdeaThemeRecord } from '@adea-ai/themes'\nimport { For, Show, createMemo, createSignal, onCleanup, type JSX } from 'solid-js'\nimport { ChevronDown, Palette } from 'lucide-solid'\nimport { cn } from '#lib/utils'\nimport { Button } from '../../ui/button/button'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from '../../ui/dropdown-menu/dropdown-menu'\nimport { PalettePreview } from './theme-preview'\n\nconst POINTER_FOCUS_TARGET_SELECTOR =\n 'a[href], area[href], button, input, select, textarea, iframe, [tabindex], [contenteditable], details > summary:first-of-type'\n\nfunction isTabStop(element: HTMLElement) {\n return (\n (element.tabIndex >= 0 ||\n (element.matches('details > summary:first-of-type') && !element.hasAttribute('tabindex'))) &&\n !element.matches(':disabled') &&\n element.getAttribute('aria-disabled') !== 'true' &&\n element.closest('[hidden], [inert], [aria-hidden=\"true\"]') === null &&\n element.getClientRects().length > 0\n )\n}\n\nexport function SettingsRow(props: {\n title: string\n icon: JSX.Element\n description?: JSX.Element\n stacked?: boolean\n children: JSX.Element\n}) {\n return (\n <section\n class={cn('flex gap-3 px-4 py-4', {\n 'flex-col': props.stacked,\n 'flex-wrap items-center': !props.stacked,\n })}\n >\n {/* Reserve readable copy before choosing a side-by-side control row.\n Wrapping follows the actual host width and enlarged text, rather\n than a viewport breakpoint that also matches a narrow popover. */}\n <div class={cn('flex min-w-0 flex-1 items-center gap-3', { 'basis-48': !props.stacked })}>\n <span\n class=\"flex size-9 shrink-0 items-center justify-center rounded-lg border bg-foreground/5 text-muted-foreground [&_svg]:size-4\"\n aria-hidden=\"true\"\n >\n {props.icon}\n </span>\n <div class=\"min-w-0\">\n <h3 class=\"text-sm font-medium\">{props.title}</h3>\n <Show when={props.description}>\n <div class=\"mt-0.5 text-xs text-muted-foreground\">{props.description}</div>\n </Show>\n </div>\n </div>\n <div class=\"min-w-0 max-w-full shrink-0\">{props.children}</div>\n </section>\n )\n}\n\n/**\n * A compact persistent theme choice. Kobalte handles menu navigation and\n * dismissal; this row moves Tab to the adjacent browser-reported stop because\n * menus consume Tab by default. Enumerating elements and checking their native\n * tabIndex keeps details summaries in the order while preserving explicit\n * tabindex overrides.\n */\nexport function ThemeRow(props: {\n appearance: 'light' | 'dark'\n selectedId: string\n preview: AdeaTheme\n themes: readonly AdeaThemeRecord[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const [portalMount, setPortalMount] = createSignal<HTMLDivElement>()\n const [triggerElement, setTriggerElement] = createSignal<HTMLButtonElement>()\n const [menuOpen, setMenuOpen] = createSignal(false)\n const [focusOutsideTarget, setFocusOutsideTarget] = createSignal<HTMLElement>()\n const [restoreTriggerFocus, setRestoreTriggerFocus] = createSignal(false)\n let focusTargetAfterTab: HTMLElement | undefined\n let focusLifecycleVersion = 0\n onCleanup(() => {\n focusLifecycleVersion += 1\n })\n const options = createMemo(() =>\n props.themes.filter((theme) => theme.appearance === props.appearance)\n )\n const selected = createMemo(\n () =>\n options().find((theme) => theme.id === props.selectedId) ??\n options().find((theme) => theme.id === props.preview.id)\n )\n const label = () => (props.appearance === 'light' ? 'Light theme' : 'Dark theme')\n const closeMenu = () => {\n if (menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(false)\n }\n const moveFocusOnTab = (event: KeyboardEvent) => {\n if (event.key !== 'Tab' || event.isComposing) return\n\n const trigger = triggerElement()\n if (!trigger) return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (!focusScope) return\n\n const focusStops = Array.from(focusScope.querySelectorAll<HTMLElement>('*')).filter(\n (element) =>\n isTabStop(element) &&\n element.closest('[role=\"menu\"], [hidden], [inert], [aria-hidden=\"true\"]') === null\n )\n const orderedFocusStops = [\n ...focusStops\n .filter((element) => element.tabIndex > 0)\n .toSorted((a, b) => a.tabIndex - b.tabIndex),\n ...focusStops.filter((element) => element.tabIndex <= 0),\n ]\n const triggerIndex = orderedFocusStops.indexOf(trigger)\n const direction = event.shiftKey ? -1 : 1\n const adjacent =\n orderedFocusStops[triggerIndex + direction] ??\n (parentDialog ? (direction > 0 ? orderedFocusStops[0] : orderedFocusStops.at(-1)) : undefined)\n\n event.stopPropagation()\n setRestoreTriggerFocus(false)\n if (adjacent) {\n event.preventDefault()\n focusTargetAfterTab = adjacent\n setFocusOutsideTarget(adjacent)\n closeMenu()\n adjacent.focus({ preventScroll: true })\n } else {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n closeMenu()\n }\n }\n return (\n <SettingsRow title={label()} icon={<Palette />}>\n <div ref={setPortalMount}>\n <DropdownMenu\n modal={false}\n open={menuOpen()}\n onOpenChange={(open) => {\n if (open !== menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(open)\n if (open) {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n }\n }}\n >\n <DropdownMenuTrigger\n ref={setTriggerElement}\n as={Button}\n variant=\"outline\"\n size=\"sm\"\n aria-label={label()}\n disabled={props.disabled || options().length === 0}\n class=\"w-full justify-between sm:w-52\"\n >\n <span class=\"flex min-w-0 flex-1 items-center gap-2\">\n <PalettePreview theme={props.preview} />\n <span class=\"min-w-0 flex-1 truncate\">{selected()?.name ?? props.preview.name}</span>\n </span>\n <ChevronDown aria-hidden=\"true\" class=\"shrink-0 text-muted-foreground\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n portalMount={portalMount()}\n class=\"max-h-(--kb-popper-content-available-height) w-(--kb-popper-anchor-width) min-w-32 overflow-x-hidden overflow-y-auto\"\n onInteractOutside={(event) => {\n if (event.detail.originalEvent.type !== 'pointerdown') return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (!(target instanceof Element) || !focusScope?.contains(target)) return\n\n const focusTarget = target.closest<HTMLElement>(POINTER_FOCUS_TARGET_SELECTOR)\n if (focusTarget && isTabStop(focusTarget)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(focusTarget)\n } else {\n setRestoreTriggerFocus(true)\n }\n }}\n onFocusOutside={(event) => {\n // The containing dialog or document body can briefly reclaim\n // focus when the menu opens. Keep that handoff from dismissing\n // it; focus moving to another descendant still closes the menu.\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (target === focusScope) {\n event.preventDefault()\n } else if (target instanceof HTMLElement && focusScope?.contains(target)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(target)\n }\n }}\n onEscapeKeyDown={() => setRestoreTriggerFocus(true)}\n onCloseAutoFocus={(event) => {\n // A prior menu instance can finish its focus cleanup after this\n // row has already reopened. Do not let that cleanup steal focus.\n if (menuOpen()) {\n event.preventDefault()\n return\n }\n\n const lifecycleVersion = focusLifecycleVersion\n const shouldRestore = restoreTriggerFocus()\n const focusTarget = focusTargetAfterTab ?? focusOutsideTarget()\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n if (shouldRestore) {\n // The saved focus may be the containing dialog rather than\n // the trigger when WebKit opens this menu from a pointer click.\n event.preventDefault()\n triggerElement()?.focus({ preventScroll: true })\n return\n }\n\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (focusTarget?.isConnected && focusScope?.contains(focusTarget)) {\n // Preserve the intended in-scope destination across\n // Kobalte's deferred stale-focus restore.\n event.preventDefault()\n queueMicrotask(() => {\n if (lifecycleVersion !== focusLifecycleVersion || menuOpen()) return\n\n const activeElement = document.activeElement\n const isMenuFocus =\n activeElement instanceof HTMLElement &&\n activeElement.closest('[role=\"menu\"]') !== null\n const isTriggerFocus = activeElement === triggerElement()\n if (\n activeElement !== focusTarget &&\n (activeElement === document.body ||\n activeElement === focusScope ||\n isMenuFocus ||\n isTriggerFocus)\n ) {\n focusTarget.focus({ preventScroll: true })\n }\n })\n return\n }\n\n const activeElement = document.activeElement\n if (\n focusScope &&\n activeElement instanceof HTMLElement &&\n activeElement !== focusScope &&\n focusScope.contains(activeElement) &&\n activeElement.closest('[role=\"menu\"]') === null\n ) {\n // Preserve a real focus target in this scope instead of\n // restoring the stale element captured when the menu mounted. A\n // focused menu item is about to unmount, so Kobalte must restore\n // focus to the trigger instead.\n event.preventDefault()\n }\n }}\n >\n <DropdownMenuRadioGroup\n value={selected()?.id ?? ''}\n aria-label={`${label()} options`}\n on:keydown={moveFocusOnTab}\n onChange={(id) => {\n if (!props.disabled && typeof id === 'string') props.onSelect(id)\n }}\n >\n <For each={options()}>\n {(theme) => (\n <DropdownMenuRadioItem\n value={theme.id}\n textValue={theme.name}\n closeOnSelect={true}\n disabled={props.disabled}\n onSelect={() => setRestoreTriggerFocus(true)}\n >\n <PalettePreview theme={theme} />\n <span class=\"min-w-0 flex-1 truncate\">{theme.name}</span>\n </DropdownMenuRadioItem>\n )}\n </For>\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </SettingsRow>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"appearance-rows.js","names":["AdeaTheme","AdeaThemeRecord","For","Show","createMemo","createSignal","onCleanup","JSX","ChevronDown","Palette","SquareTerminal","cn","Button","DropdownMenu","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuTrigger","PalettePreview","ThemeMenuPreview","POINTER_FOCUS_TARGET_SELECTOR","isTabStop","element","HTMLElement","tabIndex","matches","hasAttribute","getAttribute","closest","getClientRects","length","SettingsRow","props","title","icon","Element","description","stacked","children","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$7","_$insert","_$createComponent","when","_el$6","_tmpl$","_$effect","_p$","_v$","_v$2","e","_$className","t","undefined","ThemeOption","id","name","preview","ThemeSelectMenu","label","selectedId","triggerPreview","options","disabled","onSelect","portalMount","setPortalMount","HTMLDivElement","triggerElement","setTriggerElement","HTMLButtonElement","menuOpen","setMenuOpen","focusOutsideTarget","setFocusOutsideTarget","restoreTriggerFocus","setRestoreTriggerFocus","focusTargetAfterTab","focusLifecycleVersion","selected","find","option","closeMenu","moveFocusOnTab","event","KeyboardEvent","key","isComposing","trigger","parentDialog","focusScope","ownerDocument","body","focusStops","Array","from","querySelectorAll","filter","orderedFocusStops","toSorted","a","b","triggerIndex","indexOf","direction","shiftKey","adjacent","at","stopPropagation","preventDefault","focus","preventScroll","_el$8","_tmpl$4","_$use","modal","open","onOpenChange","ref","as","variant","size","aria-label","_el$9","_tmpl$3","_el$0","theme","onInteractOutside","detail","originalEvent","type","target","contains","focusTarget","onFocusOutside","onEscapeKeyDown","onCloseAutoFocus","lifecycleVersion","shouldRestore","isConnected","queueMicrotask","activeElement","document","isMenuFocus","isTriggerFocus","value","onChange","each","textValue","closeOnSelect","_el$1","_tmpl$6","_el$10","_el$11","_tmpl$5","ThemeRow","appearance","themes","map","TerminalRow","selectedOption","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/appearance-rows.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n// Retains the compact divided row and palette-preview selector from the pinned\n// Zeron/Adea composition; Kobalte owns option navigation and nested dismissal.\n// One shared menu serves the light, dark, and terminal rows: each option is a\n// compact theme preview with its name and one-line description beside it, and\n// the menu sizes to that content instead of clipping it at the trigger width.\nimport type { AdeaTheme, AdeaThemeRecord } from '@adea-ai/themes'\nimport { For, Show, createMemo, createSignal, onCleanup, type JSX } from 'solid-js'\nimport { ChevronDown, Palette, SquareTerminal } from 'lucide-solid'\nimport { cn } from '#lib/utils'\nimport { Button } from '../../ui/button/button'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from '../../ui/dropdown-menu/dropdown-menu'\nimport { PalettePreview, ThemeMenuPreview } from './theme-preview'\n\nconst POINTER_FOCUS_TARGET_SELECTOR =\n 'a[href], area[href], button, input, select, textarea, iframe, [tabindex], [contenteditable], details > summary:first-of-type'\n\nfunction isTabStop(element: HTMLElement) {\n return (\n (element.tabIndex >= 0 ||\n (element.matches('details > summary:first-of-type') && !element.hasAttribute('tabindex'))) &&\n !element.matches(':disabled') &&\n element.getAttribute('aria-disabled') !== 'true' &&\n element.closest('[hidden], [inert], [aria-hidden=\"true\"]') === null &&\n element.getClientRects().length > 0\n )\n}\n\nexport function SettingsRow(props: {\n title: string\n icon: JSX.Element\n description?: JSX.Element\n stacked?: boolean\n children: JSX.Element\n}) {\n return (\n <section\n class={cn('flex gap-3 px-4 py-4', {\n 'flex-col': props.stacked,\n 'flex-wrap items-center': !props.stacked,\n })}\n >\n {/* Reserve readable copy before choosing a side-by-side control row.\n Wrapping follows the actual host width and enlarged text, rather\n than a viewport breakpoint that also matches a narrow popover. */}\n <div class={cn('flex min-w-0 flex-1 items-center gap-3', { 'basis-48': !props.stacked })}>\n <span\n class=\"flex size-9 shrink-0 items-center justify-center rounded-lg border bg-foreground/5 text-muted-foreground [&_svg]:size-4\"\n aria-hidden=\"true\"\n >\n {props.icon}\n </span>\n <div class=\"min-w-0\">\n <h3 class=\"text-sm font-medium\">{props.title}</h3>\n <Show when={props.description}>\n <div class=\"mt-0.5 text-xs text-muted-foreground\">{props.description}</div>\n </Show>\n </div>\n </div>\n <div class=\"min-w-0 max-w-full shrink-0\">{props.children}</div>\n </section>\n )\n}\n\n/** One selectable palette in a theme menu. */\nexport type ThemeOption = {\n id: string\n name: string\n description?: string\n preview: AdeaTheme\n}\n\n/**\n * The shared theme picker. Kobalte handles menu navigation and dismissal;\n * this component moves Tab to the adjacent browser-reported stop because\n * menus consume Tab by default. Enumerating elements and checking their native\n * tabIndex keeps details summaries in the order while preserving explicit\n * tabindex overrides. The menu width follows its content (bounded by the\n * popper's available width) so a long theme name and its description render\n * fully instead of truncating at the trigger's width.\n */\nfunction ThemeSelectMenu(props: {\n /** Row title; also the trigger's accessible name and the group's label. */\n label: string\n selectedId: string\n /** Palette shown on the trigger; hosts pass the accent-applied preview. */\n triggerPreview: AdeaTheme\n options: readonly ThemeOption[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const [portalMount, setPortalMount] = createSignal<HTMLDivElement>()\n const [triggerElement, setTriggerElement] = createSignal<HTMLButtonElement>()\n const [menuOpen, setMenuOpen] = createSignal(false)\n const [focusOutsideTarget, setFocusOutsideTarget] = createSignal<HTMLElement>()\n const [restoreTriggerFocus, setRestoreTriggerFocus] = createSignal(false)\n let focusTargetAfterTab: HTMLElement | undefined\n let focusLifecycleVersion = 0\n onCleanup(() => {\n focusLifecycleVersion += 1\n })\n const selected = createMemo(\n () =>\n props.options.find((option) => option.id === props.selectedId) ??\n props.options.find((option) => option.id === props.triggerPreview.id)\n )\n const closeMenu = () => {\n if (menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(false)\n }\n const moveFocusOnTab = (event: KeyboardEvent) => {\n if (event.key !== 'Tab' || event.isComposing) return\n\n const trigger = triggerElement()\n if (!trigger) return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (!focusScope) return\n\n const focusStops = Array.from(focusScope.querySelectorAll<HTMLElement>('*')).filter(\n (element) =>\n isTabStop(element) &&\n element.closest('[role=\"menu\"], [hidden], [inert], [aria-hidden=\"true\"]') === null\n )\n const orderedFocusStops = [\n ...focusStops\n .filter((element) => element.tabIndex > 0)\n .toSorted((a, b) => a.tabIndex - b.tabIndex),\n ...focusStops.filter((element) => element.tabIndex <= 0),\n ]\n const triggerIndex = orderedFocusStops.indexOf(trigger)\n const direction = event.shiftKey ? -1 : 1\n const adjacent =\n orderedFocusStops[triggerIndex + direction] ??\n (parentDialog ? (direction > 0 ? orderedFocusStops[0] : orderedFocusStops.at(-1)) : undefined)\n\n event.stopPropagation()\n setRestoreTriggerFocus(false)\n if (adjacent) {\n event.preventDefault()\n focusTargetAfterTab = adjacent\n setFocusOutsideTarget(adjacent)\n closeMenu()\n adjacent.focus({ preventScroll: true })\n } else {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n closeMenu()\n }\n }\n return (\n <div ref={setPortalMount}>\n <DropdownMenu\n modal={false}\n open={menuOpen()}\n onOpenChange={(open) => {\n if (open !== menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(open)\n if (open) {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n }\n }}\n >\n <DropdownMenuTrigger\n ref={setTriggerElement}\n as={Button}\n variant=\"outline\"\n size=\"sm\"\n aria-label={props.label}\n disabled={props.disabled || props.options.length === 0}\n class=\"w-full justify-between sm:w-52\"\n >\n <span class=\"flex min-w-0 flex-1 items-center gap-2\">\n <PalettePreview theme={props.triggerPreview} />\n <span class=\"min-w-0 flex-1 truncate\">\n {selected()?.name ?? props.triggerPreview.name}\n </span>\n </span>\n <ChevronDown aria-hidden=\"true\" class=\"shrink-0 text-muted-foreground\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n portalMount={portalMount()}\n // Sized to content (at least the trigger width, never wider than the\n // popper allows) so long theme names render in full with padding for\n // the selection indicator instead of truncating at the anchor width.\n class=\"max-h-(--kb-popper-content-available-height) w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto\"\n onInteractOutside={(event) => {\n if (event.detail.originalEvent.type !== 'pointerdown') return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (!(target instanceof Element) || !focusScope?.contains(target)) return\n\n const focusTarget = target.closest<HTMLElement>(POINTER_FOCUS_TARGET_SELECTOR)\n if (focusTarget && isTabStop(focusTarget)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(focusTarget)\n } else {\n setRestoreTriggerFocus(true)\n }\n }}\n onFocusOutside={(event) => {\n // The containing dialog or document body can briefly reclaim\n // focus when the menu opens. Keep that handoff from dismissing\n // it; focus moving to another descendant still closes the menu.\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (target === focusScope) {\n event.preventDefault()\n } else if (target instanceof HTMLElement && focusScope?.contains(target)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(target)\n }\n }}\n onEscapeKeyDown={() => setRestoreTriggerFocus(true)}\n onCloseAutoFocus={(event) => {\n // A prior menu instance can finish its focus cleanup after this\n // row has already reopened. Do not let that cleanup steal focus.\n if (menuOpen()) {\n event.preventDefault()\n return\n }\n\n const lifecycleVersion = focusLifecycleVersion\n const shouldRestore = restoreTriggerFocus()\n const focusTarget = focusTargetAfterTab ?? focusOutsideTarget()\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n if (shouldRestore) {\n // The saved focus may be the containing dialog rather than\n // the trigger when WebKit opens this menu from a pointer click.\n event.preventDefault()\n triggerElement()?.focus({ preventScroll: true })\n return\n }\n\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (focusTarget?.isConnected && focusScope?.contains(focusTarget)) {\n // Preserve the intended in-scope destination across\n // Kobalte's deferred stale-focus restore.\n event.preventDefault()\n queueMicrotask(() => {\n if (lifecycleVersion !== focusLifecycleVersion || menuOpen()) return\n\n const activeElement = document.activeElement\n const isMenuFocus =\n activeElement instanceof HTMLElement &&\n activeElement.closest('[role=\"menu\"]') !== null\n const isTriggerFocus = activeElement === triggerElement()\n if (\n activeElement !== focusTarget &&\n (activeElement === document.body ||\n activeElement === focusScope ||\n isMenuFocus ||\n isTriggerFocus)\n ) {\n focusTarget.focus({ preventScroll: true })\n }\n })\n return\n }\n\n const activeElement = document.activeElement\n if (\n focusScope &&\n activeElement instanceof HTMLElement &&\n activeElement !== focusScope &&\n focusScope.contains(activeElement) &&\n activeElement.closest('[role=\"menu\"]') === null\n ) {\n // Preserve a real focus target in this scope instead of\n // restoring the stale element captured when the menu mounted. A\n // focused menu item is about to unmount, so Kobalte must restore\n // focus to the trigger instead.\n event.preventDefault()\n }\n }}\n >\n <DropdownMenuRadioGroup\n value={selected()?.id ?? ''}\n aria-label={`${props.label} options`}\n on:keydown={moveFocusOnTab}\n onChange={(id) => {\n if (!props.disabled && typeof id === 'string') props.onSelect(id)\n }}\n >\n <For each={props.options}>\n {(option) => (\n <DropdownMenuRadioItem\n value={option.id}\n textValue={option.name}\n closeOnSelect={true}\n disabled={props.disabled}\n onSelect={() => setRestoreTriggerFocus(true)}\n >\n <ThemeMenuPreview theme={option.preview} />\n <span class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span class=\"truncate\">{option.name}</span>\n {/* Visual affordance only: the accessible name stays the\n theme name, which is what keyboard and test callers\n match on. */}\n <Show when={option.description}>\n <span\n aria-hidden=\"true\"\n class=\"line-clamp-2 max-w-44 text-2xs text-muted-foreground\"\n >\n {option.description}\n </span>\n </Show>\n </span>\n </DropdownMenuRadioItem>\n )}\n </For>\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n )\n}\n\n/**\n * A compact persistent theme choice for one appearance.\n */\nexport function ThemeRow(props: {\n appearance: 'light' | 'dark'\n selectedId: string\n preview: AdeaTheme\n themes: readonly AdeaThemeRecord[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const label = () => (props.appearance === 'light' ? 'Light theme' : 'Dark theme')\n const options = createMemo<ThemeOption[]>(() =>\n props.themes\n .filter((theme) => theme.appearance === props.appearance)\n .map((theme) => ({\n id: theme.id,\n name: theme.name,\n description: theme.description,\n preview: theme,\n }))\n )\n return (\n <SettingsRow title={label()} icon={<Palette />}>\n <ThemeSelectMenu\n label={label()}\n selectedId={props.selectedId}\n triggerPreview={props.preview}\n options={options()}\n disabled={props.disabled}\n onSelect={props.onSelect}\n />\n </SettingsRow>\n )\n}\n\n/**\n * A terminal palette choice independent of the light/dark rows. The first\n * option (`'theme'`) follows the interface theme, painted with the resolved\n * preview; every catalogue record follows, both appearances, because the\n * terminal paints one fixed ANSI palette rather than an appearance axis.\n */\nexport function TerminalRow(props: {\n selectedId: string\n /** Resolved interface theme: the `theme` option's palette and the fallback. */\n preview: AdeaTheme\n themes: readonly AdeaThemeRecord[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const options = createMemo<ThemeOption[]>(() => [\n {\n id: 'theme',\n name: 'UI theme',\n description: 'Uses the interface theme.',\n preview: props.preview,\n },\n ...props.themes.map((theme) => ({\n id: theme.id,\n name: theme.name,\n description: theme.description,\n preview: theme,\n })),\n ])\n const selectedOption = () => options().find((option) => option.id === props.selectedId)\n const description = () =>\n selectedOption() && selectedOption()?.id !== 'theme'\n ? `The terminal follows ${selectedOption()?.name}.`\n : 'The terminal follows the interface theme.'\n return (\n <SettingsRow title=\"Terminal\" icon={<SquareTerminal />} description={description()}>\n <ThemeSelectMenu\n label=\"Terminal\"\n selectedId={props.selectedId}\n triggerPreview={selectedOption()?.preview ?? props.preview}\n options={options()}\n disabled={props.disabled}\n onSelect={props.onSelect}\n />\n </SettingsRow>\n )\n}\n"],"mappings":"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"}
@@ -3,6 +3,13 @@ export type AppearanceDraft = Readonly<{
3
3
  mode: 'system' | 'light' | 'dark';
4
4
  lightThemeId: string;
5
5
  darkThemeId: string;
6
+ /**
7
+ * The terminal palette: `'theme'` follows the interface theme, a theme id
8
+ * pins that theme's terminal colours. Optional so a host without a terminal
9
+ * preference renders no terminal row — the row's presence is this field's
10
+ * presence, not a second prop that could disagree with the draft.
11
+ */
12
+ terminalThemeId?: string;
6
13
  /** Theme default, a canonical preset id, or the host's custom accent draft. */
7
14
  accent: string;
8
15
  surface: 'theme' | 'frosted' | 'opaque';
@@ -1 +1 @@
1
- {"version":3,"file":"appearance-types.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/appearance-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAE/E,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAA;IACvC,kBAAkB,EAAE,OAAO,CAAA;CAC5B,CAAC,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,eAAe,CAAA;IACtB,8EAA8E;IAC9E,UAAU,EAAE,SAAS,CAAA;IACrB,SAAS,EAAE,SAAS,CAAA;IACpB,kBAAkB,EAAE,OAAO,GAAG,MAAM,CAAA;IACpC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAA;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAA;IACnD,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1F,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,GAAG;IAC3D,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,IAAI,CAAA;CACtB,CAAA"}
1
+ {"version":3,"file":"appearance-types.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/appearance-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAE/E,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAA;IACvC,kBAAkB,EAAE,OAAO,CAAA;CAC5B,CAAC,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,eAAe,CAAA;IACtB,8EAA8E;IAC9E,UAAU,EAAE,SAAS,CAAA;IACrB,SAAS,EAAE,SAAS,CAAA;IACpB,kBAAkB,EAAE,OAAO,GAAG,MAAM,CAAA;IACpC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAA;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAA;IACnD,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1F,mFAAmF;IACnF,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,qBAAqB,GAAG;IAC3D,IAAI,EAAE,OAAO,CAAA;IACb,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,IAAI,CAAA;CACtB,CAAA"}
@@ -10,6 +10,16 @@ export declare function ThemeMiniatureSplit(props: {
10
10
  dark: AdeaTheme;
11
11
  class?: string;
12
12
  }): import("solid-js").JSX.Element;
13
+ /**
14
+ * The dropdown-item preview: the ThemePreview composition (rail + panel +
15
+ * text bars + action row) at menu scale, so a menu item carries the theme's
16
+ * actual chrome rather than the three-band trigger swatch. `aria-hidden` —
17
+ * the item's accessible name stays the theme name.
18
+ */
19
+ export declare function ThemeMenuPreview(props: {
20
+ theme: AdeaTheme;
21
+ class?: string;
22
+ }): import("solid-js").JSX.Element;
13
23
  export declare function PalettePreview(props: {
14
24
  theme: AdeaTheme;
15
25
  class?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"theme-preview.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/theme-preview.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAIhD,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAeD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,kCAoCxD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAW/F;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAoBzE"}
1
+ {"version":3,"file":"theme-preview.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/theme-preview.tsx"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAIhD,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,SAAS,CAAA;IAChB,OAAO,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAA;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAeD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,kCAoCxD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAW/F;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAkD3E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,kCAoBzE"}
@@ -5,8 +5,9 @@ import { For } from "solid-js";
5
5
  var _tmpl$ = /*#__PURE__*/ template(`<span class="h-[5px] rounded-[3px]">`);
6
6
  var _tmpl$2 = /*#__PURE__*/ template(`<span data-theme-miniature aria-hidden=true><span class="flex h-full w-11 shrink-0 flex-col gap-[7px] overflow-hidden px-2 pt-3.5"></span><span class="my-2 mr-2 flex min-w-0 flex-1 flex-col gap-[7px] overflow-hidden rounded-md border border-(--appearance-preview-border) p-2.5">`);
7
7
  var _tmpl$3 = /*#__PURE__*/ template(`<span aria-hidden=true><span class="h-full w-1/2 overflow-hidden"></span><span class="h-full w-1/2 overflow-hidden">`);
8
- var _tmpl$4 = /*#__PURE__*/ template(`<span aria-hidden=true>`);
9
- var _tmpl$5 = /*#__PURE__*/ template(`<span class="h-full w-1/3">`);
8
+ var _tmpl$4 = /*#__PURE__*/ template(`<span data-theme-menu-preview aria-hidden=true><span class="flex w-5 shrink-0 flex-col items-center gap-1.5 border-e border-(--appearance-preview-border) pt-2"><span class="size-1.5 rounded-[3px]"></span><span class="size-1.5 rounded-[3px]"></span><span class="size-1.5 rounded-[3px]"></span></span><span class="m-1 flex min-w-0 flex-1 flex-col gap-1 rounded-md border border-(--appearance-preview-border) p-1.5"><span class="h-1.5 w-8 rounded-full"></span><span class="h-1 w-full rounded-full"></span><span class="h-1 w-3/4 rounded-full"></span><span class="mt-auto flex items-center gap-1"><span class="h-2.5 w-7 rounded-[3px]"></span><span class="h-2.5 w-4 rounded-[3px]"></span><span class="h-2.5 w-4 rounded-[3px]">`);
9
+ var _tmpl$5 = /*#__PURE__*/ template(`<span aria-hidden=true>`);
10
+ var _tmpl$6 = /*#__PURE__*/ template(`<span class="h-full w-1/3">`);
10
11
  function Bar(props) {
11
12
  return (() => {
12
13
  var _el$ = _tmpl$();
@@ -122,6 +123,54 @@ function ThemeMiniatureSplit(props) {
122
123
  return _el$5;
123
124
  })();
124
125
  }
126
+ /**
127
+ * The dropdown-item preview: the ThemePreview composition (rail + panel +
128
+ * text bars + action row) at menu scale, so a menu item carries the theme's
129
+ * actual chrome rather than the three-band trigger swatch. `aria-hidden` —
130
+ * the item's accessible name stays the theme name.
131
+ */
132
+ function ThemeMenuPreview(props) {
133
+ const colors = () => props.theme.colors;
134
+ return (() => {
135
+ var _el$8 = _tmpl$4(), _el$9 = _el$8.firstChild, _el$0 = _el$9.firstChild, _el$1 = _el$0.nextSibling, _el$10 = _el$1.nextSibling, _el$11 = _el$9.nextSibling, _el$12 = _el$11.firstChild, _el$13 = _el$12.nextSibling, _el$14 = _el$13.nextSibling, _el$16 = _el$14.nextSibling.firstChild, _el$17 = _el$16.nextSibling, _el$18 = _el$17.nextSibling;
136
+ effect((_p$) => {
137
+ var _v$8 = cn("flex h-16 w-28 shrink-0 overflow-hidden rounded-md border border-(--appearance-preview-border)", props.class), _v$9 = colors().surface, _v$0 = colors().border, _v$1 = colors().surfaceElevated, _v$10 = colors().accent, _v$11 = colors().surfaceActive, _v$12 = colors().surfaceActive, _v$13 = colors().background, _v$14 = colors().border, _v$15 = colors().text, _v$16 = colors().textMuted, _v$17 = colors().textMuted, _v$18 = colors().accent, _v$19 = colors().error, _v$20 = colors().surfaceActive;
138
+ _v$8 !== _p$.e && className(_el$8, _p$.e = _v$8);
139
+ _v$9 !== _p$.t && setStyleProperty(_el$8, "background-color", _p$.t = _v$9);
140
+ _v$0 !== _p$.a && setStyleProperty(_el$8, "--appearance-preview-border", _p$.a = _v$0);
141
+ _v$1 !== _p$.o && setStyleProperty(_el$9, "background-color", _p$.o = _v$1);
142
+ _v$10 !== _p$.i && setStyleProperty(_el$0, "background-color", _p$.i = _v$10);
143
+ _v$11 !== _p$.n && setStyleProperty(_el$1, "background-color", _p$.n = _v$11);
144
+ _v$12 !== _p$.s && setStyleProperty(_el$10, "background-color", _p$.s = _v$12);
145
+ _v$13 !== _p$.h && setStyleProperty(_el$11, "background-color", _p$.h = _v$13);
146
+ _v$14 !== _p$.r && setStyleProperty(_el$11, "--appearance-preview-border", _p$.r = _v$14);
147
+ _v$15 !== _p$.d && setStyleProperty(_el$12, "background-color", _p$.d = _v$15);
148
+ _v$16 !== _p$.l && setStyleProperty(_el$13, "background-color", _p$.l = _v$16);
149
+ _v$17 !== _p$.u && setStyleProperty(_el$14, "background-color", _p$.u = _v$17);
150
+ _v$18 !== _p$.c && setStyleProperty(_el$16, "background-color", _p$.c = _v$18);
151
+ _v$19 !== _p$.w && setStyleProperty(_el$17, "background-color", _p$.w = _v$19);
152
+ _v$20 !== _p$.m && setStyleProperty(_el$18, "background-color", _p$.m = _v$20);
153
+ return _p$;
154
+ }, {
155
+ e: void 0,
156
+ t: void 0,
157
+ a: void 0,
158
+ o: void 0,
159
+ i: void 0,
160
+ n: void 0,
161
+ s: void 0,
162
+ h: void 0,
163
+ r: void 0,
164
+ d: void 0,
165
+ l: void 0,
166
+ u: void 0,
167
+ c: void 0,
168
+ w: void 0,
169
+ m: void 0
170
+ });
171
+ return _el$8;
172
+ })();
173
+ }
125
174
  function PalettePreview(props) {
126
175
  const bands = () => [
127
176
  props.theme.colors.surface,
@@ -129,30 +178,30 @@ function PalettePreview(props) {
129
178
  props.theme.colors.accent
130
179
  ];
131
180
  return (() => {
132
- var _el$8 = _tmpl$4();
133
- insert(_el$8, createComponent(For, {
181
+ var _el$19 = _tmpl$5();
182
+ insert(_el$19, createComponent(For, {
134
183
  get each() {
135
184
  return bands();
136
185
  },
137
186
  children: (band) => (() => {
138
- var _el$9 = _tmpl$5();
139
- setStyleProperty(_el$9, "background-color", band);
140
- return _el$9;
187
+ var _el$20 = _tmpl$6();
188
+ setStyleProperty(_el$20, "background-color", band);
189
+ return _el$20;
141
190
  })()
142
191
  }));
143
192
  effect((_p$) => {
144
- var _v$8 = cn("flex h-[18px] w-[30px] shrink-0 overflow-hidden rounded-[5px] border border-(--appearance-preview-border)", props.class), _v$9 = props.theme.colors.border;
145
- _v$8 !== _p$.e && className(_el$8, _p$.e = _v$8);
146
- _v$9 !== _p$.t && setStyleProperty(_el$8, "--appearance-preview-border", _p$.t = _v$9);
193
+ var _v$21 = cn("flex h-[18px] w-[30px] shrink-0 overflow-hidden rounded-[5px] border border-(--appearance-preview-border)", props.class), _v$22 = props.theme.colors.border;
194
+ _v$21 !== _p$.e && className(_el$19, _p$.e = _v$21);
195
+ _v$22 !== _p$.t && setStyleProperty(_el$19, "--appearance-preview-border", _p$.t = _v$22);
147
196
  return _p$;
148
197
  }, {
149
198
  e: void 0,
150
199
  t: void 0
151
200
  });
152
- return _el$8;
201
+ return _el$19;
153
202
  })();
154
203
  }
155
204
  //#endregion
156
- export { PalettePreview, ThemeMiniature, ThemeMiniatureSplit };
205
+ export { PalettePreview, ThemeMenuPreview, ThemeMiniature, ThemeMiniatureSplit };
157
206
 
158
207
  //# sourceMappingURL=theme-preview.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme-preview.js","names":["AdeaTheme","For","cn","ThemeMiniatureProps","theme","corners","class","Bar","props","fraction","opacity","color","_el$","_tmpl$","_$effect","_p$","_v$","Math","round","_v$2","_v$3","e","_$setStyleProperty","t","a","undefined","ThemeMiniature","_el$2","_tmpl$2","_el$3","firstChild","_el$4","nextSibling","_$insert","_$createComponent","colors","foreground","_v$4","_v$5","surface","_v$6","background","_v$7","border","_$className","o","ThemeMiniatureSplit","light","dark","_el$5","_tmpl$3","_el$6","_el$7","PalettePreview","bands","accent","_el$8","_tmpl$4","each","children","band","_el$9","_tmpl$5","_v$8","_v$9","_$setStyleProperty","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/theme-preview.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n/*\n * Substantially translated from Zeron crates/ui/src/settings/appearance.rs\n * `bar`, `miniature`, `miniature_split`, and `palette_preview`, revision\n * 30a9a9537c5ec96226c87f4bf349b6f77c5dfb59, via Adea's existing\n * packages/ui/src/components/theme-preview.tsx adaptation.\n * Retains the sidebar/pane decomposition, exact bar fractions and opacity,\n * split outer corners, and three-band palette strip. GPUI and Adea's local\n * ThemeVariant are replaced by Solid and the canonical AdeaTheme schema.\n * Dynamic inline colors are theme data; no palette is authored here.\n */\nimport type { AdeaTheme } from '@adea-ai/themes'\nimport { For } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nexport type ThemeMiniatureProps = {\n theme: AdeaTheme\n corners?: 'all' | 'left' | 'right'\n class?: string\n}\n\nfunction Bar(props: { fraction: number; opacity: number; color: string }) {\n return (\n <span\n class=\"h-[5px] rounded-[3px]\"\n style={{\n width: `${Math.round(props.fraction * 100)}%`,\n 'background-color': props.color,\n opacity: props.opacity,\n }}\n />\n )\n}\n\nexport function ThemeMiniature(props: ThemeMiniatureProps) {\n return (\n <span\n data-theme-miniature\n aria-hidden=\"true\"\n class={cn(\n 'flex size-full overflow-hidden',\n {\n 'rounded-md': !props.corners || props.corners === 'all',\n 'rounded-l-md': props.corners === 'left',\n 'rounded-r-md': props.corners === 'right',\n },\n props.class\n )}\n style={{ 'background-color': props.theme.colors.surface }}\n >\n <span class=\"flex h-full w-11 shrink-0 flex-col gap-[7px] overflow-hidden px-2 pt-3.5\">\n <Bar fraction={0.7} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.85} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n <span\n class=\"my-2 mr-2 flex min-w-0 flex-1 flex-col gap-[7px] overflow-hidden rounded-md border border-(--appearance-preview-border) p-2.5\"\n style={{\n 'background-color': props.theme.colors.background,\n '--appearance-preview-border': props.theme.colors.border,\n }}\n >\n <Bar fraction={0.62} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={0.88} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.76} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.52} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n </span>\n )\n}\n\nexport function ThemeMiniatureSplit(props: { light: AdeaTheme; dark: AdeaTheme; class?: string }) {\n return (\n <span class={cn('flex size-full', props.class)} aria-hidden=\"true\">\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.light} corners=\"left\" />\n </span>\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.dark} corners=\"right\" />\n </span>\n </span>\n )\n}\n\nexport function PalettePreview(props: { theme: AdeaTheme; class?: string }) {\n const bands = () => [\n props.theme.colors.surface,\n props.theme.colors.background,\n props.theme.colors.accent,\n ]\n return (\n <span\n class={cn(\n 'flex h-[18px] w-[30px] shrink-0 overflow-hidden rounded-[5px] border border-(--appearance-preview-border)',\n props.class\n )}\n aria-hidden=\"true\"\n style={{ '--appearance-preview-border': props.theme.colors.border }}\n >\n <For each={bands()}>\n {(band) => <span class=\"h-full w-1/3\" style={{ 'background-color': band }} />}\n </For>\n </span>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"theme-preview.js","names":["AdeaTheme","For","cn","ThemeMiniatureProps","theme","corners","class","Bar","props","fraction","opacity","color","_el$","_tmpl$","_$effect","_p$","_v$","Math","round","_v$2","_v$3","e","_$setStyleProperty","t","a","undefined","ThemeMiniature","_el$2","_tmpl$2","_el$3","firstChild","_el$4","nextSibling","_$insert","_$createComponent","colors","foreground","_v$4","_v$5","surface","_v$6","background","_v$7","border","_$className","o","ThemeMiniatureSplit","light","dark","_el$5","_tmpl$3","_el$6","_el$7","ThemeMenuPreview","_el$8","_tmpl$4","_el$9","_el$0","_el$1","_el$10","_el$11","_el$12","_el$13","_el$14","_el$15","_el$16","_el$17","_el$18","_v$8","_v$9","_v$0","_v$1","surfaceElevated","_v$10","accent","_v$11","surfaceActive","_v$12","_v$13","_v$14","_v$15","text","_v$16","textMuted","_v$17","_v$18","_v$19","error","_v$20","i","n","s","h","r","d","l","u","c","w","m","PalettePreview","bands","_el$19","_tmpl$5","each","children","band","_el$20","_tmpl$6","_v$21","_v$22","_$setStyleProperty","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/theme-preview.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n/*\n * Substantially translated from Zeron crates/ui/src/settings/appearance.rs\n * `bar`, `miniature`, `miniature_split`, and `palette_preview`, revision\n * 30a9a9537c5ec96226c87f4bf349b6f77c5dfb59, via Adea's existing\n * packages/ui/src/components/theme-preview.tsx adaptation.\n * Retains the sidebar/pane decomposition, exact bar fractions and opacity,\n * split outer corners, and three-band palette strip. GPUI and Adea's local\n * ThemeVariant are replaced by Solid and the canonical AdeaTheme schema.\n * Dynamic inline colors are theme data; no palette is authored here.\n */\nimport type { AdeaTheme } from '@adea-ai/themes'\nimport { For } from 'solid-js'\nimport { cn } from '#lib/utils'\n\nexport type ThemeMiniatureProps = {\n theme: AdeaTheme\n corners?: 'all' | 'left' | 'right'\n class?: string\n}\n\nfunction Bar(props: { fraction: number; opacity: number; color: string }) {\n return (\n <span\n class=\"h-[5px] rounded-[3px]\"\n style={{\n width: `${Math.round(props.fraction * 100)}%`,\n 'background-color': props.color,\n opacity: props.opacity,\n }}\n />\n )\n}\n\nexport function ThemeMiniature(props: ThemeMiniatureProps) {\n return (\n <span\n data-theme-miniature\n aria-hidden=\"true\"\n class={cn(\n 'flex size-full overflow-hidden',\n {\n 'rounded-md': !props.corners || props.corners === 'all',\n 'rounded-l-md': props.corners === 'left',\n 'rounded-r-md': props.corners === 'right',\n },\n props.class\n )}\n style={{ 'background-color': props.theme.colors.surface }}\n >\n <span class=\"flex h-full w-11 shrink-0 flex-col gap-[7px] overflow-hidden px-2 pt-3.5\">\n <Bar fraction={0.7} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.85} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={1} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n <span\n class=\"my-2 mr-2 flex min-w-0 flex-1 flex-col gap-[7px] overflow-hidden rounded-md border border-(--appearance-preview-border) p-2.5\"\n style={{\n 'background-color': props.theme.colors.background,\n '--appearance-preview-border': props.theme.colors.border,\n }}\n >\n <Bar fraction={0.62} opacity={0.34} color={props.theme.colors.foreground} />\n <Bar fraction={0.88} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.76} opacity={0.22} color={props.theme.colors.foreground} />\n <Bar fraction={0.52} opacity={0.22} color={props.theme.colors.foreground} />\n </span>\n </span>\n )\n}\n\nexport function ThemeMiniatureSplit(props: { light: AdeaTheme; dark: AdeaTheme; class?: string }) {\n return (\n <span class={cn('flex size-full', props.class)} aria-hidden=\"true\">\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.light} corners=\"left\" />\n </span>\n <span class=\"h-full w-1/2 overflow-hidden\">\n <ThemeMiniature theme={props.dark} corners=\"right\" />\n </span>\n </span>\n )\n}\n\n/**\n * The dropdown-item preview: the ThemePreview composition (rail + panel +\n * text bars + action row) at menu scale, so a menu item carries the theme's\n * actual chrome rather than the three-band trigger swatch. `aria-hidden` —\n * the item's accessible name stays the theme name.\n */\nexport function ThemeMenuPreview(props: { theme: AdeaTheme; class?: string }) {\n const colors = () => props.theme.colors\n return (\n <span\n data-theme-menu-preview\n aria-hidden=\"true\"\n class={cn(\n 'flex h-16 w-28 shrink-0 overflow-hidden rounded-md border border-(--appearance-preview-border)',\n props.class\n )}\n style={{\n 'background-color': colors().surface,\n '--appearance-preview-border': colors().border,\n }}\n >\n <span\n class=\"flex w-5 shrink-0 flex-col items-center gap-1.5 border-e border-(--appearance-preview-border) pt-2\"\n style={{ 'background-color': colors().surfaceElevated }}\n >\n <span class=\"size-1.5 rounded-[3px]\" style={{ 'background-color': colors().accent }} />\n <span\n class=\"size-1.5 rounded-[3px]\"\n style={{ 'background-color': colors().surfaceActive }}\n />\n <span\n class=\"size-1.5 rounded-[3px]\"\n style={{ 'background-color': colors().surfaceActive }}\n />\n </span>\n <span\n class=\"m-1 flex min-w-0 flex-1 flex-col gap-1 rounded-md border border-(--appearance-preview-border) p-1.5\"\n style={{\n 'background-color': colors().background,\n '--appearance-preview-border': colors().border,\n }}\n >\n <span class=\"h-1.5 w-8 rounded-full\" style={{ 'background-color': colors().text }} />\n <span class=\"h-1 w-full rounded-full\" style={{ 'background-color': colors().textMuted }} />\n <span class=\"h-1 w-3/4 rounded-full\" style={{ 'background-color': colors().textMuted }} />\n <span class=\"mt-auto flex items-center gap-1\">\n <span class=\"h-2.5 w-7 rounded-[3px]\" style={{ 'background-color': colors().accent }} />\n <span class=\"h-2.5 w-4 rounded-[3px]\" style={{ 'background-color': colors().error }} />\n <span\n class=\"h-2.5 w-4 rounded-[3px]\"\n style={{ 'background-color': colors().surfaceActive }}\n />\n </span>\n </span>\n </span>\n )\n}\n\nexport function PalettePreview(props: { theme: AdeaTheme; class?: string }) {\n const bands = () => [\n props.theme.colors.surface,\n props.theme.colors.background,\n props.theme.colors.accent,\n ]\n return (\n <span\n class={cn(\n 'flex h-[18px] w-[30px] shrink-0 overflow-hidden rounded-[5px] border border-(--appearance-preview-border)',\n props.class\n )}\n aria-hidden=\"true\"\n style={{ '--appearance-preview-border': props.theme.colors.border }}\n >\n <For each={bands()}>\n {(band) => <span class=\"h-full w-1/3\" style={{ 'background-color': band }} />}\n </For>\n </span>\n )\n}\n"],"mappings":"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"}
@@ -117,7 +117,11 @@ export function AboutDialog(props: AboutDialogProps) {
117
117
  <div class="flex flex-col items-center gap-3 px-6 py-8 text-center">
118
118
  <img src={props.appIcon} alt="" class="size-16" aria-hidden="true" />
119
119
  <DialogTitle>{props.appName}</DialogTitle>
120
- <p class="text-sm text-primary">{versionLabel()}</p>
120
+ {/* Body text on the dialog's themed surface: primary ink measures
121
+ below AA against the lighter dialog backgrounds across schemes,
122
+ so the version and the source link carry foreground ink and keep
123
+ primary as the link's underline accent (the text-link treatment). */}
124
+ <p class="text-sm text-foreground">{versionLabel()}</p>
121
125
  <p class="text-xs text-muted-foreground">{props.copyright}</p>
122
126
  <div class="flex flex-wrap items-center justify-center gap-3">
123
127
  <ActionButton
@@ -134,6 +138,7 @@ export function AboutDialog(props: AboutDialogProps) {
134
138
  as="a"
135
139
  variant="link"
136
140
  size="sm"
141
+ class="text-foreground decoration-primary"
137
142
  href={props.sourceUrl}
138
143
  target="_blank"
139
144
  rel="noopener noreferrer"
@@ -151,7 +151,6 @@ export function AccountMenu(props: AccountMenuProps) {
151
151
  >
152
152
  <UserRound aria-hidden="true" />
153
153
  </TooltipTrigger>
154
- <TooltipContent placement="top">{local.label ?? 'Account and settings'}</TooltipContent>
155
154
  <DropdownMenuContent
156
155
  hideArrow={local.hideArrow}
157
156
  class="min-w-56 max-h-(--kb-popper-available-height) overflow-x-hidden overflow-y-auto"
@@ -204,6 +203,8 @@ export function AccountMenu(props: AccountMenuProps) {
204
203
  </Show>
205
204
  </DropdownMenuContent>
206
205
  </DropdownMenu>
206
+ {/* Both overlays own a Popper context; the tooltip must stay outside the menu root. */}
207
+ <TooltipContent placement="top">{local.label ?? 'Account and settings'}</TooltipContent>
207
208
  </Tooltip>
208
209
  )
209
210
  }
@@ -93,20 +93,31 @@ export function AccentChoices(props: AppearanceEditorProps) {
93
93
  disabled={props.saving}
94
94
  orientation="horizontal"
95
95
  aria-label="Accent"
96
- class="flex flex-wrap items-center gap-2"
96
+ // Two chips in a column beside a 3x2 swatch grid: one line of six
97
+ // swatches plus chips overflows the settings sidebar's control column,
98
+ // and the column keeps both rows of the pair balanced (2 x 28px + gap).
99
+ class="flex items-center gap-3"
97
100
  onChange={(accent) =>
98
101
  props.onChange({
99
102
  accent: accent === 'custom' ? (props.customAccentValue ?? '') : accent,
100
103
  })
101
104
  }
102
105
  >
103
- <Radio.Item value="theme">
104
- <Radio.ItemInput />
105
- <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
106
- Theme default
107
- </Radio.ItemLabel>
108
- </Radio.Item>
109
- <div class="flex max-w-full flex-wrap gap-2">
106
+ <div class="flex flex-col gap-2">
107
+ <Radio.Item value="theme">
108
+ <Radio.ItemInput />
109
+ <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
110
+ Theme default
111
+ </Radio.ItemLabel>
112
+ </Radio.Item>
113
+ <Radio.Item value="custom">
114
+ <Radio.ItemInput />
115
+ <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
116
+ Custom
117
+ </Radio.ItemLabel>
118
+ </Radio.Item>
119
+ </div>
120
+ <div class="grid grid-cols-3 gap-2">
110
121
  <For each={props.accentOptions}>
111
122
  {(option) => (
112
123
  <Radio.Item
@@ -133,12 +144,6 @@ export function AccentChoices(props: AppearanceEditorProps) {
133
144
  )}
134
145
  </For>
135
146
  </div>
136
- <Radio.Item value="custom">
137
- <Radio.ItemInput />
138
- <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
139
- Custom
140
- </Radio.ItemLabel>
141
- </Radio.Item>
142
147
  </Radio>
143
148
  )
144
149
  }
@@ -47,7 +47,7 @@ import {
47
47
  } from '../../ui/popover/popover'
48
48
  import type { AppearanceEditorProps, AppearancePopoverProps } from './appearance-types'
49
49
  import { ModeChoices, AccentChoices, GlassChoices } from './appearance-choices'
50
- import { SettingsRow, ThemeRow } from './appearance-rows'
50
+ import { SettingsRow, TerminalRow, ThemeRow } from './appearance-rows'
51
51
 
52
52
  /**
53
53
  * A live editor whose persistence and preview authority belong to its host.
@@ -99,6 +99,18 @@ export function AppearanceEditor(props: AppearanceEditorProps) {
99
99
  disabled={props.saving}
100
100
  onSelect={(darkThemeId) => props.onChange({ darkThemeId })}
101
101
  />
102
+ {/* The row exists only when the host carries a terminal preference:
103
+ the draft field is the show/hide switch, so the editor can never
104
+ render a terminal row that writes nothing. */}
105
+ <Show when={props.draft.terminalThemeId !== undefined}>
106
+ <TerminalRow
107
+ selectedId={props.draft.terminalThemeId ?? 'theme'}
108
+ preview={props.resolvedAppearance === 'dark' ? props.darkTheme : props.lightTheme}
109
+ themes={props.themes}
110
+ disabled={props.saving}
111
+ onSelect={(terminalThemeId) => props.onChange({ terminalThemeId })}
112
+ />
113
+ </Show>
102
114
  <SettingsRow title="Accent" icon={<SlidersHorizontal />} description={accentDescription()}>
103
115
  <AccentChoices {...props} />
104
116
  </SettingsRow>