@imfusion/web-ui 0.7.2-dev.6.g1f49e9fa → 0.8.0

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.
@@ -2461,7 +2461,7 @@
2461
2461
  },
2462
2462
  {
2463
2463
  "name": "NavigationMenu.Link",
2464
- "description": "NavigationMenu.Link — a top-strip (rail) link: a peer of `Trigger` for a\nsection that navigates directly instead of opening a flyout. Renders an `<a>`.\nFor a link inside a flyout, use `NavigationMenu.FlyoutLink`.\n\nA trailing `ArrowRight` slides in on hover/focus. When a custom `render` is\nsupplied the icon is omitted — the consumer's element owns its content.",
2464
+ "description": "NavigationMenu.Link — a top-strip (rail) link: a peer of `Trigger` for a\nsection that navigates directly instead of opening a flyout. Renders an `<a>`.\nFor a link inside a flyout, use `NavigationMenu.FlyoutLink`.",
2465
2465
  "props": [
2466
2466
  {
2467
2467
  "name": "active",
@@ -4250,6 +4250,14 @@
4250
4250
  }
4251
4251
  ]
4252
4252
  },
4253
+ "prose": {
4254
+ "root": {
4255
+ "name": "Prose",
4256
+ "description": "",
4257
+ "props": []
4258
+ },
4259
+ "subComponents": []
4260
+ },
4253
4261
  "row": {
4254
4262
  "root": {
4255
4263
  "name": "Row",
@@ -5306,13 +5314,6 @@
5306
5314
  "defaultValue": null,
5307
5315
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
5308
5316
  },
5309
- {
5310
- "name": "spacing",
5311
- "required": false,
5312
- "type": "| \"small\"\n| \"none\"\n| \"medium\"\n| \"large\"\n| \"spacious\"\n| null",
5313
- "defaultValue": "none",
5314
- "description": ""
5315
- },
5316
5317
  {
5317
5318
  "name": "style",
5318
5319
  "required": false,
@@ -7559,13 +7560,6 @@
7559
7560
  "defaultValue": null,
7560
7561
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7561
7562
  },
7562
- {
7563
- "name": "spacing",
7564
- "required": false,
7565
- "type": "\"default\" | \"none\" | null",
7566
- "defaultValue": "default",
7567
- "description": ""
7568
- },
7569
7563
  {
7570
7564
  "name": "variant",
7571
7565
  "required": false,
@@ -7627,13 +7621,6 @@
7627
7621
  "defaultValue": null,
7628
7622
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7629
7623
  },
7630
- {
7631
- "name": "spacing",
7632
- "required": false,
7633
- "type": "\"default\" | \"none\" | null",
7634
- "defaultValue": "default",
7635
- "description": ""
7636
- },
7637
7624
  {
7638
7625
  "name": "variant",
7639
7626
  "required": false,
@@ -7668,13 +7655,6 @@
7668
7655
  "defaultValue": null,
7669
7656
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7670
7657
  },
7671
- {
7672
- "name": "spacing",
7673
- "required": false,
7674
- "type": "\"default\" | \"none\" | null",
7675
- "defaultValue": "default",
7676
- "description": ""
7677
- },
7678
7658
  {
7679
7659
  "name": "variant",
7680
7660
  "required": false,
@@ -7702,13 +7682,6 @@
7702
7682
  "defaultValue": null,
7703
7683
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7704
7684
  },
7705
- {
7706
- "name": "spacing",
7707
- "required": false,
7708
- "type": "\"default\" | \"none\" | null",
7709
- "defaultValue": "default",
7710
- "description": ""
7711
- },
7712
7685
  {
7713
7686
  "name": "variant",
7714
7687
  "required": false,
@@ -7736,13 +7709,6 @@
7736
7709
  "defaultValue": null,
7737
7710
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7738
7711
  },
7739
- {
7740
- "name": "spacing",
7741
- "required": false,
7742
- "type": "\"default\" | \"none\" | null",
7743
- "defaultValue": "default",
7744
- "description": ""
7745
- },
7746
7712
  {
7747
7713
  "name": "variant",
7748
7714
  "required": false,
@@ -7777,13 +7743,6 @@
7777
7743
  "defaultValue": null,
7778
7744
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7779
7745
  },
7780
- {
7781
- "name": "spacing",
7782
- "required": false,
7783
- "type": "\"default\" | \"none\" | null",
7784
- "defaultValue": "default",
7785
- "description": ""
7786
- },
7787
7746
  {
7788
7747
  "name": "variant",
7789
7748
  "required": false,
@@ -7872,13 +7831,6 @@
7872
7831
  "defaultValue": null,
7873
7832
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7874
7833
  },
7875
- {
7876
- "name": "spacing",
7877
- "required": false,
7878
- "type": "\"default\" | \"none\" | null",
7879
- "defaultValue": "default",
7880
- "description": ""
7881
- },
7882
7834
  {
7883
7835
  "name": "variant",
7884
7836
  "required": false,
@@ -7940,13 +7892,6 @@
7940
7892
  "defaultValue": null,
7941
7893
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7942
7894
  },
7943
- {
7944
- "name": "spacing",
7945
- "required": false,
7946
- "type": "\"default\" | \"none\" | null",
7947
- "defaultValue": "default",
7948
- "description": ""
7949
- },
7950
7895
  {
7951
7896
  "name": "variant",
7952
7897
  "required": false,
@@ -7974,13 +7919,6 @@
7974
7919
  "defaultValue": null,
7975
7920
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
7976
7921
  },
7977
- {
7978
- "name": "spacing",
7979
- "required": false,
7980
- "type": "\"default\" | \"none\" | null",
7981
- "defaultValue": "default",
7982
- "description": ""
7983
- },
7984
7922
  {
7985
7923
  "name": "variant",
7986
7924
  "required": false,
@@ -8035,13 +7973,6 @@
8035
7973
  "defaultValue": null,
8036
7974
  "description": "Allows you to replace the component's HTML element\nwith a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
8037
7975
  },
8038
- {
8039
- "name": "spacing",
8040
- "required": false,
8041
- "type": "\"default\" | \"none\" | null",
8042
- "defaultValue": "default",
8043
- "description": ""
8044
- },
8045
7976
  {
8046
7977
  "name": "variant",
8047
7978
  "required": false,
@@ -125,6 +125,11 @@ Floating panel anchored to a trigger for contextual content, quick forms, or act
125
125
  - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .popover (jq: jq '.popover' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
126
126
  - further reading (usage/anatomy, not props): https://base-ui.com/react/components/popover.md
127
127
 
128
+ ## Prose
129
+ - category: Layout, status: experimental
130
+ Flow container that spaces long-form text and the blocks inside it. Also called an article or rich-text container. Use Stack or Row for UI layout.
131
+ - props: node_modules/@imfusion/web-ui/src/docgen/doc.gen.json -> .prose (jq: jq '.prose' node_modules/@imfusion/web-ui/src/docgen/doc.gen.json)
132
+
128
133
  ## Row
129
134
  - category: Layout, status: stable
130
135
  Horizontal layout primitive for spacing, aligning, and wrapping children. Also called a horizontal stack or flex row.
@@ -17,7 +17,7 @@ a gap or to make a deliberate deviation visible; do not refactor a project just
17
17
  | Topic | Read when |
18
18
  | ------------------------------------------------ | --------------------------------------------------------------- |
19
19
  | [library-setup](topics/library-setup.md) | Installing or repairing stylesheet and provider wiring. |
20
- | [library-boundary](topics/library-boundary.md) | Rendering Web UI components, wrapping them, or choosing a peer. |
20
+ | [library-boundary](topics/library-boundary.md) | Rendering, locking, or wrapping components, or choosing a peer. |
21
21
  | [authentication](topics/authentication.md) | Protecting routes or defining login and logout. |
22
22
  | [react](topics/react.md) | Designing component roles, state ownership, or effects. |
23
23
  | [components](topics/components.md) | Adding files or deciding component anatomy. |
@@ -13,6 +13,7 @@ sections one to one — change a topic's sections and this file follows in the s
13
13
 
14
14
  - [ ] Stay behind the library
15
15
  - [ ] Wrap primitives when the app has a reason to
16
+ - [ ] Lock a field: read-only or disabled
16
17
  - [ ] Derive types, don't import them
17
18
  - [ ] Integrations own their peers
18
19
  - [ ] Styling crosses the boundary through seams
@@ -56,6 +57,7 @@ sections one to one — change a topic's sections and this file follows in the s
56
57
  - [ ] CSS authoring
57
58
  - [ ] Build custom UI from tokens
58
59
  - [ ] Override through the sanctioned seams
60
+ - [ ] Spacing
59
61
  - [ ] The color system
60
62
  - [ ] Browser floor
61
63
  - [ ] Responsive styling
@@ -101,10 +103,9 @@ sections one to one — change a topic's sections and this file follows in the s
101
103
  - [ ] Devtools
102
104
  - [ ] Docs over memory
103
105
  - [ ] Prettier
104
- - [ ] ESLint
105
- - [ ] tsconfig
106
- - [ ] Staged files
107
- - [ ] CSS class names
106
+ - [ ] ESLint and TypeScript
107
+ - [ ] Pre-commit checks
108
+ - [ ] Vite plugins
108
109
 
109
110
  ## npm project — `npm-project`
110
111
 
@@ -28,6 +28,19 @@ Module classes.
28
28
  An `experimental` primitive should be wrapped once before it is used throughout an app. That gives an API change one place to
29
29
  land.
30
30
 
31
+ ## Lock a field: read-only or disabled
32
+
33
+ Ask whether the value is final here or the control is unavailable right now.
34
+
35
+ - `readOnly`: the value is real data the user cannot change in this context, such as an invited email or a generated ID. It
36
+ stays focusable, selectable, and copyable, screen readers announce it as read only, and the form submits it.
37
+ - `disabled`: the control does not apply until something on this screen changes, such as a field that waits for another
38
+ choice or a form that is saving. It leaves the tab order and the form data. Show the reason next to it.
39
+ - Plain text: nothing in the view is ever editable. Render a label and the value instead of a locked input.
40
+
41
+ Set one of the two. When both apply, for example a read-only field inside a disabled `Fieldset`, disabled wins in behavior
42
+ and in the library's styling. Re-derive a read-only value on the server instead of trusting the submitted copy.
43
+
31
44
  ## Derive types, don't copy them
32
45
 
33
46
  The library intentionally does not export component `Props` interfaces. Use `React.ComponentProps<typeof Component>` and
@@ -9,7 +9,7 @@ looks.
9
9
  component CSS.
10
10
  - **Partials** are reusable compositions extracted because they read as a unit. They have light logic and no styling of their
11
11
  own.
12
- - **Layout components** arrange content with `Stack`, `Row`, grids, and token gaps.
12
+ - **Layout components** arrange content with `Stack`, `Row`, grids, and token gaps, and wrap long-form text in `Prose`.
13
13
  - **Dumb components** receive data and callbacks, render UI, and own their styles. They do not fetch, route, or contain
14
14
  business rules.
15
15
 
@@ -50,6 +50,31 @@ hook, not a state flag.
50
50
  }
51
51
  ```
52
52
 
53
+ ## Spacing
54
+
55
+ Web UI components have no outer margin. The parent sets the distance between its children: `Stack` and `Row` gaps in UI,
56
+ `Prose` for long-form text. Inside a flex or grid gap a margin adds to the gap instead of collapsing, so do not add one to a
57
+ Web UI component.
58
+
59
+ ```tsx
60
+ // Wrong: the margin adds to the Stack gap.
61
+ <Stack gap="3">
62
+ <Typo.P style={{ marginBlockEnd: "1em" }}>Your study is ready.</Typo.P>
63
+ <Callout.Root>…</Callout.Root>
64
+ </Stack>
65
+
66
+ // Right: UI spaced by the gap, text spaced by Prose.
67
+ <Stack gap="3">
68
+ <Typo.P>Your study is ready.</Typo.P>
69
+ <Callout.Root>…</Callout.Root>
70
+ </Stack>
71
+
72
+ <Prose>
73
+ <Typo.H2>Export</Typo.H2>
74
+ <Typo.P>Pick a format, then a destination.</Typo.P>
75
+ </Prose>
76
+ ```
77
+
53
78
  ## The color system
54
79
 
55
80
  Use surface roles (`main`, `support`, `minor`), the separate `brand` and `primary` roles, status roles, and the three accent
@@ -88,3 +88,6 @@ export default defineConfig({
88
88
  `imfusionBrandAssets` serves the complete favicon set during development and emits it at stable root URLs during builds.
89
89
  Register `readableCssModuleNames` in every compiler that processes the app's CSS, including development, Storybook, and
90
90
  production. A compiler left out produces different class names and styles that appear to work only in some environments.
91
+
92
+ `localWebUILink` dedupes the library's peer dependencies when `@imfusion/web-ui` is linked from a local checkout
93
+ (`file:../web-ui`), so the app loads one React. It does nothing for an installed package and does not cover server rendering.
@@ -108,7 +108,8 @@ This phase reads and reports: every file stays as it is until the person approve
108
108
  releases read, then report separately:
109
109
 
110
110
  - migrations: every `Breaking` entry and migration step, mapped to the call sites it affects here and the fix the changelog
111
- shows; a step with no matching code is reported as not applicable;
111
+ shows; a step with no matching code is reported as not applicable. A style-only change, such as a removed margin, raises no
112
+ type error: find its call sites by component usage;
112
113
  - compatibility fixes required by changed imports or types that the changelog does not cover;
113
114
  - existing uses affected by a changed API or documented behavior;
114
115
  - suggestions: new features from the highlights and `Added` entries that fit what the project already builds, each with the
@@ -54,7 +54,8 @@ reason.
54
54
  ## Build the hierarchy
55
55
 
56
56
  - Frame an application with `AppShell`.
57
- - Compose `Stack` and `Row` for spacing and arrangement. Use `Separator` for a real division.
57
+ - Compose `Stack` and `Row` for spacing and arrangement, and wrap long-form text in `Prose`. Use `Separator` for a real
58
+ division.
58
59
  - Use `Typo` for text hierarchy instead of styling raw headings beside it.
59
60
  - Give a view one primary action. Make other actions quieter.
60
61
  - Choose density from the user's frequency and data volume: frequent work and large data need compact layouts; occasional