Skip to content

Commit ef401c3

Browse files
committed
Migrate Svelte UX components, state, attachments, and docs
- Add the Svelte 5 `@layerstack/ui` package and migrated component suite - Add `FormState`, `ThemeState`, and new attachment APIs - Expand component documentation and close Svelte UX parity gaps - Fix theme synchronization, dark variants, and client-only initialization
1 parent febc651 commit ef401c3

725 files changed

Lines changed: 32869 additions & 522 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.changeset/dark-variant-system.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
'@layerstack/tailwind': patch
3+
'@layerstack/ui': patch
4+
'@layerstack/docs': patch
5+
---
6+
7+
fix: Follow `prefers-color-scheme` in the `dark:` variant, not just `<html class="dark">`.
8+
9+
There were two disagreeing sources of truth for "is it dark". The theme palettes darken from
10+
`@media (prefers-color-scheme: dark)` on `:root`, which needs no JavaScript, but the `dark:` variant
11+
was keyed on the `dark` class, which is only ever set by JavaScript. Any moment the two disagreed —
12+
before hydration, or permanently when no dark themes are registered — produced dark surfaces with
13+
every `dark:` utility still in its light state. Most visibly, code blocks styled by
14+
`dark:text-(--shiki-dark)` rendered near-black tokens on a dark background.
15+
16+
The variant now mirrors the palettes: an explicit `[data-theme]` selection wins, and everything else
17+
follows the system setting. `@layerstack/docs`' `Code` component gets the same treatment for its
18+
hand-written `html.dark .shiki` rules.
19+
20+
Also fixes `ThemeInit` on client-only apps. It injects its pre-paint script through `{@html}`, and
21+
the browser never executes a `<script>` inserted that way — so with `ssr = false` the guard was
22+
inert. `@layerstack/tailwind` now exports `applyInitialTheme`, which `ThemeInit` calls directly in
23+
the browser.

‎.changeset/docs-parity.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
'@layerstack/docs-site': patch
3+
---
4+
5+
docs: Close the concept gaps against the Svelte UX docs.
6+
7+
Every old component page was compared against the new one and the missing concepts were added —
8+
around 130 new examples across ~55 components, consolidated so one example usually covers what used
9+
to be several sections. Notable additions: `Progress` color/track/color-by-value, `Month`,
10+
`MonthList`, and `YearList` selection and disabled-date shapes, `Steps` points and colors,
11+
`Timeline` layouts, `TextField` adornments/multiline/debounce, `SelectField` states and non-string
12+
option values, `MultiSelect` option variants and slots, `Drawer` placement and persistence,
13+
`Selection` select-all/single/max, and the `Gooey`/`Shine`/`Tilt` effect parameters.
14+
15+
Also fixes five pre-existing type errors in `Table`, `TreeList`, `Popover`, and `Badge` examples.
16+
17+
Examples now collapse their source by default — only the first example on a page keeps `showCode`,
18+
since it doubles as the "how do I use this" sample. The rest are one click away behind **Show code**.

‎.changeset/form-state.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@layerstack/svelte-state': minor
3+
---
4+
5+
feat: Add `FormState` — the runes replacement for `@layerstack/svelte-stores`' `formStore`.
6+
7+
`draft` is a deeply reactive copy that inputs bind to directly, so the `refresh()`/`current` dance
8+
the immer-draft-based store required is gone. `commit()` validates against an optional schema and
9+
promotes the draft to `state`; `revert()`, `revertAll()`, and `undo()` walk it back. `isDirty` and
10+
`canUndo` replace `dirtyStore`.
11+
12+
The schema is typed structurally (anything with a zod-compatible `safeParse`), so the package
13+
depends on neither zod nor immer.

‎.changeset/layerstack-ui.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@layerstack/ui': minor
3+
---
4+
5+
feat: Add `@layerstack/ui` package — Svelte 5 successor to `svelte-ux`, starting with `Icon`, the component settings/theme system (converted to runes), and shared types

