Skip to content
Sancho UI
Toggle dark mode
Getting started
Built with ☕ by
Ben McMahen

Tabs

Provide a tabbed interface, similar to that found in Material-UI.

Sancho exports the following components to create tabbed interfaces:

  • Tabs: The wrapper component for a number of Tab children.
  • Tab: An clickable tab item.
  • TabIcon: Use an icon as a tab.
  • TabPanel: Where an individual tab panel is rendered.
  • TabContent: An animated container for tab panels.

Basic usage

For accessibility purposes you should provide a unique id to each tab. That id should correspond to the id of the appropriate tab container. If the tabs extend beyond the viewport they will scroll horizontally.

function Example() {
  const [index, setIndex] = React.useState(0);

  return (
    <Tabs value={index} onChange={i => setIndex(i)}>
      <Tab id="you">For you</Tab>
      <Tab id="sports">Sports</Tab>
      <Tab id="entertainment">Entertainment</Tab>
      <Tab id="news">News</Tab>
      <Tab id="about">About</Tab>
    </Tabs>
  );
}

Sliding content

Sliding content is a nice option when working with smaller panels or mobile applications.

Twitter
What's up, you!
/** @jsx jsx */

function Example() {
  const [index, setIndex] = React.useState(0);
  const theme = useTheme();

  return (
    <Layer css={{ overflow: "hidden" }}>
      <DarkMode>
        {darkTheme => (
          <div css={{ background: darkTheme.colors.background.tint2 }}>
            <Toolbar css={{ paddingTop: theme.spaces.md }} compressed>
              <Text variant="h5">Twitter</Text>
            </Toolbar>

            <Tabs value={index} onChange={i => setIndex(i)}>
              <Tab id="you">For you</Tab>
              <Tab id="sports">Sports</Tab>
              <Tab id="entertainment">Entertainment</Tab>
              <Tab id="news">News</Tab>
              <Tab id="about">About</Tab>
            </Tabs>
          </div>
        )}
      </DarkMode>

      <Pager value={index} onRequestChange={i => setIndex(i)}>
        <TabPanel id="you" className="Tab-panel">
          <Text>What's up, you!</Text>
        </TabPanel>
        <TabPanel id="sports" className="Tab-panel">
          <Text>Sport is fun</Text>
        </TabPanel>
        <TabPanel id="entertainment" className="Tab-panel">
          <Text>We don't need no education</Text>
        </TabPanel>
        <TabPanel id="news" className="Tab-panel">
          <Text>No news is good news</Text>
        </TabPanel>
        <TabPanel id="fun" className="Tab-panel">
          <Text>About what?</Text>
        </TabPanel>
      </Pager>
    </Layer>
  );
}

With anchors

function Anchors() {
  const [index, setIndex] = React.useState(0);

  return (
    <div className="Tabs-example">
      <Tabs
        dark
        variant="evenly-spaced"
        value={index}
        onChange={i => setIndex(i)}
      >
        <Tab component="a" href="#yup">
          I will
        </Tab>
        <Tab component="a" href="#another">
          Take you places
        </Tab>
        <Tab component="a" href="#another">
          You ain't never
        </Tab>
        <Tab component="a" href="#another">
          Been
        </Tab>
      </Tabs>
    </div>
  );
}

Evenly spaced

The evenly-spaced variant is sometimes a nice option and works particularly well when utilizing icons. The tabs will scroll horizontally if overflowing.

Twitter
What's up, you!
/** @jsx jsx */

function Example() {
  const [index, setIndex] = React.useState(0);
  const theme = useTheme();

  return (
    <Layer css={{ overflow: "hidden" }}>
      <DarkMode>
        {darkTheme => (
          <div css={{ background: darkTheme.colors.palette.blue.base }}>
            <Toolbar css={{ paddingTop: theme.spaces.md }} compressed>
              <Text variant="h5">Twitter</Text>
            </Toolbar>

            <Tabs
              variant="evenly-spaced"
              value={index}
              onChange={i => setIndex(i)}
            >
              <Tab id="you">For you</Tab>
              <Tab id="sports">Sports</Tab>
              <Tab id="entertainment">Entertainment</Tab>
              <Tab id="news">News</Tab>
              <Tab id="about">About</Tab>
            </Tabs>
          </div>
        )}
      </DarkMode>

      <Pager value={index} onRequestChange={i => setIndex(i)}>
        <TabPanel id="you" className="Tab-panel">
          <Text>What's up, you!</Text>
        </TabPanel>
        <TabPanel id="sports" className="Tab-panel">
          <Text>Sport is fun</Text>
        </TabPanel>
        <TabPanel id="entertainment" className="Tab-panel">
          <Text>We don't need no education</Text>
        </TabPanel>
        <TabPanel id="news" className="Tab-panel">
          <Text>No news is good news</Text>
        </TabPanel>
        <TabPanel id="fun" className="Tab-panel">
          <Text>About what?</Text>
        </TabPanel>
      </Pager>
    </Layer>
  );
}

With icons

You can use the TabIcon component to create mobile style tab bars.

What's up, you!
/** @jsx jsx */

function Example() {
  const [index, setIndex] = React.useState(0);
  const theme = useTheme();

  return (
    <Layer css={{ maxWidth: "500px", margin: "0 auto", overflow: "hidden" }}>
      <Pager
        css={{ height: "200px" }}
        value={index}
        onRequestChange={i => setIndex(i)}
      >
        <TabPanel id="you" className="Tab-panel">
          <Text>What's up, you!</Text>
        </TabPanel>
        <TabPanel id="sports" className="Tab-panel">
          <Text>Sport is fun</Text>
        </TabPanel>
        <TabPanel id="entertainment" className="Tab-panel">
          <Text>We don't need no education</Text>
        </TabPanel>
        <TabPanel id="news" className="Tab-panel">
          <Text>No news is good news</Text>
        </TabPanel>
        <TabPanel id="fun" className="Tab-panel">
          <Text>About what?</Text>
        </TabPanel>
      </Pager>

      <DarkMode>
        {darkTheme => (
          <div css={{ background: darkTheme.colors.background.tint2 }}>
            <Tabs
              variant="evenly-spaced"
              value={index}
              slider={false}
              onChange={i => setIndex(i)}
            >
              <Tab>
                <TabIcon icon={<IconUmbrella />} label="Annotation" />
              </Tab>
              <Tab>
                <TabIcon icon={<IconTrash />} label="Chat" />
              </Tab>
              <Tab>
                <TabIcon icon={<IconArchive />} label="Box" />
              </Tab>
              <Tab>
                <TabIcon icon={<IconAperture />} label="Camera" />
              </Tab>
              <Tab>
                <TabIcon icon={<IconActivity />} label="Chart" />
              </Tab>
            </Tabs>
          </div>
        )}
      </DarkMode>
    </Layer>
  );
}

API

Tabs
value*number
The currently selected index
sliderboolean
Toggle slider visibiliby
variant"default" | "evenly-spaced"
Whether tabs should be left-aligned or justified
onChange*(value: number) => void
Change callback to control which tab is selected
children*ReactElement<TabProps, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)> | ... 14 more ... | (ReactElement<...>[] & ReactPortal)
Tab elements
animationConfigSpringConfig
spring animation configuration
Tab
children*ReactNode
The text content of the tab
onPressOnPressFunction
id*string
The id of the tab to be shared with TabContent
componentReactType<any>
badgeReactNode
An optional badge
refRef<HTMLButtonElement>
onParentSelect() => void
isActiveboolean
cssInterpolationWithTheme<any>
TabPanel
id*string
The id should correspond to the id given to the associated Tab
cssInterpolationWithTheme<any>
TabIcon
icon*ReactNode
label*string
sizeIconSizes