@sixthshift/design-system 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +222 -0
  3. package/dist/styles.css +2 -0
  4. package/dist/theme.generated.css +438 -0
  5. package/package.json +238 -0
  6. package/src/components/Avatar/Avatar.tsx +19 -0
  7. package/src/components/Avatar/index.ts +1 -0
  8. package/src/components/Badge/Badge.tsx +59 -0
  9. package/src/components/Badge/index.ts +1 -0
  10. package/src/components/BarChart/BarChart.tsx +51 -0
  11. package/src/components/BarChart/index.ts +1 -0
  12. package/src/components/Breadcrumb/Breadcrumb.tsx +47 -0
  13. package/src/components/Breadcrumb/index.ts +5 -0
  14. package/src/components/Button/Button.tsx +157 -0
  15. package/src/components/Button/index.ts +1 -0
  16. package/src/components/Calendar/Calendar.tsx +433 -0
  17. package/src/components/Calendar/calendar.hooks.ts +329 -0
  18. package/src/components/Calendar/calendar.types.ts +117 -0
  19. package/src/components/Calendar/index.ts +28 -0
  20. package/src/components/Card/Card.tsx +47 -0
  21. package/src/components/Card/index.ts +1 -0
  22. package/src/components/Checkbox/Checkbox.tsx +144 -0
  23. package/src/components/Checkbox/index.ts +1 -0
  24. package/src/components/CheckboxGroup/CheckboxGroup.tsx +173 -0
  25. package/src/components/CheckboxGroup/index.ts +5 -0
  26. package/src/components/Code/Editor/Editor.tsx +161 -0
  27. package/src/components/Code/Editor/index.ts +2 -0
  28. package/src/components/Code/Editor/semanticTokenProvider.ts +69 -0
  29. package/src/components/Code/Editor/themes.ts +112 -0
  30. package/src/components/Code/ValidationStatus/ValidationStatus.tsx +81 -0
  31. package/src/components/Code/ValidationStatus/index.ts +1 -0
  32. package/src/components/Code/Workspace/StatusBar.tsx +47 -0
  33. package/src/components/Code/Workspace/Toolbar.tsx +47 -0
  34. package/src/components/Code/Workspace/Workspace.tsx +109 -0
  35. package/src/components/Code/Workspace/index.ts +3 -0
  36. package/src/components/ColorDot/ColorDot.tsx +50 -0
  37. package/src/components/ColorDot/index.ts +1 -0
  38. package/src/components/DatePicker/DatePicker.tsx +236 -0
  39. package/src/components/DatePicker/datepicker.hooks.ts +381 -0
  40. package/src/components/DatePicker/datepicker.types.ts +140 -0
  41. package/src/components/DatePicker/index.ts +12 -0
  42. package/src/components/DateRangePicker/DateRangePicker.tsx +127 -0
  43. package/src/components/DateRangePicker/daterangepicker.types.ts +53 -0
  44. package/src/components/DateRangePicker/index.ts +2 -0
  45. package/src/components/DateTimePicker/DateTimePicker.tsx +399 -0
  46. package/src/components/DateTimePicker/datetimepicker.types.ts +48 -0
  47. package/src/components/DateTimePicker/index.ts +2 -0
  48. package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +679 -0
  49. package/src/components/DateTimeRangePicker/datetimerangepicker.types.ts +62 -0
  50. package/src/components/DateTimeRangePicker/index.ts +2 -0
  51. package/src/components/EmptyState/EmptyState.tsx +29 -0
  52. package/src/components/EmptyState/index.ts +1 -0
  53. package/src/components/Field/Field.tsx +60 -0
  54. package/src/components/Field/index.ts +1 -0
  55. package/src/components/FormField/FormField.tsx +55 -0
  56. package/src/components/FormField/index.ts +2 -0
  57. package/src/components/HeatMap/HeatMapCalendar.tsx +127 -0
  58. package/src/components/HeatMap/HeatMapMatrix.tsx +75 -0
  59. package/src/components/HeatMap/heat-map.utils.ts +15 -0
  60. package/src/components/HeatMap/index.ts +3 -0
  61. package/src/components/HoverCard/HoverCard.tsx +83 -0
  62. package/src/components/HoverCard/components/HoverCardContent.tsx +30 -0
  63. package/src/components/HoverCard/components/HoverCardContext.tsx +22 -0
  64. package/src/components/HoverCard/components/HoverCardTrigger.tsx +32 -0
  65. package/src/components/HoverCard/index.ts +3 -0
  66. package/src/components/Input/Input.tsx +48 -0
  67. package/src/components/Input/index.ts +1 -0
  68. package/src/components/LineChart/LineChart.tsx +251 -0
  69. package/src/components/LineChart/index.ts +1 -0
  70. package/src/components/Markdown/Markdown.tsx +40 -0
  71. package/src/components/Markdown/index.ts +1 -0
  72. package/src/components/Message/Message.tsx +59 -0
  73. package/src/components/Message/components/MessageBody.tsx +9 -0
  74. package/src/components/Message/components/MessageDescription.tsx +9 -0
  75. package/src/components/Message/components/MessageIcon.tsx +13 -0
  76. package/src/components/Message/components/MessageTitle.tsx +9 -0
  77. package/src/components/Message/index.ts +10 -0
  78. package/src/components/MetricList/MetricList.tsx +13 -0
  79. package/src/components/MetricList/MetricRow.tsx +30 -0
  80. package/src/components/MetricList/index.ts +2 -0
  81. package/src/components/Modal/Modal.tsx +146 -0
  82. package/src/components/Modal/components/ModalBody.tsx +9 -0
  83. package/src/components/Modal/components/ModalContext.tsx +27 -0
  84. package/src/components/Modal/components/ModalFooter.tsx +9 -0
  85. package/src/components/Modal/components/ModalHeader.tsx +29 -0
  86. package/src/components/Modal/components/index.ts +9 -0
  87. package/src/components/Modal/index.ts +13 -0
  88. package/src/components/NavBottom/NavBottom.tsx +53 -0
  89. package/src/components/NavBottom/index.ts +3 -0
  90. package/src/components/NavSide/NavItem.tsx +39 -0
  91. package/src/components/NavSide/NavSide.tsx +40 -0
  92. package/src/components/NavSide/index.ts +2 -0
  93. package/src/components/NavSide/types.ts +36 -0
  94. package/src/components/Pagination/Pagination.tsx +86 -0
  95. package/src/components/Pagination/index.ts +2 -0
  96. package/src/components/Popover/Popover.tsx +68 -0
  97. package/src/components/Popover/components/PopoverBody.tsx +32 -0
  98. package/src/components/Popover/components/PopoverClose.tsx +26 -0
  99. package/src/components/Popover/components/PopoverContext.tsx +24 -0
  100. package/src/components/Popover/components/PopoverTrigger.tsx +31 -0
  101. package/src/components/Popover/index.ts +10 -0
  102. package/src/components/ProgressBar/ProgressBar.tsx +42 -0
  103. package/src/components/ProgressBar/index.ts +1 -0
  104. package/src/components/RadioButton/RadioButton.tsx +89 -0
  105. package/src/components/RadioButton/index.ts +1 -0
  106. package/src/components/RadioButtonGroup/RadioButtonGroup.tsx +193 -0
  107. package/src/components/RadioButtonGroup/index.ts +5 -0
  108. package/src/components/SearchInput/SearchInput.tsx +45 -0
  109. package/src/components/SearchInput/index.ts +2 -0
  110. package/src/components/Select/Select.tsx +289 -0
  111. package/src/components/Select/SelectDropdown.tsx +90 -0
  112. package/src/components/Select/SelectTrigger.tsx +130 -0
  113. package/src/components/Select/index.ts +3 -0
  114. package/src/components/Select/useSelectKeyboard.ts +111 -0
  115. package/src/components/Separator/Separator.tsx +20 -0
  116. package/src/components/Separator/index.ts +1 -0
  117. package/src/components/Sheet/Sheet.tsx +136 -0
  118. package/src/components/Sheet/components/SheetBody.tsx +9 -0
  119. package/src/components/Sheet/components/SheetContext.tsx +23 -0
  120. package/src/components/Sheet/components/SheetFooter.tsx +9 -0
  121. package/src/components/Sheet/components/SheetHeader.tsx +29 -0
  122. package/src/components/Sheet/components/index.ts +9 -0
  123. package/src/components/Sheet/index.ts +13 -0
  124. package/src/components/Skeleton/Skeleton.tsx +7 -0
  125. package/src/components/Skeleton/index.ts +1 -0
  126. package/src/components/Sparkline/Sparkline.tsx +93 -0
  127. package/src/components/Sparkline/index.ts +1 -0
  128. package/src/components/Spinner/Spinner.tsx +41 -0
  129. package/src/components/Spinner/index.ts +1 -0
  130. package/src/components/StatsCard/StatsCard.tsx +40 -0
  131. package/src/components/StatsCard/index.ts +1 -0
  132. package/src/components/Switch/Switch.tsx +128 -0
  133. package/src/components/Switch/index.ts +1 -0
  134. package/src/components/Tabs/Tabs.tsx +49 -0
  135. package/src/components/Tabs/components/TabsContext.tsx +35 -0
  136. package/src/components/Tabs/components/TabsList.tsx +98 -0
  137. package/src/components/Tabs/components/TabsPanels.tsx +26 -0
  138. package/src/components/Tabs/components/TabsTrigger.tsx +69 -0
  139. package/src/components/Tabs/index.ts +3 -0
  140. package/src/components/TagChip/TagChip.tsx +46 -0
  141. package/src/components/TagChip/index.ts +1 -0
  142. package/src/components/TagInput/TagInput.tsx +60 -0
  143. package/src/components/TagInput/index.ts +1 -0
  144. package/src/components/Text/Text.tsx +35 -0
  145. package/src/components/Text/index.ts +1 -0
  146. package/src/components/TextInline/TextInline.tsx +35 -0
  147. package/src/components/TextInline/index.ts +1 -0
  148. package/src/components/Textarea/Textarea.tsx +20 -0
  149. package/src/components/Textarea/index.ts +1 -0
  150. package/src/components/TimePicker/PeriodSelector.tsx +28 -0
  151. package/src/components/TimePicker/TimeColumn.tsx +62 -0
  152. package/src/components/TimePicker/TimePicker.tsx +323 -0
  153. package/src/components/TimePicker/index.ts +7 -0
  154. package/src/components/TimePicker/timepicker.hooks.ts +173 -0
  155. package/src/components/TimePicker/timepicker.types.ts +101 -0
  156. package/src/components/Toast/Toast.tsx +111 -0
  157. package/src/components/Toast/index.ts +1 -0
  158. package/src/components/Toggle/Toggle.tsx +72 -0
  159. package/src/components/Toggle/index.ts +1 -0
  160. package/src/components/ToggleGroup/ToggleGroup.tsx +14 -0
  161. package/src/components/ToggleGroup/ToggleGroupContainer.tsx +19 -0
  162. package/src/components/ToggleGroup/ToggleGroupItem.tsx +51 -0
  163. package/src/components/ToggleGroup/ToggleGroupMultiple.tsx +61 -0
  164. package/src/components/ToggleGroup/ToggleGroupSingle.tsx +105 -0
  165. package/src/components/ToggleGroup/index.ts +2 -0
  166. package/src/components/ToggleGroup/toggleGroup.types.ts +55 -0
  167. package/src/components/Tooltip/Tooltip.tsx +66 -0
  168. package/src/components/Tooltip/components/TooltipBody.tsx +30 -0
  169. package/src/components/Tooltip/components/TooltipContext.tsx +22 -0
  170. package/src/components/Tooltip/components/TooltipTrigger.tsx +27 -0
  171. package/src/components/Tooltip/index.ts +9 -0
  172. package/src/date-time/arithmetic.ts +101 -0
  173. package/src/date-time/boundaries.ts +91 -0
  174. package/src/date-time/compare.ts +85 -0
  175. package/src/date-time/duration.ts +63 -0
  176. package/src/date-time/elapsed.ts +18 -0
  177. package/src/date-time/format.ts +722 -0
  178. package/src/date-time/index.ts +279 -0
  179. package/src/date-time/now.ts +70 -0
  180. package/src/date-time/parse.ts +170 -0
  181. package/src/date-time/serialize.ts +90 -0
  182. package/src/date-time/timezone.ts +47 -0
  183. package/src/date-time/validate.ts +278 -0
  184. package/src/hooks/index.ts +10 -0
  185. package/src/hooks/useCollapsible.ts +16 -0
  186. package/src/hooks/useControllableState.ts +54 -0
  187. package/src/hooks/useDebouncedCallback.ts +21 -0
  188. package/src/hooks/useDebouncedState.ts +20 -0
  189. package/src/hooks/useDeviceFormFactor.ts +49 -0
  190. package/src/hooks/useLocalStorage.ts +67 -0
  191. package/src/hooks/useMergedFloatingRef.ts +29 -0
  192. package/src/hooks/usePresence.ts +127 -0
  193. package/src/hooks/useStack.ts +99 -0
  194. package/src/hooks/useTheme.ts +105 -0
  195. package/src/internal/Slot.tsx +79 -0
  196. package/src/internal/index.ts +2 -0
  197. package/src/internal/rovingFocus.ts +39 -0
  198. package/src/internal/types.ts +10 -0
  199. package/src/lib/EmptyBoundary.tsx +12 -0
  200. package/src/lib/ErrorBoundary.tsx +48 -0
  201. package/src/lib/contexts/ComponentsContext/ComponentsContext.tsx +34 -0
  202. package/src/lib/contexts/ComponentsContext/index.ts +1 -0
  203. package/src/lib/contexts/OverlayContext/OverlayContext.tsx +93 -0
  204. package/src/lib/contexts/OverlayContext/hooks/useModal.tsx +125 -0
  205. package/src/lib/contexts/OverlayContext/hooks/useToast.ts +80 -0
  206. package/src/lib/contexts/OverlayContext/index.ts +6 -0
  207. package/src/lib/format.ts +51 -0
  208. package/src/lib/utils.ts +10 -0
  209. package/src/lib/withEmpty.tsx +14 -0
  210. package/src/lib/withErrorBoundary.tsx +16 -0
  211. package/src/lib/withSuspense.tsx +16 -0
  212. package/src/lib/withSuspenseAndErrorBoundary.tsx +26 -0
  213. package/src/styles/base.css +41 -0
  214. package/src/theme/index.ts +37 -0
  215. package/src/theme/palette.json +100 -0
  216. package/src/theme/palette.schema.json +40 -0
  217. package/src/theme/schema.ts +122 -0
  218. package/src/theme/theme.json +349 -0
  219. package/src/theme/theme.schema.json +876 -0
  220. package/src/theme/typography.json +7 -0
  221. package/src/theme/typography.schema.json +36 -0
  222. package/src/typography/Body.tsx +8 -0
  223. package/src/typography/Caption.tsx +8 -0
  224. package/src/typography/Code.tsx +8 -0
  225. package/src/typography/Display.tsx +8 -0
  226. package/src/typography/Emphasis.tsx +8 -0
  227. package/src/typography/Heading.tsx +23 -0
  228. package/src/typography/Label.tsx +10 -0
  229. package/src/typography/Lead.tsx +8 -0
  230. package/src/typography/Mono.tsx +8 -0
  231. package/src/typography/Muted.tsx +8 -0
  232. package/src/typography/SectionTitle.tsx +8 -0
  233. package/src/typography/Subtitle.tsx +8 -0
  234. package/src/typography/Timestamp.tsx +8 -0
  235. package/src/typography/index.ts +10 -0
  236. package/tailwind.config.ts +261 -0
