From 5eb7460c343df4970628f61fd502d56984f9e6ca Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 7 Jul 2026 14:14:31 -0400 Subject: [PATCH 1/9] deps: upgrade fuz_css with oklch --- src/lib/ApiModulesList.svelte | 2 +- src/lib/ColorSchemeInput.svelte | 2 +- src/lib/CopyToClipboard.svelte | 2 +- src/lib/DocsFooter.svelte | 2 +- src/lib/HueInput.svelte | 24 +++++++------------ src/lib/LibraryDetail.svelte | 8 +++---- src/lib/ModuleLink.svelte | 2 +- src/lib/ProjectLinks.svelte | 24 +++++++++---------- src/lib/Spiders.svelte | 20 ++++++++-------- src/lib/ThemeInput.svelte | 2 +- src/lib/alert.ts | 4 ++-- src/lib/logos.ts | 2 +- src/routes/ThemeForm.svelte | 4 +--- src/routes/docs/Alert/+page.svelte | 4 ++-- .../Contextmenu/ExampleCustomInstance.svelte | 6 ++--- .../ExampleDisableDefaultBehaviors.svelte | 2 +- .../docs/Contextmenu/ExampleSelectText.svelte | 2 +- src/routes/docs/HueInput/+page.svelte | 2 +- src/routes/docs/Svg/+page.svelte | 12 +++++----- src/routes/docs/intersect/+page.svelte | 6 ++--- svelte.config.js | 4 ++-- tsconfig.json | 4 +++- 22 files changed, 66 insertions(+), 74 deletions(-) diff --git a/src/lib/ApiModulesList.svelte b/src/lib/ApiModulesList.svelte index fe2dfde3f..2b3233e6c 100644 --- a/src/lib/ApiModulesList.svelte +++ b/src/lib/ApiModulesList.svelte @@ -25,7 +25,7 @@ {#if modules.length === 0} -

No modules match your search.

+

No modules match your search.

{:else}
    {#each modules as module (module.path)} diff --git a/src/lib/ColorSchemeInput.svelte b/src/lib/ColorSchemeInput.svelte index 2f43d6847..a7c3dd99e 100644 --- a/src/lib/ColorSchemeInput.svelte +++ b/src/lib/ColorSchemeInput.svelte @@ -22,7 +22,7 @@ https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/menubar_ro {@const selected = color_scheme === value.color_scheme}
diff --git a/src/routes/docs/Contextmenu/ExampleSelectText.svelte b/src/routes/docs/Contextmenu/ExampleSelectText.svelte index 1dfa9d6bf..5bdf4fea1 100644 --- a/src/routes/docs/Contextmenu/ExampleSelectText.svelte +++ b/src/routes/docs/Contextmenu/ExampleSelectText.svelte @@ -41,14 +41,14 @@ Try selecting text and then opening the contextmenu on it.`; -
+
{#snippet entries()} void (toggled = !toggled)}>Toggle something {/snippet} -
+

When the Fuz contextmenu opens and the user has selected text, the menu includes a -

+

Opening the contextmenu on an input or textarea opens the browser's default contextmenu.

From 067e491c40b360e150e24b2c591942f505d0046f Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Thu, 16 Jul 2026 10:49:56 -0400 Subject: [PATCH 4/9] wip --- src/lib/logos.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/lib/logos.ts b/src/lib/logos.ts index 51f1c0dcb..7ae74b1c1 100644 --- a/src/lib/logos.ts +++ b/src/lib/logos.ts @@ -4,18 +4,20 @@ import type {SvgData} from './svg.ts'; /* -Logo colors are the midpoint between the light and dark versions of color variant 5: +Logo colors are frozen brand values โ€” originally derived as the midpoint +between the light and dark mid-stops of fuz_css's pre-OKLCH palette +(today's `--palette_X_50`), and deliberately not re-derived since: ```css ---color_a: #6199d1; ---color_b: #3db33d; ---color_c: #d93636; ---color_d: #8866cc; ---color_e: #d8bc31; ---color_f: #84522a; // TODO this one isn't the midpoint bc fuz_css's color needs tweaking, too light in dark mode ---color_g: #e55d95; ---color_h: #f4672f; ---color_i: #36e2e2; +#6199d1 (blue, a) +#3db33d (green, b) +#d93636 (red, c) +#8866cc (purple, d) +#d8bc31 (yellow, e) +#84522a (brown, f) +#e55d95 (pink, g) +#f4672f (orange, h) +#36e2e2 (cyan, i) ``` */ From 265fd90a54dd9c05af98548bff6ecd3a0b79c7e7 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 22 Jul 2026 09:26:00 -0400 Subject: [PATCH 5/9] wip --- src/lib/ProjectLinks.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ProjectLinks.svelte b/src/lib/ProjectLinks.svelte index 92a47d012..72dc81baa 100644 --- a/src/lib/ProjectLinks.svelte +++ b/src/lib/ProjectLinks.svelte @@ -34,7 +34,7 @@ {name: 'fuz_app', url: 'https://app.fuz.dev/', logo: logo_fuz_app, description: '[pre-alpha] fullstack app library', glyph: '๐Ÿ—', color_class: 'palette_j_50'}, {name: 'fuz_css', url: 'https://css.fuz.dev/', logo: logo_fuz_css, description: 'CSS framework and design system for semantic HTML', glyph: '๐ŸŒฟ', color_class: 'palette_b_50'}, {name: 'fuz_ui', url: 'https://ui.fuz.dev/', logo: logo_fuz_ui, description: 'Svelte UI library', glyph: '๐Ÿงถ', color_class: 'palette_c_50'}, - {name: 'fuz_template', url: 'https://template.fuz.dev/', logo: logo_fuz_template, description: 'a static web app and Node library template with TypeScript, Svelte, SvelteKit, Vite, esbuild, Gro, and Fuz', glyph: 'โ„', color_class: 'palette_h_50'}, + {name: 'fuz_template', url: 'https://template.fuz.dev/', logo: logo_fuz_template, description: 'a web app template with TypeScript + SvelteKit + optional Rust for the fuz-stack', glyph: 'โ„', color_class: 'palette_h_50'}, {name: 'fuz_blog', url: 'https://blog.fuz.dev/', logo: logo_fuz_blog, description: 'blog software from scratch with SvelteKit', glyph: '๐Ÿ–Š๏ธ', color_class: 'palette_e_50'}, {name: 'fuz_code', url: 'https://code.fuz.dev/', logo: logo_fuz_code, description: 'syntax styling utilities and components for TypeScript, Svelte, Markdown, and more', glyph: '๐ŸŽจ', color_class: 'palette_g_50'}, {name: 'fuz_mastodon', url: 'https://mastodon.fuz.dev/', logo: logo_fuz_mastodon, description: 'Mastodon components and helpers for Svelte, SvelteKit, and Fuz', glyph: '๐Ÿฆฃ', color_class: 'palette_d_50'}, From f2399ffe938dd049292b133741edb0d3631896b8 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Wed, 29 Jul 2026 10:26:44 -0400 Subject: [PATCH 6/9] wip --- src/routes/docs/ThemeRoot/+page.svelte | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/routes/docs/ThemeRoot/+page.svelte b/src/routes/docs/ThemeRoot/+page.svelte index f597222ca..adceebbdf 100644 --- a/src/routes/docs/ThemeRoot/+page.svelte +++ b/src/routes/docs/ThemeRoot/+page.svelte @@ -181,16 +181,18 @@

Themes are plain CSS that can be sourced in a variety of ways.

-

To use Fuz's base theme:

+

+ To use Fuz's base theme, import the CSS generated by vite_plugin_fuz_css - it + includes the theme variables, base styles, and utility classes your code uses: +

<` + `script> - import '@fuzdev/fuz_css/style.css'; - import '@fuzdev/fuz_css/theme.css'; + import 'virtual:fuz.css'; import ThemeRoot from '@fuzdev/fuz_ui/ThemeRoot.svelte'; import type {Snippet} from 'svelte'; - + const {children}: {children: Snippet} = $props(); @@ -199,6 +201,13 @@ {@render children()} `} /> +

can be customized with the the nonreactive prop theme_state: From b2f131a089477cf85feced515aba84f1d2d0f958 Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Fri, 31 Jul 2026 16:14:53 -0400 Subject: [PATCH 7/9] changeset --- .changeset/quick-forks-pump.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.changeset/quick-forks-pump.md b/.changeset/quick-forks-pump.md index d816c81dd..caad31b9d 100644 --- a/.changeset/quick-forks-pump.md +++ b/.changeset/quick-forks-pump.md @@ -3,3 +3,21 @@ --- deps: upgrade fuz_css with oklch + +- `Dialog`'s backdrop dim reads fuz_css's shared `--backdrop_color` + variable (was `--dialog_bg`), so one theme variable retints every + backdrop, native and component alike. +- `ThemeRoot` warns in dev when a single-scheme theme arrives without its + `scheme_mirror` - resolve with `resolve_theme_stance` before rendering. +- Contrast becomes a modifier, matching fuz_css's registry rework: + `ThemeState` gains `contrast` (the selected modifier, persisted under + `fuz:contrast`) and `composed_theme` (the base theme with the modifier + composed over it via `compose_themes`), which `ThemeRoot` now renders. + `ThemeInput` grows a contrast select fed by fuz_css's + `contrast_modifiers` (override or hide with its `contrast_modifiers` + prop) - without it, pickers would lose low/high contrast entirely now + that the pair left `default_themes`. Both light up when the fuz_css dep + ships the new APIs; against older releases they no-op. +- Utility classes follow fuz_css's property-first palette naming: + `palette_X_NN` โ†’ `color_X_NN` (the bare `.palette_a`-`.palette_j` + component conventions are unchanged). From 87809cbef82ce41c39ceafa527022d07d9cb54ae Mon Sep 17 00:00:00 2001 From: Ryan Atkinson Date: Tue, 1 Sep 2026 18:12:00 -0400 Subject: [PATCH 8/9] wip --- .changeset/radio-menu.md | 16 ++++++ CLAUDE.md | 1 + src/lib/ColorSchemeInput.svelte | 58 ++++---------------- src/lib/RadioMenu.svelte | 96 +++++++++++++++++++++++++++++++++ src/lib/ThemeInput.svelte | 2 +- 5 files changed, 124 insertions(+), 49 deletions(-) create mode 100644 .changeset/radio-menu.md create mode 100644 src/lib/RadioMenu.svelte diff --git a/.changeset/radio-menu.md b/.changeset/radio-menu.md new file mode 100644 index 000000000..42bca39fd --- /dev/null +++ b/.changeset/radio-menu.md @@ -0,0 +1,16 @@ +--- +'@fuzdev/fuz_ui': minor +--- + +feat: `RadioMenu`, and the theme inputs use fuz_css's `palette_a` convention + +`RadioMenu` is a horizontal menu of joined `menuitemradio` buttons with one +selected, generic over the option type: `options`, a bindable `value`, a +`label` function (also the default `title` and list key), optional `title` +and `key` overrides, `onselect`, and a `children` snippet for custom button +content. `ColorSchemeInput` is now a thin `RadioMenu` over `color_schemes`; +its markup and styles are unchanged. + +`ColorSchemeInput` and `ThemeInput` buttons take the `palette_a` class - +`color_a` was the bare component convention before fuz_css's palette +rename and no longer resolves. diff --git a/CLAUDE.md b/CLAUDE.md index b0afddc3c..6b1241a71 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -110,6 +110,7 @@ consumes are listed under [Library and API generation](#library-and-api-generati ### Forms and inputs - `HueInput`, `ColorSchemeInput`, `ThemeInput` - theme controls +- `RadioMenu` - a joined-button `menuitemradio` row, the shape `ColorSchemeInput` is built on ### Icons and media diff --git a/src/lib/ColorSchemeInput.svelte b/src/lib/ColorSchemeInput.svelte index bb494aeae..c3e6f15e0 100644 --- a/src/lib/ColorSchemeInput.svelte +++ b/src/lib/ColorSchemeInput.svelte @@ -1,9 +1,9 @@ - -

- {#each color_schemes as color_scheme (color_scheme)} - {@const selected = color_scheme === value.color_scheme} - - {/each} - - - + color_scheme} + title={(color_scheme, selected) => + selected ? `${color_scheme} color scheme is selected` : `select ${color_scheme} color scheme`} +/> diff --git a/src/lib/RadioMenu.svelte b/src/lib/RadioMenu.svelte new file mode 100644 index 000000000..ef85600a7 --- /dev/null +++ b/src/lib/RadioMenu.svelte @@ -0,0 +1,96 @@ + + + + {#each options as option (key(option))} + {@const selected = option === value} + + {/each} + + + diff --git a/src/lib/ThemeInput.svelte b/src/lib/ThemeInput.svelte index cb84940f8..9e382eaf0 100644 --- a/src/lib/ThemeInput.svelte +++ b/src/lib/ThemeInput.svelte @@ -35,7 +35,7 @@
  • and opening the contextmenu in this panel. diff --git a/src/routes/docs/Contextmenu/ExampleSelectText.svelte b/src/routes/docs/Contextmenu/ExampleSelectText.svelte index 34bfe4ccb..eb2853c0f 100644 --- a/src/routes/docs/Contextmenu/ExampleSelectText.svelte +++ b/src/routes/docs/Contextmenu/ExampleSelectText.svelte @@ -52,11 +52,11 @@ Try selecting text and then opening the contextmenu on it.`;

    When the Fuz contextmenu opens and the user has selected text, the menu includes a - copy text - entry. + copy text entry.

    - Try and then opening the contextmenu on it. diff --git a/src/routes/docs/Contextmenu/Introduction.svelte b/src/routes/docs/Contextmenu/Introduction.svelte index 6c7e9d53c..ae547e3ac 100644 --- a/src/routes/docs/Contextmenu/Introduction.svelte +++ b/src/routes/docs/Contextmenu/Introduction.svelte @@ -30,10 +30,9 @@

    When you rightclick inside a , or longpress on touch devices, it searches the DOM tree for behaviors defined with - - starting from the target element up to the root. If any behaviors are found, the Fuz contextmenu - opens, showing all contextually available actions. If no behaviors are found, the default system - contextmenu opens. + starting from the target element up to the root. If any + behaviors are found, the Fuz contextmenu opens, showing all contextually available actions. If + no behaviors are found, the default system contextmenu opens.

    Here's a {root_component_name} with a inside @@ -101,11 +100,8 @@

  • holding Shift opens the system contextmenu, bypassing the Fuz contextmenu
  • - keyboard navigation and activation should work similarly to the W3C - APG menubar pattern - + keyboard navigation and activation should work similarly to the W3C + APG menubar pattern
  • Touch devices:

    @@ -130,9 +126,8 @@ Fuz contextmenu
  • - opening the contextmenu attempts haptic feedback with + opening the contextmenu attempts haptic feedback with + navigator.vibrate
  • diff --git a/src/routes/docs/Details/+page.svelte b/src/routes/docs/Details/+page.svelte index 91004f1bc..d2fff7023 100644 --- a/src/routes/docs/Details/+page.svelte +++ b/src/routes/docs/Details/+page.svelte @@ -19,8 +19,7 @@

    The component is an alternative to the element. By default it's lazy, and you can pass - eager - to render the children immediately like the base element. + eager to render the children immediately like the base element.

    Benefits of lazy children:

      diff --git a/src/routes/docs/Dialog/+page.svelte b/src/routes/docs/Dialog/+page.svelte index fe5303116..1b7b64ef2 100644 --- a/src/routes/docs/Dialog/+page.svelte +++ b/src/routes/docs/Dialog/+page.svelte @@ -66,13 +66,11 @@

      A is a modal that overlays the entire page. It uses the - native - element, so opening it with - showModal() - puts children in the browser's top layer, escaping ancestor stacking (avoiding bugs and - caveats, like unwanted overflow containment and cascading styles, without using - ). The native element also traps focus, makes the rest of the page - inert, closes on + native element, so opening it with + showModal() puts children in the + browser's top layer, escaping ancestor stacking (avoiding bugs and caveats, like unwanted + overflow containment and cascading styles, without using ). The + native element also traps focus, makes the rest of the page inert, closes on Escape, and restores focus to the previously focused element on close.

      @@ -144,15 +142,12 @@ />

      adds a close button in the top-right corner, rendered - after the content so it doesn't take initial focus. Pass - close_button={'{false}'} to remove it, or a snippet to render your own. The - snippet receives attrs with type - with the default button's placement, + after the content so it doesn't take initial focus. Pass close_button={'{false}'} + to remove it, or a snippet to render your own. The snippet receives attrs with + type with the default button's placement, styling, a11y, and the onclick that closes the dialog, plus the - . Spread - attrs - to inherit the corner-anchored button and override only the glyph, or ignore it to place the - button freely: + . Spread attrs to inherit the + corner-anchored button and override only the glyph, or ignore it to place the button freely:

      - new stuff appears {#if selected_align === 'top'} + new stuff appears + {#if selected_align === 'top'} gracefully {:else if selected_align === 'center'} ungracefully @@ -392,8 +387,7 @@ via Escape, click-outside, or the buttons asks for confirmation first.

      {/snippet} diff --git a/src/routes/docs/Docs/+page.svelte b/src/routes/docs/Docs/+page.svelte index 383e742c3..432b3775e 100644 --- a/src/routes/docs/Docs/+page.svelte +++ b/src/routes/docs/Docs/+page.svelte @@ -21,15 +21,14 @@ is used to construct this page, and all of the other /docs pages in the Fuz stack. It has a three-column responsive layout with managed navigation and uses ordinary SvelteKit patterns: it takes an array of s and renders the - current page as children, so it lives in a - +layout.svelte - wrapping your docs routes. + current page as children, so it lives in a +layout.svelte wrapping + your docs routes.

      - It requires two contexts: site_context (a - for components like ) set - once at the root layout (typically the root, anywhere up the tree works), and - library_context (a ) set in the docs layout: + It requires two contexts: site_context (a + for components like ) set once at the root layout (typically the + root, anywhere up the tree works), and library_context (a + ) set in the docs layout:

      is the reactive wrapper around a LibraryJson. It's constructed from the package.json subset - - served by plus the analyzed modules from + served by + plus the analyzed modules from virtual:svelte-docinfo.

      `} />

      - These docs you're reading are the live example. fuz_ui sets its own - as described above. See for the surrounding layout, and - / for the components that - render it. + These docs you're reading are the live example. fuz_ui sets its own + as described above. See for the + surrounding layout, and / + for the components that render it.

      diff --git a/src/routes/docs/LibraryDetail/+page.svelte b/src/routes/docs/LibraryDetail/+page.svelte index c3365188b..5d8a892e6 100644 --- a/src/routes/docs/LibraryDetail/+page.svelte +++ b/src/routes/docs/LibraryDetail/+page.svelte @@ -22,9 +22,8 @@

      renders the full metadata for a library and its repo, including its module and declaration index. See the for how to - construct one from - - and virtual:svelte-docinfo: + construct one from and + virtual:svelte-docinfo:

      `} /> @@ -32,8 +31,8 @@ It projects its library prop into for its subtree, so the module and declaration links resolve against the rendered library even when it differs from the site's own. When rendering a foreign library, pass - links_full - so the links point at the library's deployed docs instead of site-local paths: + links_full so the links point at the library's deployed docs instead of + site-local paths:

      `} /> diff --git a/src/routes/docs/LibrarySummary/+page.svelte b/src/routes/docs/LibrarySummary/+page.svelte index 3dd37169a..dc7316bb6 100644 --- a/src/routes/docs/LibrarySummary/+page.svelte +++ b/src/routes/docs/LibrarySummary/+page.svelte @@ -22,8 +22,8 @@

      renders a compact card for a library and its repo. See the Library for how to construct one from - - and virtual:svelte-docinfo: + and + virtual:svelte-docinfo:

      - and children - + and children

      {#snippet children(index)} diff --git a/src/routes/docs/Redirect/+page.svelte b/src/routes/docs/Redirect/+page.svelte index b32d41ecc..5421314b2 100644 --- a/src/routes/docs/Redirect/+page.svelte +++ b/src/routes/docs/Redirect/+page.svelte @@ -15,10 +15,8 @@

      - Adds a redirect for a page using - a meta tag - - with + Adds a redirect for a page using + a meta tag with the refresh header . Includes a rendered link and JS navigation fallback. diff --git a/src/routes/docs/Sparkline/+page.svelte b/src/routes/docs/Sparkline/+page.svelte index 4a1e7603a..b0afa75bd 100644 --- a/src/routes/docs/Sparkline/+page.svelte +++ b/src/routes/docs/Sparkline/+page.svelte @@ -37,8 +37,7 @@

      - By default each sparkline stretches its own max to full height. Pass a shared - max + By default each sparkline stretches its own max to full height. Pass a shared max so a set of sparklines renders at the same vertical scale and stays visually comparable:

      Under a large shared max, low-activity series hug the baseline. Set - scale - to compress the top of the range so small values stay legible โ€” increasingly so from - "sqrt" - to a power exponent (a number in (0, 1], where 1 is linear) to - "log". The alpha fade still tracks the linear ratio, so it keeps encoding true - magnitude: + scale to compress the top of the range so small values stay legible โ€” + increasingly so from "sqrt" to a power exponent (a number in (0, 1], + where 1 is linear) to "log". The alpha fade still tracks the linear + ratio, so it keeps encoding true magnitude:

      @@ -69,8 +66,7 @@

      linear, sqrt, cube root, - - log + log

      @@ -92,8 +88,7 @@

      Each point's stroke alpha scales with its value, from alpha_floor at 0 (default - 0.4) up to 1 at max, de-emphasizing quiet stretches. Set - alpha_floor + 0.4) up to 1 at max, de-emphasizing quiet stretches. Set alpha_floor to 1 to disable the fade:

      `} /> @@ -128,8 +123,7 @@

      draws every project's weekly series over one another at a shared scale, built on the same geometry via - - โ€” hover a line for the project's stats: + โ€” hover a line for the project's stats:

      diff --git a/src/routes/docs/ThemeRoot/+page.svelte b/src/routes/docs/ThemeRoot/+page.svelte index 6f70d20b9..c024e2bf6 100644 --- a/src/routes/docs/ThemeRoot/+page.svelte +++ b/src/routes/docs/ThemeRoot/+page.svelte @@ -35,17 +35,16 @@

      Fuz provides UI components that use - fuz_css' theming system - for dark mode and custom themes. + fuz_css' theming system for dark mode and custom + themes.

      adds global support for both the browser's - - and custom themes based on + and custom themes based on fuz_css style variables, which use CSS custom properties. - - is a singleton component that's mounted at the top-level of the page: + is a singleton component that's mounted at the top-level + of the page:

      \n\n\t{@render children()}\n`} /> @@ -55,8 +54,7 @@

      Most theme usage affects the whole page, so Fuz makes that easy.

      By default syncs its settings to the global - :root - tag and persists to localStorage. + :root tag and persists to localStorage.

      These behaviors can be customized with its props:

        @@ -74,27 +72,21 @@

        is designed to wrap every page at the top level so it can provide the selected theme and color scheme in the Svelte context via a - theme_state - instance. It works without children, but theme_state_context.get() will fail - unless you call - theme_state_context.set() - yourself. + theme_state instance. It works without children, but + theme_state_context.get() will fail unless you call + theme_state_context.set() yourself.

        This lets you call theme_state_context.get() to access the reactive - - class instance anywhere in your code. The helper components on this page like - and use - it so they don't require a - theme_state - prop. + class instance anywhere in your code. The helper + components on this page like and + use it so they don't require a + theme_state prop.

        If you don't don't want to wrap everything in for some reason, you can set a in context manually. It - must be the same reference as the - - prop: + must be the same reference as the prop:

        defaults to automatic - - detection with + detection with , and users can also set it directly:

        @@ -147,13 +138,11 @@

        By default, works with - 's - theme_state in context to save the user's preference to - localStorage. To customize this behavior, pass your own value or - onchange - props. The value defaults to theme_state_context.get() so - technically you could call set_theme_state, but it's unlikely you want to - override it in context. + 's theme_state in context to save the + user's preference to localStorage. To customize this behavior, pass your own + value or onchange props. The value defaults to + theme_state_context.get() so technically you could call + set_theme_state, but it's unlikely you want to override it in context.

        @@ -162,10 +151,10 @@

        A theme is a simple JSON collection of - fuz_css style variables - that can be transformed into CSS that set custom properties. Each variable can have values for - light and/or dark color schemes. In other words, "dark" isn't a theme, it's a mode that any - theme can implement. + fuz_css style variables that can be + transformed into CSS that set custom properties. Each variable can have values for light + and/or dark color schemes. In other words, "dark" isn't a theme, it's a mode that any theme + can implement.

        @@ -207,8 +196,7 @@ Importing @fuzdev/fuz_css/style.css or theme.css alongside virtual:fuz.css ships both layers twice - the generated CSS already contains them. Those full stylesheets are for utility-only mode, which also sets - base_css: null - and variables: null on the plugin. + base_css: null and variables: null on the plugin.

        can be customized with the the nonreactive prop @@ -241,20 +229,18 @@ theme_state.theme.name; // '${theme_state.theme.name}' theme_state.color_scheme; // '${theme_state.color_scheme}'`} />

        - For a more complete example, see - fuz_template - . + For a more complete example, see + fuz_template.

        initializes the system's theme support. Without it, the - page will not reflect the user's system - color-scheme. By default, applies the base - theme to the root of the page via create_theme_setup_script. It uses JS to add - the - .dark CSS class to the :root element. + page will not reflect the user's system color-scheme. By default, + applies the base theme to the root of the page via + create_theme_setup_script. It uses JS to add the .dark CSS class to + the :root element.

        This strategy enables color scheme and theme support with minimal CSS and optimal performance diff --git a/src/routes/docs/csp/+page.svelte b/src/routes/docs/csp/+page.svelte index d12a42469..be270bbfb 100644 --- a/src/routes/docs/csp/+page.svelte +++ b/src/routes/docs/csp/+page.svelte @@ -26,9 +26,8 @@ > Content Security Policies - with the - - helper. Fuz also provides related helpers, types, and CSP data. + with the helper. Fuz also provides related + helpers, types, and CSP data.

        The API is designed to read as an audit log: every user-added source is named at exactly one @@ -107,11 +106,10 @@ const csp_blank = create_csp_directives({ replace_defaults - โ€” the starting state. Omitted, it's - . Provided, it - replaces the library defaults wholesale: exactly the directives you list, nothing - inherited. {'{}'} starts blank; null throws (avoid the - null/undefined footgun where a conditional silently disables defaults). + โ€” the starting state. Omitted, it's . + Provided, it replaces the library defaults wholesale: exactly the directives you + list, nothing inherited. {'{}'} starts blank; null throws (avoid + the null/undefined footgun where a conditional silently disables defaults).

      • extend โ€” sources to append per directive, layered left to @@ -171,8 +169,7 @@ create_csp_directives({ overrides cannot rescue an extend for a default-deny directive in the same call: extend runs first and throws before overrides would replace the value. Move the sources into overrides directly, or opt in via - replace_defaults - and then extend. + replace_defaults and then extend.

        @@ -180,8 +177,7 @@ create_csp_directives({

        The final-pass overrides option replaces a directive's value or removes it - entirely. Highest precedence. Wins over replace_defaults and - extend. + entirely. Highest precedence. Wins over replace_defaults and extend.

      • Unknown directive keys in any of replace_defaults, extend, or - overrides - throw with the offending name. + overrides throw with the offending name.
      • Extending a directive whose current value is ['none'] throws. Opt in via @@ -260,8 +255,7 @@ create_csp_directives({replace_defaults: {}, overrides: {/* ... */}});`}
      • null for replace_defaults (top-level or per-key) throws. Omit the option for library defaults, pass {'{}'} to start blank, or use - overrides - to remove a specific directive. + overrides to remove a specific directive.
      • null per-key in extend throws with a pointer to @@ -271,13 +265,11 @@ create_csp_directives({replace_defaults: {}, overrides: {/* ... */}});`}
      • undefined per-key in any of the three stages is treated as omitted (no-op). This lets conditional patterns like - {"{'connect-src': is_prod ? [API_URL] : undefined}"} - work naturally. + {"{'connect-src': is_prod ? [API_URL] : undefined}"} work naturally.
      • Non-object entries in extend (e.g. extend: [undefined]) throw a - library error pointing at the option, instead of a cryptic native - TypeError. + library error pointing at the option, instead of a cryptic native TypeError.
      • The output is validated to ensure 'none' never appears alongside other tokens @@ -291,8 +283,7 @@ create_csp_directives({replace_defaults: {}, overrides: {/* ... */}});`}
      • Source arrays are validated to contain only strings. Non-string elements (slipped through via as any) would render as undefined or - [object Object] - in the emitted header. + [object Object] in the emitted header.
      @@ -325,10 +316,8 @@ create_csp_directives({replace_defaults: {}, overrides: {/* ... */}});`} diff --git a/src/routes/docs/icons/+page.svelte b/src/routes/docs/icons/+page.svelte index addcca698..7ee3eab9b 100644 --- a/src/routes/docs/icons/+page.svelte +++ b/src/routes/docs/icons/+page.svelte @@ -17,10 +17,8 @@

      - Fuz includes a number of icons available as data that can be mounted with the - component. Only the ones you use are included in your bundle. + Fuz includes a number of icons available as data that can be mounted with the + component. Only the ones you use are included in your bundle.

      Try different parameter combinations. Positive count values disconnect after N - cycles. - 0 disables observation. Negative or undefined never disconnects. - (the default) + cycles. 0 disables observation. Negative or undefined never + disconnects. (the default)