Skip to content

SidePanel

Basic usage

tsx
import Button from '@semcore/ui/button';
import type { SidePanelProps } from '@semcore/ui/side-panel';
import SidePanel from '@semcore/ui/side-panel';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const Demo = (props: SidePanelProps) => {
  const [visible, setVisible] = React.useState(false);

  return (
    <React.Fragment>
      <Button onClick={() => setVisible(true)}>Show SidePanel</Button>
      <SidePanel
        visible={visible}
        onClose={() => setVisible(false)}
        aria-label='SidePanel example'
        placement={props.placement}
        closable={props.closable}
        disablePreventScroll={props.disablePreventScroll}
      >
        <SidePanel.Header>
          <SidePanel.Title mt={3}>SidePanel Title</SidePanel.Title>
        </SidePanel.Header>
        <SidePanel.Body>
          <Text size={300} tag='p'>
            SidePanel content
          </Text>
        </SidePanel.Body>
      </SidePanel>
    </React.Fragment>
  );
};

export const defaultProps: SidePanelProps = {
  placement: undefined,
  closable: undefined,
  disablePreventScroll: undefined,
};

Demo.defaultProps = defaultProps;

export default Demo;
tsx
import Button from '@semcore/ui/button';
import SidePanel from '@semcore/ui/side-panel';
import type { SidePanelProps } from '@semcore/ui/side-panel';
import React from 'react';

const Demo = (props: SidePanelProps) => {
  const [visible, setVisible] = React.useState(false);

  return (
    <>
      <Button onClick={() => setVisible(true)}>Show SidePanel</Button>
      <SidePanel
        visible={visible}
        onClose={() => setVisible(false)}
        aria-label='SidePanel example'
        placement={props.placement}
        closable={props.closable}
        disablePreventScroll={props.disablePreventScroll}
      >
        <SidePanel.Header h='64px'>
          <SidePanel.Back>Go to Tool Name</SidePanel.Back>
          <SidePanel.Title mt={3}>SidePanel title</SidePanel.Title>
        </SidePanel.Header>
        <SidePanel.Body>Content</SidePanel.Body>
        <SidePanel.Footer justifyContent='center' pt={2} h='80px'>
          <Button size='l' use='primary'>Got it!</Button>
          <Button size='l' ml={2}>Cancel</Button>
        </SidePanel.Footer>
      </SidePanel>
    </>
  );
};

export const defaultProps: SidePanelProps = {
  placement: undefined,
  closable: undefined,
  disablePreventScroll: undefined,
};

Demo.defaultProps = defaultProps;

export default Demo;

Advanced usage

You can access the internal components by expanding SidePanel for SidePanel.Overlay, SidePanel.Panel or SidePanel.Close.

tsx
import Button from '@semcore/ui/button';
import type { SidePanelProps } from '@semcore/ui/side-panel';
import SidePanel from '@semcore/ui/side-panel';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const Demo = (props: SidePanelProps) => {
  const [visible, setVisible] = React.useState(false);

  return (
    <React.Fragment>
      <Button onClick={() => setVisible(true)}>Show SidePanel</Button>
      <SidePanel
        closable={props.closable}
        visible={visible}
        aria-label='SidePanel example'
        onClose={() => setVisible(false)}
        placement={props.placement}
        disablePreventScroll={props.disablePreventScroll}
      >
        <SidePanel.Overlay>
          <SidePanel.Panel>
            <SidePanel.Header>
              <SidePanel.Title mt={3}>Taking the Stage</SidePanel.Title>
            </SidePanel.Header>
            <SidePanel.Body>
              <Text size={300} tag='p'>
                Trends and Strategies for 2024 and Beyond
              </Text>
              <Button size='l' mt={3}>Read more</Button>
            </SidePanel.Body>
          </SidePanel.Panel>
        </SidePanel.Overlay>
      </SidePanel>
    </React.Fragment>
  );
};

export const defaultProps: SidePanelProps = {
  placement: undefined,
  closable: false,
  disablePreventScroll: undefined,
};

Demo.defaultProps = defaultProps;

export default Demo;

Placement

The component is supplied with three positioning options.

tsx
import Button from '@semcore/ui/button';
import Select from '@semcore/ui/select';
import type { SidePanelPlacement } from '@semcore/ui/side-panel';
import SidePanel from '@semcore/ui/side-panel';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const placements: SidePanelPlacement[] = ['left', 'right', 'bottom'];

const Demo = () => {
  const [visible, setVisible] = React.useState(false);
  const [placement, setPlacement] = React.useState(placements[1]);

  return (
    <React.Fragment>
      <Text size={300} tag='div' mb={2}>
        <label htmlFor='select-placement'>Placement</label>
      </Text>
      <Select
        id='select-placement'
        value={placement}
        options={arrToOptions(placements)}
        onChange={setPlacement}
        size='l'
      />
      <Button onClick={() => setVisible(true)} use='primary' theme='success' size='l' ml={3}>
        Show SidePanel
      </Button>
      <SidePanel
        visible={visible}
        onClose={() => setVisible(false)}
        placement={placement}
        aria-label={`Here is a ${placement}-placed side panel`}
      >
        <Text size={300} tag='p'>
          SidePanel content
        </Text>
      </SidePanel>
    </React.Fragment>
  );
};

function arrToOptions(arr: any) {
  return arr.map((i: any) => ({ value: i, label: i, children: i }));
}

export default Demo;

Disabling overlay

By default, the component is rendered with an overlay, but you can change this by not passing it.

tsx
import Button from '@semcore/ui/button';
import type { SidePanelProps } from '@semcore/ui/side-panel';
import SidePanel from '@semcore/ui/side-panel';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const Demo = (props: SidePanelProps) => {
  const [visible, setVisible] = React.useState(false);

  return (
    <React.Fragment>
      <Button onClick={() => setVisible(true)}>Show SidePanel</Button>
      <SidePanel
        visible={visible}
        onClose={() => setVisible(false)}
        placement={props.placement}
        closable={props.closable}
        disablePreventScroll={props.disablePreventScroll}
      >
        <SidePanel.Panel aria-label='SidePanel example' mt={20}>
          <SidePanel.Header>
            <SidePanel.Title mt={3}>SidePanel Title</SidePanel.Title>
          </SidePanel.Header>
          <SidePanel.Body>
            <Text size={300} tag='p'>
              SidePanel content
            </Text>
          </SidePanel.Body>
        </SidePanel.Panel>
      </SidePanel>
    </React.Fragment>
  );
};

export const defaultProps: SidePanelProps = {
  placement: undefined,
  closable: undefined,
  disablePreventScroll: undefined,
};

Demo.defaultProps = defaultProps;

export default Demo;

Portals

By default, the component is rendered to the portal, at the bottom of the body. You can redefine this behavior with PortalProvider and disable it with disablePortal.

tsx
import Button from '@semcore/ui/button';
import SidePanel from '@semcore/ui/side-panel';
import { Text } from '@semcore/ui/typography';
import React from 'react';

const Demo = () => {
  const [visible, setVisible] = React.useState(false);

  return (
    <React.Fragment>
      <Button onClick={() => setVisible(true)}>Show SidePanel</Button>
      <SidePanel visible={visible} onClose={() => setVisible(false)} disablePortal>
        <SidePanel.Panel aria-label='Taking the stage' mt={20}>
          <SidePanel.Header>
            <SidePanel.Title mt={3}>SidePanel Title</SidePanel.Title>
          </SidePanel.Header>
          <SidePanel.Body>
            <Text size={300} tag='p'>
              SidePanel content
            </Text>
          </SidePanel.Body>
        </SidePanel.Panel>
      </SidePanel>
    </React.Fragment>
  );
};

export default Demo;

Iframe

We recommend not using this component inside an iframe. Instead, use modal window or dropdown.

Released under the MIT License.

Released under the MIT License.