@@ -0,0 +1,19 @@
1
+ import { cn } from "@sixthshift/design-system/utils";
2
+ import * as React from "react";
3
+
4
+ const Avatar = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(({ className, ...props }, ref) => (
5
+ <span ref={ref} className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)} {...props} />
6
+ ));
7
+ Avatar.displayName = "Avatar";
8
+
9
+ const AvatarImage = React.forwardRef<HTMLImageElement, React.ImgHTMLAttributes<HTMLImageElement>>(({ className, alt, ...props }, ref) => (
10
+ <img ref={ref} alt={alt} className={cn("aspect-square h-full w-full", className)} {...props} />
11
+ ));
12
+ AvatarImage.displayName = "AvatarImage";
13
+
14
+ const AvatarFallback = React.forwardRef<HTMLSpanElement, React.HTMLAttributes<HTMLSpanElement>>(({ className, ...props }, ref) => (
15
+ <span ref={ref} className={cn("flex h-full w-full items-center justify-center rounded-full bg-bg-subtle font-medium text-sm", className)} {...props} />
16
+ ));
17
+ AvatarFallback.displayName = "AvatarFallback";
18
+
19
+ export { Avatar, AvatarFallback, AvatarImage };
@@ -0,0 +1 @@
1
+ export { Avatar, AvatarFallback, AvatarImage } from "./Avatar";
@@ -0,0 +1,59 @@
1
+ import { cn } from "@sixthshift/design-system/utils";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import type * as React from "react";
4
+
5
+ const badgeVariants = cva(
6
+ "inline-flex items-center rounded-md border px-2.5 py-0.5 font-semibold text-xs transition-colors focus:outline-hidden focus:ring-2 focus:ring-border-brand focus:ring-offset-2",
7
+ {
8
+ variants: {
9
+ variant: {
10
+ solid: "border-transparent shadow",
11
+ soft: "border-transparent",
12
+ outline: "",
13
+ },
14
+ intent: {
15
+ neutral: "",
16
+ primary: "",
17
+ danger: "",
18
+ success: "",
19
+ warning: "",
20
+ muted: "",
21
+ },
22
+ },
23
+ compoundVariants: [
24
+ // Solid variants
25
+ { variant: "solid", intent: "neutral", className: "bg-bg-strong text-fg-on-strong" },
26
+ { variant: "solid", intent: "primary", className: "bg-bg-brand text-fg-on-brand" },
27
+ { variant: "solid", intent: "danger", className: "bg-bg-danger text-fg-on-danger" },
28
+ { variant: "solid", intent: "success", className: "bg-bg-success text-fg-on-success" },
29
+ { variant: "solid", intent: "warning", className: "bg-bg-warning text-fg-on-warning" },
30
+ { variant: "solid", intent: "muted", className: "bg-bg-subtle text-fg-subtle" },
31
+ // Soft variants
32
+ { variant: "soft", intent: "neutral", className: "bg-bg-subtle text-fg-normal" },
33
+ { variant: "soft", intent: "primary", className: "bg-bg-brand-subtle text-fg-on-brand-subtle" },
34
+ { variant: "soft", intent: "danger", className: "bg-bg-danger-subtle text-fg-on-danger-subtle" },
35
+ { variant: "soft", intent: "success", className: "bg-bg-success-subtle text-fg-on-success-subtle" },
36
+ { variant: "soft", intent: "warning", className: "bg-bg-warning-subtle text-fg-on-warning-subtle" },
37
+ { variant: "soft", intent: "muted", className: "bg-bg-subtle text-fg-subtle" },
38
+ // Outline variants
39
+ { variant: "outline", intent: "neutral", className: "border-border-normal bg-bg-normal text-fg-normal" },
40
+ { variant: "outline", intent: "primary", className: "border-border-brand bg-bg-normal text-fg-brand" },
41
+ { variant: "outline", intent: "danger", className: "border-border-danger bg-bg-normal text-fg-danger" },
42
+ { variant: "outline", intent: "success", className: "border-border-success bg-bg-normal text-fg-success" },
43
+ { variant: "outline", intent: "warning", className: "border-border-warning bg-bg-normal text-fg-warning" },
44
+ { variant: "outline", intent: "muted", className: "border-border-normal bg-bg-normal text-fg-subtle" },
45
+ ],
46
+ defaultVariants: {
47
+ variant: "solid",
48
+ intent: "primary",
49
+ },
50
+ }
51
+ );
52
+
53
+ export type BadgeProps = React.HTMLAttributes<HTMLSpanElement> & VariantProps<typeof badgeVariants>;
54
+
55
+ export const Badge = ({ className, variant, intent, ...props }: BadgeProps) => {
56
+ return <span className={cn(badgeVariants({ variant, intent }), className)} {...props} />;
57
+ };
58
+
59
+ export { badgeVariants };
@@ -0,0 +1 @@
1
+ export { Badge, type BadgeProps, badgeVariants } from "./Badge";
@@ -0,0 +1,51 @@
1
+ import { cn } from "@sixthshift/design-system/utils";
2
+ import type * as React from "react";
3
+
4
+ export type BarChartItem = {
5
+ label: string;
6
+ value: number;
7
+ color?: string;
8
+ };
9
+
10
+ export type BarChartProps = React.HTMLAttributes<HTMLDivElement> & {
11
+ data: BarChartItem[];
12
+ showValues?: boolean;
13
+ maxValue?: number;
14
+ formatValue?: (value: number) => string;
15
+ barHeight?: number;
16
+ };
17
+
18
+ const DEFAULT_COLORS = ["var(--fg-brand)", "var(--fg-success)", "var(--fg-warning)", "var(--fg-danger)", "var(--fg-subtle)"];
19
+
20
+ export const BarChart = ({
21
+ data,
22
+ showValues = true,
23
+ maxValue: maxValueProp,
24
+ formatValue = (v) => String(v),
25
+ barHeight = 24,
26
+ className,
27
+ ...rest
28
+ }: BarChartProps) => {
29
+ const maxValue = maxValueProp ?? Math.max(...data.map((d) => d.value), 1);
30
+
31
+ return (
32
+ <div {...rest} className={cn("flex flex-col gap-2", className)}>
33
+ {data.map((item, i) => {
34
+ // Clamp both ends: a negative value would otherwise emit an invalid
35
+ // `width: -n%`, whose rendering is undefined.
36
+ const percent = Math.min(Math.max((item.value / maxValue) * 100, 0), 100);
37
+ const color = item.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length];
38
+
39
+ return (
40
+ <div key={item.label} className="flex items-center gap-3">
41
+ <span className="w-20 shrink-0 truncate text-right text-fg-subtle text-sm">{item.label}</span>
42
+ <div className="flex-1 overflow-hidden rounded-sm bg-bg-subtle" style={{ height: barHeight }}>
43
+ <div className="h-full rounded-sm transition-all duration-300" style={{ width: `${percent}%`, backgroundColor: color }} />
44
+ </div>
45
+ {showValues && <span className="w-12 shrink-0 text-right font-medium text-fg-normal text-sm">{formatValue(item.value)}</span>}
46
+ </div>
47
+ );
48
+ })}
49
+ </div>
50
+ );
51
+ };
@@ -0,0 +1 @@
1
+ export { BarChart, type BarChartItem, type BarChartProps } from "./BarChart";
@@ -0,0 +1,47 @@
1
+ import { useComponents } from "@sixthshift/design-system/components";
2
+ import { cn } from "@sixthshift/design-system/utils";
3
+ import { ChevronRight } from "lucide-react";
4
+ import { type ComponentPropsWithoutRef, forwardRef, type ReactNode } from "react";
5
+
6
+ export type BreadcrumbItem = {
7
+ label: ReactNode;
8
+ href?: string;
9
+ };
10
+
11
+ export type BreadcrumbProps = Omit<ComponentPropsWithoutRef<"nav">, "children"> & {
12
+ items: BreadcrumbItem[];
13
+ };
14
+
15
+ export const Breadcrumb = forwardRef<HTMLElement, BreadcrumbProps>(({ className, items, ...props }, ref) => {
16
+ const { Link } = useComponents();
17
+
18
+ if (items.length === 0) return null;
19
+
20
+ return (
21
+ <nav ref={ref} aria-label="breadcrumb" className={cn("", className)} {...props}>
22
+ <ol className="flex flex-wrap items-center gap-1.5 text-sm sm:gap-2.5">
23
+ {items.map((item, index) => {
24
+ const isLast = index === items.length - 1;
25
+ const isClickable = !isLast && item.href;
26
+
27
+ return (
28
+ // biome-ignore lint/suspicious/noArrayIndexKey: Breadcrumb path items maintain stable order
29
+ <li key={index} className="inline-flex items-center gap-1.5">
30
+ {isClickable ? (
31
+ <Link href={item.href!} className="text-fg-subtle transition-colors hover:text-fg-normal">
32
+ {item.label}
33
+ </Link>
34
+ ) : (
35
+ <span className={cn(isLast ? "font-medium text-fg-normal" : "text-fg-subtle")} aria-current={isLast ? "page" : undefined}>
36
+ {item.label}
37
+ </span>
38
+ )}
39
+ {!isLast && <ChevronRight className="size-3.5 text-fg-subtle" aria-hidden="true" />}
40
+ </li>
41
+ );
42
+ })}
43
+ </ol>
44
+ </nav>
45
+ );
46
+ });
47
+ Breadcrumb.displayName = "Breadcrumb";
@@ -0,0 +1,5 @@
1
+ export {
2
+ Breadcrumb,
3
+ type BreadcrumbItem,
4
+ type BreadcrumbProps,
5
+ } from "./Breadcrumb";
@@ -0,0 +1,157 @@
1
+ import { cn } from "@sixthshift/design-system/utils";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import * as React from "react";
4
+ import { Slot } from "../../internal/Slot";
5
+
6
+ const buttonVariants = cva(
7
+ "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ solid: "shadow",
12
+ outline: "border bg-bg-normal shadow-xs",
13
+ ghost: "",
14
+ link: "underline-offset-4 hover:underline",
15
+ },
16
+ intent: {
17
+ neutral: "",
18
+ danger: "",
19
+ success: "",
20
+ warning: "",
21
+ },
22
+ size: {
23
+ default: "h-9 px-4 py-2",
24
+ xs: "h-7 rounded-md px-2 text-xs",
25
+ sm: "h-8 rounded-md px-3 text-xs",
26
+ lg: "h-10 rounded-md px-8",
27
+ xl: "h-12 rounded-md px-10 text-base",
28
+ icon: "h-9 w-9",
29
+ },
30
+ },
31
+ compoundVariants: [
32
+ // Solid variants
33
+ {
34
+ variant: "solid",
35
+ intent: "neutral",
36
+ className: "bg-bg-brand text-fg-on-brand hover:bg-bg-brand-hovered active:bg-bg-brand-pressed",
37
+ },
38
+ {
39
+ variant: "solid",
40
+ intent: "danger",
41
+ className: "bg-bg-danger text-fg-on-danger hover:bg-bg-danger-hovered active:bg-bg-danger-pressed",
42
+ },
43
+ {
44
+ variant: "solid",
45
+ intent: "success",
46
+ className: "bg-bg-success text-fg-on-success hover:bg-bg-success-hovered active:bg-bg-success-pressed",
47
+ },
48
+ {
49
+ variant: "solid",
50
+ intent: "warning",
51
+ className: "bg-bg-warning text-fg-on-warning hover:bg-bg-warning-hovered active:bg-bg-warning-pressed",
52
+ },
53
+ // Outline variants
54
+ {
55
+ variant: "outline",
56
+ intent: "neutral",
57
+ className: "border-border-normal text-fg-normal hover:bg-bg-subtle-hovered active:bg-bg-subtle-pressed",
58
+ },
59
+ {
60
+ variant: "outline",
61
+ intent: "danger",
62
+ className: "border-border-danger text-fg-danger hover:bg-bg-danger-subtle-hovered active:bg-bg-danger-subtle-pressed",
63
+ },
64
+ {
65
+ variant: "outline",
66
+ intent: "success",
67
+ className: "border-border-success text-fg-success hover:bg-bg-success-subtle-hovered active:bg-bg-success-subtle-pressed",
68
+ },
69
+ {
70
+ variant: "outline",
71
+ intent: "warning",
72
+ className: "border-border-warning text-fg-warning hover:bg-bg-warning-subtle-hovered active:bg-bg-warning-subtle-pressed",
73
+ },
74
+ // Ghost variants
75
+ {
76
+ variant: "ghost",
77
+ intent: "neutral",
78
+ className: "text-fg-normal hover:bg-bg-subtle-hovered active:bg-bg-subtle-pressed",
79
+ },
80
+ {
81
+ variant: "ghost",
82
+ intent: "danger",
83
+ className: "text-fg-danger hover:bg-bg-danger-subtle-hovered active:bg-bg-danger-subtle-pressed",
84
+ },
85
+ {
86
+ variant: "ghost",
87
+ intent: "success",
88
+ className: "text-fg-success hover:bg-bg-success-subtle-hovered active:bg-bg-success-subtle-pressed",
89
+ },
90
+ {
91
+ variant: "ghost",
92
+ intent: "warning",
93
+ className: "text-fg-warning hover:bg-bg-warning-subtle-hovered active:bg-bg-warning-subtle-pressed",
94
+ },
95
+ // Link variants
96
+ {
97
+ variant: "link",
98
+ intent: "neutral",
99
+ className: "text-fg-brand",
100
+ },
101
+ {
102
+ variant: "link",
103
+ intent: "danger",
104
+ className: "text-fg-danger",
105
+ },
106
+ {
107
+ variant: "link",
108
+ intent: "success",
109
+ className: "text-fg-success",
110
+ },
111
+ {
112
+ variant: "link",
113
+ intent: "warning",
114
+ className: "text-fg-warning",
115
+ },
116
+ ],
117
+ defaultVariants: {
118
+ variant: "solid",
119
+ intent: "neutral",
120
+ size: "default",
121
+ },
122
+ }
123
+ );
124
+
125
+ export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
126
+ VariantProps<typeof buttonVariants> & {
127
+ asChild?: boolean;
128
+ loading?: boolean;
129
+ };
130
+
131
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
132
+ ({ className, variant, intent, size, asChild = false, loading = false, children, disabled, ...props }, ref) => {
133
+ const Comp = asChild ? Slot : "button";
134
+ return (
135
+ <Comp className={cn(buttonVariants({ variant, intent, size, className }))} ref={ref} disabled={disabled || loading} {...props}>
136
+ {loading ? (
137
+ <>
138
+ <svg className="animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true">
139
+ <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
140
+ <path
141
+ className="opacity-75"
142
+ fill="currentColor"
143
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
144
+ />
145
+ </svg>
146
+ {children}
147
+ </>
148
+ ) : (
149
+ children
150
+ )}
151
+ </Comp>
152
+ );
153
+ }
154
+ );
155
+ Button.displayName = "Button";
156
+
157
+ export { Button, buttonVariants };
@@ -0,0 +1 @@
1
+ export { Button, type ButtonProps, buttonVariants } from "./Button";