@cratis/pi 2.22.0 → 2.23.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/package/corpus/agents/backend-developer.md +6 -5
- package/package/corpus/agents/code-reviewer.md +7 -7
- package/package/corpus/agents/coordinator.md +5 -4
- package/package/corpus/agents/frontend-developer.md +34 -40
- package/package/corpus/agents/orchestrator.md +5 -4
- package/package/corpus/agents/performance-reviewer.md +5 -4
- package/package/corpus/agents/planner.md +5 -4
- package/package/corpus/agents/repository-investigation-reviewer.md +2 -1
- package/package/corpus/agents/repository-investigator.md +2 -1
- package/package/corpus/agents/security-reviewer.md +5 -4
- package/package/corpus/agents/slice-implementer.md +8 -2
- package/package/corpus/agents/spec-writer.md +6 -4
- package/package/corpus/harnesses/pi/extensions/subagent/agents.ts +52 -7
- package/package/corpus/harnesses/pi/extensions/subagent/index.ts +14 -0
- package/package/corpus/hooks/README.md +29 -27
- package/package/corpus/hooks/agent-stop.md +1 -5
- package/package/corpus/hooks/scripts/cratis-patterns.json +1 -1
- package/package/corpus/hooks/scripts/validate-package-subpaths.sh +1 -2
- package/package/corpus/prompts/verify-ai-setup.prompt.md +17 -7
- package/package/corpus/rules/ai-distribution.md +58 -0
- package/package/corpus/rules/components.md +77 -44
- package/package/corpus/rules/dialogs.md +24 -20
- package/package/corpus/rules/efcore.md +35 -187
- package/package/corpus/rules/framework.md +1 -1
- package/package/corpus/rules/frontend-quality.md +1 -1
- package/package/corpus/rules/frontend-testing.md +4 -4
- package/package/corpus/rules/general.md +29 -105
- package/package/corpus/rules/new-repository-intake.md +34 -0
- package/package/corpus/rules/orleans.md +13 -27
- package/package/corpus/rules/react.md +12 -12
- package/package/corpus/rules/reactors.md +28 -5
- package/package/corpus/rules/specs.scenarios.csharp.md +18 -3
- package/package/corpus/rules/specs.typescript.md +1 -1
- package/package/corpus/rules/storybook.md +2 -2
- package/package/corpus/rules/typescript.md +1 -0
- package/package/corpus/rules/vertical-slices.md +20 -15
- package/package/corpus/rules/writing-correct-examples.md +1 -0
- package/package/corpus/skills/cratis-application-react-specifications/SKILL.md +4 -4
- package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +16 -8
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +6 -4
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authentication.md +1 -1
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +1 -1
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/frontend.md +1 -1
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/local-development.md +1 -1
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/tenancy.md +7 -4
- package/package/corpus/skills/cratis-arc-command/SKILL.md +9 -7
- package/package/corpus/skills/cratis-arc-command/references/command-result.md +1 -1
- package/package/corpus/skills/cratis-arc-command/references/handler-shapes.md +2 -2
- package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +6 -3
- package/package/corpus/skills/cratis-arc-command/references/read-model-injection.md +1 -1
- package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +12 -2
- package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +5 -3
- package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +7 -4
- package/package/corpus/skills/cratis-arc-observable-query-http/SKILL.md +10 -3
- package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +13 -8
- package/package/corpus/skills/cratis-arc-react-page/SKILL.md +27 -24
- package/package/corpus/skills/cratis-arc-react-page/references/data-page.md +15 -11
- package/package/corpus/skills/cratis-arc-react-page/references/data-tables.md +9 -2
- package/package/corpus/skills/cratis-arc-react-page/references/dialogs.md +11 -9
- package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +26 -2
- package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +19 -13
- package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +17 -15
- package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +24 -20
- package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +26 -15
- package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +15 -11
- package/package/corpus/skills/cratis-chronicle-compliance/SKILL.md +14 -3
- package/package/corpus/skills/cratis-chronicle-event-constraints/SKILL.md +13 -6
- package/package/corpus/skills/cratis-chronicle-event-modeling/SKILL.md +2 -2
- package/package/corpus/skills/cratis-chronicle-event-specifications/SKILL.md +11 -5
- package/package/corpus/skills/cratis-chronicle-event-type-migration/SKILL.md +2 -2
- package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +2 -2
- package/package/corpus/skills/cratis-chronicle-projection/SKILL.md +23 -4
- package/package/corpus/skills/cratis-chronicle-projection/references/fluent-builder.md +1 -1
- package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +2 -2
- package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +22 -8
- package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +1 -1
- package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +1 -1
- package/package/corpus/skills/cratis-chronicle-read-model-specifications/SKILL.md +3 -1
- package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +1 -1
- package/package/corpus/skills/cratis-chronicle-web-workbench/SKILL.md +19 -11
- package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +11 -6
- package/package/corpus/skills/cratis-code-review/SKILL.md +8 -6
- package/package/corpus/skills/cratis-components-accessibility/SKILL.md +112 -82
- package/package/corpus/skills/cratis-components-schema-editor/SKILL.md +12 -10
- package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +11 -12
- package/package/corpus/skills/cratis-components-styling/SKILL.md +204 -170
- package/package/corpus/skills/cratis-components-toolbar/SKILL.md +32 -26
- package/package/corpus/skills/cratis-event-model-diagram/SKILL.md +1 -1
- package/package/corpus/skills/cratis-fundamentals-concept/SKILL.md +2 -2
- package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +2 -2
- package/package/corpus/skills/cratis-lens-browser-extension/SKILL.md +4 -2
- package/package/corpus/skills/cratis-performance-review/SKILL.md +4 -2
- package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +15 -5
- package/package/corpus/skills/cratis-security-review/SKILL.md +20 -3
- package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +3 -3
- package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md +12 -8
- package/package/corpus/skills/cratis-specifications-csharp/references/csharp-patterns.md +1 -1
- package/package/corpus/skills/cratis-specifications-csharp/references/integration-specs.md +7 -3
- package/package/corpus/skills/cratis-specifications-typescript/SKILL.md +6 -3
- package/package/corpus/skills/cratis-specifications-typescript/references/typescript-patterns.md +21 -4
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +29 -17
- package/package.json +1 -1
|
@@ -24,8 +24,8 @@ This skill is verified against these exact sources:
|
|
|
24
24
|
|
|
25
25
|
| Package | Version | Purpose |
|
|
26
26
|
| --- | --- | --- |
|
|
27
|
-
| `Cratis.Chronicle` | `
|
|
28
|
-
| `Cratis.Chronicle.CodeAnalysis` | `
|
|
27
|
+
| `Cratis.Chronicle` | `18.3.0` | `Cratis.Chronicle.Reactors`, `Cratis.Chronicle.Reactors.SideEffects`, `Cratis.Chronicle.EventSequences`, `Cratis.Chronicle.Events` |
|
|
28
|
+
| `Cratis.Chronicle.CodeAnalysis` | `18.3.0` | `CHR0004`, `CHR0005`, `CHR0008`, `CHR0013`, `CHR0022`, `CHR0031`, `CHR0032` |
|
|
29
29
|
|
|
30
30
|
Reverify product sources before claiming support for another version.
|
|
31
31
|
|
|
@@ -280,19 +280,33 @@ selection, a reactor or a reducer is where it happens.
|
|
|
280
280
|
## Translation via a command
|
|
281
281
|
|
|
282
282
|
A translation that adapts one area's events into another's intent runs a command
|
|
283
|
-
rather than appending directly.
|
|
284
|
-
|
|
283
|
+
rather than appending directly. With the Arc Chronicle integration the handler
|
|
284
|
+
**returns** the command — the same shape as returning an event — and Arc executes
|
|
285
|
+
it through validation and authorization; a denied, invalid or throwing result is a
|
|
286
|
+
side-effect failure that fails the partition rather than being dropped:
|
|
285
287
|
|
|
286
288
|
```csharp
|
|
287
|
-
using Cratis.Arc.
|
|
289
|
+
using Cratis.Arc.Chronicle.Reactors;
|
|
288
290
|
|
|
289
|
-
|
|
291
|
+
[ExecuteCommandsAsSystem("<role the command requires>")] // only when the command is [Roles]/[Authorize]-gated
|
|
292
|
+
public class <ReactorName> : IReactor
|
|
290
293
|
{
|
|
291
|
-
|
|
292
|
-
|
|
294
|
+
[OnceOnly]
|
|
295
|
+
public Task<<CommandName>> <MethodName>(<EventName> @event, EventContext context) =>
|
|
296
|
+
Task.FromResult(new <CommandName>(@event.<Property>));
|
|
293
297
|
}
|
|
294
298
|
```
|
|
295
299
|
|
|
300
|
+
A reactor runs with **no principal**; `[ExecuteCommandsAsSystem]` (class-level,
|
|
301
|
+
`Cratis.Arc.Chronicle.Reactors`) supplies one for the **returned** commands only.
|
|
302
|
+
A collection return is executed as commands when every element is a command.
|
|
303
|
+
|
|
304
|
+
The imperative form — inject `ICommandPipeline` (`Cratis.Arc.Commands`) and call
|
|
305
|
+
`Execute(command)` — is still supported and is the subject of the
|
|
306
|
+
**cratis-arc-command-execution** skill. It needs `[OnceOnly]` as well (`ARCCHR0006`
|
|
307
|
+
warns), the `CommandResult` must be inspected, and `[ExecuteCommandsAsSystem]`
|
|
308
|
+
does not cover it.
|
|
309
|
+
|
|
296
310
|
## Failure behavior
|
|
297
311
|
|
|
298
312
|
If a handler throws, or a returned side-effect event fails to append — a
|
|
@@ -23,7 +23,7 @@ This skill is verified against these exact sources:
|
|
|
23
23
|
|
|
24
24
|
| Package | Version | Purpose |
|
|
25
25
|
| --- | --- | --- |
|
|
26
|
-
| `Cratis.Chronicle` | `
|
|
26
|
+
| `Cratis.Chronicle` | `18.3.0` | `Cratis.Chronicle.Events`, `Cratis.Chronicle.Keys`, `Cratis.Chronicle.ReadModels` |
|
|
27
27
|
| `Cratis.Arc.Core` | current | `Cratis.Arc.Queries.ModelBound.ReadModelAttribute` and `PathAttribute` |
|
|
28
28
|
| `Cratis.Arc.MongoDB` | current | the `Observe` family of `IMongoCollection<T>` extensions |
|
|
29
29
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Read-model queries
|
|
2
2
|
|
|
3
3
|
Verified against `Cratis.Arc.Core` and `Cratis.Arc.MongoDB` as checked out
|
|
4
|
-
alongside `Cratis.Chronicle` `
|
|
4
|
+
alongside `Cratis.Chronicle` `18.3.0`. Confirm the exact Arc package version in
|
|
5
5
|
the consuming project before citing one.
|
|
6
6
|
|
|
7
7
|
## Where the pieces live
|
|
@@ -17,9 +17,11 @@ separate `When`: seeding the events is what makes the projection run.
|
|
|
17
17
|
|
|
18
18
|
| Package | Version | Purpose |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| `Cratis.Chronicle.Testing` | `
|
|
20
|
+
| `Cratis.Chronicle.Testing` | `18.3.0` | `ReadModelScenario<TReadModel>` and its `Given` builder |
|
|
21
21
|
| `Cratis.Specifications.XUnit` | `4.x` | The `Specification` base and the `ShouldXxx` assertions |
|
|
22
22
|
|
|
23
|
+
> Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
|
|
24
|
+
|
|
23
25
|
```bash
|
|
24
26
|
dotnet add package Cratis.Chronicle.Testing
|
|
25
27
|
```
|
|
@@ -17,7 +17,7 @@ This skill is verified against this exact source:
|
|
|
17
17
|
|
|
18
18
|
| Package | Version | Purpose |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| `Cratis.Chronicle` | `
|
|
20
|
+
| `Cratis.Chronicle` | `18.3.0` | `Cratis.Chronicle.Reducers`, `Cratis.Chronicle.ReadModels`, `Cratis.Chronicle.Events` |
|
|
21
21
|
|
|
22
22
|
Reverify product sources before claiming support for another version.
|
|
23
23
|
|
|
@@ -22,7 +22,7 @@ This skill is verified against this exact source:
|
|
|
22
22
|
|
|
23
23
|
| Package | Version | Purpose |
|
|
24
24
|
| --- | --- | --- |
|
|
25
|
-
| `Cratis.Chronicle` | `
|
|
25
|
+
| `Cratis.Chronicle` | `18.3.0` | the Workbench application, its hosting, screens, and commands |
|
|
26
26
|
|
|
27
27
|
Reverify before claiming a screen, route, command, or configuration key for
|
|
28
28
|
another version.
|
|
@@ -72,7 +72,9 @@ Read these before putting a Workbench on any reachable network.
|
|
|
72
72
|
- The server is designed to sit behind a proxy and trusts the immediate proxy's
|
|
73
73
|
forwarded headers unconditionally. That is only safe when the proxy is the
|
|
74
74
|
only route in.
|
|
75
|
-
- The health endpoint
|
|
75
|
+
- The health endpoint, the antiforgery probe, the gRPC descriptor-set and
|
|
76
|
+
compatibility calls, the initial-admin-password endpoints, and the gRPC
|
|
77
|
+
`ResetKernelState` call answer anonymously (`[AllowAnonymous]`).
|
|
76
78
|
|
|
77
79
|
## The screens
|
|
78
80
|
|
|
@@ -80,16 +82,18 @@ Routes are grouped by scope. Event-store-scoped screens apply to the whole
|
|
|
80
82
|
store; namespace-scoped screens apply to one tenant namespace.
|
|
81
83
|
|
|
82
84
|
**Namespace-scoped:** Recommendations (the landing screen) · Jobs · Sequences ·
|
|
83
|
-
Pivot
|
|
84
|
-
|
|
85
|
+
Pivot · Patterns · Pattern heatmap · Observers · Failed partitions · Read Models ·
|
|
86
|
+
Identities · Seed Data.
|
|
85
87
|
|
|
86
88
|
**Event-store-scoped:** Event Types · Read Model Types · Webhooks · External
|
|
87
|
-
Services · Captures · Projections · Namespaces · Seed Data.
|
|
89
|
+
Services · Captures · Projections (namespace-routed) · Namespaces · Seed Data.
|
|
88
90
|
|
|
89
|
-
**System:** Users · Applications · Connected Clients · Development
|
|
91
|
+
**System:** Users · Applications · Connected Clients · Servers · Development
|
|
92
|
+
Tools (offered only when the server reports them available).
|
|
90
93
|
|
|
91
|
-
Reducers, Reactors, and
|
|
92
|
-
|
|
94
|
+
Reducers, Reactors, Sinks and a store-wide Sequences view have routes but no menu
|
|
95
|
+
entry (their menu lines are commented out in `EventStore.tsx`). There is no
|
|
96
|
+
Dashboard screen; only a `Card`/`Chart` component pair written for one remains.
|
|
93
97
|
|
|
94
98
|
## What each screen can change
|
|
95
99
|
|
|
@@ -125,9 +129,13 @@ partition, stop/resume/delete job, and perform recommendation all fire on the
|
|
|
125
129
|
first click. Decide before clicking, not after.
|
|
126
130
|
|
|
127
131
|
**Reset kernel state is the most destructive operation in the product.** It is
|
|
128
|
-
gated three ways — the
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
gated three ways — the *operation* is compiled in only for development builds
|
|
133
|
+
(`KernelStateResetter.IsAvailable`; in any other build the gRPC call still exists,
|
|
134
|
+
answers anonymously, and is a no-op), the screen reports itself unavailable when
|
|
135
|
+
the server says so, and a confirmation dialog guards the button. Never run it
|
|
136
|
+
against a store whose data anyone still needs, and never assume a production
|
|
137
|
+
build is protected by authentication here — it is protected by the operation
|
|
138
|
+
not being there.
|
|
131
139
|
|
|
132
140
|
## Redaction and revision
|
|
133
141
|
|
|
@@ -24,7 +24,9 @@ This skill is verified against this exact source:
|
|
|
24
24
|
|
|
25
25
|
| Package | Version | Purpose |
|
|
26
26
|
| --- | --- | --- |
|
|
27
|
-
| `Cratis.Cli` | `2.
|
|
27
|
+
| `Cratis.Cli` | `3.2.0` | `cratis chronicle workbench`, its views, keys, and actions |
|
|
28
|
+
|
|
29
|
+
> Re-verified at `Cratis/cli` **v3.2.0**: the fifteen navigation views and every key binding below exist in `Source/Cli/Commands/Chronicle/Workbench` at that tag.
|
|
28
30
|
|
|
29
31
|
Reverify before claiming a view, key binding, or action for another version.
|
|
30
32
|
`cratis chronicle workbench --help` and `cratis llm-context` are the authority
|
|
@@ -61,9 +63,11 @@ The navigation pane groups fifteen views into five sections:
|
|
|
61
63
|
| Projections | Projections · Read Models |
|
|
62
64
|
| Server | Event Stores · Namespaces · Applications · Users · Identities · Subscriptions |
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
pane
|
|
66
|
+
Every table view renders a detail for its selected row — `RenderDetail` is
|
|
67
|
+
abstract on the shared `FilterableTableView`, so activating a row always
|
|
68
|
+
surfaces its full detail in the detail pane or a centered overlay; the event
|
|
69
|
+
and read-model views open richer overlays of their own. Detail views never
|
|
70
|
+
appear in the navigation pane.
|
|
67
71
|
|
|
68
72
|
Each refresh fetches one consistent snapshot of the store: version info, event
|
|
69
73
|
stores, namespaces, observers, failed partitions, jobs, recommendations, event
|
|
@@ -127,8 +131,9 @@ Several views bind a key to an operation that changes the running server:
|
|
|
127
131
|
Each has a bulk form that applies to every checked row.
|
|
128
132
|
|
|
129
133
|
Every one of these opens a centered confirmation modal that states the action
|
|
130
|
-
cannot be undone
|
|
131
|
-
`
|
|
134
|
+
cannot be undone. **Only an explicit `Y` (or the Confirm button) confirms;
|
|
135
|
+
`Enter`, `Escape` and `N` all cancel** — the modal is cancel-focused on purpose,
|
|
136
|
+
so a reflexive Enter never runs a destructive action. **That modal is not authorization.** A request to inspect a live store does
|
|
132
137
|
not authorize replay, retry, stop, resume, perform, or ignore. Before pressing
|
|
133
138
|
one of those keys:
|
|
134
139
|
|
|
@@ -18,9 +18,11 @@ change did not touch is a note, never a blocker.
|
|
|
18
18
|
|
|
19
19
|
| Package | Version | Purpose |
|
|
20
20
|
| --- | --- | --- |
|
|
21
|
-
| `Cratis.Arc.Core` | `22.
|
|
22
|
-
| `Cratis.Chronicle` | `
|
|
23
|
-
| `Cratis.Fundamentals` | `7.
|
|
21
|
+
| `Cratis.Arc.Core` | `22.16.0` | Command, query, validation and analyzer surface (`ARC0001`–`ARC0015` in `DiagnosticDescriptors`, plus `ARC0016`–`ARC0018` from the command-operation analyzer) |
|
|
22
|
+
| `Cratis.Chronicle` | `18.3.0` | Event, projection, read-model and constraint surface |
|
|
23
|
+
| `Cratis.Fundamentals` | `7.19.2` | `ConceptAs<T>`, `IInstancesOf<T>`, the DI conventions |
|
|
24
|
+
|
|
25
|
+
> Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
|
|
24
26
|
|
|
25
27
|
Reverify against the owning product repository before asserting a framework
|
|
26
28
|
contract this file does not already state.
|
|
@@ -97,9 +99,9 @@ there is nothing to review under a red build.
|
|
|
97
99
|
- No `@ts-ignore` or `@ts-expect-error` without a comment saying why.
|
|
98
100
|
- Full descriptive names — never `e`, `idx`, `prev`, `dir`, `pos`.
|
|
99
101
|
- `CommandDialog` from `@cratis/components/CommandDialog` for command dialogs;
|
|
100
|
-
`Dialog` from `@cratis/components/Dialogs` for data-only dialogs. **Never**
|
|
101
|
-
|
|
102
|
-
- No hard-coded hex or rgb colors —
|
|
102
|
+
`Dialog` from `@cratis/components/Dialogs` for data-only dialogs. **Never** a
|
|
103
|
+
vendor or hand-rolled modal.
|
|
104
|
+
- No hard-coded hex or rgb colors — `--cratis-*` tokens only. No
|
|
103
105
|
`!important` without a justifying comment.
|
|
104
106
|
- Components live in the slice folder. No barrel `index.ts` that re-exports one
|
|
105
107
|
component, and no technical `hooks/` / `utils/` / `types/` grouping at feature
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cratis-components-accessibility
|
|
3
|
-
description: Apply the accessibility conventions Cratis Components actually implements — dialog initial-focus discipline and the armed-Enter hazard, supplying every accessible name as a localizable prop, putting the accessible name on the focusable element rather than the wrapper,
|
|
3
|
+
description: Apply the accessibility conventions Cratis Components 4 actually implements — dialog initial-focus discipline and the armed-Enter hazard, supplying every accessible name as a localizable prop or provider message, putting the accessible name on the focusable element rather than the wrapper, keeping decorative icons hidden, and customizing through parts without fighting the component's own ARIA. Use when building or reviewing a dialog, a form control, a data table, a toast, or any component whose accessible name is currently a hard-coded English string. Do not use as a general WCAG conformance guide.
|
|
4
4
|
license: MIT
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -17,8 +17,11 @@ what is written here.
|
|
|
17
17
|
|
|
18
18
|
| Package | Version | Verified from |
|
|
19
19
|
| --- | --- | --- |
|
|
20
|
-
| `@cratis/components` | `
|
|
21
|
-
|
|
20
|
+
| `@cratis/components` | `4.6.0` | `Source/Dialogs/*` (`DialogInitialFocus`, `DialogImplementation`), `Source/CommandForm/fields/fieldAccessibility.tsx`, `Source/for_accessibility/*`, `Source/SchemaEditor/*`, `Source/ObjectNavigationalBar/*`, `Source/MIGRATION.md`, `Documentation/Styling/pass-through.md`, `Documentation/Common/cratis-components-provider.md`, `Documentation/renderers/index.md` |
|
|
21
|
+
|
|
22
|
+
Focus, overlay and collection behavior come from React Aria **internally** — the
|
|
23
|
+
dialog is a React Aria `Modal` inside a `ModalOverlay`; you never import React
|
|
24
|
+
Aria yourself, and its class names are not a styling or testing hook.
|
|
22
25
|
|
|
23
26
|
## 1. Dialog focus discipline
|
|
24
27
|
|
|
@@ -58,119 +61,146 @@ read anything.
|
|
|
58
61
|
`Cancel` degrades to `Content` automatically when the chosen button set has
|
|
59
62
|
nothing to dismiss with, so it is always safe to ask for.
|
|
60
63
|
|
|
61
|
-
`DialogInitialFocus` imports from `@cratis/components/Dialogs`.
|
|
64
|
+
`DialogInitialFocus` imports from `@cratis/components/Dialogs`. While `isBusy`
|
|
65
|
+
is set the dialog marks its content `inert` and disables every dismissal path,
|
|
66
|
+
so a user cannot interact with a half-committed form.
|
|
62
67
|
|
|
63
|
-
## 2. Every accessible name is a prop —
|
|
68
|
+
## 2. Every accessible name is a prop or a provider message — never a baked-in English string
|
|
64
69
|
|
|
65
70
|
This is the library's strongest and most consistent convention: any string a
|
|
66
|
-
screen reader will read is exposed as an overridable, localizable prop
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
71
|
+
screen reader will read is exposed as an overridable, localizable prop, and the
|
|
72
|
+
library-wide ones also come from `CratisComponentsProvider`'s `messages`. The
|
|
73
|
+
precedence is always the same: **a named component prop wins, then the matching
|
|
74
|
+
provider message, then the English default.** Set the provider messages once for
|
|
75
|
+
the application's locale, and the per-instance props where one control needs a
|
|
76
|
+
different name.
|
|
77
|
+
|
|
78
|
+
| Component | Prop | Provider message |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| `Dialog` / `CommandDialog` / `StepperCommandDialog` | `closeAriaLabel`; `okLabel`, `cancelLabel`, `yesLabel`, `noLabel` | `messages.dialog` (`ok`, `cancel`, `yes`, `no`, `close`) |
|
|
81
|
+
| `CommandStepper` / `StepperCommandDialog` | `nextLabel`, `previousLabel` | `messages.stepper` (`next`, `previous`, `submit`) |
|
|
82
|
+
| `DataPage` | `actionsAriaLabel`, `globalSearchAriaLabel`, `paginatorAriaLabels` | `messages.dataTable`, `messages.paginator` |
|
|
83
|
+
| `DataTableForQuery` / `DataTableForObservableQuery` | `paginatorAriaLabels` | `messages.paginator` (`navigation`, `first`, `previous`, `next`, `last`) |
|
|
84
|
+
| `Column` (filter menu) | `filterLabels` — match mode, clear, apply, true, false | `messages.columnFilter` |
|
|
85
|
+
| `Toaster` | `dismissAriaLabel` | `messages.notifications` (`dismiss`, `region`) |
|
|
86
|
+
| `Dropdown` | `aria-label`, `aria-labelledby`, `aria-describedby` | `messages.dropdown` (`showOptions`, `clearSelection`) |
|
|
87
|
+
| `DatePickerInput` / `CalendarField` | `aria-label` / `aria-labelledby` for the segmented **group**; `todayLabel`, `clearLabel` | `messages.datePicker` (`today`, `clear`, `openCalendar`, `previousMonth`, `nextMonth`, `label`) |
|
|
88
|
+
| Every CommandForm field | `aria-label` (falls back to the field `title`), `aria-describedby`, `id` | — |
|
|
89
|
+
| `SchemaEditor` | `labels` | — |
|
|
90
|
+
| `ObjectNavigationalBar` | `backLabel` — tooltip **and** accessible name | — |
|
|
91
|
+
| `ToolbarButton` | `title` — required; the accessible name and the tooltip | — |
|
|
92
|
+
| `Toolbar` | `aria-label` | `messages.toolbar` (`label`, default `'Tools'`) |
|
|
93
|
+
| `ToolbarFanOutItem` / `ToolbarFolder` | `tooltip` / `title` — required | — |
|
|
94
|
+
| `RatingField` | `starAriaLabel` | — |
|
|
95
|
+
| `ChipsField` | `removeAriaLabel` | — |
|
|
88
96
|
|
|
89
97
|
In a localized application, treat any component whose accessible name you have
|
|
90
|
-
not supplied
|
|
98
|
+
not supplied — and any provider message group left at its English default — as
|
|
99
|
+
a defect.
|
|
91
100
|
|
|
92
101
|
## 3. Put the name on the focusable element, not the wrapper
|
|
93
102
|
|
|
94
103
|
An accessible name has to land on the element that actually receives focus and
|
|
95
|
-
carries the role. `Dropdown` demonstrates the rule: `id
|
|
96
|
-
|
|
97
|
-
and the control id is deliberately not duplicated onto the
|
|
98
|
-
external `<label htmlFor>` associates correctly.
|
|
104
|
+
carries the role. `Dropdown` demonstrates the rule: `id` and the `aria-*`
|
|
105
|
+
attributes route to the **trigger** (`data-cratis-part='trigger'`), not to the
|
|
106
|
+
layout wrapper, and the control id is deliberately not duplicated onto the
|
|
107
|
+
wrapper so an external `<label htmlFor>` associates correctly. A single select
|
|
108
|
+
follows the button/listbox pattern and a filtered one is a combobox — so in a
|
|
109
|
+
test, query the trigger by its accessible name or its part, **not** by
|
|
110
|
+
`role="combobox"`.
|
|
99
111
|
|
|
100
112
|
```tsx
|
|
101
113
|
<label htmlFor='role'>Advisory role</label>
|
|
102
114
|
<Dropdown id='role' value={role} options={roles} aria-describedby='role-help' />
|
|
103
115
|
```
|
|
104
116
|
|
|
117
|
+
`DatePickerInput` is a segmented field: its `id` identifies the **focus group**,
|
|
118
|
+
not a native text input, so name it with `aria-label`/`aria-labelledby` on the
|
|
119
|
+
group. `Tooltip` enhances exactly one real focusable child so focus, hover and
|
|
120
|
+
`aria-describedby` stay together — wrap text, fragments or several siblings in
|
|
121
|
+
one native control first. Several `RadioButtonField`s bound to one property need
|
|
122
|
+
the same explicit `name` for native arrow-key group navigation.
|
|
123
|
+
|
|
105
124
|
Apply the same rule to your own wrapper components: forward `id`, `tabIndex`,
|
|
106
125
|
and `aria-*` down to the focusable child rather than putting them on a
|
|
107
126
|
container.
|
|
108
127
|
|
|
109
|
-
## 4.
|
|
110
|
-
|
|
111
|
-
Icons and loading spinners inside a labelled control are marked
|
|
112
|
-
`aria-hidden='true'` so a button's accessible name is exactly its label and not
|
|
113
|
-
"pi pi-plus Add account". Do the same in application components: an icon that
|
|
114
|
-
sits beside a text label carries no information of its own.
|
|
128
|
+
## 4. Field errors are announced — do not duplicate them
|
|
115
129
|
|
|
116
|
-
|
|
130
|
+
Every CommandForm field runs its title and validation messages through one
|
|
131
|
+
helper: the control's accessible name falls back to the field `title`, and when
|
|
132
|
+
the field has errors a visually hidden `<span id="…-errors">` is rendered and
|
|
133
|
+
linked from the control's `aria-describedby` (merged with any `aria-describedby`
|
|
134
|
+
you pass). Arc renders the visible error text; the hidden span exists only for
|
|
135
|
+
assistive technology. Do **not** render a second announcement or wire your own
|
|
136
|
+
`aria-describedby` to the visible error — you would announce it twice.
|
|
117
137
|
|
|
118
|
-
|
|
119
|
-
Components uses this deliberately where PrimeReact 11 emits ARIA that is invalid
|
|
120
|
-
or points at ids it never renders — for example removing `aria-sort` from a sort
|
|
121
|
-
control that carries `role="button"`, and removing `role` and `aria-controls`
|
|
122
|
-
from stepper headers whose referenced panels have no matching ids.
|
|
138
|
+
## 5. Decorative icons are hidden
|
|
123
139
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
140
|
+
Icons and loading spinners inside a labelled control are marked
|
|
141
|
+
`aria-hidden='true'` so a button's accessible name is exactly its label and not
|
|
142
|
+
the icon's text. Do the same in application components: an icon that sits beside
|
|
143
|
+
a text label carries no information of its own (`<FaPlus aria-hidden='true' />`).
|
|
127
144
|
|
|
128
|
-
|
|
129
|
-
the element it lands on. Removing a broken role usually leaves a natively
|
|
130
|
-
keyboard-accessible element behind, which is better than a role that lies.
|
|
145
|
+
## 6. Customize through parts without fighting the component's ARIA
|
|
131
146
|
|
|
132
|
-
|
|
147
|
+
Parts (`pt` and `data-cratis-part`) are for **presentation**. The component owns
|
|
148
|
+
the role, the name and the state attributes on its elements: *named behavior
|
|
149
|
+
props override conflicting part attributes*, so a `role` or `aria-*` value you
|
|
150
|
+
push through `pt` onto a part the component already labels is either overridden
|
|
151
|
+
or produces two competing semantics. Put identity and ARIA on the documented
|
|
152
|
+
behavior props (§2, §3) and keep `pt` to `className`, `style` and data
|
|
153
|
+
attributes. State is expressed through valid ARIA plus a data attribute
|
|
154
|
+
(`aria-invalid` + `data-invalid`, `data-disabled`, `data-selected`) — express your
|
|
155
|
+
own component state the same way, never through made-up attributes.
|
|
133
156
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
157
|
+
One focus lifecycle per interactive surface: never nest a second modal or focus
|
|
158
|
+
trap inside a Components dialog to borrow another look, and never combine two
|
|
159
|
+
keyboard-selection owners for one control. A presentation adapter must preserve
|
|
160
|
+
the Components contract without adding a second semantic control.
|
|
138
161
|
|
|
139
|
-
## What Cratis Components does
|
|
162
|
+
## What Cratis Components does — and does not — give you
|
|
140
163
|
|
|
141
164
|
Be accurate about this — over-promising accessibility is worse than saying
|
|
142
165
|
nothing.
|
|
143
166
|
|
|
144
|
-
- **
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
application
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
167
|
+
- **There is an automated scan, on representative surfaces.** The library runs
|
|
168
|
+
`axe-core` (WCAG 2 A and AA rules) over a set of representative foundation
|
|
169
|
+
surfaces in its own specs, and Storybook carries the accessibility addon. That
|
|
170
|
+
proves those surfaces have no *automated* violations; it is not a conformance
|
|
171
|
+
certification, it does not cover every component, and it cannot see keyboard
|
|
172
|
+
order, focus restoration, screen-reader phrasing or color relationships the
|
|
173
|
+
product introduces.
|
|
174
|
+
- **Modal focus management is real**: focus moves in per §1, the backdrop and the
|
|
175
|
+
document behind are handled by the React Aria modal, Escape and backdrop
|
|
176
|
+
dismissal follow `dismissable`, and busy content is `inert`. Verify keyboard
|
|
177
|
+
order, initial focus, focus restoration and screen-reader output in the
|
|
178
|
+
application's supported browsers and assistive technologies — Components does
|
|
179
|
+
not certify them for you.
|
|
180
|
+
- **Breadcrumbs and drill-ins in `SchemaEditor`, `ObjectContentEditor` and
|
|
181
|
+
`ObjectNavigationalBar` are native `<button>`s** (with `aria-current` on the
|
|
182
|
+
current crumb), so they are focusable and keyboard-activatable. Anything beyond
|
|
183
|
+
that — shortcut keys, arrow-key grid navigation — is not implemented; verify
|
|
184
|
+
against the component source before documenting it.
|
|
185
|
+
- **A custom design still owns visible focus, contrast, target size, reduced
|
|
186
|
+
motion, forced colors and responsive behavior.** Components supplies semantic
|
|
187
|
+
behavior and the `--cratis-focus-ring` token; it cannot infer the product's
|
|
188
|
+
color relationships.
|
|
189
|
+
- **No skip links, roving-tabindex utilities or live regions** for application
|
|
190
|
+
layouts beyond the toast region (`messages.notifications.region` names it).
|
|
162
191
|
|
|
163
192
|
## Verify
|
|
164
193
|
|
|
165
194
|
- Every dialog whose confirm action is destructive or irreversible sets
|
|
166
195
|
`initialFocus` to `DialogInitialFocus.Cancel` or `Content`.
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
|
|
196
|
+
- `CratisComponentsProvider` carries the locale and every `messages` group the
|
|
197
|
+
application renders; no accessible name in application code is a hard-coded
|
|
198
|
+
English string.
|
|
170
199
|
- `id`, `tabIndex`, and `aria-*` on a wrapper component reach the focusable
|
|
171
|
-
child, not the container.
|
|
200
|
+
child, not the container; a `DatePickerInput` is named on its group.
|
|
172
201
|
- Icons beside a text label are `aria-hidden`.
|
|
173
|
-
-
|
|
174
|
-
|
|
175
|
-
-
|
|
176
|
-
|
|
202
|
+
- No `role`/`aria-*` is injected through `pt`; no CSS or test targets a React Aria
|
|
203
|
+
class name.
|
|
204
|
+
- Field errors are not announced twice.
|
|
205
|
+
- No claim of keyboard support, automated coverage, or WCAG conformance is made
|
|
206
|
+
that the source does not back.
|
|
@@ -21,9 +21,8 @@ case where the shape itself is data.
|
|
|
21
21
|
|
|
22
22
|
| Package | Version | Verified from |
|
|
23
23
|
| --- | --- | --- |
|
|
24
|
-
| `@cratis/components` | `
|
|
25
|
-
| `
|
|
26
|
-
| `react` | `^19.0.0` | peer of `@cratis/components@3.0.0` |
|
|
24
|
+
| `@cratis/components` | `4.6.0` | its package manifest and the `SchemaEditor` / `ObjectContentEditor` sources |
|
|
25
|
+
| `react` | `^19.0.0` | peer of `@cratis/components@4.6.0` |
|
|
27
26
|
|
|
28
27
|
## The schema type these editors consume
|
|
29
28
|
|
|
@@ -147,10 +146,11 @@ among its siblings. Save is disabled while any name is invalid.
|
|
|
147
146
|
|
|
148
147
|
### Localization
|
|
149
148
|
|
|
150
|
-
`SchemaEditorLabels` has
|
|
151
|
-
`edit`, `save`, `cancel`, `addProperty
|
|
152
|
-
`
|
|
153
|
-
`
|
|
149
|
+
`SchemaEditorLabels` has fourteen fields, nine of them accessible names:
|
|
150
|
+
menu actions `edit`, `save`, `cancel`, `addProperty`; accessible names `actions`,
|
|
151
|
+
`navigateBack`, `navigateToItemDefinition`, `navigateToProperties`,
|
|
152
|
+
`propertyName`, `propertyType`, `arrayItemType`, `deleteProperty`; and the
|
|
153
|
+
messages `emptyMessage`, `invalidJson`. Pass `labels` with the ones you want to change — they merge
|
|
154
154
|
over the English defaults. Never rely on the built-in English strings in a
|
|
155
155
|
localized application.
|
|
156
156
|
|
|
@@ -218,9 +218,11 @@ name — localize it). It is click-only, like the editors' own breadcrumbs.
|
|
|
218
218
|
|
|
219
219
|
## Styling
|
|
220
220
|
|
|
221
|
-
Both editors expose `className` only
|
|
222
|
-
|
|
223
|
-
the
|
|
221
|
+
Both editors expose `className` only — no `pt`. Restyle their internals with CSS
|
|
222
|
+
scoped under that class, reaching the controls they render (buttons, inputs,
|
|
223
|
+
the embedded `Dropdown`) through their `data-cratis-part` values and the
|
|
224
|
+
`--cratis-*` tokens; there is no global provider pass-through in Components 4 —
|
|
225
|
+
see the **cratis-components-styling** skill.
|
|
224
226
|
|
|
225
227
|
## Verify
|
|
226
228
|
|
|
@@ -14,9 +14,8 @@ field across every step is valid.
|
|
|
14
14
|
|
|
15
15
|
| Package | Version | Verified from |
|
|
16
16
|
| --- | --- | --- |
|
|
17
|
-
| `@cratis/components` | `
|
|
18
|
-
| `@cratis/arc.react` | `>=20.3.1 <23` | peer range declared by `@cratis/components@
|
|
19
|
-
| `primereact` | `^11.0.0` | peer of `@cratis/components@3.0.0` |
|
|
17
|
+
| `@cratis/components` | `4.6.0` | its package manifest, `Source/CommandDialog/*` (`StepperCommandDialog`, `CommandStepper`, `StepperPanel`), `Documentation/StepperCommandDialog/*`, `Documentation/CommandStepper/*` |
|
|
18
|
+
| `@cratis/arc.react` | `>=20.3.1 <23` | peer range declared by `@cratis/components@4.6.0` |
|
|
20
19
|
|
|
21
20
|
## Choose it over `CommandDialog` when
|
|
22
21
|
|
|
@@ -84,7 +83,7 @@ import { useDialog } from '@cratis/arc.react/dialogs';
|
|
|
84
83
|
|
|
85
84
|
const [CreateProjectWrapper, showCreateProject] = useDialog(CreateProjectDialog);
|
|
86
85
|
|
|
87
|
-
<MenuItem label='New project' icon={
|
|
86
|
+
<MenuItem label='New project' icon={FaPlus} command={() => showCreateProject()} /> // icon is a component type, e.g. from 'react-icons/fa6'
|
|
88
87
|
<CreateProjectWrapper />
|
|
89
88
|
```
|
|
90
89
|
|
|
@@ -155,8 +154,6 @@ Stepper-level props (inherited from the stepper customization surface):
|
|
|
155
154
|
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` |
|
|
156
155
|
| `headerPosition` | `'top' \| 'bottom'` | `'top'` |
|
|
157
156
|
| `linear` | `boolean` | `true` |
|
|
158
|
-
| `showNavigation` | `boolean` | `true` |
|
|
159
|
-
| `showSubmit` | `boolean` | `true` |
|
|
160
157
|
| `start` / `end` | `React.ReactNode` | extra content beside the step headers |
|
|
161
158
|
| `onChangeStep` | `(event: { index: number }) => void` | — |
|
|
162
159
|
|
|
@@ -164,12 +161,14 @@ Command-form props (`initialValues`, `currentValues`, `validateOn`,
|
|
|
164
161
|
`validateOnInit`, `onSuccess`, `onValidationFailure`, `onFailed`,
|
|
165
162
|
`autoServerValidate`, …) all apply as well.
|
|
166
163
|
|
|
167
|
-
### Two
|
|
164
|
+
### Two part targets
|
|
168
165
|
|
|
169
|
-
The inherited `pt`, `
|
|
170
|
-
|
|
171
|
-
reach the **outer dialog**.
|
|
172
|
-
of a
|
|
166
|
+
The inherited `pt` (`StepperParts`: `root`, `list`, `step`, `header`, `number`,
|
|
167
|
+
`title`, `separator`, `panels`, `panel`) targets the **inner stepper**. Use
|
|
168
|
+
`dialogPt` (`DialogParts`) and `dialogClassName` to reach the **outer dialog**.
|
|
169
|
+
Getting these the wrong way round is the usual cause of a `pt` that appears to do
|
|
170
|
+
nothing. (`ptOptions`/`unstyled` and their `dialog*` twins are accepted for
|
|
171
|
+
Components 3 source compatibility and do nothing.)
|
|
173
172
|
|
|
174
173
|
## Dismissal while the command runs
|
|
175
174
|
|
|
@@ -193,7 +192,7 @@ children.
|
|
|
193
192
|
| The same property bound on two steps | Each property appears on exactly one step |
|
|
194
193
|
| A `StepperPanel` without `header` | `header` is the navigation label |
|
|
195
194
|
| Several panels wrapped in one fragment | A fragment counts as **one** step — give each step its own `StepperPanel` child |
|
|
196
|
-
| A raw
|
|
195
|
+
| A raw control (`TextInput`, a native `<input>`) for a command value | Use a `CommandForm` field, or the value is never bound and validation never re-runs |
|
|
197
196
|
| Seeding a required value in `onBeforeExecute` | Use `initialValues` |
|
|
198
197
|
| `pt` applied expecting it to reach the dialog | `pt` targets the stepper; use `dialogPt` |
|
|
199
198
|
|