Repository navigation
[Component Audit] LayoutPanel: full-bleed children reach the panel's outer edge - #10774
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| LayoutPanel | 21.3 kB (+34 B) · 4.9 kB CSS (+47 B) | — | ✓ · ✓ · ✓ |
| AppShell | 91.1 kB (+7 B) · 13.5 kB CSS (0) | — | — · — · — |
| Layout | 7.0 kB (0) · 2.3 kB CSS (0) | — | ✓ · ✓ · ✓ |
3 more components
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| LayoutContent | 17.7 kB (0) · 1.7 kB CSS (0) | — | ✓ · ✓ · ✓ |
| LayoutFooter | 6.1 kB (0) · 1.6 kB CSS (0) | — | ✓ · ✓ · — |
| LayoutHeader | 6.2 kB (0) · 1.6 kB CSS (0) | — | ✓ · ✓ · — |
Package size: @astryxdesign/core 7.21 MB packed (+504 B); no new dependencies.
API changes: none in this pull request
Committed API report behind this build: cli 29 rows, core 36 rows, theme-butter 1 row, theme-y2k 1 row; run pnpm api:report.
Touched components checked; add ci:run-visual to run the full suite.
Generated by PR Enrichment workflow | View full report
There was a problem hiding this comment.
Approved. CI passes on this head.
The four automatic edge styles in LayoutPanel.tsx now publish the inset they apply, as component:LayoutPanel FR3 and architecture:container-padding require. The new publication tests fail against the old component and pass here, and a full-bleed Divider in a padding={6} Layout now reaches the panel's outer edge while the existing Layout stories render unchanged.
- Non-blocking:
LayoutPanel.spec.md,container-padding.mdandlayout-regions.mdstill describe the automatic-edge mismatch as an open gap; a follow-up record change can remove those statements.
[Automated review]
User impact
A child that bleeds to its container's edges now reaches a panel's outer edge. On an edge where a
LayoutPaneltakes the Layout's own inset (its outer inline edge, and a block edge with no header or footer beside it), the panel applied that inset but told its children the inner inset. When the two differ, a full-bleed child stopped short:padding={6}, a<Divider isFullBleed />in a start panel stopped 8px before the panel's outer edge (24px applied, 16px told). It now reaches the edge, in left-to-right and right-to-left.padding={0}, the same Divider ran 16px past the panel's outer edge into its clip. It now ends at the edge.TableorTabList, or a nestedLayout.Builders get docs that match the component:
hasDividersays which edge it draws on, that the Layout'sdefaultHasDividersdoes not apply, and to leave it off beside aResizeHandlethat draws its own line;paddingsays that0is full bleed;refis listed.Audit result
core/LayoutPanel(released in@astryxdesign/coreunder./Layout)1.16.6f8a426486eedacd2c1cda05791364a597e5ed99aa666cdd8260LayoutPanel.spec.md(authority: current), unchanged. FR3 already requires the panel to publish container-padding values equal to the padding it applies (architecture:container-padding) and records the automatic-path mismatch as an implementation gap (Current-state impact); this pull request closes that gap in code. No observational backfill was prepared.--container-padding-*value. No prop, default, DOM, target, or applied padding changes.rolewhile the panel does not overflow (AR1); caller role and label reach the root (FR5); a scrolling panel carriesrole="group"andaria-label="Content"(AR3); the audit's axe pass reports no violationslayout-paneltarget on the painting root (padding and divider paint there);--color-border, spacing tokens, and logical properties onlyref,className,style, DOM, data, ARIA, and event props reach the root (FR6)--color-borderline on the content-facing edge; no radius or elevation; the slide motion is the resize controller's (FR7)not measuredstyle/DOM/data/ARIA/event props, the per-edge inset and its publication (automatic, beside a header and footer, explicit, and Layoutpadding={0}). Open FIXes: Needs Review 3 and 4hasDividerdid not name its edge, the Layout default, or theResizeHandleline;paddingdid not say0is full bleed;refhad no entryMeasured weight is 96 of 100 before (§5b not measured) and 100 after. §11 is not run for an existing core component.
Why the score moved: the publication fix closes the §4 FIX; new unit cases close three §6 FIXes; the doc fixes close three §8 FIXes; §5b is measured.
Pre-fix score: scored from base source before any change. Night Watch records only the landed post-fix result in the score ledger, so the pre-fix score lives here.
Findings fixed
component:LayoutPanelFR3;architecture:container-padding(a region publishes its applied padding)--container-padding-*. Red, then green: the new publication unit case fails at the fixture commit and passes after the fix; the Panel States receipts fail every automatic outer edge (applies 24, publishes 16) and the full-bleed Divider (ends 8px short) against a Storybook built from the fixture commit, and pass after the fixroleexposes no role or namestyle, DOM, data, ARIA, and event props reaching the root had no testarchitecture:public-component-apiINV5–INV8paddingreplacement, or the published valuespadding={0}, explicitpadding); Panel States receipts for every edge,padding={2}, and full bleedhasDividerdocs said only "Border on the appropriate edge"; the JSDoc'sResizeHandlenote, the shared gap, and the Layout-default rule were missingfamily:layout-regionsFR5paddingconditionpaddingdocs did not say that it also replaces the shared gap, or that0is full bleedrefhad no doc entry.github/a11y-audit-axe.jsonroutes the axe pass to the four Layout stories the audit spec usesNeeds Review
LayoutPanel.spec.mdFR3 and Current-state impact, and the "Known conformance gap" and region-publisher row inarchitecture:container-padding, still describe the publication gap; the LayoutPanel verification map still lists the gaps the new tests close. A later owner-approved record change can remove them.hasDividerand an adjacentResizeHandleline from both painting (family:layout-regionsFR5). Which component prevents it is an owner decision; the docs now tell callers to leavehasDivideroff there.isScrollable={false}, which edge carries the divider, the shared gap, and the full-bleed reach are measured in this audit's browser receipts, but no check that runs on every Layout change covers them. The publication itself now has unit cases.xstylemerge order (FIX). No test pins it.edgeon a panel (observation, owned bycomponent:List). List's docs say the automatic padding of LayoutPanel is not supported foredge="outset"andedge="bleed". With this fix that host state publishes its applied padding; whether List admits it is List's decision. Not scored against LayoutPanel.hasDividerandpaddingselect styles but are not reflected bythemeProps.architecture:component-theming-surfaceINV6 requires reflection for variant, size, selection, disabled, and interaction state, and no current record requires it for these props, so rubric T6 has no owner here.Evidence
data-panel-case) in plain frames with Layoutpadding={6}: start and end panels with and without a divider, a start panel beside a header and footer, a full-bleed Divider inside,padding={2},padding={0},width="10rem", anavigationlandmark with a label, overflowing content, and overflowing content withisScrollable={false}.76f4997(component unchanged from base; thepadding={0}unit case was added later), fails only the publication checks: in all five Panel States frames each automatic outer edge applies 24px but publishes 16px, and the full-bleed Divider ends 8px before the panel's outer edge. Every other check passes, and the six frames of existing stories pass.ci:run-a11yandci:run-rtl: all 11 audit tests pass in artifactpr-a11y-evidence-dacd2c1-1(sha256:697d84df1609b0b55e959f6324f3cf487ed97a8fce7221f4566267e8d98a8586), each receipt bound to builddacd2c1; the audit's axe pass over the four Layout stories reports no violations; pr-rtl and Stable visual regression green. One unrelated Lightbox timing check inpr-interactionfailed on the first attempt and was rerun. Locally, all 11 frames pass their sensor receipts bound to the head. Against the red-before build, the six frames of existing stories (With Sidebar light, dark, and RTL; Dual Panels; Content Width with Start Panel, LTR and RTL) are byte-identical. In the five Panel States frames, the only changed pixels are the 8 CSS px of the full-bleed Divider at the panel's outer edge.layout-paneltarget;flex-shrink: 0; page direction; not inert; no line on the outer edge, and a line on the content-facing edge is 1px solid--color-border; applied padding equals published padding on every edge; the panel stays inside its Layout;padding={6}: a start panel applies 24 / 16 / 24 / 24px (inline start, inline end, block start, block end), an end panel 16 / 24 / 24 / 24px; beside a header and footer the block edges are 16px; without a divider the panel overlaps the content by 16px on its content-facing edge, with a divider it does not;padding={2}8px on every edge;padding={0}0;width="10rem"160px; the landmark carriesrole="navigation"andaria-label="Sections"; the overflowing panel scrolls and carriesrole="group"andaria-label="Content"(attributes; the accessibility-tree check is the existing scroll-region spec); withisScrollable={false}it clips and has no role; the full-bleed Divider spans the panel's padding box;Closed evidence inventory
LayoutPanel,LayoutPanelPropsLayout/index.tsLayoutPanel.doc.mjsarchitecture:public-component-apilayout-paneltarget, non-shrinkingLayoutPanel.tsxwidth(number, string),resizablewinsLayoutPanel.tsxwidth,resizableisScrollable={false}LayoutPanel.tsxisScrollablescrolling,not-scrollablecasesLayoutPanel.tsxhasDividerpadding, full bleed, publicationLayoutPanel.tsxpaddingbleed-childarchitecture:container-paddingLayoutPanel.tsxhasDividerLayoutPanel.tsx,useScrollRegionProps.tsrole,labellandmark,scrollingcasesref, DOM, data, ARIA, event props,className,style,xstyleLayoutPanel.tsxref(new)xstyleorder untested)LayoutPanel.tsx,resizablePane.tspaneSlide.interaction.browser.spec.ts,collapsedPanel.interaction.browser.spec.ts,resizableSlot.test.tsxresizable,widthLayoutPanel.tsxdesign:bidirectionalityLayoutPanel.tsxFR10 eligibility report
{ "schema": "astryx.audit-eligibility/v1", "component": "LayoutPanel", "package": "core", "mode": "night-watch", "rubricVersion": "1.16.6", "repository": { "base": "f8a426486ee", "head": "dacd2c1cda05791364a597e5ed99aa666cdd8260" }, "contract": { "id": "component:LayoutPanel", "authority": "current", "changed": false }, "inventory": { "closed": true, "rows": 12, "open": [] }, "unresolved": { "objective": [ "root, scrolling, clipping, divider edge, shared gap, and full-bleed reach have no ongoing automated check", "xstyle merge order untested" ], "manual": [ "record follow-up: FR3 implementation-gap text, Current-state impact, verification-map gaps, and the container-padding known conformance gap", "FR4: which component prevents a panel divider and a ResizeHandle line from both painting" ], "ownedElsewhere": [ "component:List eligibility of an automatic LayoutPanel as an edge host" ] }, "remediations": [ {"id": "FR3", "kind": "bug-fix", "evidence": "publication unit case and Panel States receipts red at the fixture commit, green at head"}, {"id": "V5/AR1", "kind": "objective-test", "evidence": "no role or name without a caller role"}, {"id": "V3/FR6", "kind": "objective-test", "evidence": "style, DOM, data, ARIA, and event props"}, {"id": "V3/FR3", "kind": "objective-test", "evidence": "published inset on automatic, header-and-footer, zero-padding, and explicit edges"}, {"id": "X5b/P31", "kind": "doc-drift", "evidence": "hasDivider edge, shared gap, Layout default, ResizeHandle line; padding replaces the shared gap and 0 is full bleed; ref entry"} ], "approvals": { "specOwner": "success (no record change)" }, "checks": "green at dacd2c1 (CI run 42615976084)", "eligible": false, "reasons": [ "spec:AST-029 is phase accepted; FR11 activation has not shipped" ] }