Skip to content

Commit

Permalink
feat: segmented control - toggle group implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Avinash Verma committed Dec 5, 2024
1 parent e2e052c commit a35772f
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 0 deletions.
13 changes: 13 additions & 0 deletions lib/src/components/segmented-control/SegmentedControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { SegmentedControlDescription } from './SegmentedControlDescription'
import { SegmentedControlHeading } from './SegmentedControlHeading'
import { SegmentedControlIcon } from './SegmentedControlIcon'
import { SegmentedControlItem } from './SegmentedControlItem'
import { SegmentedControlRoot } from './SegmentedControlRoot'

export const SegmentedControl = {
Root: SegmentedControlRoot,
Item: SegmentedControlItem,
Heading: SegmentedControlHeading,
Description: SegmentedControlDescription,
Icon: SegmentedControlIcon
}
43 changes: 43 additions & 0 deletions lib/src/components/segmented-control/SegmentedControlContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react'

import type { SegmentedControlRootProps } from './SegmentedControlRoot'

interface SegmentedControlContextValue {
size: SegmentedControlRootProps['size']
}

export interface SegmentedControlProviderProps
extends SegmentedControlContextValue {
children: React.ReactNode
}

const SegmentedControlContext =
React.createContext<SegmentedControlContextValue | null>(null)

export const SegmentedControlProvider = ({
size,
children
}: SegmentedControlProviderProps): JSX.Element => {
const value = React.useMemo<SegmentedControlContextValue>(
() => ({ size }),
[size]
)

return (
<SegmentedControlContext.Provider value={value}>
{children}
</SegmentedControlContext.Provider>
)
}

export const useSegmentedControl = (): SegmentedControlContextValue => {
const context = React.useContext(SegmentedControlContext)

if (!context) {
throw new Error(
'useSegmentedControlContext must be used within a SegmentedControlProvider'
)
}

return context
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as React from 'react'

import { styled } from '../../stitches'
import { Text } from '../text'
import { useSegmentedControl } from './SegmentedControlContext'

const StyledText = styled(Text, {
fontFamily: '$body',
color: '$textSubtle',
variants: {
size: {
sm: {
fontSize: '$xs'
},
md: {
fontSize: '$sm'
},
lg: {
fontSize: '$md'
}
}
}
})

export const SegmentedControlDescription = (
props: Omit<React.ComponentProps<typeof StyledText>, 'size'>
): JSX.Element => {
const { size } = useSegmentedControl()
return <StyledText {...props} size={size} />
}
31 changes: 31 additions & 0 deletions lib/src/components/segmented-control/SegmentedControlHeading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react'

import { styled } from '../../stitches'
import { Heading } from '../heading'
import { useSegmentedControl } from './SegmentedControlContext'

const StyledHeading = styled(Heading, {
fontFamily: '$body',
fontWeight: 600,
color: '$textBold',
variants: {
size: {
sm: {
fontSize: '$sm'
},
md: {
fontSize: '$md'
},
lg: {
fontSize: '$lg'
}
}
}
})

export const SegmentedControlHeading = (
props: Omit<React.ComponentProps<typeof StyledHeading>, 'size'>
): JSX.Element => {
const { size } = useSegmentedControl()
return <StyledHeading {...props} size={size} />
}
11 changes: 11 additions & 0 deletions lib/src/components/segmented-control/SegmentedControlIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react'

import { Icon } from '../icon'
import { useSegmentedControl } from './SegmentedControlContext'

export const SegmentedControlIcon = (
props: Omit<React.ComponentProps<typeof Icon>, 'size'>
): JSX.Element => {
const { size } = useSegmentedControl()
return <Icon {...props} size={size} />
}
58 changes: 58 additions & 0 deletions lib/src/components/segmented-control/SegmentedControlItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as React from 'react'

import { styled } from '../../stitches'
import { ToggleGroup } from '../toggle-group'
import { useSegmentedControl } from './SegmentedControlContext'

const StyledItem = styled(ToggleGroup.Item, {
bg: 'transparent',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
border: 'none',
borderRadius: '$2 !important',
boxShadow: 'none',
variants: {
size: {
sm: {
p: '$4 $24',
gap: '$3',
maxWidth: '203px'
},
md: {
p: '$24 $5',
gap: '$4',
maxWidth: '256px'
},
lg: {
p: '$24 $5',
gap: '$4',
maxWidth: '306px'
}
}
},
'&[data-state=on]': {
bg: 'white',
boxShadow: 'none'
},
'&:hover[data-state=off]': {
bg: '$primary300'
},
'$:focus': {
boxShadow: '$primary'
},
'&[disabled]': {
opacity: 0.3
},
'&:active': {
bg: '$primary100'
}
})

export const SegmentedControlItem = (
props: Omit<React.ComponentProps<typeof StyledItem>, 'size'>
): JSX.Element => {
const { size } = useSegmentedControl()

return <StyledItem {...props} size={size} />
}
45 changes: 45 additions & 0 deletions lib/src/components/segmented-control/SegmentedControlRoot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as React from 'react'

import { styled } from '../../stitches'
import { ToggleGroup } from '../toggle-group'
import { SegmentedControlProvider } from './SegmentedControlContext'

const StyledRoot = styled(ToggleGroup.Root, {
bg: '$primary200',
p: '$1',
borderRadius: '$3',
variants: {
size: {
sm: {},
md: {},
lg: {}
}
}
})

export type SegmentedControlRootProps = Omit<
React.ComponentProps<typeof StyledRoot>,
'gap' | 'type' | 'wrap'
>

export const SegmentedControlRoot = ({
size,
children,
...props
}: SegmentedControlRootProps): JSX.Element => {
return (
<SegmentedControlProvider size={size}>
<StyledRoot
{...props}
type="single"
wrap={false}
gap={null}
hasGap
size={size}
orientation="horizontal"
>
{children}
</StyledRoot>
</SegmentedControlProvider>
)
}
1 change: 1 addition & 0 deletions lib/src/components/segmented-control/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './SegmentedControl'

0 comments on commit a35772f

Please sign in to comment.