Skip to content

feat(drawer): add organism component#258

Merged
egdev6 merged 4 commits into
mainfrom
feat/23-drawer-organism
Jun 5, 2026
Merged

feat(drawer): add organism component#258
egdev6 merged 4 commits into
mainfrom
feat/23-drawer-organism

Conversation

@ludevdot
Copy link
Copy Markdown
Collaborator

@ludevdot ludevdot commented Jun 4, 2026

Summary

Closes #23

  • Adds the Drawer organism with Radix Dialog-backed focus, dismissal, and compound slots.
  • Covers logical placements, responsive mobile bottom-sheet behavior, sizing, safe-area footer padding, and reduced-motion seams.
  • Adds Storybook examples, docs, tests, export wiring, and accessibility hardening from Judgment Day review.

Review scope

  • Primary files/areas:
    • src/components/organisms/drawer/**
    • src/index.ts
    • src/styles/theme.css
    • docs/COMPONENTS.md
    • docs/DESIGN.md
  • Out of scope:
    • Global Button gradient contrast behavior beyond Drawer story trigger mitigation.
    • Local SDD/Judgment artifacts and harness files (.atl/, judgment/, reports/).
  • Review workload: large. Maintainer explicitly approved a single-PR exception for this Drawer component work.

Type of change

  • New component
  • Existing component update/refactor
  • Bug fix
  • Accessibility
  • Design tokens
  • Storybook/docs
  • Infrastructure/tooling
  • NPM/dependencies

Workflow gates

  • Linked issue is present with Closes #NNN or maintainer approved an exception.
  • Linked issue has label status:approved before implementation starts.
  • Work was started through the Project flow: assignee set, Project status In progress, branch/worktree recorded.
  • PR title follows Conventional Commit format: <type>(<optional scope>): <description>.
  • Commits follow the same commitlint-enforced format.
  • Diff is focused; unrelated work is called out in Review scope.
  • MCP/runtime artifacts are absent: .playwright-mcp, page-*.png, page-*.jpeg, *.md.playwright-output.

Component evidence (required for component changes)

  • Validated component spec is linked or quoted in the issue.
  • Accessibility contract from the spec was implemented or deviations are explained below.
  • Follows the 6-file pattern: types.ts, use*.ts, Component.tsx, Component.test.tsx, Component.stories.tsx, index.ts.
  • CVA variants live in types.ts; JSX component has no state, CVA calls, or business logic.
  • Public props with runtime defaults have matching @default JSDoc in types.ts (node scripts/verify-prop-default-docs.mjs).
  • Uses design tokens from theme.css; no hardcoded colors or arbitrary color utilities.
  • Storybook covers default, variants, documented states, edge cases, and dark mode when visually different.
  • Component audit result is PASS or accepted PASS WITH WARNINGS.
  • Visual review result is included when visuals changed.

Accessibility evidence

  • Role/name semantics verified with Testing Library queries or equivalent.
  • Keyboard-only behavior verified: Tab / Shift+Tab, Enter / Space, Arrow keys, Escape, Home / End / typeahead where applicable.
  • Focus lifecycle verified: initial focus, roving/active descendant, focus restore, trap/portal behavior where applicable.
  • Disabled, required, invalid/error, loading, and empty states expose the expected semantics where applicable.
  • Reduced motion behavior is respected where motion changed.
  • Screen reader or axe/manual evidence is included below when applicable.

Validation evidence

  • TypeScript: pnpm exec tsc --noEmit
  • Unit tests: pnpm test -- src/components/organisms/drawer/Drawer.test.tsx
  • Build/package: pnpm run build ✅, pnpm run verify:package
  • Storybook or visual check: pnpm run storybook-build
  • Accessibility check:
    • Drawer trigger aria-controls is only present while content is mounted/open.
    • Non-native asChild triggers support Enter/Space keyboard activation.
    • Disabled asChild triggers block child side effects and do not open.
    • Drawer Placement story triggers use opaque backgrounds for deterministic contrast checks in light/dark mode.
    • Judgment Day Round 2: APPROVED ✅
  • Security/dependency check: N/A — no dependency changes.

Screenshots or recordings

N/A — component behavior is covered by Storybook stories and local visual/a11y checks.

Notes for reviewer

  • Drawer side placements (start/end) adapt to bottom-sheet layout below md; on md+, logical LTR/RTL placement seams are exposed via data-* attributes and responsive classes.
  • Drawer.Title is required in development/test so the dialog has an accessible name.
  • dismissible and closeOnEscape are intentionally independent; explicit close controls remain available for non-dismissible drawers.
  • The large diff is mostly the new component, tests, and stories; this PR intentionally keeps the approved single-PR scope.
  • The Project item is now In progress; assignee and approved label are present.

@ludevdot ludevdot requested a review from egdev6 as a code owner June 4, 2026 20:16
@ludevdot ludevdot added the type:feature Feature changes label Jun 4, 2026
@ludevdot ludevdot self-assigned this Jun 4, 2026
Copy link
Copy Markdown
Member

@egdev6 egdev6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the thorough Drawer work. CI and the overall component structure look strong, but I found two implementation issues that should be fixed before merge.

Also, small PR hygiene note: the Workflow gates section still says the Project flow is unchecked and the issue appears as Todo, but #23 now shows In progress. Please update that metadata while touching the PR body.

Comment thread src/components/organisms/drawer/useDrawer.ts Outdated
Comment thread src/components/organisms/drawer/useDrawer.ts Outdated
@ludevdot ludevdot requested a review from egdev6 June 5, 2026 07:26
@ludevdot
Copy link
Copy Markdown
Collaborator Author

ludevdot commented Jun 5, 2026

@egdev6 I found a few follow-up Drawer suggestions while reviewing the requested fixes, but I do not want to expand this PR without your opinion.

My read:

  • Strongest candidates before merge: Drawer.Trigger asChild and Drawer.Close asChild should probably forward wrapper props to the child, composing handlers where needed. That better matches the Radix-style asChild contract and avoids losing aria-*, data-*, id, title, tracking handlers, etc.
  • Low-risk polish: suppress Radix description warnings when Drawer.Description is intentionally omitted, and add reduced-motion suppression to the drawer overlay fade.
  • Design decision / likely defer: whether size="full" for top/bottom drawers should force full viewport height or remain a max-height semantic.

Happy to handle whichever subset you think should be in this PR, or defer them to a follow-up issue if you prefer keeping this review focused.

@egdev6
Copy link
Copy Markdown
Member

egdev6 commented Jun 5, 2026

Thanks for checking before expanding the PR.

My recommendation: include the asChild prop forwarding for Drawer.Trigger and Drawer.Close before merge. That is the same class of public API issue as the handler composition fix, since consumers can reasonably expect wrapper props like id, aria-*, data-*, title, and tracking handlers to survive the asChild path.

I would defer the description-warning suppression and reduced-motion overlay polish to a follow-up, and keep the size="full" top/bottom behavior as a separate design decision.

@ludevdot
Copy link
Copy Markdown
Collaborator Author

ludevdot commented Jun 5, 2026

Thanks, included this before merge.

I added asChild wrapper prop forwarding for both Drawer.Trigger and Drawer.Close, including id, aria-*, data-*, title, and composed tracking handlers. I also added regression coverage for the trigger open path and close dismissal path, and kept the other drawer follow-ups out of this PR scope.

Validation:

  • pnpm exec biome check src/components/organisms/drawer/Drawer.tsx src/components/organisms/drawer/useDrawer.ts src/components/organisms/drawer/types.ts src/components/organisms/drawer/Drawer.test.tsx
  • pnpm vitest run src/components/organisms/drawer/Drawer.test.tsx
  • pnpm exec tsc --noEmit --incremental false
  • pre-push full pnpm test, 32 files / 608 tests passed

Pushed in 0ed388e0 (fix(drawer): forward asChild wrapper props).

Copy link
Copy Markdown
Member

@egdev6 egdev6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this addresses the asChild forwarding follow-up.

I verified wrapper props and handlers now land on both Drawer.Trigger and Drawer.Close custom children, with regression coverage for both paths. CI is green, including the accessibility audit.

Looks good from my side.

@egdev6 egdev6 merged commit dcb8432 into main Jun 5, 2026
10 checks passed
@egdev6 egdev6 deleted the feat/23-drawer-organism branch June 5, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:feature Feature changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ORGANISMS] Drawer

2 participants