Skip to content

Commit

Permalink
Add Segment Group (#1017)
Browse files Browse the repository at this point in the history
Add Segment Group
  • Loading branch information
tszhong0411 authored Jan 30, 2025
2 parents 640f7f3 + bd30342 commit 7497b37
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 59 deletions.
5 changes: 5 additions & 0 deletions .changeset/swift-phones-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tszhong0411/ui': patch
---

Add Segment Group component
31 changes: 31 additions & 0 deletions apps/docs/src/app/ui/components/segment-group.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: Segment Group
description: Organizes and navigates between sections in a view.
link:
doc: https://ark-ui.com/react/docs/components/segment-group
api: https://ark-ui.com/react/docs/components/segment-group#api-reference
---

<ComponentPreview name='segment-group/segment-group' />

## Usage

```tsx
import { SegmentGroup, SegmentGroupItem } from '@tszhong0411/ui'
```

```tsx
<SegmentGroup>
<SegmentGroupItem value='Next.js'>Next.js</SegmentGroupItem>
</SegmentGroup>
```

## Examples

### Disabled

<ComponentPreview name='segment-group/disabled' />

### Vertical

<ComponentPreview name='segment-group/vertical' />
26 changes: 26 additions & 0 deletions apps/docs/src/components/demos/segment-group/disabled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { SegmentGroup, SegmentGroupItem } from '@tszhong0411/ui'

const frameworks = [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Svelte', value: 'svelte', disabled: true },
{ label: 'Vue', value: 'vue' }
]

const SegmentGroupDisabledDemo = () => {
return (
<SegmentGroup defaultValue='react'>
{frameworks.map((framework) => (
<SegmentGroupItem
key={framework.value}
value={framework.value}
disabled={framework.disabled}
>
{framework.label}
</SegmentGroupItem>
))}
</SegmentGroup>
)
}

export default SegmentGroupDisabledDemo
22 changes: 22 additions & 0 deletions apps/docs/src/components/demos/segment-group/segment-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { SegmentGroup, SegmentGroupItem } from '@tszhong0411/ui'

const frameworks = [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Svelte', value: 'svelte' },
{ label: 'Vue', value: 'vue' }
]

const SegmentGroupDemo = () => {
return (
<SegmentGroup defaultValue='react'>
{frameworks.map((framework) => (
<SegmentGroupItem key={framework.value} value={framework.value}>
{framework.label}
</SegmentGroupItem>
))}
</SegmentGroup>
)
}

export default SegmentGroupDemo
22 changes: 22 additions & 0 deletions apps/docs/src/components/demos/segment-group/vertical.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { SegmentGroup, SegmentGroupItem } from '@tszhong0411/ui'

const frameworks = [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Svelte', value: 'svelte' },
{ label: 'Vue', value: 'vue' }
]

const SegmentGroupVerticalDemo = () => {
return (
<SegmentGroup orientation='vertical' defaultValue='react'>
{frameworks.map((framework) => (
<SegmentGroupItem key={framework.value} value={framework.value}>
{framework.label}
</SegmentGroupItem>
))}
</SegmentGroup>
)
}

export default SegmentGroupVerticalDemo
4 changes: 4 additions & 0 deletions apps/docs/src/config/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ const COMPONENT_LINKS = [
href: '/ui/components/scroll-area',
text: 'Scroll Area'
},
{
href: '/ui/components/segment-group',
text: 'Segment Group'
},
{
href: '/ui/components/select',
text: 'Select'
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"preinstall": "npx --yes only-allow pnpm",
"lint": "turbo lint && eslint . --max-warnings 0",
"lint:fix": "turbo lint:fix && eslint --fix . && pnpm format:write && tsx scripts/fix-cspell.ts",
"prepare": "simple-git-hooks",
"prepare": "simple-git-hooks && pnpm build:packages",
"release": "changeset publish",
"test:e2e": "turbo test:e2e",
"test:e2e:inspector": "turbo test:e2e:inspector",
Expand Down Expand Up @@ -79,7 +79,7 @@
"prettier": "^3.4.2",
"simple-git-hooks": "^2.11.1",
"ts-morph": "^25.0.0",
"tsup": "8.3.6",
"tsup": "8.3.0",
"tsx": "^4.19.2",
"turbo": "^2.3.4",
"typescript": "5.7.3",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export * from './progress'
export * from './radio-group'
export * from './resizable'
export * from './scroll-area'
export * from './segment-group'
export * from './select'
export * from './separator'
export * from './sheet'
Expand All @@ -55,5 +56,4 @@ export * from './toggle-group'
export * from './tooltip'
export * from './tree-view'
export * from './visually-hidden'
// Ark UI
export { createListCollection, createTreeCollection } from '@ark-ui/react'
67 changes: 67 additions & 0 deletions packages/ui/src/segment-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { SegmentGroup as SegmentGroupPrimitive } from '@ark-ui/react'
import { cn } from '@tszhong0411/utils'

type SegmentGroupProps = React.ComponentProps<typeof SegmentGroupPrimitive.Root>

const SegmentGroup = (props: SegmentGroupProps) => {
const { className, children, orientation = 'horizontal', ...rest } = props

return (
<SegmentGroupPrimitive.Root
orientation={orientation}
className={cn(
'flex items-start',
orientation === 'horizontal' ? 'gap-4 border-b' : 'flex-col gap-1 border-l',
className
)}
{...rest}
>
<SegmentGroupIndicator />
{children}
</SegmentGroupPrimitive.Root>
)
}

type SegmentGroupIndicatorProps = React.ComponentProps<typeof SegmentGroupPrimitive.Indicator>

const SegmentGroupIndicator = (props: SegmentGroupIndicatorProps) => {
const { className, ...rest } = props

return (
<SegmentGroupPrimitive.Indicator
className={cn(
'border-foreground',
'data-[orientation=horizontal]:bottom-0 data-[orientation=horizontal]:w-[var(--width)] data-[orientation=horizontal]:translate-y-px data-[orientation=horizontal]:border-b-2',
'data-[orientation=vertical]:h-[var(--height)] data-[orientation=vertical]:-translate-x-px data-[orientation=vertical]:border-l-2',
className
)}
{...rest}
/>
)
}

type SegmentGroupItemProps = React.ComponentProps<typeof SegmentGroupPrimitive.Item>

const SegmentGroupItem = (props: SegmentGroupItemProps) => {
const { className, children, ...rest } = props

return (
<SegmentGroupPrimitive.Item
className={cn(
'text-muted-foreground hover:text-accent-foreground cursor-pointer font-medium transition-colors',
'data-[orientation=horizontal]:px-1 data-[orientation=horizontal]:pb-3',
'data-[orientation=vertical]:px-3 data-[orientation=vertical]:py-1.5',
'data-[state=checked]:text-foreground',
'data-[disabled]:text-muted-foreground data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',
className
)}
{...rest}
>
{children}
<SegmentGroupPrimitive.ItemControl />
<SegmentGroupPrimitive.ItemHiddenInput />
</SegmentGroupPrimitive.Item>
)
}

export { SegmentGroup, SegmentGroupIndicator, SegmentGroupItem }
Loading

0 comments on commit 7497b37

Please sign in to comment.