create-lykomi-app 0.11.1 → 0.13.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.
- package/README.md +8 -0
- package/package.json +1 -1
- package/presets/foundry-iq/files/AGENTS.md +6 -0
- package/presets/foundry-iq/files/README.md +20 -0
- package/presets/foundry-iq/files/agent/app/agent.py +3 -0
- package/presets/foundry-iq/files/agent/app/main.py +22 -4
- package/presets/foundry-iq/files/agent/pyproject.toml +3 -3
- package/presets/foundry-iq/files/src/main.tsx +2 -1
- package/presets/neo4j/files/AGENTS.md +6 -0
- package/presets/neo4j/files/README.md +20 -0
- package/presets/neo4j/files/agent/app/agent.py +3 -0
- package/presets/neo4j/files/agent/app/main.py +19 -0
- package/presets/neo4j/files/agent/pyproject.toml +3 -3
- package/presets/neo4j/files/src/main.tsx +2 -1
- package/presets/neo4j/manifest.json +1 -1
- package/template/AGENTS.md +6 -0
- package/template/README.md +43 -4
- package/template/_agents/skills/lykomi-author-chat-module/SKILL.md +57 -0
- package/template/_agents/skills/lykomi-author-chat-module/references/PROCESS_GUIDE.md +203 -0
- package/template/_agents/skills/lykomi-author-chat-module/references/form-ux.md +579 -0
- package/template/_agents/skills/lykomi-build-agent-forms/SKILL.md +36 -0
- package/template/_agents/skills/lykomi-build-agent-forms/references/PROCESS_GUIDE.md +203 -0
- package/template/_agents/skills/lykomi-build-agent-forms/references/form-ux.md +579 -0
- package/template/_agents/skills/lykomi-build-workbench/SKILL.md +37 -0
- package/template/_agents/skills/lykomi-build-workbench/references/PROCESS_GUIDE.md +203 -0
- package/template/_agents/skills/lykomi-build-workbench/references/form-ux.md +579 -0
- package/template/_agents/skills/lykomi-verify-agent-apis/SKILL.md +42 -0
- package/template/_agents/skills/lykomi-verify-agent-apis/references/PROCESS_GUIDE.md +203 -0
- package/template/_agents/skills/lykomi-verify-agent-apis/references/form-ux.md +579 -0
- package/template/_agents/skills/lykomi-verify-ui/SKILL.md +31 -0
- package/template/_claude/skills/lykomi-author-chat-module/SKILL.md +57 -0
- package/template/_claude/skills/lykomi-author-chat-module/references/PROCESS_GUIDE.md +203 -0
- package/template/_claude/skills/lykomi-author-chat-module/references/form-ux.md +579 -0
- package/template/_claude/skills/lykomi-build-agent-forms/SKILL.md +36 -0
- package/template/_claude/skills/lykomi-build-agent-forms/references/PROCESS_GUIDE.md +203 -0
- package/template/_claude/skills/lykomi-build-agent-forms/references/form-ux.md +579 -0
- package/template/_claude/skills/lykomi-build-workbench/SKILL.md +37 -0
- package/template/_claude/skills/lykomi-build-workbench/references/PROCESS_GUIDE.md +203 -0
- package/template/_claude/skills/lykomi-build-workbench/references/form-ux.md +579 -0
- package/template/_claude/skills/lykomi-verify-agent-apis/SKILL.md +42 -0
- package/template/_claude/skills/lykomi-verify-agent-apis/references/PROCESS_GUIDE.md +203 -0
- package/template/_claude/skills/lykomi-verify-agent-apis/references/form-ux.md +579 -0
- package/template/_claude/skills/lykomi-verify-ui/SKILL.md +31 -0
- package/template/agent/app/agent.py +3 -1
- package/template/agent/app/main.py +15 -1
- package/template/agent/app/skills.py +70 -0
- package/template/agent/pyproject.toml +3 -3
- package/template/agent/skills/plan-work/SKILL.md +18 -0
- package/template/agent/tests/test_skills.py +75 -0
- package/template/package.json +5 -5
- package/template/src/main.tsx +2 -1
- package/template/src/pages/starter-prompts.tsx +9 -2
- package/template/src/showcase/context-inspector.tsx +110 -0
- package/template/src/showcase/dashboard-example.tsx +157 -0
- package/template/src/showcase/feedback-example.tsx +135 -0
- package/template/src/showcase/form-example.tsx +171 -0
- package/template/src/showcase/form-model.ts +38 -0
- package/template/src/showcase/module.tsx +47 -0
- package/template/src/showcase/process-example.tsx +118 -0
- package/template/src/showcase/showcase-page.tsx +218 -0
- package/template/src/showcase/source-panel.tsx +50 -0
- package/template/src/showcase/table-example.tsx +180 -0
- package/template/src/showcase/table-model.ts +48 -0
- package/template/src/showcase/use-context-preview.ts +55 -0
- package/template/src/showcase/use-task-context.ts +107 -0
- package/template/src/showcase/windows-example.tsx +106 -0
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
<!-- Generated from docs/FORM_UX.md; do not edit. -->
|
|
2
|
+
|
|
3
|
+
# Opinionated form and renderer UX
|
|
4
|
+
|
|
5
|
+
This is the default contract for developers and coding agents using LYKOMI UI.
|
|
6
|
+
Use it for native UI, generated forms, list-item inspectors and custom renderers.
|
|
7
|
+
Depart from the default only when the user explicitly requests the different interaction
|
|
8
|
+
or layout. A request for a domain-specific renderer does not request a different UX.
|
|
9
|
+
|
|
10
|
+
## Semantic composition: decide what belongs where
|
|
11
|
+
|
|
12
|
+
Start from the person's task and the real schema, not a visual template or an
|
|
13
|
+
alphabetical dump of properties. Keep one semantic order in View, Edit and
|
|
14
|
+
Read-only. These placements are product defaults; preserve an established domain
|
|
15
|
+
workflow and depart only on explicit user instruction.
|
|
16
|
+
|
|
17
|
+
| Order | Content and purpose | Placement |
|
|
18
|
+
| ----- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| 1 | Identity and orientation: what item is this, what is this form for? | One title, optional one-sentence purpose, parent/context when needed. Reuse identity already supplied by the host. |
|
|
20
|
+
| 2 | Current situation and next step: state, outcome, blocker requiring action. | Compact status/summary near the title. Put an actionable blocker before affected fields; put field-specific errors at the field. Do not invent a status from completeness. |
|
|
21
|
+
| 3 | Core facts needed to recognise, assign or act on the record. | First visible group: the relevant identity/name field, type/category, responsible person and date/deadline. Include only facts meaningful to this task. |
|
|
22
|
+
| 4 | Main work: the decision or information the person is here to supply/review. | Clearly named sections, in task order. Put a prerequisite before its dependent field. Group related fields; put narrative explanations in full-width slots. |
|
|
23
|
+
| 5 | Evidence and related material supporting the decision. | Citations, sources, attachments and related records near the finding they substantiate, or in a dedicated Evidence section. Keep links usable in reading mode. |
|
|
24
|
+
| 6 | Secondary information that rarely changes the next action. | Additional details, collapsed only when safe. Technical identifiers, timestamps, audit/version information go last in metadata/support, never as primary editable fields. |
|
|
25
|
+
| 7 | Complete the current transaction. | One Save/Cancel group for Edit/Create, owned by the host. Primary action last; destructive actions live separately with explicit meaning. Reading states have task actions instead of a submit bar. |
|
|
26
|
+
|
|
27
|
+
Required is a validation property, not the only ordering rule. Keep essential
|
|
28
|
+
inputs visible early; do not collapse a missing required input or an unresolved
|
|
29
|
+
error. Do not sort all required fields ahead of their prerequisites or split a
|
|
30
|
+
logical group. Use short, task-specific section names such as “Ownership”,
|
|
31
|
+
“Assessment” or “Evidence”; “Details” alone is not a useful name for every group.
|
|
32
|
+
One page title is level 1, sections below it level 2; an embedded form headed at
|
|
33
|
+
level 2 uses level 3 sections. Adjust semantic heading level without inventing
|
|
34
|
+
another typography style.
|
|
35
|
+
|
|
36
|
+
Before generating UI, map each applicable field to a group and explain its role
|
|
37
|
+
(identity, status, core fact, decision, evidence or metadata). Reuse schema labels,
|
|
38
|
+
help, options, applicability and persisted order; do not fabricate backend fields.
|
|
39
|
+
An existing empty value keeps its slot so later values and Edit do not move.
|
|
40
|
+
Store grouping in the schema or shared composition rather than separate read/edit
|
|
41
|
+
layouts. Keep summaries concise and grounded in saved values; avoid repeating
|
|
42
|
+
all the fields above the form.
|
|
43
|
+
|
|
44
|
+
## Reading, Read-only and temporarily disabled
|
|
45
|
+
|
|
46
|
+
| State | Values and interactions | Actions |
|
|
47
|
+
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
48
|
+
| View, with write access | Saved values as readable text, matching the edit field slots. Text selection, copying, links and context selection work. | Explicit Edit is available. No Save/Cancel yet. |
|
|
49
|
+
| Edit/Create | Controls replace values within the same sections and slots. Clearly explain required fields, validation and blockers. | One Save/Create and Cancel transaction. |
|
|
50
|
+
| Read-only record | Same information hierarchy and normal text contrast, with readable/copyable values. Explain the reason once near the header when available, such as “Published version” or “Read-only access”. | No Edit, inline edit triggers or Save/Cancel. Reading actions, links, export and permitted discussion remain available. |
|
|
51
|
+
| One protected field in an editable record | Keep its saved value readable in its normal slot; explain the field-specific lock/managed-source reason. | Other writable fields still work. No editor or Save for this field. |
|
|
52
|
+
| Temporarily disabled control | Retain the control while a prerequisite, save or load is pending; explain what enables it. | Prevent duplicate/invalid action; restore availability when the condition resolves. |
|
|
53
|
+
|
|
54
|
+
Use display values for a read-only record, not a page of grey disabled inputs.
|
|
55
|
+
Do not dim the whole form, hide meaningful values or show input-required/error
|
|
56
|
+
badges that the reader cannot act on. Keep an explicit empty state (“Not set”,
|
|
57
|
+
or the schema's display convention); zero and false remain real values.
|
|
58
|
+
Selection keeps the same leading context marker; it never grants write access.
|
|
59
|
+
|
|
60
|
+
Read-only is enforced by application permissions and save handlers, not by CSS.
|
|
61
|
+
When access is unknown, withhold writes until resolved. Field locks, edit rights
|
|
62
|
+
and review rights are distinct: check the actual permission for each action.
|
|
63
|
+
Historical snapshots must not mutate or review the live record. A permission
|
|
64
|
+
change must stop writes without silently losing a draft. Do not use blur to save.
|
|
65
|
+
|
|
66
|
+
## Compose the shipped presets
|
|
67
|
+
|
|
68
|
+
Import `FormLayout`, `FormHeader`, `FormSection`, `FormActions`, `Field`, `FieldSet`,
|
|
69
|
+
`ReadOnlyField`, `Input`, `Textarea` and `Button` from `@lykomi/web-primitives`.
|
|
70
|
+
Use the existing themed `FormDialog`, `SurfaceCard` and `CollectionSurface` from
|
|
71
|
+
`@lykomi/web-ui` for the host surface. These presets compose with them;
|
|
72
|
+
do not put another card around every field or another form inside a form.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<FormLayout>
|
|
76
|
+
<FormHeader title="Contact details" description="How we can reach you." />
|
|
77
|
+
<FormSection title="Contact" description="Use your work contact details.">
|
|
78
|
+
<Field label="Email" htmlFor="contact-email" hint="We use this for updates.">
|
|
79
|
+
<Input id="contact-email" type="email" autoComplete="email" />
|
|
80
|
+
</Field>
|
|
81
|
+
</FormSection>
|
|
82
|
+
<FormActions className="justify-end">
|
|
83
|
+
<Button variant="outline" type="button">
|
|
84
|
+
Cancel
|
|
85
|
+
</Button>
|
|
86
|
+
<Button type="submit">Save</Button>
|
|
87
|
+
</FormActions>
|
|
88
|
+
</FormLayout>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The application supplies its save handlers and one outer `<form>` if needed.
|
|
92
|
+
Preset layout components do not submit, fetch or store data.
|
|
93
|
+
|
|
94
|
+
## Automatic field context
|
|
95
|
+
|
|
96
|
+
The selected field context uses a short leading marker beside its label. This marker
|
|
97
|
+
stays visible when moving into chat and is separate from input and keyboard focus.
|
|
98
|
+
Do not replace focus indicators with the context marker.
|
|
99
|
+
|
|
100
|
+
`Field` and `ReadOnlyField` participate in agent context automatically when used
|
|
101
|
+
with `@lykomi/web-ui`. Focus or click a field, then enter chat: the request carries
|
|
102
|
+
its label, current value, target path and text selection. Values are read from the
|
|
103
|
+
current control at request time. No page-specific focus handlers, context store
|
|
104
|
+
updates or context hook are needed. `Input` and `Textarea` remain leaf controls;
|
|
105
|
+
wrap them in `Field` to supply their label and field boundary.
|
|
106
|
+
|
|
107
|
+
Use `name` on the control for a semantic target path. The control ID is the
|
|
108
|
+
fallback. Hidden/inert fields, closed windows and inactive workbench windows
|
|
109
|
+
cannot remain the active subject. The mobile switch to Chat retains the current
|
|
110
|
+
field, while changing the route clears it. Password inputs are excluded. For
|
|
111
|
+
other sensitive values set `agentContext={false}` on `Field` or `ReadOnlyField`,
|
|
112
|
+
or `data-agent-context="off"` on a containing surface.
|
|
113
|
+
|
|
114
|
+
This gives the agent context, not write access. The application owns validation,
|
|
115
|
+
draft updates, saving and permissions through its registered tools. The starter's
|
|
116
|
+
`use-draft-tools.ts` demonstrates guarded, unsaved edits using `usePageTools`.
|
|
117
|
+
|
|
118
|
+
Applications with richer field metadata can register a `FieldContextSource`
|
|
119
|
+
through `registerFieldContextSource(id, { selector, getRefId, ignoreSelector })`.
|
|
120
|
+
Their source takes precedence over nested primitive fields, preventing duplicate
|
|
121
|
+
context. `getActiveFieldContext()` supplies the shared element, target and caret
|
|
122
|
+
snapshot to their domain projection. Registration returns a cleanup function.
|
|
123
|
+
The shared tracker owns focus and selection; entity identifiers, change tracking
|
|
124
|
+
and persistence remain in the application.
|
|
125
|
+
|
|
126
|
+
## Interaction contract
|
|
127
|
+
|
|
128
|
+
- Open (including a list double-click or keyboard activation) starts in reading mode.
|
|
129
|
+
Edit is an explicit, discoverable action; Create starts in editing mode.
|
|
130
|
+
- Labels, field order, sections, width and value origins stay in the same slots when
|
|
131
|
+
switching modes. Keep the field layout mounted and replace only the value/control.
|
|
132
|
+
Preserve expanded sections and reading position. Empty values retain their slots.
|
|
133
|
+
- Prefer one column. Put a small pair on one row only when its meaning requires it.
|
|
134
|
+
Long text gets its own full-width section. Use container width rather than screen width
|
|
135
|
+
when forms appear in side panels.
|
|
136
|
+
- Inline edits have visible Edit, Save and Cancel controls, with keyboard access and
|
|
137
|
+
focus restoration. Escape cancels; a multiline Enter writes a newline. Do not save
|
|
138
|
+
long text on blur. Do not put links or other controls inside an edit button or label.
|
|
139
|
+
- The host owns identity, navigation and the transactional Save/Cancel controls.
|
|
140
|
+
Embedded renderers do not repeat the host's title or submit controls.
|
|
141
|
+
- Retain dirty input on failed save or conflict. Show an actionable error and let the
|
|
142
|
+
person retry. Explain a disabled Save; for long forms link errors to their fields.
|
|
143
|
+
- Associate labels with controls; use descriptive help and errors, not placeholders
|
|
144
|
+
as labels. Use an accessible Dialog for modal detail views (focus trap, Escape,
|
|
145
|
+
return focus), including mobile.
|
|
146
|
+
|
|
147
|
+
## Themes and spacing
|
|
148
|
+
|
|
149
|
+
Use semantic tokens (`background`, `card`, `foreground`, `muted-foreground`, `border`,
|
|
150
|
+
`primary`, `ring`, `destructive`) and the existing theme. Never invent a color palette,
|
|
151
|
+
hard-code white/black surfaces, or create a second theme in a custom renderer.
|
|
152
|
+
Tailwind spacing utilities resolve through the host's `--spacing` token.
|
|
153
|
+
The default rhythm is 8 units between sections, 4 between fields, 2 between actions
|
|
154
|
+
and between a heading and help. At the standard 4px unit these are 32/16/8px.
|
|
155
|
+
Use `density="compact"` for constrained inspectors; keep controls comfortably usable.
|
|
156
|
+
Use the host radius tokens. Read/edit mode does not change density.
|
|
157
|
+
Test light, dark, narrow containers, long labels, empty values, keyboard and errors.
|
|
158
|
+
|
|
159
|
+
## Evidence behind the default
|
|
160
|
+
|
|
161
|
+
Checked 2026-10-06:
|
|
162
|
+
|
|
163
|
+
- [Atlassian inline edit](https://atlassian.design/components/inline-edit/usage/)
|
|
164
|
+
supports matched read/edit alignment and explicit controls, with special care for
|
|
165
|
+
long text and blur behavior.
|
|
166
|
+
- [Carbon forms](https://www.carbondesignsystem.com/building-blocks/core/patterns/forms)
|
|
167
|
+
supports logical grouping, a single-column default, contextual spacing and useful
|
|
168
|
+
validation timing.
|
|
169
|
+
- [WAI labels](https://www.w3.org/WAI/tutorials/forms/labels/) and
|
|
170
|
+
[WAI validation](https://www.w3.org/WAI/tutorials/forms/validation/) ground naming
|
|
171
|
+
and understandable errors.
|
|
172
|
+
- [GOV.UK error summary](https://design-system.service.gov.uk/components/error-summary/)
|
|
173
|
+
describes focused summaries linking errors to fields.
|
|
174
|
+
|
|
175
|
+
These are a baseline for usability checks, not a claim that the presets alone guarantee
|
|
176
|
+
accessibility or usability. Browser evidence must exercise the application's real flows.
|
|
177
|
+
|
|
178
|
+
## Release boundary
|
|
179
|
+
|
|
180
|
+
New presets must be released through Changesets before downstream applications import
|
|
181
|
+
them. A local sibling workspace can validate this source but cannot prove registry
|
|
182
|
+
availability. Downstream adapters may compose the already-published `FieldSet`, `Field`
|
|
183
|
+
and surface components until the preset release is available; then switch their internal
|
|
184
|
+
composition to these presets without changing the user-facing contract.
|
|
185
|
+
|
|
186
|
+
## Selection and active context
|
|
187
|
+
|
|
188
|
+
Use one quiet leading marker for selected blocks, fields, tabs and item panels:
|
|
189
|
+
2px wide, inset 6px vertically, theme primary at 55% opacity. The shared
|
|
190
|
+
`--selection-marker-width` and `--selection-marker-color` overrides may adapt it
|
|
191
|
+
to the theme. Selection changes no layout geometry and adds no colored outer
|
|
192
|
+
frame, fill or shadow. Workbench chrome uses a neutral theme border. Keyboard
|
|
193
|
+
focus, input validation, drop targets and pending-review frames keep their
|
|
194
|
+
respective semantics. Compact process navigation uses a subtle primary surface for its
|
|
195
|
+
inspected step; overview navigation retains a primary border and subtle fill.
|
|
196
|
+
These task-navigation controls are the explicit exception to the leading marker. Temporary windows remain identifiable through the unpinned
|
|
197
|
+
icon, accessible name and tooltip.
|
|
198
|
+
|
|
199
|
+
`ReadOnlyField label hint emptyLabel` renders a semantic label/value pair with
|
|
200
|
+
selectable text and usable links, preserving the `Field` spacing rhythm. Use it
|
|
201
|
+
for View/Read-only and keep the same `FormLayout`/`FormSection` composition.
|
|
202
|
+
`FormSection level={2}` pairs with a page-level `FormHeader level={1}`; its default
|
|
203
|
+
level 3 pairs with the default header level 2. The source preview opens in View
|
|
204
|
+
and lets you exercise Edit, Cancel/Save and simulated read-only access.
|
|
205
|
+
|
|
206
|
+
## Required indicators and field frames
|
|
207
|
+
|
|
208
|
+
Use quiet inline “(Required)” text in mixed Create/Edit forms; no pill or badge
|
|
209
|
+
frame. Do not show input requirements in View or permanently read-only records.
|
|
210
|
+
`Field` derives the visible marker from its single control's `required` or
|
|
211
|
+
`aria-required` state; use `ReadOnlyField` for reading states.
|
|
212
|
+
Keep `required`/`aria-required` on the actual control and actionable validation.
|
|
213
|
+
A star requires an explanation at the form start; when almost all fields are
|
|
214
|
+
mandatory, marking the exceptions “(optional)” is a valid explicit product choice.
|
|
215
|
+
See [W3C H90](https://www.w3.org/WAI/WCAG22/Techniques/html/H90) and
|
|
216
|
+
[GOV.UK question pages](https://design-system.service.gov.uk/patterns/question-pages/).
|
|
217
|
+
|
|
218
|
+
Display values use the same neutral theme border, radius and padding as their
|
|
219
|
+
editor, without pretending to be disabled controls. Multi-line values and editors
|
|
220
|
+
share line height and a minimum height; editors grow with their content. Reserve
|
|
221
|
+
the reading height on the actual textarea, not just its wrapper. Verify that the
|
|
222
|
+
textarea has no hidden lines and that following sections do not jump. Double-click
|
|
223
|
+
on form text stays in View so text selection works; explicit Edit enters editing.
|
|
224
|
+
|
|
225
|
+
Field frames and editors use the same theme radius, including enum/select buttons and multiline controls. Keep single-line heights consistent; chips have their own pill treatment. Group secondary metadata in a compact footer with one separator. Helpers explain meaningful decisions in everyday language, not storage formats or schema internals. Suggestion popovers anchor to the input, match its width, fit the viewport and support keyboard selection/dismissal.
|
|
226
|
+
|
|
227
|
+
## Keeping skill guidance current
|
|
228
|
+
|
|
229
|
+
Edit this document rather than reproducing the rules in plugin skills. Run `pnpm sync:form-ux` to regenerate their bundled `references/form-ux.md` resources. `pnpm check:form-ux` (part of `pnpm test` and CI) rejects stale resources. Skills read the bundled reference even when installed outside the framework checkout.
|
|
230
|
+
|
|
231
|
+
## Fixed content versus editable values
|
|
232
|
+
|
|
233
|
+
A catalogue question, instruction or computed explanation is content. Render it
|
|
234
|
+
without input chrome: `ReadOnlyField valueAppearance="content"`. The default
|
|
235
|
+
`valueAppearance="field"` preserves a framed value slot for records whose fields
|
|
236
|
+
become editable through Edit. Choose the presentation from the meaning of the
|
|
237
|
+
value, not the current page mode, so fixed content stays content in View and Edit.
|
|
238
|
+
Content remains selectable and links stay usable; do not replace it with a
|
|
239
|
+
disabled input. Appearance does not grant or revoke edit permission. Keep
|
|
240
|
+
permission enforcement and pending-change review independent of presentation.
|
|
241
|
+
|
|
242
|
+
## Lists and data tables
|
|
243
|
+
|
|
244
|
+
Use the shared `useDataTable` / `DataTableFrame` / `DataTableToolbar` /
|
|
245
|
+
`DataTable` / `DataTablePagination` family. Start with the person's task:
|
|
246
|
+
identify records, compare values, find exceptions or review a queue. Put the
|
|
247
|
+
identity column first and keep the fields needed for that task visible. Keep
|
|
248
|
+
metadata secondary; do not size columns alphabetically or from the longest
|
|
249
|
+
raw value. Long names must not push status and dates off-screen.
|
|
250
|
+
|
|
251
|
+
Define each column's `size`, `minSize` and `maxSize` in its `ColumnDef`.
|
|
252
|
+
Give identity/narrative columns more room than dates, states and numeric
|
|
253
|
+
values. The shared defaults are 80px minimum and 1200px maximum. The hook's
|
|
254
|
+
`defaultColumn` configures shared bounds; individual
|
|
255
|
+
columns override them. Mark selection and action columns
|
|
256
|
+
`enableResizing: false` and give them fixed bounds. Use `meta.align` for
|
|
257
|
+
numbers and short comparable values, with consistent formatting and units.
|
|
258
|
+
Do not apply a nested fixed `max-width` to text that should benefit from
|
|
259
|
+
resizing. Use truncation for long identity text, expose the full value on
|
|
260
|
+
hover, and make the item inspector the place to read/edit long content.
|
|
261
|
+
|
|
262
|
+
Users can resize a header's separate separator by dragging, use arrow keys
|
|
263
|
+
(Shift for larger steps), Home/End for bounds, and Enter or double-click to
|
|
264
|
+
reset. The resize target must not also sort. Honor `enableResizing` and
|
|
265
|
+
individual bounds. User widths are part of `DataTableState.columnSizing`;
|
|
266
|
+
URL state stores them under a namespaced `widths` key. Each list on a page
|
|
267
|
+
needs a stable unique URL prefix. User choices override author defaults;
|
|
268
|
+
reset widths separately from filters and sorting.
|
|
269
|
+
|
|
270
|
+
For an ordinary bounded list, pass `maxHeight` (a responsive value such as
|
|
271
|
+
`min(70vh, 42rem)`) and keep the header sticky. The table owns one row
|
|
272
|
+
viewport, while toolbar and paging controls stay outside it. Focus mode
|
|
273
|
+
uses `fill` to occupy the available panel height. Preserve horizontal
|
|
274
|
+
position while navigating rows vertically. Keep native wheel, trackpad,
|
|
275
|
+
touch and keyboard scrolling; never translate all vertical wheel events
|
|
276
|
+
into sideways scrolling. Bounded tables fit the current viewport and leave room for their scrollbar and
|
|
277
|
+
action row. Compose `DataTableFrame` with `DataTablePagination` so wrapped paging
|
|
278
|
+
controls contribute their actual height. `fitViewport={false}` opts out for a host that deliberately owns
|
|
279
|
+
that sizing. The native horizontal scrollbar and bottom arrow controls remain
|
|
280
|
+
reachable without first scrolling through every row.
|
|
281
|
+
Honor reduced motion. Keep essential information visible before overflow.
|
|
282
|
+
A frozen identity column must leave room for the scrolling columns. At narrow
|
|
283
|
+
widths the shared table releases a wide frozen prefix while keeping narrow
|
|
284
|
+
leading utility columns fixed when they fit; column widths remain unchanged.
|
|
285
|
+
|
|
286
|
+
For a dedicated long-list view, use `DataTable scrollMode="page"` and let its
|
|
287
|
+
containing page own the one vertical scroll. Pass `stickyHeaderOffset` for the
|
|
288
|
+
height of sticky navigation and filters above it. The shared table keeps its
|
|
289
|
+
compact horizontal arrows above the column labels when columns overflow;
|
|
290
|
+
both remain reachable while the rows scroll, and the arrows disappear when
|
|
291
|
+
all columns fit. The mirrored sticky labels are visual only; sorting and
|
|
292
|
+
selection controls remain in the original header at the top of the list.
|
|
293
|
+
Do not add a
|
|
294
|
+
second vertical row viewport or a second horizontal scrollport. Keep the
|
|
295
|
+
sticky stack compact: let the page hero scroll away, collapse optional facet
|
|
296
|
+
chips behind Filters on narrow panes, and retain search, the active filter
|
|
297
|
+
count, horizontal navigation and column labels. Show the task's useful
|
|
298
|
+
columns by default and let the horizontal scroller reach the rest. A width
|
|
299
|
+
breakpoint may hide genuinely secondary fields, but must not make horizontal
|
|
300
|
+
overflow disappear by silently hiding the columns a user came to compare.
|
|
301
|
+
For thousands of rows, use paging or the bounded, virtualized focus mode
|
|
302
|
+
instead of mounting the entire dataset in the page.
|
|
303
|
+
|
|
304
|
+
`spacer={false}` lets the first content column use spare width, up to its
|
|
305
|
+
maximum. A user-resized column keeps its chosen width. The default spacer
|
|
306
|
+
keeps declared column widths and leaves spare room at the end. Explicit
|
|
307
|
+
responsive column gates are separate from persisted visibility; shrinking
|
|
308
|
+
the panel must never overwrite the user's column choices.
|
|
309
|
+
|
|
310
|
+
Configure default sorting, filters, visibility and page size through
|
|
311
|
+
`initialState` for an uncontrolled table, or through the URL adapter's
|
|
312
|
+
`defaults` when controlled. Use real schema values and stable IDs. Choose
|
|
313
|
+
a default sort meaningful to the workflow (for example latest activity,
|
|
314
|
+
nearest deadline, or priority), and show the active sort/filter controls.
|
|
315
|
+
An explicitly cleared filter or sort must stay cleared after reload. Do
|
|
316
|
+
not silently reapply author defaults over the user's state.
|
|
317
|
+
|
|
318
|
+
Check long/empty/mixed values, pointer and keyboard resizing, width reset,
|
|
319
|
+
filter/sort defaults and overrides, both scroll axes, sticky/frozen columns,
|
|
320
|
+
and light/dark themes in wide and narrow containers. Tests and screenshots
|
|
321
|
+
verify behavior; claims of improved enjoyment require task-based user testing.
|
|
322
|
+
|
|
323
|
+
This contract draws on [NN/g's table task research](https://www.nngroup.com/articles/data-tables/),
|
|
324
|
+
[React Spectrum's column resizing and persistence](https://react-spectrum.adobe.com/v3/TableView.html),
|
|
325
|
+
[WAI's keyboard interaction patterns](https://www.w3.org/WAI/ARIA/apg/patterns/grid/),
|
|
326
|
+
and [TanStack's column sizing contract](https://tanstack.com/table/v8/docs/guide/column-sizing).
|
|
327
|
+
These are complementary references, not a single design-system benchmark.
|
|
328
|
+
|
|
329
|
+
Paged bounded tables reserve a stable viewport when standard pagination has multiple pages, so the next/previous controls do not jump on a short final page. `stableHeight` explicitly overrides this behavior. Page changes return to the top while preserving the horizontal position; resizing columns preserves the current reading position.
|
|
330
|
+
|
|
331
|
+
Use a single native horizontal scrollport per table. Bounded tables place their arrows below the row viewport; page-owned tables keep compact arrows in the sticky header stack. Do not duplicate the horizontal scrollbar with a synchronized second track.
|
|
332
|
+
|
|
333
|
+
### Workspace navigation loading
|
|
334
|
+
|
|
335
|
+
Use the shared navigation skeleton for the first sidebar load and compact rail.
|
|
336
|
+
An individual branch can resolve to no visible children: show a small loading ring
|
|
337
|
+
inside the existing disclosure control, not as invented child rows. Keep the
|
|
338
|
+
control mounted, focusable and `aria-busy` while an unknown branch loads; retain
|
|
339
|
+
its normal toggle behavior. A focused heading has no disclosure button: use its
|
|
340
|
+
existing gutter for a named busy status with the same loading ring. A known empty branch stays empty during refresh.
|
|
341
|
+
Selected rows and their ancestors keep the same label size, weight and spacing as
|
|
342
|
+
unselected rows; use the shared selected background and foreground tokens.
|
|
343
|
+
Set `NavGroup.loading` or `NavItem.childrenLoading` from the existing read state;
|
|
344
|
+
do not manufacture a navigable or disabled "Loading..." item. When workspace
|
|
345
|
+
children are promoted into their own group, carry their loading state with them.
|
|
346
|
+
Skeletons use native geometry, semantic sidebar theme tokens and reduced-motion
|
|
347
|
+
preferences. Keep known rows visible during refresh. Loading presentation must
|
|
348
|
+
not schedule another read, add a reveal timer, or resize the content shell.
|
|
349
|
+
Workspace availability and breadcrumb arrival must not change pane header height
|
|
350
|
+
or chat-body padding. These are shared layout/theme geometry, not data states.
|
|
351
|
+
|
|
352
|
+
Sidebar scrolling follows navigation intent, not every tree update. Reveal the
|
|
353
|
+
active row once on a route change or when its first authorized row arrives,
|
|
354
|
+
using the nearest clipped edge. Pointer, wheel and keyboard interaction give the
|
|
355
|
+
user ownership of the reading position. Branch expansion, pagination, refresh
|
|
356
|
+
and status updates must not recenter the selected page or restart reveal timers.
|
|
357
|
+
Keep reveal work scoped to that sidebar's own scrollport; never scroll the page
|
|
358
|
+
or move keyboard focus as a side effect of loading.
|
|
359
|
+
|
|
360
|
+
Branch pagination uses a shared native button aligned with its child rows and
|
|
361
|
+
the sidebar theme. Keep the control mounted and focusable while busy, expose
|
|
362
|
+
its busy/disabled semantics, and guard repeat activation.
|
|
363
|
+
On the final page, retain the focused action as a quiet completion state until
|
|
364
|
+
focus leaves it; removing the focused button must not strand focus on the page.
|
|
365
|
+
The branch owner still owns the authorized cursor and request lifecycle;
|
|
366
|
+
presentation must not add automatic loading loops or another observer.
|
|
367
|
+
|
|
368
|
+
Chat homes keep their static heading and helper copy mounted. While the actual
|
|
369
|
+
context is unknown, show a theme skeleton rather than briefly painting generic
|
|
370
|
+
context. Use `ActionListSkeleton` for first-load starters, workflow actions and
|
|
371
|
+
recent chats, driven by their existing read state. Keep successfully loaded
|
|
372
|
+
suggestions and chats visible on refresh; settle empty and failed reads instead
|
|
373
|
+
of leaving a permanent skeleton. Do not disable the composer or trigger work.
|
|
374
|
+
The global home has no item context: do not mount contextual starter placeholders
|
|
375
|
+
above its create action. Reserve the action row itself, and put history skeletons
|
|
376
|
+
inside the existing Recent and Pinned cards. Keep those cards and their headings
|
|
377
|
+
stable through pending, populated and empty states, including narrow layouts.
|
|
378
|
+
|
|
379
|
+
## Wizards and process guidance
|
|
380
|
+
|
|
381
|
+
Use `ProcessSteps` for a connected status rail and `ProcessGuide` for that rail
|
|
382
|
+
plus a focused guidance/action panel. This section is the maintained component
|
|
383
|
+
contract; the standalone process guide and skill resources are generated from it.
|
|
384
|
+
Use a wizard for sequential input and a process overview for resumable work;
|
|
385
|
+
independent tasks belong in a task list rather than a misleading sequence.
|
|
386
|
+
|
|
387
|
+
- Start with `variant="compact"` and expanded guidance for an active task.
|
|
388
|
+
Collapse only genuinely secondary help; do not hide the required next action. Use `framed` to make the rail and guidance read as
|
|
389
|
+
one component; omit a duplicate frame inside an existing panel. Vertical
|
|
390
|
+
rails center as a group while labels remain aligned to the start.
|
|
391
|
+
- Highlight the inspected compact step with a subtle primary fill and primary
|
|
392
|
+
label; other steps use a quiet neutral surface. Keep the guidance unfilled,
|
|
393
|
+
with a primary step label identifying its owner. The compact horizontal rail
|
|
394
|
+
sits above the labels: completed segments and outlined checks use primary,
|
|
395
|
+
unfinished segments stay neutral. Vertical connectors advance only between
|
|
396
|
+
two completed steps. Reserve semantic warning/error colors for those states;
|
|
397
|
+
inspection never changes status. Overview steps retain their selected border.
|
|
398
|
+
- Separate actual progress (`currentStepId`) from the inspected step
|
|
399
|
+
(`selectedStepId`). Allow explicit navigation to completed steps so users can
|
|
400
|
+
revise earlier inputs. Supply Back actions when useful. The host owns
|
|
401
|
+
validation, persistence, permissions and invalidation of dependent results.
|
|
402
|
+
- Author the panel's `content` and `actions` with standard forms and Buttons.
|
|
403
|
+
Use filled Buttons for the main forward transaction; outlined Buttons for
|
|
404
|
+
revising completed input and Back. The component must not invent actions,
|
|
405
|
+
choose their variants, or silently run jobs when a step is inspected.
|
|
406
|
+
- Announce actual current-step status changes even while an earlier step is
|
|
407
|
+
inspected; do not announce whole forms or every progress tick. Running work
|
|
408
|
+
needs honest task-specific progress rather than a percentage inferred from
|
|
409
|
+
the step count. Use a task list for work without a meaningful sequence.
|
|
410
|
+
- Use explicit complete/ready/running/blocked/error/skipped/pending statuses.
|
|
411
|
+
Compact locked steps use a short status; a `message` explains prerequisites
|
|
412
|
+
on hover and keyboard focus, in detailed view and unfolded guidance. Errors
|
|
413
|
+
remain visible. Do not communicate state through color alone.
|
|
414
|
+
- Preserve unsaved values while guidance is folded. Hosts persist drafts when
|
|
415
|
+
navigating between steps; folding is not saving. Use theme semantic tokens,
|
|
416
|
+
the accessible disclosure and reduced-motion behavior provided by the component.
|
|
417
|
+
- Native TypeScript verifies published installed-package exports. Stored JSX
|
|
418
|
+
separately verifies the deployed renderer scope. New framework APIs must be
|
|
419
|
+
published before downstream production consumers import them.
|
|
420
|
+
|
|
421
|
+
### Shared process and chat context
|
|
422
|
+
|
|
423
|
+
Opt in with `ProcessGuide agentContext={{ id, label, sourcePage, active }}`. Use a stable process-instance ID scoped by its canonical source page; use a readable process label. `active` is required: the host must set it to `false` for inactive tabs, background panels and builder previews, or unmount the guide. A mounted guide without this prop remains presentation-only. With multiple active guides, pointer or keyboard interaction determines which process the With control highlights; all active process snapshots remain available to the agent.
|
|
424
|
+
|
|
425
|
+
The same committed host props supply the guide, the With control and the next AG-UI request. Context carries `currentStepId` (execution position), `selectedStepId` (inspected guidance) and each step's identity, status, optionality, selectability, description and blocker. Plain string description/message values are included automatically; for JSX, provide `contextText={{ description, message }}` with the equivalent plain-text guidance. React nodes, input values and callbacks are never scraped or serialized. Expose relevant form data through the normal field/context APIs.
|
|
426
|
+
|
|
427
|
+
`ui_process_get_context` reads current active processes and identifies the focused process. `ui_process_select_step` takes `processId`, `sourcePage` and `stepId`, validates the live registration and explicit selectability, then calls the same selection handler as a user click. Its `requested` result acknowledges dispatch, not a completed host transition: read live context afterward. It never executes, skips, approves, publishes or completes work. Those transactions remain host-owned, permission-checked tools. The existing `ui_get_context` includes process references too.
|
|
428
|
+
|
|
429
|
+
Context is refreshed on each user request and by the live read tools; it is not a continuous stream of browser changes into a response already being generated. After navigation or an action, refresh context before giving the next guidance. Sent-message context retains the original snapshot. Automatic live process context is separate from optional user pins and survives the user switching into chat, while inactive/unmounted guides are excluded.
|
|
430
|
+
|
|
431
|
+
### Status symbols, selection and optionality
|
|
432
|
+
|
|
433
|
+
Use these exact `ProcessStepStatus` values; do not infer execution state from selection or optionality.
|
|
434
|
+
|
|
435
|
+
| `status` | Default label | Symbol | Meaning |
|
|
436
|
+
| ---------- | --------------- | --------------------- | --------------------------------------------------------------------------------------------------- |
|
|
437
|
+
| `pending` | Waiting | Outlined clock | Awaiting availability or scheduling; not ready yet. Use `blocked` for a known preventing condition. |
|
|
438
|
+
| `ready` | Ready | Open circle | Available to start, but not started. The inspected ready step adds a centered dot. |
|
|
439
|
+
| `running` | In progress | Spinner | Execution has actually started; honor reduced motion. |
|
|
440
|
+
| `complete` | Completed | Outlined check-circle | Work was completed and accepted by the host. |
|
|
441
|
+
| `blocked` | Blocked | Standalone lock | A prerequisite or permission prevents execution; explain it with `message`. |
|
|
442
|
+
| `error` | Needs attention | Outlined alert-circle | Failure or invalid result requires correction or retry; keep `message` visible. |
|
|
443
|
+
| `skipped` | Skipped | Outlined minus-circle | The host recorded an explicit skip decision; do not present it as completed work. |
|
|
444
|
+
|
|
445
|
+
`currentStepId` is the actual process position. `selectedStepId` is the step being inspected; its surface highlights which guidance belongs to it. The dot is an additional selection cue only for `ready`: inspecting a completed, running, blocked or skipped step preserves its status symbol. Without a valid selection, the component inspects the current step. Avoid an ambiguous `active` or `disabled` boolean for these distinct concepts.
|
|
446
|
+
|
|
447
|
+
`selectable` explicitly permits inspection when `onStepSelect` is provided. It never means executable: a host can allow inspection of a blocked step without permitting its action. Status and `optional` never authorize navigation by themselves.
|
|
448
|
+
|
|
449
|
+
Set `optional: true` independently of status. Unstarted optional steps use a dashed-circle marker in place of the pending clock or ready open circle. Running, completed, blocked, failed and skipped steps keep their status symbols. The default visible label is `Optional`; localize it using `optionalLabel`. It remains visible at compact density and is included in interactive accessible names. An optional step can still be blocked. Provide host-owned Skip/Back actions through the guidance `actions` slot: the host checks policy, persists the decision, sets `status: "skipped"`, and chooses the new `currentStepId`. There is no automatic skip, persistence or prerequisite resolution in this component. Completion accepts both `complete` and `skipped`, but neither selection nor optionality alone marks a process finished.
|
|
450
|
+
|
|
451
|
+
### Shared component API for builders
|
|
452
|
+
|
|
453
|
+
This self-contained contract is available in the bundled skill reference;
|
|
454
|
+
no framework repository checkout is needed. Verify the installed/deployed API
|
|
455
|
+
before authoring because a host may expose an earlier version.
|
|
456
|
+
|
|
457
|
+
`ProcessSteps` accepts `steps`, `currentStepId`, `selectedStepId`,
|
|
458
|
+
`onStepSelect(id)`, `variant` (`compact` or `overview`, default `compact`),
|
|
459
|
+
`orientation` (`responsive`, `vertical` or `horizontal`, default `responsive`),
|
|
460
|
+
`density` (`comfortable` or `compact`, default `comfortable`), optional
|
|
461
|
+
`showChevrons` (boolean, default false) and an accessible
|
|
462
|
+
`label` (default `Process progress`). Each step has a stable unique string `id`,
|
|
463
|
+
string `label`, and explicit `status`: `pending`, `ready`, `running`, `complete`,
|
|
464
|
+
`blocked`, `error` or `skipped`. Optional fields are `statusLabel` (localized text),
|
|
465
|
+
`description`, `message`, `selectable`, `optional` and `optionalLabel`. Only explicitly selectable steps with
|
|
466
|
+
an `onStepSelect` callback navigate; callbacks never advance actual progress.
|
|
467
|
+
A non-selectable blocked step with a message exposes a focusable tooltip.
|
|
468
|
+
|
|
469
|
+
`showChevrons` adds decorative separators only to horizontal `compact` navigation.
|
|
470
|
+
Their size and reserved gap follow `density`; the progress track stays above the
|
|
471
|
+
steps. Responsive narrow or explicitly vertical layouts retain their connected vertical
|
|
472
|
+
track, and `overview` is unchanged. Chevrons convey sequence, never status.
|
|
473
|
+
|
|
474
|
+
Horizontal rails retain readable minimum step widths and scroll inside their own viewport when needed. Overflow alone reveals previous/next buttons and subtle edge fades; swiping, trackpad scrolling and keyboard navigation also work. Scrolling never selects a step or advances progress. Selecting or focusing a step brings it into the rail viewport without scrolling the host page. Manual scrolling is not snapped back to the selected step. Buttons respect reduced motion and RTL. Localize their names with `scrollLabels={{ previous: "Previous steps", next: "Next steps" }}`.
|
|
475
|
+
|
|
476
|
+
Keep default `orientation="responsive"` for a full wizard: it stacks vertically in narrow containers. Use `orientation="horizontal"` for an embedded progress strip that should remain horizontal even on mobile. Guidance and host content remain outside the scroll viewport. Do not hide steps, truncate essential labels or make the entire page scroll sideways.
|
|
477
|
+
|
|
478
|
+
Use standalone `ProcessSteps density="compact"` for progress-only display: one
|
|
479
|
+
marker and label per step, with accessible status text. There is no guidance
|
|
480
|
+
panel. `onStepSelect(id)` is entirely host-owned: open a document picker,
|
|
481
|
+
navigate to a page or trigger another permitted action; it need not inspect
|
|
482
|
+
inline guidance. Omit the callback for a passive progress indicator.
|
|
483
|
+
|
|
484
|
+
`ProcessGuide` accepts the same props and adds per-step `title` (text), plus `content` and
|
|
485
|
+
`actions` (React nodes), plus these guide-level props:
|
|
486
|
+
|
|
487
|
+
| Prop | Contract |
|
|
488
|
+
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
489
|
+
| `framed` | Optional themed frame; default false. |
|
|
490
|
+
| `headingLevel` | 2, 3 or 4; default 3. |
|
|
491
|
+
| `guidance` | `expanded` (default) or `collapsible`. |
|
|
492
|
+
| `defaultGuidanceOpen` | Initial uncontrolled disclosure state; default false. |
|
|
493
|
+
| `guidanceOpen`, `onGuidanceOpenChange(open)` | Optional host-controlled disclosure state. |
|
|
494
|
+
| `guidanceToggleLabel` | Localized disclosure text; default `Guidance & actions`. |
|
|
495
|
+
| `guidanceTogglePlacement` | `guidance` (default) or `step`; compact collapsible guides can place the disclosure in the inspected step. Explicit step selection opens guidance, including reselection. Initial open state remains configurable. |
|
|
496
|
+
| `showPosition` | Optional numeric position in guidance; default false. The owning step label remains when the task title differs. |
|
|
497
|
+
| `formatPosition(index, total)` | Localized position text when `showPosition` is true; index is one-based. |
|
|
498
|
+
| `completion` | Content shown only when no step is inspected/current and every step is complete or skipped. |
|
|
499
|
+
|
|
500
|
+
The selected step falls back to the current step if its ID is absent/invalid.
|
|
501
|
+
Changing inspected steps remounts their content; hosts must retain drafts outside
|
|
502
|
+
that content. Folding guidance keeps the same inputs mounted. Empty arrays render
|
|
503
|
+
nothing. The component never fetches, saves, authorizes, validates or runs a job.
|
|
504
|
+
|
|
505
|
+
Example composition, after availability is verified:
|
|
506
|
+
|
|
507
|
+
```jsx
|
|
508
|
+
<ProcessGuide
|
|
509
|
+
framed
|
|
510
|
+
variant="compact"
|
|
511
|
+
guidance="expanded"
|
|
512
|
+
currentStepId="review"
|
|
513
|
+
selectedStepId={inspectedStep}
|
|
514
|
+
onStepSelect={setInspectedStep}
|
|
515
|
+
steps={[
|
|
516
|
+
{
|
|
517
|
+
id: "documents",
|
|
518
|
+
label: "Documents",
|
|
519
|
+
status: "complete",
|
|
520
|
+
selectable: true,
|
|
521
|
+
title: "Select the source documents",
|
|
522
|
+
content: documentFields,
|
|
523
|
+
actions: (
|
|
524
|
+
<Button type="button" variant="outline" onClick={openDocumentEditor}>
|
|
525
|
+
Change documents
|
|
526
|
+
</Button>
|
|
527
|
+
),
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
id: "review",
|
|
531
|
+
label: "Review",
|
|
532
|
+
status: "ready",
|
|
533
|
+
selectable: true,
|
|
534
|
+
description: "Check the findings before confirming.",
|
|
535
|
+
content: reviewFields,
|
|
536
|
+
actions: (
|
|
537
|
+
<Button type="button" onClick={validateAndSaveReview}>
|
|
538
|
+
Confirm review
|
|
539
|
+
</Button>
|
|
540
|
+
),
|
|
541
|
+
},
|
|
542
|
+
]}
|
|
543
|
+
/>
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
The host supplies the fields and handlers in this example, including saving
|
|
547
|
+
changes and invalidating results after source edits. In native TypeScript import
|
|
548
|
+
from the published package and its stylesheet. In stored JSX use only verified
|
|
549
|
+
scope symbols without imports.
|
|
550
|
+
|
|
551
|
+
### Design references
|
|
552
|
+
|
|
553
|
+
- [USWDS step indicator](https://designsystem.digital.gov/components/step-indicator/):
|
|
554
|
+
distinguish current/completed/pending and keep explicit headings/navigation.
|
|
555
|
+
- [GOV.UK multiple tasks](https://design-system.service.gov.uk/patterns/complete-multiple-tasks/):
|
|
556
|
+
resumable work needs clear task statuses and prerequisites.
|
|
557
|
+
- [Carbon progress indicator](https://www.carbondesignsystem.com/building-blocks/core/components/progress-indicator/guidelines):
|
|
558
|
+
a stable sequence and validation are prerequisites for linear task guidance.
|
|
559
|
+
- [WAI disclosure pattern](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/):
|
|
560
|
+
keyboard operation and expanded state for unfolding guidance.
|
|
561
|
+
|
|
562
|
+
These inform the design; usability with real users still needs validation.
|
|
563
|
+
|
|
564
|
+
### List toolbar control density
|
|
565
|
+
|
|
566
|
+
List toolbars use the shared `Button size="sm"` density for New, grouping,
|
|
567
|
+
Filters, Columns and other text actions. Authored `DataTableToolbar actions`
|
|
568
|
+
use the same primitive and size; do not mix the default-height button into that
|
|
569
|
+
row. Let the button primitive own font family, weight, size, control radius,
|
|
570
|
+
outline surface and interaction states. Table controls must not restyle ordinary
|
|
571
|
+
outline buttons with a different radius, translucent fill or shadow reset.
|
|
572
|
+
Retain meaningful states such as active filters, dashed facet boundaries and
|
|
573
|
+
pressed grouping. Icon-only toolbar controls share the same height and focus
|
|
574
|
+
behavior. Menus and badges retain their own semantic surface treatment.
|
|
575
|
+
|
|
576
|
+
Verify the rendered toolbar in light/dark themes and at narrow widths. Compare
|
|
577
|
+
computed height, font, weight and radius of authored actions with built-in
|
|
578
|
+
Filters/Columns; using the same component name alone does not establish parity.
|
|
579
|
+
Use CSS and shared primitive variants, without observers or per-button requests.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lykomi-build-agent-forms
|
|
3
|
+
description: Build forms in a LYKOMI UI app with automatic field context, explicit editing, validation and guarded agent tools. Use when adding or changing forms or field-level agent interactions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Read [the shared form contract](references/form-ux.md) before changing the form.
|
|
7
|
+
Inspect the installed `@lykomi/web-primitives` and `@lykomi/web-ui` declarations;
|
|
8
|
+
use the project's pinned API rather than an unreleased example.
|
|
9
|
+
|
|
10
|
+
## Compose the form
|
|
11
|
+
|
|
12
|
+
- Use `FormLayout`, `FormHeader`, `Field` and the shared inputs. Open existing
|
|
13
|
+
records in view mode; Edit replaces values with controls in the same slots.
|
|
14
|
+
- A `Field` around a named control, or `ReadOnlyField`, automatically supplies
|
|
15
|
+
the selected field's label, current value and text selection to AG-UI.
|
|
16
|
+
Do not add page-specific focus listeners or a second field-context store.
|
|
17
|
+
- Give controls semantic `name` values and associate labels with IDs. An
|
|
18
|
+
unwrapped `Input` is deliberately not an agent field (search and chat also
|
|
19
|
+
use inputs).
|
|
20
|
+
- Use `agentContext={false}` for sensitive fields. Passwords are excluded by
|
|
21
|
+
the built-in collector. Custom context projections must also omit secrets.
|
|
22
|
+
|
|
23
|
+
## Keep updates app-owned
|
|
24
|
+
|
|
25
|
+
Register edit tools with `usePageTools` only while the form can be edited.
|
|
26
|
+
Validate arguments at execution time, restrict writable field names, and compare
|
|
27
|
+
the expected value with the current draft before replacing it. A stale tool call
|
|
28
|
+
must return a conflict instead of overwriting a newer user edit.
|
|
29
|
+
|
|
30
|
+
Agent changes should enter the same unsaved draft as manual edits. Save, Cancel,
|
|
31
|
+
permissions and persistence belong to the application. Preserve dirty input on
|
|
32
|
+
validation or network failure. Label in-memory demo saving honestly.
|
|
33
|
+
|
|
34
|
+
In a generated starter, inspect `src/showcase/form-example.tsx` and
|
|
35
|
+
`src/pages/use-draft-tools.ts` for working examples. Verify the outgoing AG-UI
|
|
36
|
+
request after selecting text and entering chat, including on a narrow viewport.
|