diff --git a/.changeset/aschild-slottable-decorations.md b/.changeset/aschild-slottable-decorations.md deleted file mode 100644 index 5f0cc4e..0000000 --- a/.changeset/aschild-slottable-decorations.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@reactive/silk": patch ---- - -Fix `asChild` on every part that renders a decoration alongside its children. `Select.Trigger`, `Accordion.Trigger`, `DropdownMenu.SubTrigger`, `DropdownMenu.Item`, and `Field.Label` each threw "Primitive.\* failed to slot onto its children" because the chevron / caret / shortcut / required indicator was a second slot child. Their children are now wrapped in `Slot.Slottable`, so a custom element receives its own children plus the appended decoration. This applies even where the decoration is conditional (`DropdownMenu.Item shortcut`, `Field.Label` on a required field) — the `null` branch counted as a second child, so those parts threw on `asChild` regardless. The default (non-`asChild`) render path is unchanged. - -Two assembled parts cannot support `asChild` at all, and now say so at the type level instead of throwing at runtime: `asChild` is omitted from `SelectItemProps` and `SelectContentProps`, matching `Checkbox`, `Switch`, `Slider`, `RadioGroup`, and `Progress`. `Select.Item` wraps children in `RadixSelect.ItemText`, and `Slottable` substitutes the consumer's children unwrapped, so no arrangement yields "consumer element is the item, containing indicator + `ItemText`". `Select.Content` assembles a Viewport plus both scroll buttons, so there is likewise no single slot target. - -The rule and its `null`-branch pitfall are documented once in [ARCHITECTURE.md](../docs/ARCHITECTURE.md#aschild-with-decorations). diff --git a/.changeset/comment-footer-slot.md b/.changeset/comment-footer-slot.md deleted file mode 100644 index a908848..0000000 --- a/.changeset/comment-footer-slot.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@reactive/silk": minor ---- - -Add a `footer` slot to `Comment` for a trailing affordance that belongs to the comment rather than to its replies. It renders in the content column after the replies and outside their rail. - -`CommentThread` now routes its "Continue thread" button there. It previously went through the `replies` slot, which always wraps its content in a railed reply stack, so a comment at `maxDepth` with nothing nested inline drew a reply rail beside a lone button. diff --git a/.changeset/cowork-font-defaults.md b/.changeset/cowork-font-defaults.md deleted file mode 100644 index f4d21aa..0000000 --- a/.changeset/cowork-font-defaults.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@reactive/silk-core": minor -"@reactive/silk": minor ---- - -Cowork-inspired font defaults: first-class `sans` / `serif` / `mono` families. - -**breaking:** -- `TypographyRecord.family` is now a `FontFamilyName` (`'sans' | 'serif' | 'mono'`) instead of a raw CSS `font-family` stack. -- `SemanticTokens` gains required `fontFamily: Record` (CSS stacks). Exhaustive `Record` / merge helpers must include it. -- Default stacks lead with Inter / Source Serif 4 / JetBrains Mono (plus system fallbacks). Only `headingXl` (display / page H1) uses `serif`; section/panel `headingLg` and other roles stay `sans`. -- Web CSS emits `--silk-font-sans`, `--silk-font-serif`, `--silk-font-mono`; role vars are indirect (`--silk-typography-*-family: var(--silk-font-…)`). - -Silk still ships no font files — load the faces yourself or fall through to system. Override via `createTheme({ semantic: { fontFamily: { sans: '…' } } })` or the `--silk-font-*` CSS variables. diff --git a/.changeset/field-horizontal-wrapped-slots.md b/.changeset/field-horizontal-wrapped-slots.md deleted file mode 100644 index 8744742..0000000 --- a/.changeset/field-horizontal-wrapped-slots.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@reactive/silk": patch ---- - -Keep `Field.Root orientation="horizontal"` correct when slots sit inside a layout wrapper. The grid pinned only direct `Field.Label` / `Description` / `Error` children to column 2, so a `Stack` or `Inline` around the description auto-placed into the control column — even though Field already treats those wrappers as transparent when wiring `aria-describedby`. Wrappers holding a slot are now pinned too, and the label owns row 1 so the control stays beside it regardless of child order. diff --git a/.changeset/field-labelledby-presence.md b/.changeset/field-labelledby-presence.md deleted file mode 100644 index 2eced07..0000000 --- a/.changeset/field-labelledby-presence.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@reactive/silk": patch ---- - -Only wire `aria-labelledby` from Field context when a `Field.Label` is actually rendered, and point it at the label's own id. A `Slider` in a label-less `Field.Root` no longer gets a dangling `aria-labelledby`, so its `aria-label` names the `role="slider"` thumb again. - -Detect `Field.Label` / `Description` / `Error` among descendants (not only direct children) so layout wrappers like `Inline` / `Stack` still populate `aria-labelledby` / `aria-describedby`. Nested `Field.Root` boundaries are respected. diff --git a/.changeset/field-slider-label-association.md b/.changeset/field-slider-label-association.md deleted file mode 100644 index 657701f..0000000 --- a/.changeset/field-slider-label-association.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@reactive/silk": patch ---- - -`Slider` inside a single-mode `Field.Root` no longer gets a dangling or non-functional Label `htmlFor`. Field detects labelledby-marked controls (`fieldLabelAssociation`), omits automatic `htmlFor` / control `id`, and keeps naming on the thumb via `aria-labelledby`. Explicit `id` / `htmlFor` still win. - -`Field.Root required` still shows the label indicator for Slider fields; `required` / `aria-required` are not forwarded onto the thumb because range / `role="slider"` always has a value and does not support those attributes. diff --git a/.changeset/floating-stacking-scale.md b/.changeset/floating-stacking-scale.md deleted file mode 100644 index 86b9d08..0000000 --- a/.changeset/floating-stacking-scale.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@reactive/silk': patch ---- - -Dialog overlay and content now draw their `z-index` from the shared floating stacking scale, so page content with a modest `z-index` (sticky headers, app chrome) no longer paints over the scrim or the panel. The overlay previously had no `z-index` at all and content used a local `z-index: 1`. - -Dialog sits below popovers, menus, selects, tooltips, and toasts on that scale. Those surfaces portal to the body as siblings of the dialog panel rather than descendants, so they must outrank it to remain visible when opened from inside a dialog. diff --git a/.changeset/native-motion-preference.md b/.changeset/native-motion-preference.md deleted file mode 100644 index 824c6f6..0000000 --- a/.changeset/native-motion-preference.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@reactive/silk-native': minor ---- - -Stop native Spinner and Progress from flashing their reduced-motion appearance on mount. React Native exposes the OS preference only through async `AccessibilityInfo`, so the first render is now `'unresolved'`: motion stays suppressed, but the full-motion visuals render until the OS confirms `'reduced'`. Adds `useMotionPreference` for components that swap appearance (not just animation) and caches the OS answer so only the first mount is ever unresolved. diff --git a/.changeset/native-visual-forms.md b/.changeset/native-visual-forms.md deleted file mode 100644 index 4d5e644..0000000 --- a/.changeset/native-visual-forms.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@reactive/silk-native': minor ---- - -Expand the native renderer with visual primitives (Surface, Card, Heading, Badge, Separator, Avatar, StatusDot, Skeleton, Spinner, Progress) and forms (Input, Textarea, Field, Checkbox, Switch, RadioGroup). Same silk-core recipes as web; RNW a11y compat helpers; Slider deferred to preserve the shared array-valued contract. diff --git a/.changeset/portal-theme-scope.md b/.changeset/portal-theme-scope.md deleted file mode 100644 index 3b00bbd..0000000 --- a/.changeset/portal-theme-scope.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@reactive/silk": patch ---- - -Reconstitute the nearest ThemeProvider scope on portaled Dialog content so theme CSS variables resolve outside the provider DOM subtree. diff --git a/.changeset/ranked-escape-hatches.md b/.changeset/ranked-escape-hatches.md deleted file mode 100644 index 409c64a..0000000 --- a/.changeset/ranked-escape-hatches.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@reactive/silk': minor ---- - -Rank the escape hatches and make the cascade contract explicit. - -- New `@reactive/silk/styles.layer.css` entry ships the extracted stylesheet wrapped in `@layer silk`, so unlayered consumer CSS overrides Silk deterministically instead of depending on bundler stylesheet order. The unlayered `styles.css` is unchanged and still the default, since the layered build also loses to unlayered consumer resets. -- New `cssVars()` helper types the public component hooks for the `style` prop, replacing the `as CSSProperties` cast that custom properties otherwise require (and that silences misspelled variable names). `silkComponentVarNames` exports the hook list, guarded by a conformance test against the extracted CSS. -- `--silk-scrollarea-thumb` now follows the same `var(hook, fallback)` pattern as every other hook. It was previously assigned on the ScrollArea root, which shadowed consumer overrides of equal specificity. diff --git a/.changeset/scrollarea-viewport-tabindex.md b/.changeset/scrollarea-viewport-tabindex.md deleted file mode 100644 index 9aa46d7..0000000 --- a/.changeset/scrollarea-viewport-tabindex.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@reactive/silk': patch ---- - -Make ScrollArea viewport keyboard-focusable by default (`tabIndex={0}`) so scrollable regions meet axe `scrollable-region-focusable`. diff --git a/.changeset/silk-foundation.md b/.changeset/silk-foundation.md deleted file mode 100644 index 9656d21..0000000 --- a/.changeset/silk-foundation.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@reactive/silk-core": minor -"@reactive/silk": minor ---- - -Foundation release: platform-neutral tokens/theme/recipes in `@reactive/silk-core`, web renderer with Linaria + Radix exemplars (Box, Stack, Text, Button, Avatar, Dialog, Identity), ThemeProvider/SilkProvider, and registry scaffold. diff --git a/.changeset/single-axis-layout-primitives.md b/.changeset/single-axis-layout-primitives.md deleted file mode 100644 index 4b38d58..0000000 --- a/.changeset/single-axis-layout-primitives.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@reactive/silk-core': minor -'@reactive/silk': minor ---- - -Layout flow direction is a property of the component, never a prop: `Stack` is vertical, `Inline` is horizontal, and neither can flip its axis. - -A `direction` prop would mean the same `align`/`justify` values silently swap visual axis per call site. Fixing the axis per component — rather than renaming the props — keeps the standard flexbox reading of `align` and `justify` correct everywhere. - -- **`Stack` is vertical-only.** `stackRecipe.variants` is exactly `gap`, `align`, `justify`, `rail`. Reach for `Inline` for horizontal flow; it additionally carries `wrap`, `direction` (`row | row-reverse`, order rather than axis), and the web-only `collapseBelow`. -- **Choosing between them:** vertical is `Stack`, horizontal is `Inline`. Their defaults differ deliberately — `Stack` is `align="stretch"`, `Inline` is `align="center"` and `wrap="wrap"` — so set `align`/`wrap` explicitly when a row must stretch to equal heights or must not reflow. -- **Centering** is `align`/`justify` set to `"center"`. `Container` owns max-width measure centering (`margin-inline: auto` + `max-width`). -- **`Grid` has `justify`** (`start | center | end | stretch`, default `stretch`) mapped to `justify-items`, pairing with `align` → `align-items`: `columns` always emits `1fr` tracks, so there is no free space for `justify-content` to distribute. On `Stack` and `Inline`, `justify` is `justify-content`. diff --git a/.changeset/slider-multi-thumb-a11y.md b/.changeset/slider-multi-thumb-a11y.md deleted file mode 100644 index 80e5297..0000000 --- a/.changeset/slider-multi-thumb-a11y.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@reactive/silk": patch ---- - -Name multi-thumb `Slider` thumbs when `thumbLabels` is omitted: fall back to Field label or an indexed root `aria-label`, and wire `aria-describedby` on every thumb. Explicit `thumbLabels` clear Field `aria-labelledby` so they win in accessible name computation. diff --git a/.changeset/stage-1-layout.md b/.changeset/stage-1-layout.md deleted file mode 100644 index 49b5a99..0000000 --- a/.changeset/stage-1-layout.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@reactive/silk-core": minor -"@reactive/silk": minor ---- - -Stage 1 layout system: `Inline`, `Grid`, `Container`, `Separator`, and `Box` padding; system density via `compactSpace` + `data-density` space remaps; web-only `collapseBelow` container queries; ThemeProvider density / nested theme inheritance. diff --git a/.changeset/stage-2-visual-forms.md b/.changeset/stage-2-visual-forms.md deleted file mode 100644 index f6042ce..0000000 --- a/.changeset/stage-2-visual-forms.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -"@reactive/silk-core": minor -"@reactive/silk": minor ---- - -Stage 2 visual primitives and forms foundation. - -**breaking:** -- `ToneName`: add `success` to every exhaustive `Record` / switch. -- `InteractionToneColors`: add required `text`, `subtleHover`, and `subtleActive` (old soft/outline/ghost remaps of `border`/`hover` are gone — use the new slots). -- `SemanticTokens`: add `color.surfaceSunken`, `color.overlay`, `shadow.{raised,overlay}`, and `focusRing.{width,offset}`; typography adds `headingSm` / `headingXl`. -- Light solid fills use palette step 11 (was 9) so `onSolid: #fff` meets WCAG 4.5:1. -- `createSharedSemanticScales()` is removed — use the `sharedSemanticScales` constant. -- `MotionName` adds `loop` (1200ms, linear) for continuous indeterminate motion; `fast`/`normal`/`slow` stay one-shot transition durations. Exhaustive `Record` literals must add `loop`. -- Tone `hover` / `active` are now three distinct fills alongside `solid` in both schemes. Light `hover` is blended between palette steps 11 and 12 rather than being step 12 (which collided with `active`), and neutral `active` is step 11 rather than step 12 (which collided with `solid`). Themes that hardcoded those hex values must re-derive them. -- `FieldContextValue` drops `controlId`; `inputId` is now the single resolved control id. `Field.Root` gains `controlId` for naming that control — setting `id` on the control itself no longer retargets Label `htmlFor`, which previously required a post-hydration effect and produced a dangling `for=` on the server. - -Adds `Surface`, `Card`, `Heading`, `Badge`, `Skeleton`, `Spinner`, `Progress`, `Field`, `Input`, `Textarea`, `Checkbox`, `RadioGroup`, `Switch`, `Slider`; settings-form fixture; contrast and theming acceptance tests. diff --git a/.changeset/stage-3-interaction-primitives.md b/.changeset/stage-3-interaction-primitives.md deleted file mode 100644 index fda0d1d..0000000 --- a/.changeset/stage-3-interaction-primitives.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@reactive/silk-core': minor -'@reactive/silk': minor ---- - -Stage 3 interaction primitives: Popover, Tooltip, DropdownMenu, Select, Tabs, Accordion, ScrollArea, Toast, Toggle/ToggleGroup — shared floating-surface motion, recipes, portal theme reconstitution, InspectorPanel fixture, and CI performance budgets. diff --git a/.changeset/stage-4-composites.md b/.changeset/stage-4-composites.md deleted file mode 100644 index 7ef0efa..0000000 --- a/.changeset/stage-4-composites.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@reactive/silk-core': minor -'@reactive/silk': minor ---- - -Stage 4 composites: product components, serializable models, and composition standard. - -- Add `@reactive/silk-core/models` (Identity/Stat/Media/Post/Comment/Notification/Profile/FeedEntry) and composite recipes. -- Close primitive gaps: Card/Surface `interactive` hover elevation, Inline `direction`, Stack `rail`, `StatusDot`. -- Ship composites: MediaObject, ActionBar, StatGroup, EmptyState, PostCard, Comment, CommentThread, Notification, FeedItem, ProfileCard, SettingsPanel. -- Document the compound-first dual API in `docs/COMPOSITES.md`. -- Retrofit Identity onto Inline (additive `model` prop — non-breaking). -- SocialFeed exit fixture; registry sync script emits consumer-owned composite source. diff --git a/.changeset/stage-5-theming-core.md b/.changeset/stage-5-theming-core.md deleted file mode 100644 index 012bd78..0000000 --- a/.changeset/stage-5-theming-core.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@reactive/silk-core': minor ---- - -Stage 5 theming maturity (core): palette generation, paired dark derivation, and contrast auditing. - -- Add `generateScale(seedHex, colorScheme)` — OKLCH 12-step ramps from canonical sRGB hex. -- Add `generatePairedPalette(brandHex)` — tenant recipe producing full light+dark palettes (accent + brand-tinted gray; optional danger/success seeds). -- Add `checkThemeContrast`, `contrastRatio`, `relativeLuminance`, and `parseCanonicalHex` for CI/tooling. -- Depends on `culori` for OKLCH conversion and gamut mapping (private to the generator). diff --git a/.changeset/stage-5-theming-web.md b/.changeset/stage-5-theming-web.md deleted file mode 100644 index fb83b04..0000000 --- a/.changeset/stage-5-theming-web.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@reactive/silk': minor ---- - -Stage 5 theming maturity (web): portal variable channels and re-exports. - -- Split theme-scope CSS vars into `semanticVars` (replaced by nested `theme`/`colorScheme`) and `customVars` (component hooks that inherit through named children into portals). -- Re-export `generateScale`, `generatePairedPalette`, `checkThemeContrast`, and related types from `@reactive/silk`. -- Document the frozen public component CSS-variable list via `silkComponentVarMeta` / `formatComponentVarDocsTable`. diff --git a/.changeset/stage-6-silk-native.md b/.changeset/stage-6-silk-native.md deleted file mode 100644 index 2ee97d3..0000000 --- a/.changeset/stage-6-silk-native.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@reactive/silk-native': minor ---- - -Introduce `@reactive/silk-native`: React Native renderer for Silk with context-based `ThemeProvider` / `SilkProvider`, style mappers from `silk-core` recipes, and exemplar components `Box`, `Stack`, `Inline`, `Text`, and `Button`. Same semantic Theme object and recipe contracts as web; no CSS variables. diff --git a/apps/docs/CHANGELOG.md b/apps/docs/CHANGELOG.md new file mode 100644 index 0000000..f8ba4c0 --- /dev/null +++ b/apps/docs/CHANGELOG.md @@ -0,0 +1,31 @@ +# @reactive/silk-docs + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [2c7c49f] +- Updated dependencies [2b03511] +- Updated dependencies [b4fd11a] +- Updated dependencies [2b03511] +- Updated dependencies [338fe46] +- Updated dependencies [338fe46] +- Updated dependencies [2c7c49f] +- Updated dependencies [c3b0184] +- Updated dependencies [c3b0184] +- Updated dependencies [3f24b2f] +- Updated dependencies [2c7c49f] +- Updated dependencies [3fd5030] +- Updated dependencies [09d876d] +- Updated dependencies [3bf1155] +- Updated dependencies [338fe46] +- Updated dependencies [7b6407b] +- Updated dependencies [338fe46] +- Updated dependencies [2c7c49f] +- Updated dependencies [3bf1155] +- Updated dependencies [e2aa5b9] +- Updated dependencies [e2aa5b9] +- Updated dependencies [0789bd0] + - @reactive/silk@0.1.0 + - @reactive/silk-core@0.1.0 + - @reactive/silk-native@0.1.0 diff --git a/apps/docs/package.json b/apps/docs/package.json index 8f16cdc..d931106 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -1,7 +1,7 @@ { "name": "@reactive/silk-docs", "private": true, - "version": "0.0.0", + "version": "0.0.1", "description": "Storybook documentation site for Silk", "license": "MIT", "type": "module", diff --git a/apps/native-example/CHANGELOG.md b/apps/native-example/CHANGELOG.md new file mode 100644 index 0000000..7b576cc --- /dev/null +++ b/apps/native-example/CHANGELOG.md @@ -0,0 +1,19 @@ +# @reactive/silk-native-example + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [b4fd11a] +- Updated dependencies [c3b0184] +- Updated dependencies [c3b0184] +- Updated dependencies [09d876d] +- Updated dependencies [3bf1155] +- Updated dependencies [7b6407b] +- Updated dependencies [338fe46] +- Updated dependencies [2c7c49f] +- Updated dependencies [3bf1155] +- Updated dependencies [e2aa5b9] +- Updated dependencies [0789bd0] + - @reactive/silk-core@0.1.0 + - @reactive/silk-native@0.1.0 diff --git a/apps/native-example/package.json b/apps/native-example/package.json index bf6aea9..63f36e9 100644 --- a/apps/native-example/package.json +++ b/apps/native-example/package.json @@ -2,7 +2,7 @@ "name": "@reactive/silk-native-example", "private": true, "type": "module", - "version": "0.0.0", + "version": "0.0.1", "description": "Expo example consuming @reactive/silk-native (Stage 6 exit demo)", "license": "MIT", "main": "index.ts", diff --git a/packages/silk-core/CHANGELOG.md b/packages/silk-core/CHANGELOG.md new file mode 100644 index 0000000..2a98f5b --- /dev/null +++ b/packages/silk-core/CHANGELOG.md @@ -0,0 +1,59 @@ +# @reactive/silk-core + +## 0.1.0 + +### Minor Changes + +- b4fd11a: Cowork-inspired font defaults: first-class `sans` / `serif` / `mono` families. + + **breaking:** + + - `TypographyRecord.family` is now a `FontFamilyName` (`'sans' | 'serif' | 'mono'`) instead of a raw CSS `font-family` stack. + - `SemanticTokens` gains required `fontFamily: Record` (CSS stacks). Exhaustive `Record` / merge helpers must include it. + - Default stacks lead with Inter / Source Serif 4 / JetBrains Mono (plus system fallbacks). Only `headingXl` (display / page H1) uses `serif`; section/panel `headingLg` and other roles stay `sans`. + - Web CSS emits `--silk-font-sans`, `--silk-font-serif`, `--silk-font-mono`; role vars are indirect (`--silk-typography-*-family: var(--silk-font-…)`). + + Silk still ships no font files — load the faces yourself or fall through to system. Override via `createTheme({ semantic: { fontFamily: { sans: '…' } } })` or the `--silk-font-*` CSS variables. + +- 09d876d: Foundation release: platform-neutral tokens/theme/recipes in `@reactive/silk-core`, web renderer with Linaria + Radix exemplars (Box, Stack, Text, Button, Avatar, Dialog, Identity), ThemeProvider/SilkProvider, and registry scaffold. +- 3bf1155: Layout flow direction is a property of the component, never a prop: `Stack` is vertical, `Inline` is horizontal, and neither can flip its axis. + + A `direction` prop would mean the same `align`/`justify` values silently swap visual axis per call site. Fixing the axis per component — rather than renaming the props — keeps the standard flexbox reading of `align` and `justify` correct everywhere. + + - **`Stack` is vertical-only.** `stackRecipe.variants` is exactly `gap`, `align`, `justify`, `rail`. Reach for `Inline` for horizontal flow; it additionally carries `wrap`, `direction` (`row | row-reverse`, order rather than axis), and the web-only `collapseBelow`. + - **Choosing between them:** vertical is `Stack`, horizontal is `Inline`. Their defaults differ deliberately — `Stack` is `align="stretch"`, `Inline` is `align="center"` and `wrap="wrap"` — so set `align`/`wrap` explicitly when a row must stretch to equal heights or must not reflow. + - **Centering** is `align`/`justify` set to `"center"`. `Container` owns max-width measure centering (`margin-inline: auto` + `max-width`). + - **`Grid` has `justify`** (`start | center | end | stretch`, default `stretch`) mapped to `justify-items`, pairing with `align` → `align-items`: `columns` always emits `1fr` tracks, so there is no free space for `justify-content` to distribute. On `Stack` and `Inline`, `justify` is `justify-content`. + +- 7b6407b: Stage 1 layout system: `Inline`, `Grid`, `Container`, `Separator`, and `Box` padding; system density via `compactSpace` + `data-density` space remaps; web-only `collapseBelow` container queries; ThemeProvider density / nested theme inheritance. +- 338fe46: Stage 2 visual primitives and forms foundation. + + **breaking:** + + - `ToneName`: add `success` to every exhaustive `Record` / switch. + - `InteractionToneColors`: add required `text`, `subtleHover`, and `subtleActive` (old soft/outline/ghost remaps of `border`/`hover` are gone — use the new slots). + - `SemanticTokens`: add `color.surfaceSunken`, `color.overlay`, `shadow.{raised,overlay}`, and `focusRing.{width,offset}`; typography adds `headingSm` / `headingXl`. + - Light solid fills use palette step 11 (was 9) so `onSolid: #fff` meets WCAG 4.5:1. + - `createSharedSemanticScales()` is removed — use the `sharedSemanticScales` constant. + - `MotionName` adds `loop` (1200ms, linear) for continuous indeterminate motion; `fast`/`normal`/`slow` stay one-shot transition durations. Exhaustive `Record` literals must add `loop`. + - Tone `hover` / `active` are now three distinct fills alongside `solid` in both schemes. Light `hover` is blended between palette steps 11 and 12 rather than being step 12 (which collided with `active`), and neutral `active` is step 11 rather than step 12 (which collided with `solid`). Themes that hardcoded those hex values must re-derive them. + - `FieldContextValue` drops `controlId`; `inputId` is now the single resolved control id. `Field.Root` gains `controlId` for naming that control — setting `id` on the control itself no longer retargets Label `htmlFor`, which previously required a post-hydration effect and produced a dangling `for=` on the server. + + Adds `Surface`, `Card`, `Heading`, `Badge`, `Skeleton`, `Spinner`, `Progress`, `Field`, `Input`, `Textarea`, `Checkbox`, `RadioGroup`, `Switch`, `Slider`; settings-form fixture; contrast and theming acceptance tests. + +- 2c7c49f: Stage 3 interaction primitives: Popover, Tooltip, DropdownMenu, Select, Tabs, Accordion, ScrollArea, Toast, Toggle/ToggleGroup — shared floating-surface motion, recipes, portal theme reconstitution, InspectorPanel fixture, and CI performance budgets. +- 3bf1155: Stage 4 composites: product components, serializable models, and composition standard. + + - Add `@reactive/silk-core/models` (Identity/Stat/Media/Post/Comment/Notification/Profile/FeedEntry) and composite recipes. + - Close primitive gaps: Card/Surface `interactive` hover elevation, Inline `direction`, Stack `rail`, `StatusDot`. + - Ship composites: MediaObject, ActionBar, StatGroup, EmptyState, PostCard, Comment, CommentThread, Notification, FeedItem, ProfileCard, SettingsPanel. + - Document the compound-first dual API in `docs/COMPOSITES.md`. + - Retrofit Identity onto Inline (additive `model` prop — non-breaking). + - SocialFeed exit fixture; registry sync script emits consumer-owned composite source. + +- e2aa5b9: Stage 5 theming maturity (core): palette generation, paired dark derivation, and contrast auditing. + + - Add `generateScale(seedHex, colorScheme)` — OKLCH 12-step ramps from canonical sRGB hex. + - Add `generatePairedPalette(brandHex)` — tenant recipe producing full light+dark palettes (accent + brand-tinted gray; optional danger/success seeds). + - Add `checkThemeContrast`, `contrastRatio`, `relativeLuminance`, and `parseCanonicalHex` for CI/tooling. + - Depends on `culori` for OKLCH conversion and gamut mapping (private to the generator). diff --git a/packages/silk-core/package.json b/packages/silk-core/package.json index 40aeafa..b0fc0fd 100644 --- a/packages/silk-core/package.json +++ b/packages/silk-core/package.json @@ -1,6 +1,6 @@ { "name": "@reactive/silk-core", - "version": "0.0.0", + "version": "0.1.0", "description": "Platform-neutral tokens, themes, and recipe contracts for Silk", "license": "MIT", "type": "module", diff --git a/packages/silk-native/CHANGELOG.md b/packages/silk-native/CHANGELOG.md new file mode 100644 index 0000000..99c5793 --- /dev/null +++ b/packages/silk-native/CHANGELOG.md @@ -0,0 +1,21 @@ +# @reactive/silk-native + +## 0.1.0 + +### Minor Changes + +- c3b0184: Stop native Spinner and Progress from flashing their reduced-motion appearance on mount. React Native exposes the OS preference only through async `AccessibilityInfo`, so the first render is now `'unresolved'`: motion stays suppressed, but the full-motion visuals render until the OS confirms `'reduced'`. Adds `useMotionPreference` for components that swap appearance (not just animation) and caches the OS answer so only the first mount is ever unresolved. +- c3b0184: Expand the native renderer with visual primitives (Surface, Card, Heading, Badge, Separator, Avatar, StatusDot, Skeleton, Spinner, Progress) and forms (Input, Textarea, Field, Checkbox, Switch, RadioGroup). Same silk-core recipes as web; RNW a11y compat helpers; Slider deferred to preserve the shared array-valued contract. +- 0789bd0: Introduce `@reactive/silk-native`: React Native renderer for Silk with context-based `ThemeProvider` / `SilkProvider`, style mappers from `silk-core` recipes, and exemplar components `Box`, `Stack`, `Inline`, `Text`, and `Button`. Same semantic Theme object and recipe contracts as web; no CSS variables. + +### Patch Changes + +- Updated dependencies [b4fd11a] +- Updated dependencies [09d876d] +- Updated dependencies [3bf1155] +- Updated dependencies [7b6407b] +- Updated dependencies [338fe46] +- Updated dependencies [2c7c49f] +- Updated dependencies [3bf1155] +- Updated dependencies [e2aa5b9] + - @reactive/silk-core@0.1.0 diff --git a/packages/silk-native/package.json b/packages/silk-native/package.json index 38b60c3..c80c069 100644 --- a/packages/silk-native/package.json +++ b/packages/silk-native/package.json @@ -1,6 +1,6 @@ { "name": "@reactive/silk-native", - "version": "0.0.0", + "version": "0.1.0", "description": "React Native renderer for Silk — semantic themes and recipe contracts without CSS variables", "license": "MIT", "type": "module", diff --git a/packages/silk/CHANGELOG.md b/packages/silk/CHANGELOG.md new file mode 100644 index 0000000..f2d484e --- /dev/null +++ b/packages/silk/CHANGELOG.md @@ -0,0 +1,102 @@ +# @reactive/silk + +## 0.1.0 + +### Minor Changes + +- 2b03511: Add a `footer` slot to `Comment` for a trailing affordance that belongs to the comment rather than to its replies. It renders in the content column after the replies and outside their rail. + + `CommentThread` now routes its "Continue thread" button there. It previously went through the `replies` slot, which always wraps its content in a railed reply stack, so a comment at `maxDepth` with nothing nested inline drew a reply rail beside a lone button. + +- b4fd11a: Cowork-inspired font defaults: first-class `sans` / `serif` / `mono` families. + + **breaking:** + + - `TypographyRecord.family` is now a `FontFamilyName` (`'sans' | 'serif' | 'mono'`) instead of a raw CSS `font-family` stack. + - `SemanticTokens` gains required `fontFamily: Record` (CSS stacks). Exhaustive `Record` / merge helpers must include it. + - Default stacks lead with Inter / Source Serif 4 / JetBrains Mono (plus system fallbacks). Only `headingXl` (display / page H1) uses `serif`; section/panel `headingLg` and other roles stay `sans`. + - Web CSS emits `--silk-font-sans`, `--silk-font-serif`, `--silk-font-mono`; role vars are indirect (`--silk-typography-*-family: var(--silk-font-…)`). + + Silk still ships no font files — load the faces yourself or fall through to system. Override via `createTheme({ semantic: { fontFamily: { sans: '…' } } })` or the `--silk-font-*` CSS variables. + +- 2c7c49f: Rank the escape hatches and make the cascade contract explicit. + + - New `@reactive/silk/styles.layer.css` entry ships the extracted stylesheet wrapped in `@layer silk`, so unlayered consumer CSS overrides Silk deterministically instead of depending on bundler stylesheet order. The unlayered `styles.css` is unchanged and still the default, since the layered build also loses to unlayered consumer resets. + - New `cssVars()` helper types the public component hooks for the `style` prop, replacing the `as CSSProperties` cast that custom properties otherwise require (and that silences misspelled variable names). `silkComponentVarNames` exports the hook list, guarded by a conformance test against the extracted CSS. + - `--silk-scrollarea-thumb` now follows the same `var(hook, fallback)` pattern as every other hook. It was previously assigned on the ScrollArea root, which shadowed consumer overrides of equal specificity. + +- 09d876d: Foundation release: platform-neutral tokens/theme/recipes in `@reactive/silk-core`, web renderer with Linaria + Radix exemplars (Box, Stack, Text, Button, Avatar, Dialog, Identity), ThemeProvider/SilkProvider, and registry scaffold. +- 3bf1155: Layout flow direction is a property of the component, never a prop: `Stack` is vertical, `Inline` is horizontal, and neither can flip its axis. + + A `direction` prop would mean the same `align`/`justify` values silently swap visual axis per call site. Fixing the axis per component — rather than renaming the props — keeps the standard flexbox reading of `align` and `justify` correct everywhere. + + - **`Stack` is vertical-only.** `stackRecipe.variants` is exactly `gap`, `align`, `justify`, `rail`. Reach for `Inline` for horizontal flow; it additionally carries `wrap`, `direction` (`row | row-reverse`, order rather than axis), and the web-only `collapseBelow`. + - **Choosing between them:** vertical is `Stack`, horizontal is `Inline`. Their defaults differ deliberately — `Stack` is `align="stretch"`, `Inline` is `align="center"` and `wrap="wrap"` — so set `align`/`wrap` explicitly when a row must stretch to equal heights or must not reflow. + - **Centering** is `align`/`justify` set to `"center"`. `Container` owns max-width measure centering (`margin-inline: auto` + `max-width`). + - **`Grid` has `justify`** (`start | center | end | stretch`, default `stretch`) mapped to `justify-items`, pairing with `align` → `align-items`: `columns` always emits `1fr` tracks, so there is no free space for `justify-content` to distribute. On `Stack` and `Inline`, `justify` is `justify-content`. + +- 7b6407b: Stage 1 layout system: `Inline`, `Grid`, `Container`, `Separator`, and `Box` padding; system density via `compactSpace` + `data-density` space remaps; web-only `collapseBelow` container queries; ThemeProvider density / nested theme inheritance. +- 338fe46: Stage 2 visual primitives and forms foundation. + + **breaking:** + + - `ToneName`: add `success` to every exhaustive `Record` / switch. + - `InteractionToneColors`: add required `text`, `subtleHover`, and `subtleActive` (old soft/outline/ghost remaps of `border`/`hover` are gone — use the new slots). + - `SemanticTokens`: add `color.surfaceSunken`, `color.overlay`, `shadow.{raised,overlay}`, and `focusRing.{width,offset}`; typography adds `headingSm` / `headingXl`. + - Light solid fills use palette step 11 (was 9) so `onSolid: #fff` meets WCAG 4.5:1. + - `createSharedSemanticScales()` is removed — use the `sharedSemanticScales` constant. + - `MotionName` adds `loop` (1200ms, linear) for continuous indeterminate motion; `fast`/`normal`/`slow` stay one-shot transition durations. Exhaustive `Record` literals must add `loop`. + - Tone `hover` / `active` are now three distinct fills alongside `solid` in both schemes. Light `hover` is blended between palette steps 11 and 12 rather than being step 12 (which collided with `active`), and neutral `active` is step 11 rather than step 12 (which collided with `solid`). Themes that hardcoded those hex values must re-derive them. + - `FieldContextValue` drops `controlId`; `inputId` is now the single resolved control id. `Field.Root` gains `controlId` for naming that control — setting `id` on the control itself no longer retargets Label `htmlFor`, which previously required a post-hydration effect and produced a dangling `for=` on the server. + + Adds `Surface`, `Card`, `Heading`, `Badge`, `Skeleton`, `Spinner`, `Progress`, `Field`, `Input`, `Textarea`, `Checkbox`, `RadioGroup`, `Switch`, `Slider`; settings-form fixture; contrast and theming acceptance tests. + +- 2c7c49f: Stage 3 interaction primitives: Popover, Tooltip, DropdownMenu, Select, Tabs, Accordion, ScrollArea, Toast, Toggle/ToggleGroup — shared floating-surface motion, recipes, portal theme reconstitution, InspectorPanel fixture, and CI performance budgets. +- 3bf1155: Stage 4 composites: product components, serializable models, and composition standard. + + - Add `@reactive/silk-core/models` (Identity/Stat/Media/Post/Comment/Notification/Profile/FeedEntry) and composite recipes. + - Close primitive gaps: Card/Surface `interactive` hover elevation, Inline `direction`, Stack `rail`, `StatusDot`. + - Ship composites: MediaObject, ActionBar, StatGroup, EmptyState, PostCard, Comment, CommentThread, Notification, FeedItem, ProfileCard, SettingsPanel. + - Document the compound-first dual API in `docs/COMPOSITES.md`. + - Retrofit Identity onto Inline (additive `model` prop — non-breaking). + - SocialFeed exit fixture; registry sync script emits consumer-owned composite source. + +- e2aa5b9: Stage 5 theming maturity (web): portal variable channels and re-exports. + + - Split theme-scope CSS vars into `semanticVars` (replaced by nested `theme`/`colorScheme`) and `customVars` (component hooks that inherit through named children into portals). + - Re-export `generateScale`, `generatePairedPalette`, `checkThemeContrast`, and related types from `@reactive/silk`. + - Document the frozen public component CSS-variable list via `silkComponentVarMeta` / `formatComponentVarDocsTable`. + +### Patch Changes + +- 2c7c49f: Fix `asChild` on every part that renders a decoration alongside its children. `Select.Trigger`, `Accordion.Trigger`, `DropdownMenu.SubTrigger`, `DropdownMenu.Item`, and `Field.Label` each threw "Primitive.\* failed to slot onto its children" because the chevron / caret / shortcut / required indicator was a second slot child. Their children are now wrapped in `Slot.Slottable`, so a custom element receives its own children plus the appended decoration. This applies even where the decoration is conditional (`DropdownMenu.Item shortcut`, `Field.Label` on a required field) — the `null` branch counted as a second child, so those parts threw on `asChild` regardless. The default (non-`asChild`) render path is unchanged. + + Two assembled parts cannot support `asChild` at all, and now say so at the type level instead of throwing at runtime: `asChild` is omitted from `SelectItemProps` and `SelectContentProps`, matching `Checkbox`, `Switch`, `Slider`, `RadioGroup`, and `Progress`. `Select.Item` wraps children in `RadixSelect.ItemText`, and `Slottable` substitutes the consumer's children unwrapped, so no arrangement yields "consumer element is the item, containing indicator + `ItemText`". `Select.Content` assembles a Viewport plus both scroll buttons, so there is likewise no single slot target. + + The rule and its `null`-branch pitfall are documented once in [ARCHITECTURE.md](../docs/ARCHITECTURE.md#aschild-with-decorations). + +- 2b03511: Keep `Field.Root orientation="horizontal"` correct when slots sit inside a layout wrapper. The grid pinned only direct `Field.Label` / `Description` / `Error` children to column 2, so a `Stack` or `Inline` around the description auto-placed into the control column — even though Field already treats those wrappers as transparent when wiring `aria-describedby`. Wrappers holding a slot are now pinned too, and the label owns row 1 so the control stays beside it regardless of child order. +- 338fe46: Only wire `aria-labelledby` from Field context when a `Field.Label` is actually rendered, and point it at the label's own id. A `Slider` in a label-less `Field.Root` no longer gets a dangling `aria-labelledby`, so its `aria-label` names the `role="slider"` thumb again. + + Detect `Field.Label` / `Description` / `Error` among descendants (not only direct children) so layout wrappers like `Inline` / `Stack` still populate `aria-labelledby` / `aria-describedby`. Nested `Field.Root` boundaries are respected. + +- 338fe46: `Slider` inside a single-mode `Field.Root` no longer gets a dangling or non-functional Label `htmlFor`. Field detects labelledby-marked controls (`fieldLabelAssociation`), omits automatic `htmlFor` / control `id`, and keeps naming on the thumb via `aria-labelledby`. Explicit `id` / `htmlFor` still win. + + `Field.Root required` still shows the label indicator for Slider fields; `required` / `aria-required` are not forwarded onto the thumb because range / `role="slider"` always has a value and does not support those attributes. + +- 2c7c49f: Dialog overlay and content now draw their `z-index` from the shared floating stacking scale, so page content with a modest `z-index` (sticky headers, app chrome) no longer paints over the scrim or the panel. The overlay previously had no `z-index` at all and content used a local `z-index: 1`. + + Dialog sits below popovers, menus, selects, tooltips, and toasts on that scale. Those surfaces portal to the body as siblings of the dialog panel rather than descendants, so they must outrank it to remain visible when opened from inside a dialog. + +- 3f24b2f: Reconstitute the nearest ThemeProvider scope on portaled Dialog content so theme CSS variables resolve outside the provider DOM subtree. +- 3fd5030: Make ScrollArea viewport keyboard-focusable by default (`tabIndex={0}`) so scrollable regions meet axe `scrollable-region-focusable`. +- 338fe46: Name multi-thumb `Slider` thumbs when `thumbLabels` is omitted: fall back to Field label or an indexed root `aria-label`, and wire `aria-describedby` on every thumb. Explicit `thumbLabels` clear Field `aria-labelledby` so they win in accessible name computation. +- Updated dependencies [b4fd11a] +- Updated dependencies [09d876d] +- Updated dependencies [3bf1155] +- Updated dependencies [7b6407b] +- Updated dependencies [338fe46] +- Updated dependencies [2c7c49f] +- Updated dependencies [3bf1155] +- Updated dependencies [e2aa5b9] + - @reactive/silk-core@0.1.0 diff --git a/packages/silk/package.json b/packages/silk/package.json index efa1671..cc2d6ef 100644 --- a/packages/silk/package.json +++ b/packages/silk/package.json @@ -1,6 +1,6 @@ { "name": "@reactive/silk", - "version": "0.0.0", + "version": "0.1.0", "description": "Long-lived design system foundation for React — semantic themes, Linaria CSS, Radix behavior", "license": "MIT", "type": "module",