toggle-group.tsx 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. 'use client';
  2. import * as React from 'react';
  3. import { Toggle as TogglePrimitive } from '@base-ui/react/toggle';
  4. import { ToggleGroup as ToggleGroupPrimitive } from '@base-ui/react/toggle-group';
  5. import { type VariantProps } from 'class-variance-authority';
  6. import { cn } from '@/lib/utils';
  7. import { toggleVariants } from '@/components/ui/toggle';
  8. const ToggleGroupContext = React.createContext<
  9. VariantProps<typeof toggleVariants> & {
  10. spacing?: number;
  11. orientation?: 'horizontal' | 'vertical';
  12. }
  13. >({
  14. size: 'default',
  15. variant: 'default',
  16. spacing: 2,
  17. orientation: 'horizontal',
  18. });
  19. function ToggleGroup({
  20. className,
  21. variant,
  22. size,
  23. spacing = 2,
  24. orientation = 'horizontal',
  25. children,
  26. ...props
  27. }: ToggleGroupPrimitive.Props &
  28. VariantProps<typeof toggleVariants> & {
  29. spacing?: number;
  30. orientation?: 'horizontal' | 'vertical';
  31. }) {
  32. return (
  33. <ToggleGroupPrimitive
  34. data-slot="toggle-group"
  35. data-variant={variant}
  36. data-size={size}
  37. data-spacing={spacing}
  38. data-orientation={orientation}
  39. style={{ '--gap': spacing } as React.CSSProperties}
  40. className={cn(
  41. 'rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] data-vertical:flex-col data-vertical:items-stretch',
  42. className,
  43. )}
  44. {...props}
  45. >
  46. <ToggleGroupContext.Provider
  47. value={{ variant, size, spacing, orientation }}
  48. >
  49. {children}
  50. </ToggleGroupContext.Provider>
  51. </ToggleGroupPrimitive>
  52. );
  53. }
  54. function ToggleGroupItem({
  55. className,
  56. children,
  57. variant = 'default',
  58. size = 'default',
  59. ...props
  60. }: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
  61. const context = React.useContext(ToggleGroupContext);
  62. return (
  63. <TogglePrimitive
  64. data-slot="toggle-group-item"
  65. data-variant={context.variant || variant}
  66. data-size={context.size || size}
  67. data-spacing={context.spacing}
  68. className={cn(
  69. 'group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg shrink-0 focus:z-10 focus-visible:z-10 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t',
  70. toggleVariants({
  71. variant: context.variant || variant,
  72. size: context.size || size,
  73. }),
  74. className,
  75. )}
  76. {...props}
  77. >
  78. {children}
  79. </TogglePrimitive>
  80. );
  81. }
  82. export { ToggleGroup, ToggleGroupItem };