Skip to content

Instantly share code, notes, and snippets.

@KacperKozak
Created April 3, 2023 11:22
Show Gist options
  • Save KacperKozak/c792541997d6b832a131bfb0c47b94e7 to your computer and use it in GitHub Desktop.
Save KacperKozak/c792541997d6b832a131bfb0c47b94e7 to your computer and use it in GitHub Desktop.
React tabs
import React, { ReactNode } from 'react'
export interface TabProps {
name: string
isActive?: boolean
children: ReactNode
}
export const Tab = ({ children }: TabProps) => <>{children}</>
import { Box } from '+components/base/Box'
import { Clickable } from '+components/base/Clickable'
import styled from '@emotion/styled'
import React, { Children, ReactElement, useState } from 'react'
import { TabProps } from './Tab'
interface TabsProps {
children: ReactElement<TabProps>[] | ReactElement<TabProps>
}
export const Tabs = ({ children }: TabsProps) => {
const items = Children.toArray(children) as ReactElement<TabProps>[]
const currentIndex = items.findIndex((el) => el.props.isActive)
const [active, setActive] = useState(currentIndex > 0 ? currentIndex : 0)
const activeItem = items[active]
return (
<Box>
<Nav>
{items.map((el, index) => (
<button
key={index}
onClick={() => setActive(index)}
color={index === active ? 'brand' : 'text'}
fontWeight={index === active ? 'bold' : 'normal'}
p={2}
borderBottomWidth={2}
borderBottomColor={index === active ? 'brand' : 'border'}
borderBottomStyle="solid"
>
{el.props.name}
</button>
))}
</Nav>
<Box pt={3}>{activeItem && <activeItem.type {...activeItem.props} />}</Box>
</Box>
)
}
const Nav = styled.div({
position: 'relative',
display: 'grid',
gridAutoColumns: '1fr',
gridAutoFlow: 'column',
})
const NavItem = styled(Clickable)({
display: 'block',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment