Skip to content

Commit a9bf088

Browse files
authored
feat(scraps): Add documentation for SlideOverPanel (#102993)
This component has a bunch of use, including via `GlobalDrawer` but no Scraps story! I'm about to do some work with it (supporting deferred rendering, and overspring padding) and it's a lot easier to do that in Scraps. This felt like the right time to lift this component up in the folder hierarchy, too, and convert to a named export. Does this component need any API changes or improvements before it's "official"? e.g., `collapsed` is awkward, passing `className` IMO is awkward, and so on All other feedback welcome
1 parent f63c9b4 commit a9bf088

File tree

8 files changed

+82
-7
lines changed

8 files changed

+82
-7
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {SlideOverPanel} from './slideOverPanel';
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: SlideOverPanel
3+
description: A multi-purpose panel that can be used to reveal more information in a UI without directing to another page.
4+
source: 'sentry/components/core/slideOverPanel'
5+
resources:
6+
js: https://github.com/getsentry/sentry/blob/master/static/app/components/slideOverPanel.tsx
7+
---
8+
9+
import * as Storybook from 'sentry/stories';
10+
11+
import {SlideOverPanelPlayground} from 'sentry/stories/playground/slideOverPanel';
12+
13+
import SlideOverDocumentation from '!!type-loader!@sentry/scraps/slideOverPanel';
14+
15+
export const documentation = SlideOverDocumentation;
16+
17+
The `SlideOverPanel` component is a panel that can appear on the right, left, or bottom of the page content to reveal more information. It's commonly used for UIs like the Widget Builder to open panels that provide more details or supplementary UIs.
18+
19+
<Storybook.Demo>
20+
<SlideOverPanelPlayground />
21+
</Storybook.Demo>
22+
23+
<br />
24+
25+
## Basic Usage
26+
27+
```jsx
28+
<Button onClick={() => setIsPanelOpen(true)}>Open Panel</Button>
29+
30+
<SlideOverPanel collapsed={!isPanelOpen} slidePosition="right">
31+
<Container border="primary" height="100%" padding="md">
32+
<Button onClick={() => setIsPanelOpen(false)}>Close Panel</Button>
33+
</Container>
34+
</SlideOverPanel>
35+
```
36+
37+
> [!NOTE]
38+
> To enable exit animations, you'll need to wrap `<SlideOverPanel />` in an `<AnimatePresence />` component, and render the panel conditionally (e.g., `{isPanelOpen &&}`) instead of using the `collapsed` prop.

static/app/components/slideOverPanel.tsx renamed to static/app/components/core/slideOverPanel/slideOverPanel.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,27 @@ const COLLAPSED_STYLES = {
2424

2525
type SlideOverPanelProps = {
2626
children: React.ReactNode;
27+
/**
28+
* Whether the panel is visible. In most cases it's better to conditionally render this component rather than use this prop, since it'll defer rendering the panel contents until they're needed.
29+
*/
2730
collapsed: boolean;
2831
ariaLabel?: string;
2932
className?: string;
3033
'data-test-id'?: string;
34+
/**
35+
* Callback that fires every time the panel opens.
36+
*/
3137
onOpen?: () => void;
3238
panelWidth?: string;
3339
ref?: React.Ref<HTMLDivElement>;
3440
slidePosition?: 'right' | 'bottom' | 'left';
41+
/**
42+
* A Framer Motion `Transition` object that specifies the transition properties that apply when the panel opens and closes.
43+
*/
3544
transitionProps?: Transition;
3645
};
3746

38-
export default SlideOverPanel;
39-
40-
function SlideOverPanel({
47+
export function SlideOverPanel({
4148
'data-test-id': testId,
4249
ariaLabel,
4350
collapsed,

static/app/components/globalDrawer/components.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import styled from '@emotion/styled';
33
import {mergeRefs} from '@react-aria/utils';
44
import type {Transition} from 'framer-motion';
55

6+
import {SlideOverPanel} from '@sentry/scraps/slideOverPanel';
7+
68
import {Button} from 'sentry/components/core/button';
79
import type {DrawerOptions} from 'sentry/components/globalDrawer';
8-
import SlideOverPanel from 'sentry/components/slideOverPanel';
910
import {IconClose} from 'sentry/icons/iconClose';
1011
import {t} from 'sentry/locale';
1112
import {space} from 'sentry/styles/space';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {Fragment, useState} from 'react';
2+
import {AnimatePresence} from 'framer-motion';
3+
4+
import {Button} from '@sentry/scraps/button';
5+
import {Container} from '@sentry/scraps/layout';
6+
import {SlideOverPanel} from '@sentry/scraps/slideOverPanel';
7+
8+
export function SlideOverPanelPlayground() {
9+
const [isPanelOpen, setIsPanelOpen] = useState<boolean>(false);
10+
11+
return (
12+
<Fragment>
13+
<Button onClick={() => setIsPanelOpen(true)}>Open Panel</Button>
14+
15+
<AnimatePresence>
16+
{isPanelOpen && (
17+
<SlideOverPanel collapsed={false} slidePosition="right">
18+
<Container border="primary" height="100%" padding="md">
19+
<Button onClick={() => setIsPanelOpen(false)}>Close Panel</Button>
20+
</Container>
21+
</SlideOverPanel>
22+
)}
23+
</AnimatePresence>
24+
</Fragment>
25+
);
26+
}

static/app/views/dashboards/widgetBuilder/components/widgetBuilderSlideout.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import {useTheme} from '@emotion/react';
33
import styled from '@emotion/styled';
44
import isEqual from 'lodash/isEqual';
55

6+
import {SlideOverPanel} from '@sentry/scraps/slideOverPanel';
7+
68
import {Breadcrumbs} from 'sentry/components/breadcrumbs';
79
import {openConfirmModal} from 'sentry/components/confirm';
810
import {Alert} from 'sentry/components/core/alert';
911
import {Button} from 'sentry/components/core/button';
1012
import {ExternalLink, Link} from 'sentry/components/core/link';
1113
import ErrorBoundary from 'sentry/components/errorBoundary';
12-
import SlideOverPanel from 'sentry/components/slideOverPanel';
1314
import {IconClose} from 'sentry/icons';
1415
import {t, tctCode} from 'sentry/locale';
1516
import {space} from 'sentry/styles/space';

static/app/views/preprod/buildDetails/main/insights/appSizeInsightsSidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import {AnimatePresence, motion} from 'framer-motion';
44

55
import {Button} from '@sentry/scraps/button';
66
import {Flex} from '@sentry/scraps/layout';
7+
import {SlideOverPanel} from '@sentry/scraps/slideOverPanel';
78
import {Heading} from '@sentry/scraps/text/heading';
89

910
import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip';
10-
import SlideOverPanel from 'sentry/components/slideOverPanel';
1111
import {IconClose, IconGrabbable} from 'sentry/icons';
1212
import {t} from 'sentry/locale';
1313
import {useResizableDrawer} from 'sentry/utils/useResizableDrawer';

static/app/views/prevent/preventAI/manageReposPanel.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {Fragment} from 'react';
22

3+
import {SlideOverPanel} from '@sentry/scraps/slideOverPanel';
4+
35
import {Alert} from 'sentry/components/core/alert';
46
import {Button} from 'sentry/components/core/button';
57
import {CompactSelect} from 'sentry/components/core/compactSelect';
@@ -9,7 +11,6 @@ import {Switch} from 'sentry/components/core/switch';
911
import {Heading, Text} from 'sentry/components/core/text';
1012
import FieldGroup from 'sentry/components/forms/fieldGroup';
1113
import LoadingIndicator from 'sentry/components/loadingIndicator';
12-
import SlideOverPanel from 'sentry/components/slideOverPanel';
1314
import {IconClose} from 'sentry/icons';
1415
import {t, tct} from 'sentry/locale';
1516
import type {OrganizationIntegration, Repository} from 'sentry/types/integrations';

0 commit comments

Comments
 (0)