chore(ui): add button group component

This commit is contained in:
theborakompanioni 2026-01-10 11:44:27 +01:00
parent afb4b1e47b
commit 4a72ff6034
No known key found for this signature in database
GPG key ID: E8070AF0053AAC0D
2 changed files with 94 additions and 26 deletions

View file

@ -24,6 +24,7 @@ import { jamSettingsStore } from '@/store/jamSettingsStore'
import { jmSessionStore } from '@/store/jmSessionStore'
import { DevBadge } from '../dev/DevBadge'
import { Alert, AlertDescription } from '../ui/alert'
import { ButtonGroup } from '../ui/button-group'
import { Label } from '../ui/label'
import { OrderbookTable, type OrderTableEntry } from './OrderbookTable'
@ -276,40 +277,33 @@ export const OrderbookContent = ({ className }: OrderbookContentProps) => {
{/* TODO: replace manual dropdown with shadcn component */}
<div className="relative" ref={dropdownRef}>
<div className="flex">
<Button
variant="outline"
className="rounded-r-none"
size="sm"
onClick={handleReload}
disabled={isFetching}
>
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
{t('orderbook.button_reload_title')}
</Button>
<div className="relative">
<ButtonGroup>
<Button
variant="outline"
className="rounded-r-none"
size="sm"
onClick={handleReload}
disabled={isFetching}
>
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
{t('orderbook.button_reload_title')}
</Button>
<Button
variant="outline"
size="sm"
className="rounded-l-none border-l-0"
onClick={() => setShowRefreshDropdown(!showRefreshDropdown)}
disabled={isFetching}
>
<ChevronDownIcon />
</Button>
{showRefreshDropdown && (
<div className="bg-background absolute top-full right-0 z-100 mt-1 min-w-[200px] rounded-md border py-2 shadow-lg">
<Button
variant="ghost"
size="sm"
className="w-full justify-start rounded-none"
onClick={handleClearAndReload}
disabled={isFetching}
>
{t('orderbook.button_refresh_text')}
</Button>
</div>
)}
</div>
</ButtonGroup>
{showRefreshDropdown && (
<div className="bg-background absolute top-full right-0 z-100 mt-1 min-w-[200px] rounded-md border py-2 shadow-lg">
<Button variant="ghost" size="sm" onClick={handleClearAndReload} disabled={isFetching}>
{t('orderbook.button_refresh_text')}
</Button>
</div>
)}
</div>
</div>

View file

@ -0,0 +1,74 @@
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { Separator } from '@/components/ui/separator'
import { cn } from '@/lib/utils'
const buttonGroupVariants = cva(
"flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2",
{
variants: {
orientation: {
horizontal:
'[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none',
vertical:
'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none',
},
},
defaultVariants: {
orientation: 'horizontal',
},
},
)
function ButtonGroup({
className,
orientation,
...props
}: React.ComponentProps<'div'> & VariantProps<typeof buttonGroupVariants>) {
return (
<div
role="group"
data-slot="button-group"
data-orientation={orientation}
className={cn(buttonGroupVariants({ orientation }), className)}
{...props}
/>
)
}
function ButtonGroupText({
className,
asChild = false,
...props
}: React.ComponentProps<'div'> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : 'div'
return (
<Comp
className={cn(
"bg-muted flex items-center gap-2 rounded-md border px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
className,
)}
{...props}
/>
)
}
function ButtonGroupSeparator({
className,
orientation = 'vertical',
...props
}: React.ComponentProps<typeof Separator>) {
return (
<Separator
data-slot="button-group-separator"
orientation={orientation}
className={cn('bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto', className)}
{...props}
/>
)
}
export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText }