@mittwald/flow-react-components 0.2.0-alpha.932 → 0.2.0-alpha.945

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 (54) hide show
  1. package/AGENTS.md +72 -65
  2. package/CHANGELOG.md +65 -0
  3. package/PATTERNS.md +57 -0
  4. package/dist/assets/doc-properties.json +2690 -2758
  5. package/dist/css/all-layered.css +1 -1
  6. package/dist/css/all.css +1 -1
  7. package/dist/js/packages/components/src/components/CodeBlock/CodeBlock.mjs +2 -1
  8. package/dist/js/packages/components/src/components/CodeBlock/CodeBlock.mjs.map +1 -1
  9. package/dist/js/packages/components/src/components/List/components/Items/Items.mjs +2 -0
  10. package/dist/js/packages/components/src/components/List/components/Items/Items.mjs.map +1 -1
  11. package/dist/js/packages/components/src/components/List/components/Items/components/Item/Item.mjs +10 -6
  12. package/dist/js/packages/components/src/components/List/components/Items/components/Item/Item.mjs.map +1 -1
  13. package/dist/js/packages/components/src/components/List/components/Items/components/Item/hooks/useGridItemProps.mjs +1 -28
  14. package/dist/js/packages/components/src/components/List/components/Items/components/Item/hooks/useGridItemProps.mjs.map +1 -1
  15. package/dist/js/packages/components/src/components/Modal/Modal.mjs +3 -0
  16. package/dist/js/packages/components/src/components/Modal/Modal.mjs.map +1 -1
  17. package/dist/js/packages/components/src/components/Modal/Modal.module.scss.mjs +4 -2
  18. package/dist/js/packages/components/src/components/Modal/Modal.module.scss.mjs.map +1 -1
  19. package/dist/js/packages/components/src/components/Table/Table.mjs +10 -2
  20. package/dist/js/packages/components/src/components/Table/Table.mjs.map +1 -1
  21. package/dist/js/packages/components/src/components/Table/Table.module.scss.mjs +6 -2
  22. package/dist/js/packages/components/src/components/Table/Table.module.scss.mjs.map +1 -1
  23. package/dist/js/packages/components/src/components/Table/components/TableColumn/TableColumn.mjs +18 -2
  24. package/dist/js/packages/components/src/components/Table/components/TableColumn/TableColumn.mjs.map +1 -1
  25. package/dist/js/packages/components/src/lib/hooks/dom/useVirtualKeyboardVisible.mjs +29 -0
  26. package/dist/js/packages/components/src/lib/hooks/dom/useVirtualKeyboardVisible.mjs.map +1 -0
  27. package/dist/js/packages/design-tokens/dist/json/all-dark.json.mjs +4 -2
  28. package/dist/js/packages/design-tokens/dist/json/all-dark.json.mjs.map +1 -1
  29. package/dist/js/packages/design-tokens/dist/json/all-light.json.mjs +4 -2
  30. package/dist/js/packages/design-tokens/dist/json/all-light.json.mjs.map +1 -1
  31. package/dist/types/components/CodeBlock/CodeBlock.d.ts.map +1 -1
  32. package/dist/types/components/LayoutCard/stories/Default.stories.d.ts +1 -0
  33. package/dist/types/components/LayoutCard/stories/Default.stories.d.ts.map +1 -1
  34. package/dist/types/components/List/components/Items/Items.d.ts.map +1 -1
  35. package/dist/types/components/List/components/Items/components/Item/Item.d.ts +9 -2
  36. package/dist/types/components/List/components/Items/components/Item/Item.d.ts.map +1 -1
  37. package/dist/types/components/List/components/Items/components/Item/hooks/useGridItemProps.d.ts +2 -1
  38. package/dist/types/components/List/components/Items/components/Item/hooks/useGridItemProps.d.ts.map +1 -1
  39. package/dist/types/components/List/typedList.d.ts +2 -3
  40. package/dist/types/components/List/typedList.d.ts.map +1 -1
  41. package/dist/types/components/Modal/Modal.d.ts.map +1 -1
  42. package/dist/types/components/Table/Table.d.ts +11 -1
  43. package/dist/types/components/Table/Table.d.ts.map +1 -1
  44. package/dist/types/components/Table/components/TableColumn/TableColumn.d.ts +5 -1
  45. package/dist/types/components/Table/components/TableColumn/TableColumn.d.ts.map +1 -1
  46. package/dist/types/components/Table/stories/Default.stories.d.ts +1 -0
  47. package/dist/types/components/Table/stories/Default.stories.d.ts.map +1 -1
  48. package/dist/types/lib/hooks/dom/useVirtualKeyboardVisible.d.ts +19 -0
  49. package/dist/types/lib/hooks/dom/useVirtualKeyboardVisible.d.ts.map +1 -0
  50. package/dist/types/lib/hooks/dom/useVirtualKeyboardVisible.test.d.ts +2 -0
  51. package/dist/types/lib/hooks/dom/useVirtualKeyboardVisible.test.d.ts.map +1 -0
  52. package/dist/types/lib/theming/hooks/useDesignTokens.d.ts +82 -0
  53. package/dist/types/lib/theming/hooks/useDesignTokens.d.ts.map +1 -1
  54. package/package.json +23 -23
package/AGENTS.md CHANGED
@@ -25,8 +25,8 @@ src/components/Button/
25
25
  └── *.browser.test.tsx # behavior tests (when behavior is non-trivial)
26
26
  ```
27
27
 
28
- The barrel exports the view first (only on `@flr-generate` components), then
29
- the component:
28
+ The barrel exports the view first (only on `@flr-generate` components), then the
29
+ component:
30
30
 
31
31
  ```ts
32
32
  export * from "./view";
@@ -51,7 +51,8 @@ import {
51
51
  } from "@/lib/componentFactory/flowComponent";
52
52
 
53
53
  export interface ButtonProps
54
- extends PropsWithChildren<Omit<Aria.ButtonProps, "children">>,
54
+ extends
55
+ PropsWithChildren<Omit<Aria.ButtonProps, "children">>,
55
56
  FlowComponentProps<HTMLButtonElement> {
56
57
  /** The color of the button. @default "primary" */
57
58
  color?: "primary" | "accent" | "secondary" | "danger";
@@ -71,21 +72,21 @@ Conventions:
71
72
  - Props type is exported as `<Name>Props`; it extends the wrapped React Aria
72
73
  props plus `FlowComponentProps<RefElement>`.
73
74
  - **Ref as prop** (React 19) — no `forwardRef`.
74
- - `options.type`: `"ui"` (default — gets props-context isolation),
75
- `"layout"`, or `"provider"`. The factory applies `ClearPropsContext`
76
- isolation for UI components itself — don't add extra clearing casually.
75
+ - `options.type`: `"ui"` (default — gets props-context isolation), `"layout"`,
76
+ or `"provider"`. The factory applies `ClearPropsContext` isolation for UI
77
+ components itself — don't add extra clearing casually.
77
78
  - The registered name must match the component/directory name, and the props
78
79
  type must be registered in `src/components/propTypes/index.ts`
79
- (`FlowComponentPropsTypes`) — `flowComponent` names are typed as `keyof`
80
- of that hand-maintained registry, so a missing entry fails the typecheck.
80
+ (`FlowComponentPropsTypes`) — `flowComponent` names are typed as `keyof` of
81
+ that hand-maintained registry, so a missing entry fails the typecheck.
81
82
  - Most components wrap `react-aria-components` primitives; expose ARIA props
82
83
  directly only where React Aria lacks the behavior.
83
84
 
84
85
  ## PropsContext — contextual composability
85
86
 
86
87
  `PropsContext` makes components adapt **automatically** when composed inside
87
- other components: they receive default prop values and, mainly, CSS classes
88
- from their surroundings. This is the backbone of Flow's composability.
88
+ other components: they receive default prop values and, mainly, CSS classes from
89
+ their surroundings. This is the backbone of Flow's composability.
89
90
 
90
91
  ```tsx
91
92
  // IllustratedMessage.tsx — every <Icon> inside renders large:
@@ -102,44 +103,50 @@ return (
102
103
  ```
103
104
 
104
105
  - Contexts **nest** (a context can configure props contexts of nested
105
- components) and support **dynamic props**:
106
- `dynamic((localProps) => value)` derives values from the consumer's props.
106
+ components) and support **dynamic props**: `dynamic((localProps) => value)`
107
+ derives values from the consumer's props.
107
108
  - Local props always win over context props.
108
- - Although exported, `PropsContext` is **primarily an internal API** — prefer
109
- it for intra-Flow composition, not as a consumer-facing feature.
109
+ - Although exported, `PropsContext` is **primarily an internal API** — prefer it
110
+ for intra-Flow composition, not as a consumer-facing feature.
110
111
  - **Only put remote-capable components into a `PropsContext`** — non-remote
111
112
  components break remote rendering.
112
113
  - When parent context must not leak into a component's children, use targeted
113
114
  clearing, e.g. `wrapWith: <ClearPropsContext />` (see `Modal.tsx`).
114
115
 
116
+ Why this works the way it does across the remote boundary:
117
+ [docs/remote-ui.md](../../docs/remote-ui.md).
118
+
115
119
  ## Views — remote-transparent composition
116
120
 
117
- Components tagged `/** @flr-generate all */` get a generated view
118
- (`view.ts` + `src/views/<Name>View.tsx`). **Inside `flr-universal` components,
119
- compose other Flow components through their views** (`@/views/*`) — a view
120
- automatically switches to the remote counterpart in a remote context:
121
+ Components tagged `/** @flr-generate all */` get a generated view (`view.ts` +
122
+ `src/views/<Name>View.tsx`). **Inside `flr-universal` components, compose other
123
+ Flow components through their views** (`@/views/*`) — a view automatically
124
+ switches to the remote counterpart in a remote context:
121
125
 
122
126
  ```tsx
123
- import ButtonView from "@/views/ButtonView"; // ✓ works local and remote
124
- import { Button } from "@/components/Button"; // ✗ host-only in remote context
127
+ import ButtonView from "@/views/ButtonView"; // ✓ works local and remote
128
+ import { Button } from "@/components/Button"; // ✗ host-only in remote context
125
129
  ```
126
130
 
131
+ Why this works the way it does across the remote boundary:
132
+ [docs/remote-ui.md](../../docs/remote-ui.md).
133
+
127
134
  Remote generation details:
128
135
 
129
136
  - `@flr-generate all` on the component const marks it for generation.
130
137
  - `@flr-ignore-props` excludes props that must not cross the remote boundary —
131
- either because they cannot be serialized, or because they could do **too
132
- much on the host side**. A global ignore list lives in
138
+ either because they cannot be serialized, or because they could do **too much
139
+ on the host side**. A global ignore list lives in
133
140
  `dev/remote-components-generator/config.ts`: `style` and
134
- `dangerouslySetInnerHTML` are always ignored for safety; `ref`,
135
- `controller`, `tunnel`, `key`, `children`, `wrapWith` because they don't
136
- serialize. Use the per-component tag for additional cases (see
137
- `TunnelEntry.tsx`).
141
+ `dangerouslySetInnerHTML` are always ignored for safety; `ref`, `controller`,
142
+ `tunnel`, `key`, `children`, `wrapWith` because they don't serialize. Use the
143
+ per-component tag for additional cases (see `TunnelEntry.tsx`).
138
144
  - After changing props of an `@flr-generate` component:
139
145
  `pnpm nx build:remote-components components` and **commit** the results
140
146
  (view.ts, `src/views/*`, `remote-*/src/auto-generated/**`).
141
- - Props of these components are consumed by mStudio extension developers —
142
- no breaking changes; deprecate instead:
147
+ - Props of these components are consumed by mStudio extension developers — no
148
+ breaking changes; deprecate instead. Why this matters:
149
+ [docs/remote-ui.md](../../docs/remote-ui.md).
143
150
 
144
151
  ```tsx
145
152
  const warnDeprecation = useWarnDeprecation();
@@ -150,8 +157,8 @@ if ("action" in props) {
150
157
 
151
158
  ## Styling
152
159
 
153
- - One `<Name>.module.scss` per component. Scoped class names are generated
154
- from the component's **path** (`dev/vite/cssModuleClassNameGenerator.ts`) —
160
+ - One `<Name>.module.scss` per component. Scoped class names are generated from
161
+ the component's **path** (`dev/vite/cssModuleClassNameGenerator.ts`) —
155
162
  deliberately semantic CSS that could be used standalone. Never bypass CSS
156
163
  modules for component roots (the global reset targets `flow--` classes).
157
164
  - Root class is the lower-camel component name (`.button`); modifier classes
@@ -159,8 +166,8 @@ if ("action" in props) {
159
166
  - Class composition with `clsx`, consumer `className` appended last:
160
167
  `clsx(styles.button, styles[size], styles[color], className)`.
161
168
  - **Use design-token CSS variables** — global (`--font-size-text--m`) or
162
- component-namespaced (`--button--corner-radius`). No hard-coded colors,
163
- sizes, radii.
169
+ component-namespaced (`--button--corner-radius`). No hard-coded colors, sizes,
170
+ radii.
164
171
  - Shared mixins via `@use "@/styles/mixins/…"`: `focus` (focus ring),
165
172
  `formControl` (border/color/interaction states of form fields), `ellipsis`.
166
173
  Group repeated variants in local mixins.
@@ -169,12 +176,12 @@ if ("action" in props) {
169
176
 
170
177
  ## Testing — the actual bar
171
178
 
172
- | Artifact | When |
173
- | --- | --- |
174
- | `stories/Default.stories.tsx` | **Always.** Realistic args, controls, meaningful variants. Story title category matches the docs (`Actions/…`, `Form Controls/…`, `Overlays/…`, `Status/…`). |
179
+ | Artifact | When |
180
+ | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
181
+ | `stories/Default.stories.tsx` | **Always.** Realistic args, controls, meaningful variants. Story title category matches the docs (`Actions/…`, `Form Controls/…`, `Overlays/…`, `Status/…`). |
175
182
  | `*.browser.test.tsx` (vitest browser mode) | Component has real **behavior**: interaction, controlled state, async flows, form integration, controllers. Render with `vitest-browser-react`, interact via `userEvent`, query by role. |
176
- | `*.test.ts(x)` (unit) | Pure logic in `src/lib/` or component utility functions. |
177
- | `*.test-types.tsx` | Generic/typed public APIs — `expectTypeOf` plus `@ts-expect-error` negative assertions. |
183
+ | `*.test.ts(x)` (unit) | Pure logic in `src/lib/` or component utility functions. |
184
+ | `*.test-types.tsx` | Generic/typed public APIs — `expectTypeOf` plus `@ts-expect-error` negative assertions. |
178
185
 
179
186
  Run: `pnpm nx test:unit components`,
180
187
  `pnpm nx test:browser components --browser.name=webkit`. Browser tests need
@@ -183,10 +190,10 @@ Run: `pnpm nx test:unit components`,
183
190
  ## i18n & a11y
184
191
 
185
192
  - Component-internal UI text lives in colocated `locales/de-DE.locale.json`
186
- **and** `locales/en-US.locale.json` — always add both languages. The
187
- strings support ICU MessageFormat (variables, `plural`, `select` — see
188
- `PasswordCreationField/locales/` for real usage). Import the files with a
189
- glob import and consume them via the Flow hook:
193
+ **and** `locales/en-US.locale.json` — always add both languages. The strings
194
+ support ICU MessageFormat (variables, `plural`, `select` — see
195
+ `PasswordCreationField/locales/` for real usage). Import the files with a glob
196
+ import and consume them via the Flow hook:
190
197
 
191
198
  ```tsx
192
199
  import locales from "./locales/*.locale.json";
@@ -199,19 +206,19 @@ Run: `pnpm nx test:unit components`,
199
206
  initially: every `locales/` directory in the package gets the new file.
200
207
  - Icon-only buttons get a localized `aria-label`; decorative icons are
201
208
  `aria-hidden` (the `Icon` component handles this when no label is given).
202
- - Form fields wire label/description/error via `useFieldComponent`
203
- (generates ids, sets `aria-describedby`).
209
+ - Form fields wire label/description/error via `useFieldComponent` (generates
210
+ ids, sets `aria-describedby`).
204
211
 
205
212
  ## Public API surfaces
206
213
 
207
- | Export | Contents |
208
- | --- | --- |
209
- | `.` (default) | Everything listed **manually** in `src/components/public.ts` — new public components must be added there. |
210
- | `./internal` | Advanced internals (`flowComponent`, prop helper types, …). |
211
- | `./flr-universal` | Curated subset that works local *and* remote. Adding to `public.ts` does **not** add here. |
214
+ | Export | Contents |
215
+ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
216
+ | `.` (default) | Everything listed **manually** in `src/components/public.ts` — new public components must be added there. |
217
+ | `./internal` | Advanced internals (`flowComponent`, prop helper types, …). |
218
+ | `./flr-universal` | Curated subset that works local _and_ remote. Adding to `public.ts` does **not** add here. |
212
219
  | `./nextjs`, `./react-hook-form`, `./password-tools` | Integrations (`src/integrations/`): wrappers around third-party dependencies that not every consumer should pay for — they get their own export entry instead of entering the core surface. |
213
- | `./all.css` | Bundled stylesheet. |
214
- | `./doc-properties` | Generated prop metadata for the docs site. |
220
+ | `./all.css` | Bundled stylesheet. |
221
+ | `./doc-properties` | Generated prop metadata for the docs site. |
215
222
 
216
223
  Prop JSDoc feeds the generated `doc-properties.json` and the docs site: write
217
224
  doc comments on public props, use `@default` for defaults and `@internal` for
@@ -219,14 +226,14 @@ props to hide.
219
226
 
220
227
  ## Misc
221
228
 
222
- - Feature flags: `src/flags.ts` holds a few behavior toggles; there is no
223
- formal policy around them.
229
+ - Feature flags: `src/flags.ts` holds a few behavior toggles; there is no formal
230
+ policy around them.
224
231
  - `SettingsProvider` (`src/components/SettingsProvider/`) is the built-in
225
232
  persistence for component settings (e.g. `List` remembering its view
226
233
  settings), with pluggable backends (localStorage by default). Internal
227
234
  component infrastructure — extension developers don't need it.
228
- - `stories/lib.tsx` holds story-only fixtures — never import it from
229
- component code.
235
+ - `stories/lib.tsx` holds story-only fixtures — never import it from component
236
+ code.
230
237
  - Storybook discovers all `src/**/*.stories.tsx` automatically; there is no
231
238
  registry to update.
232
239
 
@@ -235,12 +242,12 @@ props to hide.
235
242
  Easy-to-miss conventions not spelled out above. Full details and examples in
236
243
  [PATTERNS.md](./PATTERNS.md).
237
244
 
238
- - **`PropsContext` is structural, not just styling** — nested entries,
239
- `dynamic` children, semantic defaults (icon size, heading level, status), and
240
- contextual `wrapWith` define much of a composite's internal API.
245
+ - **`PropsContext` is structural, not just styling** — nested entries, `dynamic`
246
+ children, semantic defaults (icon size, heading level, status), and contextual
247
+ `wrapWith` define much of a composite's internal API.
241
248
  - **The factory supplies hidden infrastructure** — memoization, nested-context
242
- preservation, slot propagation, UI isolation, and tunnel entry/provider
243
- wiring are all automatic consequences of `flowComponent`; don't rebuild them.
249
+ preservation, slot propagation, UI isolation, and tunnel entry/provider wiring
250
+ are all automatic consequences of `flowComponent`; don't rebuild them.
244
251
  - **Raw string children get `Text`-normalized** where typography is
245
252
  context-driven (detect raw strings, wrap in `Text`); explicit structured
246
253
  children are left intact.
@@ -248,7 +255,7 @@ Easy-to-miss conventions not spelled out above. Full details and examples in
248
255
  still use `:global(.flow--…)` when independently rendered Flow descendants
249
256
  must affect layout.
250
257
  - **Controllers coexist with declarative props** — overlay-like APIs support
251
- controlled/uncontrolled props *and* a controller object, not one or the other.
258
+ controlled/uncontrolled props _and_ a controller object, not one or the other.
252
259
  - **Complex behavior is split by vocabulary** — `components/` for render,
253
260
  `hooks/` for behavior, `lib/` for pure transforms, `models/` for durable
254
261
  state.
@@ -258,8 +265,8 @@ Easy-to-miss conventions not spelled out above. Full details and examples in
258
265
  - **The empty `Default` story is intentional** — realistic args and rendering
259
266
  live in the typed `meta`, so `export const Default: Story = {}` is the norm.
260
267
  - **CSS leans on modern relational/low-specificity selectors** — `:has`,
261
- `:where`, logical properties, data attributes, and container boundaries
262
- reduce the need for runtime styling props.
263
- - **Universal exports are deliberately explicit** — remote-safe values and
264
- their types are curated in `flr-universal.ts` independently of the main
265
- public surface; adding to `public.ts` does not add them there.
268
+ `:where`, logical properties, data attributes, and container boundaries reduce
269
+ the need for runtime styling props.
270
+ - **Universal exports are deliberately explicit** — remote-safe values and their
271
+ types are curated in `flr-universal.ts` independently of the main public
272
+ surface; adding to `public.ts` does not add them there.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,71 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.2.0-alpha.945](https://github.com/mittwald/flow/compare/0.2.0-alpha.944...0.2.0-alpha.945) (2026-07-23)
7
+
8
+ **Note:** Version bump only for package @mittwald/flow-react-components
9
+
10
+ # [0.2.0-alpha.944](https://github.com/mittwald/flow/compare/0.2.0-alpha.943...0.2.0-alpha.944) (2026-07-23)
11
+
12
+ **Note:** Version bump only for package @mittwald/flow-react-components
13
+
14
+ # [0.2.0-alpha.943](https://github.com/mittwald/flow/compare/0.2.0-alpha.942...0.2.0-alpha.943) (2026-07-23)
15
+
16
+ **Note:** Version bump only for package @mittwald/flow-react-components
17
+
18
+ # [0.2.0-alpha.942](https://github.com/mittwald/flow/compare/0.2.0-alpha.941...0.2.0-alpha.942) (2026-07-23)
19
+
20
+ **Note:** Version bump only for package @mittwald/flow-react-components
21
+
22
+ # [0.2.0-alpha.941](https://github.com/mittwald/flow/compare/0.2.0-alpha.940...0.2.0-alpha.941) (2026-07-23)
23
+
24
+ ### Bug Fixes
25
+
26
+ * **CodeBlock:** fix undefined max height in code block ([8773c73](https://github.com/mittwald/flow/commit/8773c73c7ca63cf3b69a5177712ed8a34bed4fd0))
27
+ * require Node >= 24 (the tested and supported runtime) ([7f9a8ec](https://github.com/mittwald/flow/commit/7f9a8ec0b34fc9db009dc330a3632e3b1ee41eea))
28
+
29
+ # [0.2.0-alpha.940](https://github.com/mittwald/flow/compare/0.2.0-alpha.939...0.2.0-alpha.940) (2026-07-23)
30
+
31
+ ### Features
32
+
33
+ * **Table:** add configurable column widths ([#2682](https://github.com/mittwald/flow/issues/2682)) ([c0b9a45](https://github.com/mittwald/flow/commit/c0b9a45a89f75246cead39a940a8e23d65acf160))
34
+
35
+ # [0.2.0-alpha.939](https://github.com/mittwald/flow/compare/0.2.0-alpha.938...0.2.0-alpha.939) (2026-07-23)
36
+
37
+ **Note:** Version bump only for package @mittwald/flow-react-components
38
+
39
+ # [0.2.0-alpha.938](https://github.com/mittwald/flow/compare/0.2.0-alpha.937...0.2.0-alpha.938) (2026-07-23)
40
+
41
+ ### Performance Improvements
42
+
43
+ * **List:** memoize items so they don't re-render when loading more ([#2677](https://github.com/mittwald/flow/issues/2677)) ([deb547a](https://github.com/mittwald/flow/commit/deb547a07849ce89a59bca9aab7e3a5e33812b54))
44
+
45
+ # [0.2.0-alpha.937](https://github.com/mittwald/flow/compare/0.2.0-alpha.936...0.2.0-alpha.937) (2026-07-22)
46
+
47
+ ### Bug Fixes
48
+
49
+ * **PasswordCreationField:** fix overflow ([#2686](https://github.com/mittwald/flow/issues/2686)) ([e668e98](https://github.com/mittwald/flow/commit/e668e98b3bd91a4e06089fc3ec21cb5ca2703d70))
50
+
51
+ # [0.2.0-alpha.936](https://github.com/mittwald/flow/compare/0.2.0-alpha.935...0.2.0-alpha.936) (2026-07-22)
52
+
53
+ **Note:** Version bump only for package @mittwald/flow-react-components
54
+
55
+ # [0.2.0-alpha.935](https://github.com/mittwald/flow/compare/0.2.0-alpha.934...0.2.0-alpha.935) (2026-07-22)
56
+
57
+ ### Bug Fixes
58
+
59
+ * **Modal:** keep mobile modals with forms usable when the virtual keyboard opens ([#2423](https://github.com/mittwald/flow/issues/2423)) ([#2671](https://github.com/mittwald/flow/issues/2671)) ([5b1b856](https://github.com/mittwald/flow/commit/5b1b8563d6e5e7a0a5c046620104480f1f7620cd))
60
+
61
+ # [0.2.0-alpha.934](https://github.com/mittwald/flow/compare/0.2.0-alpha.933...0.2.0-alpha.934) (2026-07-21)
62
+
63
+ ### Features
64
+
65
+ * **components:** add reusable slim scrollbar mixin and apply to scroll containers ([#2672](https://github.com/mittwald/flow/issues/2672)) ([a06dd9a](https://github.com/mittwald/flow/commit/a06dd9a4e88899612eba19a21f6464ba0a98167e))
66
+
67
+ # [0.2.0-alpha.933](https://github.com/mittwald/flow/compare/0.2.0-alpha.932...0.2.0-alpha.933) (2026-07-21)
68
+
69
+ **Note:** Version bump only for package @mittwald/flow-react-components
70
+
6
71
  # [0.2.0-alpha.932](https://github.com/mittwald/flow/compare/0.2.0-alpha.931...0.2.0-alpha.932) (2026-07-21)
7
72
 
8
73
  **Note:** Version bump only for package @mittwald/flow-react-components
package/PATTERNS.md CHANGED
@@ -19,6 +19,63 @@ not guarantees. Never edit generated files (`view.ts`, `src/views/`,
19
19
 
20
20
  ---
21
21
 
22
+ ## Guiding principles
23
+
24
+ The **why** behind the concrete rules below. When a specific pattern is unclear
25
+ or a new situation isn't covered, fall back to these; the numbered sections are
26
+ these principles applied. (`→` points to the sections each one mostly governs.)
27
+
28
+ 1. **Composition is the architecture.** `PropsContext` is the backbone —
29
+ components adapt to their surroundings automatically (classes, icon size,
30
+ heading level) instead of the consumer wiring everything. When a parent
31
+ shapes its descendants, do it through context, not child-cloning or
32
+ prop-drilling. → §3.
33
+ 2. **Build on standards; don't reinvent accessibility.** Nearly everything wraps
34
+ `react-aria-components`; expose ARIA directly only where react-aria has a
35
+ gap. Accessibility is non-negotiable: semantic roots, labels for icon-only
36
+ controls, `aria-hidden` for decoration, generated `id` / `aria-describedby`.
37
+ → §1, §8.
38
+ 3. **A factory hides the infrastructure — convention over configuration.**
39
+ `flowComponent` supplies memoization, context isolation, slot/tunnel wiring,
40
+ and `wrapWith`; never rebuild it by hand. Ref-as-prop (no `forwardRef`),
41
+ forward `...rest`, defaults in destructuring. The payoff: every component
42
+ looks the same. → §1.
43
+ 4. **Single source of truth; generate what's derivable.** Tokens, views, icons,
44
+ the `propTypes` registry, and doc-properties are generated and committed,
45
+ never hand-maintained twice. (It's why this catalog is _referenced_ from
46
+ `AGENTS.md`, not duplicated into it.) → §4, §5.
47
+ 5. **The public API is a contract — extend, don't break.** Export surfaces
48
+ (`public.ts`, `flr-universal.ts`, `internal.ts`) are curated by hand. Remote
49
+ props for extension developers are additive; deprecate with
50
+ `useWarnDeprecation` instead of renaming/removing. JSDoc + `@default` /
51
+ `@internal` _is_ the API's documentation. → §5, §2, §4.
52
+ 6. **Design comes from UX — base tokens are taboo.** Never hard-code
53
+ colors/sizes/radii; compose existing design tokens, and add component tokens
54
+ only with an established design. → §6.
55
+ 7. **TypeScript is a contract, kept precise.** `interface` for a component's own
56
+ extensible prop shape; a `type` alias for
57
+ intersections/`Omit`/`Pick`/generics. Types are tested (`*.test-types.tsx`),
58
+ and names derive from the registry rather than parallel unions. → §2, §11.
59
+ 8. **Enforce consistency with tooling, not discipline.** Prefer an
60
+ ESLint/Prettier rule + autofix over hundreds of hand edits. Write
61
+ self-explanatory code with minimal comments. → §12.
62
+ 9. **Colocate by role.** `components/` (render), `hooks/` (behavior), `lib/`
63
+ (pure transforms), `models/` (durable state), `locales/`, `stories/`.
64
+ Cross-cutting imports use the `@/` alias; a component's own feature stays
65
+ relative. → §7, §12.
66
+ 10. **Effort scales with risk.** Testing bar: a story always, a browser test for
67
+ real behavior, a unit test for pure logic, a type test for generics. i18n
68
+ always ships both `de-DE` and `en-US` (ICU). Reach for modern CSS (`:where`,
69
+ `:has`, logical properties, container queries, `data-*` state) before adding
70
+ runtime styling props. → §11, §9, §6.
71
+
72
+ **In one sentence:** composable, accessibility-first React components built on
73
+ react-aria, unified by a factory, backed by a generated single source of truth,
74
+ with a public API treated as a contract and visual design driven by UX tokens —
75
+ and consistency enforced by tooling, not maintained by hand.
76
+
77
+ ---
78
+
22
79
  ## 1. Component definition
23
80
 
24
81
  - **Factory registration** — public Flow components via