@astryxdesign/lab 0.6.2-canary.bfee8a4 → 0.6.2-canary.cdde227

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.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/lab",
3
- "version": "0.6.2-canary.bfee8a4",
3
+ "version": "0.6.2-canary.cdde227",
4
4
  "description": "Experimental Astryx components — published to npm only under the @canary dist-tag for early testing; never released as a stable (latest) version.",
5
5
  "author": "Meta Open Source",
6
6
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@stylexjs/stylex": ">=0.10.0",
49
- "@astryxdesign/core": "0.6.2-canary.bfee8a4",
49
+ "@astryxdesign/core": "0.6.2-canary.cdde227",
50
50
  "react": ">=19.0.0",
51
51
  "react-dom": ">=19.0.0"
52
52
  },
@@ -56,8 +56,8 @@
56
56
  "d3-shape": "^3.2.0"
57
57
  },
58
58
  "devDependencies": {
59
- "@astryxdesign/a11y-spec": "0.6.2-canary.bfee8a4",
60
- "@astryxdesign/cli": "0.6.2-canary.bfee8a4",
59
+ "@astryxdesign/a11y-spec": "0.6.2-canary.cdde227",
60
+ "@astryxdesign/cli": "0.6.2-canary.cdde227",
61
61
  "@babel/cli": "^7.29.7",
62
62
  "@babel/core": "^7.29.7",
63
63
  "@babel/preset-react": "^7.29.7",
@@ -0,0 +1,274 @@
1
+ ---
2
+ schema_version: 3
3
+ template_version: 5
4
+ kind: component
5
+ id: component:Drawer
6
+ authority: draft
7
+ archive_reason: null
8
+ superseded_by: null
9
+ approved_by: null
10
+ approved_at: null
11
+ owners: [cixzhang, imdreamrunner]
12
+ review_triggers: [public-api, behavior, layout, theming, accessibility]
13
+ verified_by:
14
+ [
15
+ packages/lab/src/Drawer/Drawer.test.tsx,
16
+ .github/scripts/modal-close-visibility.js,
17
+ apps/storybook/rtl-audit/rtl-audit.mjs,
18
+ scripts/check-knowledge.mjs,
19
+ ]
20
+ modules: []
21
+ families: [family:overlay-dismissal]
22
+ design_specs: []
23
+ architecture:
24
+ [
25
+ architecture:component-theming-surface,
26
+ architecture:layer-runtime,
27
+ architecture:public-component-api,
28
+ architecture:react-component-runtime,
29
+ ]
30
+ contributing: []
31
+ system_specs: [spec:AST-027/DEC-3]
32
+ ---
33
+
34
+ # Drawer component contract
35
+
36
+ ## Contract at a glance
37
+
38
+ | Area | Contract |
39
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
40
+ | Current Lab surface | No public-API delta. At this commit, the experimental `@astryxdesign/lab` root exports `Drawer` and `DrawerProps`; `DrawerProps` extends `BaseProps<HTMLDialogElement>`, separately declares `ref`, and requires `isOpen`, `onOpenChange`, `label`, and `children`. This records current reachability, not a stable compatibility promise. |
41
+ | Behavior | Drawer-owned visibility is controlled by the caller for a viewport-relative, full-height logical-side overlay. Native mode is selected from `hasScrim` at open; changing it while open is unsupported, although the current implementation updates scrim styling, `aria-modal`, modal-root clicks, and body lock live. Drawer-local registration gates Escape for same-presentation siblings and assigns non-modal z-index; modal paint is browser-owned, while mixed-presentation and nested stacking are unspecified. Exit renders current children. |
42
+ | End-user impact | None from this documentation-only record; current modal/non-modal semantics, focus return, dismissal, motion, sizing, and sibling ordering remain unchanged. |
43
+ | Builder impact | None; there is no migration or new caller choice. State and content remain caller-owned; Drawer renders the caller's current children during exit. Sibling composition remains current consumer guidance. |
44
+ | Compatibility/readiness | Additive documentation with no runtime or default change; Drawer remains experimental in Lab, this record remains `draft`, and its candidate statements require approval. FR13–FR14 record named family/top-layer conformance gaps. |
45
+ | Review checks | Reject regional, docked, or block-axis models; claims that modality and scrim are currently independent; or claims that the local registry and non-modal `show()` path satisfy shared dismissal/top-layer rules, guarantee mixed-presentation or nested ordering, or establish stable API/theming compatibility. |
46
+ | Record context | `component:Drawer` FR1–FR14 and AR1–AR6 are draft candidate statements. Linked records govern only within their own declared authority and scope. |
47
+
48
+ This table summarizes the draft body below; it does not change this record's declared authority.
49
+
50
+ ## Intent
51
+
52
+ Drawer presents contextual details or controls in a full-height side panel that
53
+ floats over the current page without reflowing it. It supports modal inspection
54
+ with a scrim and non-modal master-detail inspection that leaves the page behind
55
+ available.
56
+
57
+ This draft records the viewport-only Lab component that exists on current `main`.
58
+ It introduces no runtime, styling, theming, or public-API change. In particular,
59
+ it does not revive a regional, pane-scoped, or container-targeted Drawer model.
60
+
61
+ ## Compatibility and migration
62
+
63
+ - Released default preserved: `not yet released`; Drawer remains in
64
+ `@astryxdesign/lab`.
65
+ - Compatibility class: additive maintainer documentation only; runtime, DOM,
66
+ styling, targets, props, and consumer docs remain unchanged.
67
+ - Controlled/uncontrolled behavior: unchanged for Drawer-owned paths; callers
68
+ provide `isOpen`, while direct native mutation through the public dialog ref is
69
+ outside that guarantee.
70
+ - Migration decision: none.
71
+
72
+ Consumer migration instructions belong in consumer docs and release notes.
73
+
74
+ ## Ownership boundary
75
+
76
+ **Owns**
77
+
78
+ - The viewport-relative side-panel surface, logical edge, inline-size budget, and
79
+ entry/exit motion.
80
+ - The current presentation input: its value at native open selects `showModal()`
81
+ or `show()`. Changing it while open is unsupported; current live effects are
82
+ recorded as implementation facts rather than durable transition policy.
83
+ - Drawer-local focus entry/return, built-in close affordance, uncanceled
84
+ backdrop-click handling, and retention of its host through controlled exit
85
+ while rendering current caller-owned children.
86
+ - The local registration order used for same-presentation sibling Escape
87
+ eligibility and non-modal z-index assignment. Modal paint order is browser-owned.
88
+
89
+ **Does not own / non-goals**
90
+
91
+ - Caller-provided headers, forms, inspectors, footers, or other content.
92
+ - Block-axis sheets — owned by `component:BottomSheet`.
93
+ - Persistent panels that reserve layout space or push page content.
94
+ - Regional or pane-scoped placement, a caller-supplied container, or independent
95
+ modality and scrim axes. Those are not current Drawer concepts.
96
+ - Cross-family Escape and platform-close ordering — owned by
97
+ `family:overlay-dismissal`; current Drawer has a recorded local-adoption gap.
98
+ - Button painting for the built-in close affordance — delegated to
99
+ `component:Button` through IconButton.
100
+
101
+ ## Public concepts
102
+
103
+ Consumer prop syntax and examples remain in `Drawer.doc.mjs`.
104
+
105
+ | Concept | Closed values or states | Meaning | Availability by state | Default | Owner | Stability | Invalid-value behavior |
106
+ | ------------------ | --------------------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------- | ----------------------------------- | ------------------ | ------------------------- | ------------------------------------------------------ |
107
+ | visibility | open, closed | whether caller-controlled Drawer presentation is requested | all presentations | caller-controlled | `component:Drawer` | experimental Lab contract | required controlled value |
108
+ | logical edge | inline start, inline end | viewport edge from which the panel enters and exits | open and exiting | inline end | `component:Drawer` | experimental Lab contract | closed type rejects other values |
109
+ | presentation | modal with scrim, non-modal without scrim | native open mode and associated initial semantics | chosen when the native dialog opens; live changes are unsupported | modal with scrim | `component:Drawer` | experimental Lab contract | one current boolean selects the initial mode |
110
+ | inline-size budget | pixel number or valid CSS length | desktop inline size and reveal-mode mobile cap | desktop and mobile page-reveal mode | `400px` | `component:Drawer` | experimental Lab contract | invalid CSS lengths are unsupported |
111
+ | mobile coverage | page reveal, full viewport | whether narrow viewports retain a visible page strip | viewports at or below the mobile boundary | 56px page reveal | `component:Drawer` | experimental Lab contract | closed boolean |
112
+ | close affordance | built-in close button present, absent | whether Drawer supplies its top-trailing close action | modal and non-modal presentations | present | `component:Drawer` | experimental Lab contract | closed boolean |
113
+ | sibling order | earlier opened, later opened, exiting, closed | same-presentation local Escape eligibility and non-modal z-index assignment | sibling Drawers using one presentation mode | later opened is last registry entry | `component:Drawer` | experimental Lab contract | mixed-presentation and nested stacking are unspecified |
114
+
115
+ ## Behavioral and layout contract
116
+
117
+ | ID | Candidate invariant | Basis | Draft review state |
118
+ | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
119
+ | FR1 | Drawer MUST remain a viewport-relative, full-block-size overlay on the logical inline-start or inline-end edge and MUST NOT reserve layout space or reflow the page beneath it. | Current source, docs, stories, and tests | Verified current behavior; no new behavior decided |
120
+ | FR2 | The logical edge selected for an open Drawer MUST remain latched through its exit even when caller state changes the live edge prop during close. | Current exit-side test and implementation | Verified current behavior |
121
+ | FR3 | The desktop inline-size budget MUST accept pixel numbers or CSS lengths and remain bounded by the viewport. At or below 640px, page-reveal mode MUST preserve 56px and use `width` as a cap; full-mobile mode MUST override `width` with `100dvw`. | Current docs, styles, and width tests | Verified current behavior |
122
+ | FR4 | Visibility through Drawer-owned behavior MUST follow `isOpen`. Uncanceled Escape and modal-backdrop handling, and the built-in close action, request `false`; Drawer prevents its handled native `cancel` event from closing the dialog directly. During controlled exit, Drawer keeps its host and content region mounted while rendering the caller's current `children`. | Current prop contract and lifecycle tests | Verified for Drawer-owned paths; direct native mutation through the public ref is outside this guarantee |
123
+ | FR5 | At open time, `hasScrim={true}` MUST select native `showModal()` with `aria-modal`, body scroll locking, and a visible backdrop; `hasScrim={false}` MUST select non-modal `show()` and leave the page behind interactive. Changing `hasScrim` while open is not a supported native-mode transition. The current implementation still updates scrim styling, `aria-modal`, modal-root click handling, and body locking live without switching the native mode. | Current source, docs, and initial-mode tests | Initial modes verified; live presentation changes unsupported |
124
+ | FR6 | An uncanceled modal root/backdrop click (`target === currentTarget` while live `hasScrim` is true) MUST request close. Descendant clicks and dialog-root clicks while live `hasScrim` is false MUST NOT request close, and non-modal presentation MUST NOT install an invisible outside-pointer dismissal plane. | Current click tests | Verified current behavior |
125
+ | FR7 | The built-in close affordance MUST appear by default in both presentations, carry an accessible name, and request close without taking open-state ownership. Callers may explicitly omit it. | Current docs and close-button tests | Verified current behavior |
126
+ | FR8 | Opening MUST present the native dialog and attempt to focus the first rendered `[data-autofocus]` descendant, if any. After a completed controlled close, Drawer MUST attempt to restore focus to the element that was active before opening. | Current presence hook and focus tests | Verified for completed controlled close |
127
+ | FR9 | Closing MUST retain the panel host, content region, edge, and native dialog while the exit remains visible and continue rendering the caller's current `children`. Once the visible exit completes, Drawer MUST release native dialog state and hide the panel before the next paint. | Current lifecycle tests and browser close-visibility guard | Observable outcome verified; mechanism private |
128
+ | FR10 | Current Drawer-local coordination is registration-based. Among open sibling Drawers using the same presentation mode, the most recently registered handles a Drawer-local Escape event that reaches it; closing or unmounting unregisters it so the prior open Drawer becomes eligible. Non-modal siblings receive increasing local z-indexes, while modal paint order is browser-owned. Mixed-presentation visual ordering and nested stacking are unspecified. | Current source, docs, and non-modal stack tests | Recorded current behavior; local family adoption gap remains |
129
+ | FR11 | At this commit, `DrawerProps` extends `BaseProps<HTMLDialogElement>` and separately declares `ref`. The root filters `open`, merges `xstyle`, `className`, and `style`, forwards remaining unclaimed props, composes consumer `onClick` and `onKeyDown`, and owns `aria-label`, `aria-modal`, and `onCancel`. A consumer `onKeyDown` that prevents default cancels Drawer-owned Escape handling. | Current source and focused keyboard tests | Recorded current Lab behavior; not a stable compatibility decision |
130
+ | FR12 | At this commit, the painted root dialog emits the documented `drawer` target and `side` selector axis and applies the container-padding reset. No separate Drawer target is currently emitted for content or scrim; future target qualification remains owned by `architecture:component-theming-surface`. | Current source, docs, and structural target metadata | Current reachability only; no target-admission decision |
131
+ | FR13 | Drawer currently uses a component-local registry for open order, Escape eligibility, and non-modal z-index assignment. It does not control native modal top-layer order. That implementation is a deviation from `family:overlay-dismissal/FR1`, not an accepted family exception or a new component-local policy. | Current family adoption table | Known current adoption gap |
132
+ | FR14 | Non-modal Drawer currently uses `dialog.show()` plus a page-level z-index band rather than a native top-layer host. That implementation is a named conformance gap against `spec:AST-027/DEC-3`, not part of the durable component contract. | Current source and `spec:AST-027` | Known current top-layer gap |
133
+
134
+ ### Allowed variation
135
+
136
+ - **AV1 — Caller content.** Any renderable inspector/detail content may occupy the
137
+ scrolling content region without becoming Drawer-owned anatomy. Drawer renders
138
+ current `children`; callers decide whether the underlying data remains available
139
+ during exit.
140
+ - **AV2 — Inline size.** Consumers may choose the desktop budget within valid CSS
141
+ and viewport constraints. It remains the cap in mobile page-reveal mode, while
142
+ full-mobile mode uses `100dvw` instead.
143
+ - **AV3 — Presentation.** The value at native open selects modal or non-modal
144
+ dialog mode. Changing `hasScrim` while open is unsupported; current live scrim,
145
+ ARIA, root-click, and body-lock updates are implementation effects rather than a
146
+ supported native-mode transition.
147
+ - **AV4 — Close control.** Callers may hide the built-in close button.
148
+ - **AV5 — Motion duration.** Themes may alter the transform transition duration;
149
+ close timing follows computed CSS and reduced-motion preferences.
150
+
151
+ ### Representative states
152
+
153
+ | State | Required invariant | Allowed variation |
154
+ | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
155
+ | Closed | no native dialog presentation or visible panel | caller content may remain mounted in React |
156
+ | Modal inspector | opened with `hasScrim` true via `showModal()` with scrim, modal semantics, and body lock | edge, width, caller content, autofocus destination, and built-in close affordance |
157
+ | Non-modal master-detail inspector | opened with `hasScrim` false via `show()`; no scrim, `aria-modal`, modal-root dismissal, or body lock; Escape requires an event reaching the dialog | edge, width, caller content, and built-in close affordance |
158
+ | Narrow viewport with page reveal | panel does not exceed its `width` cap and preserves 56px of the page | requested width below the cap |
159
+ | Narrow full-coverage viewport | panel uses `100dvw`, overriding the requested `width` | caller content |
160
+ | Two non-modal sibling Drawers | later-opened open Drawer receives a higher page-level z-index and handles Escape dispatched within it | edge, width, and caller content |
161
+ | Exiting Drawer | panel host, content region, logical edge, and native presentation remain while the exit is visible; current children render | caller-controlled child data and motion duration |
162
+
163
+ ### Transformation and precedence order
164
+
165
+ - **ORD1 — Open.** Resolve the current logical edge and width, retain the rendered
166
+ panel, capture the currently focused element, use current `hasScrim` to select
167
+ the native dialog mode, then honor a rendered autofocus destination.
168
+ - **ORD2 — Close.** During controlled close, Drawer keeps its panel and
169
+ caller-provided content visible through the exit animation. After exit,
170
+ presentation ends without an intermediate visible frame, and Drawer attempts to
171
+ restore focus to the previously focused element when available.
172
+ - **ORD3 — Sibling order.** For same-presentation sibling Drawers, registration
173
+ order gates Drawer-local Escape handling; non-modal siblings also receive
174
+ increasing z-indexes. Modal paint order is browser-owned. Mixed-presentation
175
+ visual ordering and nested stacking are unspecified.
176
+
177
+ ### Performance and resources
178
+
179
+ - **PR1 — Exit cleanup.** Any resources used to coordinate exit are released after
180
+ completion, interruption, or unmount.
181
+ - **PR2 — Presentation cleanup.** Controlled closing or unmounting Drawer releases
182
+ native presentation and any active body scroll lock.
183
+ - **PR3 — Viewport-relative sizing.** Drawer derives sizing from `width`,
184
+ `isFullWidthOnMobile`, and the viewport; callers do not supply a regional
185
+ measurement target.
186
+
187
+ ## Accessibility contract
188
+
189
+ - **AR1 — Name.** `label` is a required string forwarded to `aria-label`; caller
190
+ content is not used as an implicit name. Current code does not reject an empty
191
+ or whitespace-only value.
192
+ - **AR2 — Modal truthfulness.** At open time, `hasScrim={true}` uses native modal
193
+ dialog state and `aria-modal`; `hasScrim={false}` uses non-modal dialog state and
194
+ omits `aria-modal`. Changing `hasScrim` while open is not a supported transition.
195
+ - **AR3 — Keyboard dismissal.** For sibling Drawers using the same presentation
196
+ mode, Escape requests close only for the last-opened still-open Drawer when a
197
+ Drawer-local event reaches it; a consumer `onKeyDown` that prevents default
198
+ cancels Drawer-owned keydown handling, and unrelated keys do not dismiss. Mixed
199
+ presentation modes are not covered by this guarantee.
200
+ - **AR4 — Focus lifecycle.** Focus enters visible Drawer content through the
201
+ documented autofocus/native path and, after a completed controlled close, Drawer
202
+ attempts to restore focus to the element that was active when the Drawer opened.
203
+ - **AR5 — Close affordance.** The built-in close action retains an accessible name
204
+ and Button-owned keyboard/focus behavior in both presentations.
205
+ - **AR6 — Direction and motion.** Logical inset placement follows computed
206
+ direction; slide-direction mirroring currently requires a `[dir="rtl"]`
207
+ ancestor. Self-applied `dir="rtl"` and CSS-only direction do not trigger
208
+ transform mirroring. Motion reduces under `prefers-reduced-motion` without
209
+ changing the final state.
210
+
211
+ ## Design relationships
212
+
213
+ | Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
214
+ | ---------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------ | -------------- | ------------------ |
215
+ | Panel | Paints the full-height side surface and owns edge, width, border, shadow, and motion. | Current source and public docs | Prominent | FR1–FR3, FR9, FR12 |
216
+ | Content region | Provides full-height scrolling for caller-owned inspector content. | Current source and public docs | Prominent | FR4, AV1 |
217
+ | Close button | Supplies the persistent top-trailing dismissal action when enabled. | `component:Button` | Supporting | FR7, AR5 |
218
+ | Modal scrim | At initial modal open, communicates the scrim-backed presentation and provides root-click activation behind the panel. | Current source and public docs | Supporting | FR5, FR6, AR2 |
219
+ | Page reveal | Preserves overlay context on narrow viewports unless full coverage is requested. | Current public docs | Supporting | FR3 |
220
+
221
+ The root Panel carries the current `drawer` target and reflects `side`. Consumer
222
+ docs do not yet declare canonical `usage.anatomy`, and no separate Drawer target is
223
+ currently reachable for Content region, Close button, or Modal scrim. This draft
224
+ does not decide future target qualification.
225
+
226
+ ## Family and system relationships
227
+
228
+ - `family:overlay-dismissal` owns cross-component Escape and platform-close
229
+ ordering. Drawer is a member but remains local-only on current `main`; FR13
230
+ records that adoption gap without legitimizing a parallel policy.
231
+ - `architecture:layer-runtime` owns the distinction between native modal hosting,
232
+ non-modal dialog presentation, top-layer behavior, and shared layer plumbing.
233
+ - `architecture:public-component-api` owns stable API admission and compatibility.
234
+ Drawer remains experimental in Lab; FR11 records current DOM/ref/event
235
+ reachability without making a stable compatibility decision.
236
+ - `architecture:react-component-runtime` owns effect/resource cleanup, native-host
237
+ synchronization, and node/lifecycle safety. This draft records Drawer-owned
238
+ visible close and focus-handoff outcomes.
239
+ - `architecture:component-theming-surface` owns target qualification and future
240
+ anatomy mapping; this draft records the existing `drawer` target only.
241
+ - `spec:AST-027/DEC-3` requires equivalent floating interactions to use an
242
+ applicable native top-layer host. Current non-modal Drawer does not yet conform;
243
+ FR14 records that system-owned gap without adopting its implementation.
244
+
245
+ ## Verification map
246
+
247
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
248
+ | --------------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
249
+ | FR1–FR7 | `Drawer.test.tsx` render, initial-mode, click, sizing, side, and control suites | closed/open, both edges, initial modal/non-modal modes, mobile widths | Layout reflows; an initial mode gains the wrong semantics; uncanceled root-click or full-mobile sizing becomes nondeterministic. | `audit:Drawer/behavior` |
250
+ | FR11 | Drawer source and focused keyboard composition/cancellation tests | filtered `open`, merged styling/ref, forwarded unclaimed props, owned ARIA/cancel, composed click/keydown | Current forwarding changes without review or built-in Escape ignores documented consumer cancellation. | `audit:Drawer/public-api` |
251
+ | FR8, AR1–AR5 | `Drawer.test.tsx` label forwarding, autofocus, close, and focus-return suites | initial modal/non-modal modes, autofocus target, connected previously focused element | Focus moves before presentation, completed controlled close fails to restore focus, or label forwarding/dismissal naming breaks. | `audit:Drawer/accessibility` |
252
+ | FR9, PR1–PR2 | close timing tests, browser close-visibility guard, and presence-hook source inspection | controlled close, transform end, unrelated transition, lost-event backstop | Native presentation ends before visible exit, the host is stranded, cleanup paths retain resources, or an intermediate frame paints outside native presentation. | `audit:Drawer/motion` |
253
+ | FR10, FR13, AR3 | Drawer non-modal LIFO tests plus source and `family:overlay-dismissal` adoption table | two non-modal siblings, Drawer-local keydown, unmount, remaining sibling | One event closes two tested siblings, Drawer-local behavior is promised globally, or tested non-modal ordering is extended to mixed/nested cases. | `audit:Drawer/layers` |
254
+ | FR14 | Drawer source plus `spec:AST-027` impact inventory and DEC-3 | non-modal `show()` host and page-level stack band | The current workaround is documented as conforming or mistaken for durable component policy. | `audit:Drawer/layers` |
255
+ | FR12 | source, `Drawer.doc.mjs`, and current target discovery | start/end root Panel and inherited container context | Current root target/axis or padding reset changes, or the record claims an unreachable child target or decides future admission. | `audit:Drawer/theming` |
256
+ | AR6 | side tests and source inspection plus Storybook ancestor-RTL audit | settled `end` placement under ancestor RTL; transform mirroring and reduced motion source-inspected | Audited settled placement or source-inspected ancestor mirroring/reduced-motion behavior changes without corresponding evidence. | `audit:Drawer/accessibility` |
257
+
258
+ ## Decision log
259
+
260
+ None. This draft records current facts and introduces no component-local design,
261
+ API, theming, scope, or layer-system decision.
262
+
263
+ ## Open questions
264
+
265
+ None. Regional placement, independent modality/scrim axes, and block-axis sheets
266
+ are outside the current component boundary. Any future proposal for them requires
267
+ fresh public-API and design authority rather than being inferred from this
268
+ current-state backfill.
269
+
270
+ ## Content boundary
271
+
272
+ This file does not duplicate consumer prop tables or examples, private registry
273
+ and transition algorithms, current audit scores, implementation steps, or shared
274
+ family/system rules. It links to their owners.