‎.changeset/real-keys-battle.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@layerstack/svelte-attachments': minor
3+
---
4+
5+
feat: Add `@layerstack/svelte-attachments` package
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@layerstack/svelte-attachments': minor
3+
'@layerstack/svelte-table': patch
4+
---
5+
6+
feat: Add `portal`, `popover`, and `scrollIntoView` attachments. `popover` takes an `onClickOutside` callback in place of the `clickOutside` custom event.
7+
8+
`tableOrderStore().onHeaderClick` now accepts either `{ column }` or a `CustomEvent`-shaped `{ detail: { column } }`, so it works with both `@layerstack/ui`'s `Table` and Svelte UX's.

‎.changeset/theme-desync.md‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
'@layerstack/svelte-state': patch
3+
'@layerstack/svelte-stores': patch
4+
'@layerstack/tailwind': patch
5+
'@layerstack/docs': patch
6+
---
7+
8+
fix: Stop the fallback settings from stripping the applied theme, and derive `dark:` from the themes.
9+
10+
`getSettings()` builds a fallback outside a `settings()` provider, and that fallback constructed a
11+
theme store with **no themes configured**. Its constructor still ran, read `localStorage`, wrote
12+
`<html data-theme="dark">`, and then — because `[].includes('dark')` is false — *removed* the `dark`
13+
class the real instance had just applied. The result was `data-theme="dark"` with no `dark` class:
14+
a dark palette with every `dark:` utility still light, most visibly light code tokens on a dark
15+
background. Whether it happened at all depended on when the fallback was first touched, which is why
16+
it was intermittent, and why toggling the theme fixed it.
17+
18+
A theme store with nothing configured is now inert — it never touches the document or
19+
`localStorage`. A stored theme the app no longer defines is also ignored rather than applied, since
20+
it cannot be classified as light or dark.
21+
22+
The `dark:` variant is now generated from the themes themselves. A theme declares its darkness with
23+
`color-scheme: dark`, so that is the single source of truth: `@custom-variant dark` lists every dark
24+
`[data-theme]` alongside `.dark` and the `prefers-color-scheme` fallback. The palette and the variant
25+
can no longer disagree, whatever JavaScript does.
26+
27+
`@layerstack/docs` moves its Shiki color rules out of `Code.svelte`'s `<style>` block — Svelte
28+
compiles those, so Tailwind never saw the `dark:` variant there — and into `styles.css`, which also
29+
covers the runtime-highlighted blocks that the markdown-only rule missed.

‎.changeset/theme-state.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@layerstack/svelte-state': patch
3+
---
4+
5+
feat: Add `ThemeState` (replaces `createThemeStore` from `@layerstack/svelte-stores`) and export a `breakpoints` constant

‎.changeset/ui-code-copybutton.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@layerstack/ui': minor
3+
---
4+
5+
feat: Add `Code` and `CopyButton`. `shiki` and `@shikijs/transformers` are optional peer dependencies — `Code` renders plain text when they are not installed.
6+
7+
`ApiDocs`, `StoreSubscribe`, `State`, and `Preview` are not being migrated from Svelte UX; see `MIGRATION.md` for replacements.

‎.changeset/ui-form.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@layerstack/ui': minor
3+
---
4+
5+
feat: Migrate `Form`, the last remaining Svelte UX component.
6+
7+
- The nine slot props collapse to a single `{ form }` snippet argument — a `FormState` carrying
8+
`draft`, `state`, `errors`, `isDirty`, `canUndo`, `commit`, `revert`, `revertAll`, and `undo`.
9+
- `on:change` is the `onChange(value)` callback prop, and no longer fires on mount.
10+
- `refresh()`/`current` are gone: `form.draft` is deeply reactive, so `bind:value={form.draft.name}`
11+
is enough.
12+
- A `form` prop accepts externally owned `FormState`, for reading or driving the form from outside.

0 commit comments

Comments
 (0)