@xsolla/xui-b2b-drawer 0.148.0 → 0.148.2

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.
Files changed (2) hide show
  1. package/README.md +227 -0
  2. package/package.json +7 -7
package/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # B2B Drawer
2
+
3
+ A slide-in panel that opens from the right edge of the screen, designed for B2B settings panels, multi-step flows, and auxiliary content that should not disrupt the main interface. Supports an optional stepper sidebar for multi-step workflows.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @xsolla/xui-b2b-drawer
9
+ # or
10
+ yarn add @xsolla/xui-b2b-drawer
11
+ ```
12
+
13
+ ## Demo
14
+
15
+ ### Basic Drawer
16
+
17
+ ```tsx
18
+ import React, { useState } from 'react';
19
+ import { Drawer } from '@xsolla/xui-b2b-drawer';
20
+ import { Button } from '@xsolla/xui-button';
21
+ import { Typography } from '@xsolla/xui-typography';
22
+
23
+ export default function BasicDrawer() {
24
+ const [open, setOpen] = useState(false);
25
+
26
+ return (
27
+ <>
28
+ <Button variant="primary" tone="brand" size="sm" onPress={() => setOpen(true)}>
29
+ Open Drawer
30
+ </Button>
31
+ <Drawer
32
+ open={open}
33
+ onClose={() => setOpen(false)}
34
+ title="Settings"
35
+ footer={
36
+ <>
37
+ <Button variant="secondary" tone="mono" size="sm" onPress={() => setOpen(false)}>
38
+ Cancel
39
+ </Button>
40
+ <Button variant="primary" tone="brand" size="sm" onPress={() => setOpen(false)}>
41
+ Save
42
+ </Button>
43
+ </>
44
+ }
45
+ >
46
+ <Typography variant="bodyMd">Drawer body content goes here.</Typography>
47
+ </Drawer>
48
+ </>
49
+ );
50
+ }
51
+ ```
52
+
53
+ ### Size Variants
54
+
55
+ ```tsx
56
+ // sm = 480px, md = 620px (default), lg = 1056px
57
+ <Drawer open={open} onClose={onClose} title="Small" size="sm">{...}</Drawer>
58
+ <Drawer open={open} onClose={onClose} title="Medium" size="md">{...}</Drawer>
59
+ <Drawer open={open} onClose={onClose} title="Large" size="lg">{...}</Drawer>
60
+ ```
61
+
62
+ ### With Back Button
63
+
64
+ ```tsx
65
+ <Drawer
66
+ open={open}
67
+ onClose={onClose}
68
+ title="Step Details"
69
+ onBack={() => goToPreviousStep()}
70
+ >
71
+ {/* back arrow appears in the header */}
72
+ </Drawer>
73
+ ```
74
+
75
+ ### With Header Action
76
+
77
+ ```tsx
78
+ import { Button } from '@xsolla/xui-button';
79
+
80
+ <Drawer
81
+ open={open}
82
+ onClose={onClose}
83
+ title="User Profile"
84
+ headerAction={
85
+ <Button variant="ghost" tone="brand" size="sm">
86
+ View history
87
+ </Button>
88
+ }
89
+ >
90
+ {/* action renders between the title and the close button */}
91
+ </Drawer>
92
+ ```
93
+
94
+ ### With Stepper Sidebar
95
+
96
+ Use the `stepper` prop to render a `@xsolla/xui-b2b-stepper` alongside the content panel, creating a guided multi-step flow.
97
+
98
+ ```tsx
99
+ import React, { useState } from 'react';
100
+ import { Drawer } from '@xsolla/xui-b2b-drawer';
101
+ import { Stepper } from '@xsolla/xui-b2b-stepper';
102
+ import { Button } from '@xsolla/xui-button';
103
+ import { Typography } from '@xsolla/xui-typography';
104
+
105
+ const STEPS = [
106
+ { title: 'Account', description: 'Name and email' },
107
+ { title: 'Billing', description: 'Payment method' },
108
+ { title: 'Confirm', description: 'Review and submit' },
109
+ ];
110
+
111
+ export default function StepperDrawer() {
112
+ const [open, setOpen] = useState(false);
113
+ const [active, setActive] = useState(0);
114
+
115
+ const steps = STEPS.map((s, i) => ({
116
+ ...s,
117
+ state: i < active ? 'complete' as const : i === active ? 'current' as const : 'incomplete' as const,
118
+ }));
119
+
120
+ const isLast = active === steps.length - 1;
121
+
122
+ return (
123
+ <>
124
+ <Button variant="primary" tone="brand" size="sm" onPress={() => { setActive(0); setOpen(true); }}>
125
+ Open Wizard
126
+ </Button>
127
+ <Drawer
128
+ open={open}
129
+ onClose={() => setOpen(false)}
130
+ title={STEPS[active].title}
131
+ onBack={active > 0 ? () => setActive(a => a - 1) : undefined}
132
+ stepper={
133
+ <Stepper
134
+ steps={steps}
135
+ direction="vertical"
136
+ surface
137
+ onClick={({ number }) => setActive(number - 1)}
138
+ />
139
+ }
140
+ footer={
141
+ <>
142
+ <Button variant="secondary" tone="mono" size="sm" onPress={() => setOpen(false)}>
143
+ Cancel
144
+ </Button>
145
+ <Button
146
+ variant="primary"
147
+ tone="brand"
148
+ size="sm"
149
+ onPress={() => isLast ? setOpen(false) : setActive(a => a + 1)}
150
+ >
151
+ {isLast ? 'Submit' : 'Next'}
152
+ </Button>
153
+ </>
154
+ }
155
+ >
156
+ <Typography variant="bodyMd">Content for step {active + 1}.</Typography>
157
+ </Drawer>
158
+ </>
159
+ );
160
+ }
161
+ ```
162
+
163
+ ### Scrollable Content with Footer Shadow
164
+
165
+ ```tsx
166
+ <Drawer
167
+ open={open}
168
+ onClose={onClose}
169
+ title="Long Content"
170
+ footerShadow
171
+ footer={<Button variant="primary" tone="brand" size="sm">Done</Button>}
172
+ >
173
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
174
+ {Array.from({ length: 40 }, (_, i) => (
175
+ <Typography key={i} variant="bodyMd">Item {i + 1}</Typography>
176
+ ))}
177
+ </div>
178
+ </Drawer>
179
+ ```
180
+
181
+ ## API Reference
182
+
183
+ ### Drawer
184
+
185
+ | Prop | Type | Default | Description |
186
+ | :--- | :--- | :------ | :---------- |
187
+ | `open` | `boolean` | `false` | Whether the drawer is visible. |
188
+ | `onClose` | `() => void` | - | Called when the drawer should close (Escape key, overlay click, close button). |
189
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Width preset: sm=480px, md=620px, lg=1056px. |
190
+ | `title` | `ReactNode` | - | Title displayed in the header. |
191
+ | `onBack` | `() => void` | - | When provided, renders a back arrow button in the header. |
192
+ | `headerAction` | `ReactNode` | - | Optional element rendered between the title and the close button. |
193
+ | `closeOnOverlayClick` | `boolean` | `true` | Whether clicking the backdrop closes the drawer. |
194
+ | `closeOnEscape` | `boolean` | `true` | Whether pressing Escape closes the drawer. |
195
+ | `footer` | `ReactNode` | - | Footer content (typically action buttons). |
196
+ | `footerAlign` | `"center" \| "right"` | `"right"` | Alignment of footer content. |
197
+ | `footerShadow` | `boolean` | `false` | Show a drop shadow above the footer (useful with scrollable content). |
198
+ | `footerFullWidth` | `boolean` | `true` | Whether footer buttons stretch to full width. |
199
+ | `stepper` | `ReactNode` | - | Optional stepper sidebar rendered to the left of the content panel. |
200
+ | `children` | `ReactNode` | - | Main scrollable body content. |
201
+ | `initialFocusRef` | `RefObject<HTMLElement>` | - | Ref to the element that should receive focus when the drawer opens. |
202
+ | `themeMode` | `string` | - | Override the global theme mode for this component. |
203
+ | `themeProductContext` | `string` | - | Override the global product context for this component. |
204
+
205
+ **Deprecated props** (still accepted for backwards compatibility):
206
+
207
+ | Prop | Replacement |
208
+ | :--- | :---------- |
209
+ | `isOpen` | `open` |
210
+ | `header` | `title` + `onBack` |
211
+ | `bottom` | `footer` |
212
+
213
+ ## Behaviour
214
+
215
+ - Slides in from the right with an animated transition.
216
+ - Renders in a portal (z-index controlled by `theme.sizing.drawer().zIndex`) so it always appears above page content.
217
+ - Traps keyboard focus inside the drawer while open; restores focus to the previously active element on close.
218
+ - Body scroll is locked while the drawer is open on web.
219
+ - When `stepper` is provided, the panel widens to accommodate the sidebar to the left of the content area.
220
+
221
+ ## Accessibility
222
+
223
+ - `role="dialog"` and `aria-modal="true"` on the drawer panel.
224
+ - Header title is linked via `aria-labelledby`.
225
+ - Focus trap keeps Tab and Shift+Tab within the drawer.
226
+ - Escape key closes the drawer (unless `closeOnEscape={false}`).
227
+ - Close and back buttons have accessible labels.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsolla/xui-b2b-drawer",
3
- "version": "0.148.0",
3
+ "version": "0.148.2",
4
4
  "main": "./web/index.js",
5
5
  "module": "./web/index.mjs",
6
6
  "types": "./web/index.d.ts",
@@ -13,12 +13,12 @@
13
13
  "test:coverage": "vitest run --coverage"
14
14
  },
15
15
  "dependencies": {
16
- "@xsolla/xui-b2b-stepper": "0.148.0",
17
- "@xsolla/xui-button": "0.148.0",
18
- "@xsolla/xui-core": "0.148.0",
19
- "@xsolla/xui-icons-base": "0.148.0",
20
- "@xsolla/xui-primitives-core": "0.148.0",
21
- "@xsolla/xui-typography": "0.148.0"
16
+ "@xsolla/xui-b2b-stepper": "0.148.2",
17
+ "@xsolla/xui-button": "0.148.2",
18
+ "@xsolla/xui-core": "0.148.2",
19
+ "@xsolla/xui-icons-base": "0.148.2",
20
+ "@xsolla/xui-primitives-core": "0.148.2",
21
+ "@xsolla/xui-typography": "0.148.2"
22
22
  },
23
23
  "peerDependencies": {
24
24
  "react": ">=16.8.0",