@imfusion/web-ui 0.10.1-dev.2.gb6347f49 → 0.10.1-dev.6.gf715361a
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.
- package/CHANGELOG.md +49 -0
- package/package.json +1 -1
- package/src/llms/skills/imf-web-ui-conventions/templates/AUDIT_CHECKLIST.md +1 -0
- package/src/llms/skills/imf-web-ui-conventions/topics/authentication.md +2 -3
- package/src/llms/skills/imf-web-ui-conventions/topics/components.md +4 -1
- package/src/llms/skills/imf-web-ui-conventions/topics/data.md +11 -5
- package/src/llms/skills/imf-web-ui-conventions/topics/project-structure.md +11 -0
- package/src/llms/skills/imf-web-ui-conventions/topics/react.md +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Agent skills — Nikolaus Brunner <brunner@imfusion.com>
|
|
8
|
+
- `imf-web-ui-conventions` has query factories own a numeric `staleTime` chosen by how fast other people change the data.
|
|
9
|
+
Loaders call `queryClient.query(options)` without an override, and `"static"` no longer appears in factories or
|
|
10
|
+
`defaultOptions`, where it blocked invalidation refetches.
|
|
11
|
+
- `imf-web-ui-conventions` puts a route's own views, forms, hooks, and tests in a `-<file-name>/` folder beside the route
|
|
12
|
+
file, and reserves `partials/` for parts that more than one route uses.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
3
16
|
## `0.10.0` 2026.10.15
|
|
4
17
|
|
|
5
18
|
### Highlights
|
|
@@ -234,6 +247,37 @@ AppShell sections draw no dividers. Delete overrides of the border properties, w
|
|
|
234
247
|
- --imf-ui-appshell-border-width: var(--imf-ui-border-size-2);
|
|
235
248
|
```
|
|
236
249
|
|
|
250
|
+
Navbar sections pad themselves with `--imf-ui-appshell-navbar-padding`, and that rule outranks a single class. Delete your
|
|
251
|
+
own section padding, and set the variable when the gutter needs to change:
|
|
252
|
+
|
|
253
|
+
```diff
|
|
254
|
+
- .navSection { padding: 0 var(--imf-ui-appshell-padding); }
|
|
255
|
+
+ .root { --imf-ui-appshell-navbar-padding: var(--imf-ui-size-5); }
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Nav links widen past the gutter only as `AppShell.NavItem`. Replace hand-built navbar links, and pass a router link through
|
|
259
|
+
`render`:
|
|
260
|
+
|
|
261
|
+
```diff
|
|
262
|
+
- <MyNavLink to="/products" icon={Box} label="Products" />
|
|
263
|
+
+ <AppShell.NavItem render={<Link to="/products" />} icon={<Icon glyph={Box} />}>Products</AppShell.NavItem>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Above `lg` the aside docks whether or not `open` is set. Render no aside when there is nothing to show, not an empty one:
|
|
267
|
+
|
|
268
|
+
```diff
|
|
269
|
+
- <AppShell.Aside>{selected ? <Details /> : <div />}</AppShell.Aside>
|
|
270
|
+
+ {selected ? <AppShell.Aside><Details /></AppShell.Aside> : null}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The navbar's first row and Main's offset read the header height while an `AppShell.Header` is rendered, even when CSS hides
|
|
274
|
+
it. Render the header conditionally instead of hiding it or setting the height to `0`:
|
|
275
|
+
|
|
276
|
+
```diff
|
|
277
|
+
- <AppShell.Header className={styles.hiddenOnDesktop}>…</AppShell.Header>
|
|
278
|
+
+ {isDesktop ? null : <AppShell.Header>…</AppShell.Header>}
|
|
279
|
+
```
|
|
280
|
+
|
|
237
281
|
### Breaking
|
|
238
282
|
|
|
239
283
|
- **Breaking:** The library supports Safari 17.5, Chrome 123, and Firefox 120 or newer. — Nikolaus Brunner <brunner@imfusion.com>
|
|
@@ -241,6 +285,11 @@ AppShell sections draw no dividers. Delete overrides of the border properties, w
|
|
|
241
285
|
- The JavaScript build targets the same versions.
|
|
242
286
|
- **Breaking:** AppShell sections draw no dividers, and the `--imf-ui-appshell-border-color`, `--imf-ui-appshell-border-width`, and `--imf-ui-appshell-border-style` properties are removed. ([WEBSDK-243](https://imfusion.atlassian.net/browse/WEBSDK-243)) — Nikolaus Brunner <brunner@imfusion.com>
|
|
243
287
|
- **Breaking:** `AppShell.Main` is the scroll container and the document does not scroll; window scroll listeners, scroll restoration, and `scrollTo` target `AppShell.Main`. ([WEBSDK-243](https://imfusion.atlassian.net/browse/WEBSDK-243)) — Nikolaus Brunner <brunner@imfusion.com>
|
|
288
|
+
- **Breaking:** AppShell owns its navbar and aside layout. ([WEBSDK-243](https://imfusion.atlassian.net/browse/WEBSDK-243)) — Nikolaus Brunner <brunner@imfusion.com>
|
|
289
|
+
- Navbar sections pad themselves with `--imf-ui-appshell-navbar-padding` through a rule that outranks a single class.
|
|
290
|
+
- Only `AppShell.NavItem` widens past the navbar gutter.
|
|
291
|
+
- Above `lg` the aside docks whether or not `open` is set.
|
|
292
|
+
- The navbar's first row and Main's offset read the header height whenever an `AppShell.Header` is rendered.
|
|
244
293
|
|
|
245
294
|
### Added
|
|
246
295
|
|
package/package.json
CHANGED
|
@@ -18,9 +18,8 @@ The file layout is in [project-structure.md](project-structure.md).
|
|
|
18
18
|
Use one server-backed current-user query as the identity source:
|
|
19
19
|
|
|
20
20
|
- Put it in `api/auth/queries.ts` and define its key and schema with the [data.md](data.md) pattern.
|
|
21
|
-
- Expose query options as `context.api.auth.getUser()
|
|
22
|
-
- Call `queryClient.query(
|
|
23
|
-
component.
|
|
21
|
+
- Expose query options as `context.api.auth.getUser()`, with a numeric `staleTime` set in the factory.
|
|
22
|
+
- Call `queryClient.query(options)` in a loader (see [data.md](data.md)) or a query hook in a component.
|
|
24
23
|
- Keep credentials and access tokens out of React state.
|
|
25
24
|
- Do not infer authentication from local storage, decoded tokens, route flags, or permission-gated UI.
|
|
26
25
|
|
|
@@ -29,7 +29,8 @@ export function UserCard({ name, onEdit }: UserCardProps) {
|
|
|
29
29
|
## Grouping
|
|
30
30
|
|
|
31
31
|
Group by component role, such as layout or domain UI, according to the project structure. Do not create a hierarchy before
|
|
32
|
-
the project needs one.
|
|
32
|
+
the project needs one. Components that only one route uses go in that route's `-` folder, not a shared group; see
|
|
33
|
+
[project-structure.md](project-structure.md).
|
|
33
34
|
|
|
34
35
|
## One file or a folder
|
|
35
36
|
|
|
@@ -50,3 +51,5 @@ The barrel only re-exports the public pieces.
|
|
|
50
51
|
|
|
51
52
|
Keep a component's stylesheet, tests, and local types beside the component. A container that needs styling usually wants to
|
|
52
53
|
be a layout or dumb component instead.
|
|
54
|
+
|
|
55
|
+
A route-local component keeps its stylesheet and tests in the route's `-` folder beside it.
|
|
@@ -85,11 +85,17 @@ export function getDetails(options?: QueryOptions<User>) {
|
|
|
85
85
|
}
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
Callers choose `queryClient.query`, `useSuspenseQuery`, or another Query API.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`
|
|
92
|
-
|
|
88
|
+
Callers choose `queryClient.query`, `useSuspenseQuery`, or another Query API. The factory owns `staleTime` as a number,
|
|
89
|
+
chosen by how fast other people change the data: near zero for data others edit often, minutes for data that rarely changes.
|
|
90
|
+
A router loader reads the cache with `queryClient.query(options)` and no override, not the deprecated `ensureQueryData` or
|
|
91
|
+
`fetchQuery`.
|
|
92
|
+
|
|
93
|
+
Never set `staleTime: "static"` in a factory or in `defaultOptions`. A query whose observers are all static is never
|
|
94
|
+
refetched, so invalidation after a mutation does nothing. Invalidation marks a query stale even when its `staleTime` is a
|
|
95
|
+
number, so the app's own mutations still refresh the data. Changes made by others show once the window expires.
|
|
96
|
+
|
|
97
|
+
Mutation factories likewise return `mutationOptions`, own their mutation key and parsing, and are passed to `useMutation`; do
|
|
98
|
+
not inline those options at the call site.
|
|
93
99
|
|
|
94
100
|
## Router context access
|
|
95
101
|
|
|
@@ -29,6 +29,17 @@ Create the root providers, current-user boundary, and pathless `_public/` and `_
|
|
|
29
29
|
new app starts `_app/` with a minimal `AppShell` unless it has no persistent authenticated navigation. An established app
|
|
30
30
|
keeps its working shell choice.
|
|
31
31
|
|
|
32
|
+
## Route-local code
|
|
33
|
+
|
|
34
|
+
A route file holds its search schema and `validateSearch`, its loaders, and its pending, error, and not-found components.
|
|
35
|
+
Route-local code that outgrows small in-file components (views, forms, hooks, tests) goes in a sibling folder named `-` plus
|
|
36
|
+
the route file's name: `route.tsx` gets `-route/`, `products.tsx` gets `-products/`. TanStack Router ignores files and
|
|
37
|
+
folders with a leading `-` when it builds the route tree, so the folder never becomes a route. The folder holds the route's
|
|
38
|
+
views with their props types, hooks, `.module.css` files, and tests. A component small enough to sit in the route file stays
|
|
39
|
+
there.
|
|
40
|
+
|
|
41
|
+
`partials/` holds only parts that more than one route uses.
|
|
42
|
+
|
|
32
43
|
## Imports
|
|
33
44
|
|
|
34
45
|
Use `./` for siblings and `#/` for imports elsewhere in `src/`:
|
|
@@ -5,10 +5,12 @@ looks.
|
|
|
5
5
|
|
|
6
6
|
## Composition: pages (smart containers), partials, dumb components
|
|
7
7
|
|
|
8
|
-
- **Pages** live in `routes/`. They load data, read URL state, coordinate actions, and compose the view.
|
|
9
|
-
component CSS.
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
- **Pages** live in `routes/`. They load data, read URL state, coordinate actions, and compose the view. Route files hold the
|
|
9
|
+
search schema, loaders, and pending, error, and not-found components. They do not own component CSS. Route-local views and
|
|
10
|
+
forms live in the route's `-` folder, as [project-structure.md](project-structure.md) describes, and that folder's
|
|
11
|
+
`.module.css` files are component styles.
|
|
12
|
+
- **Partials** are compositions that more than one route uses, extracted because they read as a unit. They have light logic
|
|
13
|
+
and no styling of their own.
|
|
12
14
|
- **Layout components** arrange content with `Stack`, `Row`, grids, and token gaps, and wrap long-form text in `Prose`.
|
|
13
15
|
- **Dumb components** receive data and callbacks, render UI, and own their styles. They do not fetch, route, or contain
|
|
14
16
|
business rules.
|