Skip to content

Commit 6a00b0e

Browse files
authored
feat(components/SidePanel): import components via SidePanel.Header, SidePanel.Body, SidePanel.Footer
1 parent 6474c9f commit 6a00b0e

File tree

5 files changed

+83
-66
lines changed

5 files changed

+83
-66
lines changed

packages/components/src/components/SidePanel/SidePanel.mdx

+10-21
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@ SidePanel is a panel that slides out from the edges of the screen.
1717
It's often used for navigation, menus, or to display details about the page a user is on.
1818

1919
```tsx
20-
import {
21-
SidePanel,
22-
SidePanelHeader,
23-
SidePanelContent,
24-
SidePanelFooter,
25-
} from '@koobiq/react-components';
20+
import { SidePanel } from '@koobiq/react-components';
2621
```
2722

2823
<Story of={Stories.Base} />
@@ -35,9 +30,9 @@ import {
3530

3631
The component has the following helper components:
3732

38-
- `SidePanelHeader` — header of the side panel
39-
- `SidePanelContent`content area of the component for placing the main information
40-
- `SidePanelFooter` — footer of the component, can contain various actions.
33+
- `SidePanel.Header` — header of the side panel
34+
- `SidePanel.Body`body of the component for placing the main information
35+
- `SidePanel.Footer` — footer of the component, can contain various actions.
4136

4237
## Usage
4338

@@ -61,22 +56,16 @@ The `children` prop can be `ReactNode` or a render function with the `SidePanelP
6156
The render function can help pass a function to close the side panel.
6257

6358
```tsx
64-
import {
65-
Button,
66-
SidePanel,
67-
SidePanelHeader,
68-
SidePanelContent,
69-
SidePanelFooter,
70-
} from '@koobiq/react-components';
59+
import { Button, SidePanel } from '@koobiq/react-components';
7160

7261
<SidePanel control={(props) => <Button {...props}>Open</Button>}>
7362
{({ close }) => (
7463
<>
75-
<SidePanelHeader>Title</SidePanelHeader>
76-
<SidePanelContent>Content</SidePanelContent>
77-
<SidePanelFooter>
78-
<Button onClick={close}>Close</Button>
79-
</SidePanelFooter>
64+
<SidePanel.Header>Title</SidePanel.Header>
65+
<SidePanel.Body>Content</SidePanel.Body>
66+
<SidePanel.Footer>
67+
<Button onPress={close}>Close</Button>
68+
</SidePanel.Footer>
8069
</>
8170
)}
8271
</SidePanel>;

packages/components/src/components/SidePanel/SidePanel.stories.tsx

+32-33
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ import { Toggle } from '../Toggle';
77

88
import {
99
SidePanel,
10-
SidePanelContent,
11-
SidePanelFooter,
12-
SidePanelHeader,
1310
sidePanelPropPosition,
1411
type SidePanelProps,
1512
sidePanelPropSize,
@@ -18,7 +15,11 @@ import {
1815
const meta = {
1916
title: 'Components/SidePanel',
2017
component: SidePanel,
21-
subcomponents: { SidePanelHeader, SidePanelContent, SidePanelFooter },
18+
subcomponents: {
19+
'SidePanel.Header': SidePanel.Header,
20+
'SidePanel.Body': SidePanel.Body,
21+
'SidePanel.Footer': SidePanel.Footer,
22+
},
2223
parameters: {
2324
layout: 'centered',
2425
},
@@ -37,10 +38,10 @@ export const Base: Story = {
3738
>
3839
{({ close }) => (
3940
<>
40-
<SidePanelHeader>
41+
<SidePanel.Header>
4142
Web Security: Safeguarding the Digital World
42-
</SidePanelHeader>
43-
<SidePanelContent>
43+
</SidePanel.Header>
44+
<SidePanel.Body>
4445
<FlexBox gap="m" direction="column">
4546
<span>
4647
Web security is a crucial aspect of modern digital
@@ -87,13 +88,13 @@ export const Base: Story = {
8788
and data in an increasingly connected world.
8889
</span>
8990
</FlexBox>
90-
</SidePanelContent>
91-
<SidePanelFooter>
91+
</SidePanel.Body>
92+
<SidePanel.Footer>
9293
<Button onPress={close}>Ok</Button>
9394
<Button variant="fade-contrast-filled" onPress={close}>
9495
Cancel
9596
</Button>
96-
</SidePanelFooter>
97+
</SidePanel.Footer>
9798
</>
9899
)}
99100
</SidePanel>
@@ -114,13 +115,11 @@ export const Size: Story = {
114115
>
115116
{({ close }) => (
116117
<>
117-
<SidePanelHeader>I have a {size} size</SidePanelHeader>
118-
<SidePanelContent>
119-
But there&#39;s nothing to say…
120-
</SidePanelContent>
121-
<SidePanelFooter>
118+
<SidePanel.Header>I have a {size} size</SidePanel.Header>
119+
<SidePanel.Body>But there&#39;s nothing to say…</SidePanel.Body>
120+
<SidePanel.Footer>
122121
<Button onPress={close}>Ok</Button>
123-
</SidePanelFooter>
122+
</SidePanel.Footer>
124123
</>
125124
)}
126125
</SidePanel>
@@ -145,13 +144,13 @@ export const Position: Story = {
145144
>
146145
{({ close }) => (
147146
<>
148-
<SidePanelHeader>I have a {position} position</SidePanelHeader>
149-
<SidePanelContent>
150-
But there&#39;s nothing to say…
151-
</SidePanelContent>
152-
<SidePanelFooter>
147+
<SidePanel.Header>
148+
I have a {position} position
149+
</SidePanel.Header>
150+
<SidePanel.Body>But there&#39;s nothing to say…</SidePanel.Body>
151+
<SidePanel.Footer>
153152
<Button onPress={close}>Ok</Button>
154-
</SidePanelFooter>
153+
</SidePanel.Footer>
155154
</>
156155
)}
157156
</SidePanel>
@@ -170,10 +169,10 @@ export const ControlledOpen: Story = {
170169
<>
171170
<Button onPress={on}>Open</Button>
172171
<SidePanel open={open} size="small" onOpenChange={set} {...args}>
173-
<SidePanelHeader>
172+
<SidePanel.Header>
174173
Web Security: Safeguarding the Digital World
175-
</SidePanelHeader>
176-
<SidePanelContent>
174+
</SidePanel.Header>
175+
<SidePanel.Body>
177176
<FlexBox gap="m" direction="column">
178177
<span>
179178
Web security is a crucial aspect of modern digital
@@ -219,13 +218,13 @@ export const ControlledOpen: Story = {
219218
data in an increasingly connected world.
220219
</span>
221220
</FlexBox>
222-
</SidePanelContent>
223-
<SidePanelFooter>
221+
</SidePanel.Body>
222+
<SidePanel.Footer>
224223
<Button onPress={off}>Ok</Button>
225224
<Button variant="fade-contrast-filled" onPress={off}>
226225
Cancel
227226
</Button>
228-
</SidePanelFooter>
227+
</SidePanel.Footer>
229228
</SidePanel>
230229
</>
231230
);
@@ -254,8 +253,8 @@ export const Settings: Story = {
254253
>
255254
{({ close }) => (
256255
<>
257-
<SidePanelHeader>Adjust me</SidePanelHeader>
258-
<SidePanelContent>
256+
<SidePanel.Header>Adjust me</SidePanel.Header>
257+
<SidePanel.Body>
259258
<FlexBox gap="l" direction="column">
260259
<Toggle
261260
checked={hideBackdrop}
@@ -282,10 +281,10 @@ export const Settings: Story = {
282281
Disable the exit by pressing ESC key
283282
</Toggle>
284283
</FlexBox>
285-
</SidePanelContent>
286-
<SidePanelFooter>
284+
</SidePanel.Body>
285+
<SidePanel.Footer>
287286
<Button onPress={close}>Ok</Button>
288-
</SidePanelFooter>
287+
</SidePanel.Footer>
289288
</>
290289
)}
291290
</SidePanel>

packages/components/src/components/SidePanel/SidePanel.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ describe('SidePanel', () => {
135135

136136
test('should call the onOpenChange handler when clicked', async () => {
137137
const onOpenChange = vi.fn();
138-
const onClick = vi.fn();
138+
const onPress = vi.fn();
139139

140140
render(
141141
<SidePanel
@@ -145,7 +145,7 @@ describe('SidePanel', () => {
145145
slotProps: {
146146
'close-button': {
147147
'data-testid': 'close-button',
148-
onClick,
148+
onPress,
149149
},
150150
},
151151
},
@@ -160,7 +160,7 @@ describe('SidePanel', () => {
160160
await userEvent.click(closeButton);
161161

162162
expect(onOpenChange).toHaveBeenCalledTimes(1);
163-
expect(onClick).toHaveBeenCalledTimes(1);
163+
expect(onPress).toHaveBeenCalledTimes(1);
164164
});
165165
});
166166

packages/components/src/components/SidePanel/SidePanel.tsx

+21-3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@ import {
1212
import { Transition } from 'react-transition-group';
1313

1414
import { Backdrop } from '../Backdrop';
15-
import { Dialog, type DialogProps } from '../Dialog';
15+
import {
16+
Dialog,
17+
DialogContent,
18+
DialogFooter,
19+
DialogHeader,
20+
type DialogProps,
21+
} from '../Dialog';
1622

1723
import s from './SidePanel.module.css';
1824
import type { SidePanelProps, SidePanelRef } from './types';
1925

20-
export const SidePanel = forwardRef<SidePanelRef, SidePanelProps>(
26+
const SidePanelComponent = forwardRef<SidePanelRef, SidePanelProps>(
2127
(props, ref) => {
2228
const {
2329
size = 'medium',
@@ -148,4 +154,16 @@ export const SidePanel = forwardRef<SidePanelRef, SidePanelProps>(
148154
}
149155
);
150156

151-
SidePanel.displayName = 'SidePanel';
157+
SidePanelComponent.displayName = 'SidePanel';
158+
159+
type CompoundedComponent = typeof SidePanelComponent & {
160+
Header: typeof DialogHeader;
161+
Body: typeof DialogContent;
162+
Footer: typeof DialogFooter;
163+
};
164+
165+
export const SidePanel = SidePanelComponent as CompoundedComponent;
166+
167+
SidePanel.Header = DialogHeader;
168+
SidePanel.Body = DialogContent;
169+
SidePanel.Footer = DialogFooter;
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1+
import { DialogHeader, DialogFooter, DialogContent } from '../Dialog';
2+
13
export * from './SidePanel';
24
export * from './types';
3-
export { DialogHeader, DialogFooter, DialogContent } from '../Dialog';
45

5-
export {
6-
DialogHeader as SidePanelHeader,
7-
DialogContent as SidePanelContent,
8-
DialogFooter as SidePanelFooter,
9-
} from '../Dialog';
6+
/**
7+
* @deprecated
8+
* This component has been deprecated, please use `SidePanel.Header` instead.
9+
*/
10+
export const SidePanelHeader = DialogHeader;
11+
/**
12+
* @deprecated
13+
* This component has been deprecated, please use `SidePanel.Body` instead.
14+
*/
15+
export const SidePanelContent = DialogContent;
16+
/**
17+
* @deprecated
18+
* This component has been deprecated, please use `SidePanel.Footer` instead.
19+
*/
20+
export const SidePanelFooter = DialogFooter;

0 commit comments

Comments
 (0)