Skip to content

Commit f32064b

Browse files
authored
Create new Modal DrawerLauncher component (#2744)
## Summary: Creates new `DrawerLauncher` and `DrawerDialog` components with three alignments: `inlineStart`, `inlineEnd`, and `blockEnd`. Ensures dialogs can be used with RTL writing mode. Issue: WB-2048 ## Test plan: 1. Ensure FlexibleDialog can be used standalone 2. Ensure DrawerLauncher with DrawerDialog can be positioned on left, right, and bottom 3. Ensure DrawerLauncher can be used with RTL writing mode 4. Ensure tests pass Author: marcysutton Reviewers: beaesguerra, marcysutton Required Reviewers: Approved By: beaesguerra Checks: ✅ 12 checks were successful, ⏭️ 2 checks have been skipped Pull Request URL: #2744
1 parent 83620b4 commit f32064b

27 files changed

+4457
-187
lines changed

.changeset/empty-maps-watch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@khanacademy/wonder-blocks-modal": patch
3+
---
4+
5+
Fix RTL positioning of close button in ModalPanel

.changeset/hot-birds-scream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@khanacademy/wonder-blocks-modal": minor
3+
---
4+
5+
Add DrawerLauncher and DrawerDialog components for sliding in from the left, right, or bottom.

.storybook/preview.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,23 @@ const withThemeSwitcher: Decorator = (
162162
};
163163

164164
/**
165-
* Wraps a story with `<div dir="rtl">` so it is shown in rtl mode.
165+
* Sets the dir attribute on document.documentElement and wraps story with dir div.
166+
* This ensures portaled content (like modals) can detect the direction.
166167
*/
167168
const withLanguageDirection: Decorator = (Story, context) => {
169+
React.useEffect(() => {
170+
if (context.globals.direction === "rtl") {
171+
document.documentElement.setAttribute("dir", "rtl");
172+
} else {
173+
document.documentElement.setAttribute("dir", "ltr");
174+
}
175+
176+
// Cleanup on unmount
177+
return () => {
178+
document.documentElement.removeAttribute("dir");
179+
};
180+
}, [context.globals.direction]);
181+
168182
if (context.globals.direction === "rtl") {
169183
return (
170184
<div dir="rtl">
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import type {ArgTypes} from "@storybook/react";
2+
3+
export default {
4+
// Accessibility props (discriminated union)
5+
title: {
6+
control: {type: "text"},
7+
table: {
8+
category: "Accessibility (one required)",
9+
type: {summary: "string | ReactElement"},
10+
},
11+
},
12+
"aria-label": {
13+
control: {type: "text"},
14+
table: {
15+
category: "Accessibility (one required)",
16+
type: {summary: "string"},
17+
},
18+
},
19+
"aria-labelledby": {
20+
control: {type: "text"},
21+
table: {
22+
category: "Accessibility (one required)",
23+
type: {summary: "string"},
24+
},
25+
},
26+
titleId: {
27+
control: {type: "text"},
28+
table: {
29+
type: {summary: "string"},
30+
},
31+
},
32+
33+
// Core props
34+
content: {
35+
control: {type: undefined},
36+
table: {
37+
type: {
38+
summary:
39+
"ReactElement | (({title: ReactElement}) => ReactElement)",
40+
},
41+
},
42+
},
43+
44+
// Interaction props
45+
onClose: {
46+
table: {
47+
type: {summary: "() => unknown"},
48+
},
49+
description:
50+
"Called when close button clicked. Prefer DrawerLauncher onClose instead.",
51+
},
52+
closeButtonVisible: {
53+
control: {type: "boolean"},
54+
table: {
55+
type: {summary: "boolean"},
56+
},
57+
},
58+
59+
// Styling and customization
60+
role: {
61+
control: "radio",
62+
options: ["dialog", "alertdialog"],
63+
defaultValue: "dialog",
64+
table: {
65+
defaultValue: {summary: "dialog"},
66+
type: {summary: "dialog | alertdialog"},
67+
},
68+
},
69+
styles: {
70+
control: {type: undefined},
71+
table: {
72+
type: {summary: "DrawerDialogStyles"},
73+
},
74+
},
75+
76+
// Testing
77+
testId: {
78+
control: {type: "text"},
79+
table: {
80+
type: {summary: "string"},
81+
},
82+
},
83+
"aria-describedby": {
84+
control: {type: "text"},
85+
table: {
86+
type: {summary: "string"},
87+
},
88+
},
89+
} satisfies ArgTypes;

0 commit comments

Comments
 (0)