@usace/groundwork 1.0.2 → 1.0.4

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 (79) hide show
  1. package/dist/groundwork.es.js +5131 -0
  2. package/dist/groundwork.umd.js +30 -0
  3. package/dist/style.css +1 -0
  4. package/package.json +11 -3
  5. package/.eslintrc.cjs +0 -18
  6. package/.github/workflows/deploy-docs.yml +0 -59
  7. package/.github/workflows/publish.yml +0 -19
  8. package/index.html +0 -13
  9. package/lib/catalyst/alert.jsx +0 -110
  10. package/lib/catalyst/avatar.jsx +0 -64
  11. package/lib/catalyst/badge.jsx +0 -72
  12. package/lib/catalyst/checkbox.jsx +0 -160
  13. package/lib/catalyst/dialog.jsx +0 -101
  14. package/lib/catalyst/dropdown.jsx +0 -202
  15. package/lib/catalyst/fieldset.jsx +0 -87
  16. package/lib/catalyst/input.jsx +0 -78
  17. package/lib/catalyst/listbox.jsx +0 -195
  18. package/lib/catalyst/pagination.jsx +0 -75
  19. package/lib/catalyst/radio.jsx +0 -144
  20. package/lib/catalyst/select.jsx +0 -78
  21. package/lib/catalyst/switch.jsx +0 -203
  22. package/lib/catalyst/textarea.jsx +0 -59
  23. package/lib/components/breadcrumbs.jsx +0 -46
  24. package/lib/components/button.jsx +0 -219
  25. package/lib/components/display/headings.jsx +0 -39
  26. package/lib/components/display/text.jsx +0 -48
  27. package/lib/components/hero.jsx +0 -51
  28. package/lib/components/layout/container.jsx +0 -13
  29. package/lib/components/layout/usace-box.jsx +0 -26
  30. package/lib/components/link.jsx +0 -18
  31. package/lib/components/table.jsx +0 -146
  32. package/lib/composite/footer/essayons.jsx +0 -12
  33. package/lib/composite/footer/footer-links.jsx +0 -33
  34. package/lib/composite/footer/index.jsx +0 -148
  35. package/lib/composite/footer/logo-banner.jsx +0 -55
  36. package/lib/composite/footer/social-links.jsx +0 -60
  37. package/lib/composite/header/index.jsx +0 -83
  38. package/lib/composite/header/navbar-links.jsx +0 -113
  39. package/lib/composite/header/usa-banner/USABanner.jsx +0 -114
  40. package/lib/composite/header/usa-banner/usa-banner.css +0 -220
  41. package/lib/composite/site-wrapper/index.jsx +0 -52
  42. package/lib/index.jsx +0 -19
  43. package/postcss.config.js +0 -6
  44. package/public/Magnifying_glass_icon.svg +0 -5
  45. package/public/armystar-logo-rb.svg +0 -4
  46. package/public/cwbi-logo.png +0 -0
  47. package/public/essayonscrest.png +0 -0
  48. package/public/icon-dot-gov.svg +0 -1
  49. package/public/icon-https.svg +0 -1
  50. package/public/nww-lucky-peak-dam.jpg +0 -0
  51. package/public/rsgis-logo.png +0 -0
  52. package/public/us_flag_small.png +0 -0
  53. package/public/usace-logo-color.svg +0 -1
  54. package/src/App.jsx +0 -38
  55. package/src/app-bundles/index.js +0 -4
  56. package/src/app-bundles/route-bundle.js +0 -36
  57. package/src/app-components/code-example.jsx +0 -17
  58. package/src/app-components/copy-button.jsx +0 -32
  59. package/src/app-components/props-table.jsx +0 -43
  60. package/src/app-components/sub-site-banner.jsx +0 -15
  61. package/src/app-pages/documentation/_docs-page.jsx +0 -31
  62. package/src/app-pages/documentation/_docs-sidebar.jsx +0 -111
  63. package/src/app-pages/documentation/_template.jsx +0 -55
  64. package/src/app-pages/documentation/app-shell/index.jsx +0 -39
  65. package/src/app-pages/documentation/app-shell/site-wrapper.jsx +0 -190
  66. package/src/app-pages/documentation/buttons/index.jsx +0 -170
  67. package/src/app-pages/documentation/index.jsx +0 -57
  68. package/src/app-pages/documentation/layout/container.jsx +0 -68
  69. package/src/app-pages/documentation/layout/index.jsx +0 -52
  70. package/src/app-pages/documentation/layout/usace-box.jsx +0 -76
  71. package/src/app-pages/documentation/navigation/breadcrumbs.jsx +0 -119
  72. package/src/app-pages/documentation/navigation/index.jsx +0 -31
  73. package/src/app-pages/documentation/types/index.jsx +0 -31
  74. package/src/app-pages/documentation/types/link.jsx +0 -72
  75. package/src/app-pages/home.jsx +0 -71
  76. package/src/index.css +0 -3
  77. package/src/main.jsx +0 -18
  78. package/tailwind.config.js +0 -31
  79. package/vite.config.js +0 -46
@@ -1,195 +0,0 @@
1
- 'use client'
2
-
3
- import {
4
- Listbox as HeadlessListbox,
5
- ListboxButton as HeadlessListboxButton,
6
- ListboxOption as HeadlessListboxOption,
7
- ListboxOptions as HeadlessListboxOptions,
8
- ListboxSelectedOption as HeadlessListboxSelectedOption,
9
- Transition as HeadlessTransition,
10
- } from '@headlessui/react'
11
- import clsx from 'clsx'
12
- import { Fragment } from 'react'
13
-
14
- export function Listbox({ className, placeholder, autoFocus, 'aria-label': ariaLabel, children: options, ...props }) {
15
- return (
16
- <HeadlessListbox {...props} multiple={false}>
17
- <HeadlessListboxButton
18
- autoFocus={autoFocus}
19
- data-slot="control"
20
- aria-label={ariaLabel}
21
- className={clsx([
22
- className,
23
-
24
- // Basic layout
25
- 'group relative block w-full',
26
-
27
- // Background color + shadow applied to inset pseudo element, so shadow blends with border in light mode
28
- 'before:absolute before:inset-px before:rounded-[calc(theme(borderRadius.lg)-1px)] before:bg-white before:shadow',
29
-
30
- // Background color is moved to control and shadow is removed in dark mode so hide `before` pseudo
31
- 'dark:before:hidden',
32
-
33
- // Hide default focus styles
34
- 'focus:outline-none',
35
-
36
- // Focus ring
37
- 'after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-inset after:ring-transparent sm:after:data-[focus]:ring-2 sm:after:data-[focus]:ring-blue-500',
38
-
39
- // Disabled state
40
- 'data-[disabled]:opacity-50 before:data-[disabled]:bg-zinc-950/5 before:data-[disabled]:shadow-none',
41
- ])}
42
- >
43
- <HeadlessListboxSelectedOption
44
- as="span"
45
- options={options}
46
- placeholder={placeholder && <span className="block truncate text-zinc-500">{placeholder}</span>}
47
- className={clsx([
48
- // Basic layout
49
- 'relative block w-full appearance-none rounded-lg py-[calc(theme(spacing[2.5])-1px)] sm:py-[calc(theme(spacing[1.5])-1px)]',
50
-
51
- // Set minimum height for when no value is selected
52
- 'min-h-11 sm:min-h-9',
53
-
54
- // Horizontal padding
55
- 'pl-[calc(theme(spacing[3.5])-1px)] pr-[calc(theme(spacing.7)-1px)] sm:pl-[calc(theme(spacing.3)-1px)]',
56
-
57
- // Typography
58
- 'text-left text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white forced-colors:text-[CanvasText]',
59
-
60
- // Border
61
- 'border border-zinc-950/10 group-data-[active]:border-zinc-950/20 group-data-[hover]:border-zinc-950/20 dark:border-white/10 dark:group-data-[active]:border-white/20 dark:group-data-[hover]:border-white/20',
62
-
63
- // Background color
64
- 'bg-transparent dark:bg-white/5',
65
-
66
- // Invalid state
67
- 'group-data-[invalid]:border-red-500 group-data-[invalid]:group-data-[hover]:border-red-500 group-data-[invalid]:dark:border-red-600 group-data-[invalid]:data-[hover]:dark:border-red-600',
68
-
69
- // Disabled state
70
- 'group-data-[disabled]:border-zinc-950/20 group-data-[disabled]:opacity-100 group-data-[disabled]:dark:border-white/15 group-data-[disabled]:dark:bg-white/[2.5%] dark:data-[hover]:group-data-[disabled]:border-white/15',
71
- ])}
72
- />
73
- <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
74
- <svg
75
- className="size-5 stroke-zinc-500 group-data-[disabled]:stroke-zinc-600 sm:size-4 dark:stroke-zinc-400 forced-colors:stroke-[CanvasText]"
76
- viewBox="0 0 16 16"
77
- aria-hidden="true"
78
- fill="none"
79
- >
80
- <path d="M5.75 10.75L8 13L10.25 10.75" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
81
- <path d="M10.25 5.25L8 3L5.75 5.25" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
82
- </svg>
83
- </span>
84
- </HeadlessListboxButton>
85
- <HeadlessTransition
86
- as={Fragment}
87
- leave="transition-opacity duration-100 ease-in pointer-events-none"
88
- leaveFrom="opacity-100"
89
- leaveTo="opacity-0"
90
- >
91
- <HeadlessListboxOptions
92
- as="div"
93
- anchor={{
94
- to: 'selection start',
95
- offset: 'var(--anchor-offset)',
96
- padding: 'var(--anchor-padding)',
97
- }}
98
- className={clsx(
99
- // Anchor positioning
100
- '[--anchor-offset:-1.625rem] [--anchor-padding:theme(spacing.4)] sm:[--anchor-offset:-1.375rem]',
101
-
102
- // Base styles
103
- 'isolate w-max min-w-[calc(var(--button-width)+1.75rem)] select-none scroll-py-1 rounded-xl p-1',
104
-
105
- // Invisible border that is only visible in `forced-colors` mode for accessibility purposes
106
- 'outline outline-1 outline-transparent focus:outline-none',
107
-
108
- // Handle scrolling when menu won't fit in viewport
109
- 'overflow-y-scroll overscroll-contain',
110
-
111
- // Popover background
112
- 'bg-white/75 backdrop-blur-xl dark:bg-zinc-800/75',
113
-
114
- // Shadows
115
- 'shadow-lg ring-1 ring-zinc-950/10 dark:ring-inset dark:ring-white/10'
116
- )}
117
- >
118
- {options}
119
- </HeadlessListboxOptions>
120
- </HeadlessTransition>
121
- </HeadlessListbox>
122
- )
123
- }
124
-
125
- export function ListboxOption({ children, className, ...props }) {
126
- const sharedClasses = clsx(
127
- // Base
128
- 'flex min-w-0 items-center',
129
-
130
- // Icons
131
- '[&>[data-slot=icon]]:size-5 [&>[data-slot=icon]]:shrink-0 [&>[data-slot=icon]]:text-zinc-500 [&>[data-slot=icon]]:group-data-[focus]/option:text-white sm:[&>[data-slot=icon]]:size-4 forced-colors:[&>[data-slot=icon]]:text-[CanvasText] forced-colors:[&>[data-slot=icon]]:group-data-[focus]/option:text-[Canvas]',
132
-
133
- // Avatars
134
- '[&>[data-slot=avatar]]:size-6 sm:[&>[data-slot=avatar]]:size-5'
135
- )
136
-
137
- return (
138
- <HeadlessListboxOption as={Fragment} {...props}>
139
- {({ selectedOption }) => {
140
- if (selectedOption) {
141
- return <div className={clsx(className, sharedClasses)}>{children}</div>
142
- }
143
-
144
- return (
145
- <div
146
- className={clsx(
147
- // Basic layout
148
- 'group/option grid cursor-default grid-cols-[theme(spacing.5),1fr] items-baseline gap-x-1.5 rounded-lg py-2.5 pl-2.5 pr-3.5 sm:grid-cols-[theme(spacing.4),1fr] sm:py-1.5 sm:pl-2 sm:pr-3',
149
-
150
- // Typography
151
- 'text-base/6 text-zinc-950 sm:text-sm/6 dark:text-white forced-colors:text-[CanvasText]',
152
-
153
- // Focus
154
- 'outline-none data-[focus]:bg-blue-500 data-[focus]:text-white',
155
-
156
- // Forced colors mode
157
- 'forced-color-adjust-none forced-colors:data-[focus]:bg-[Highlight] forced-colors:data-[focus]:text-[HighlightText]',
158
-
159
- // Disabled
160
- 'data-[disabled]:opacity-50'
161
- )}
162
- >
163
- <svg
164
- className="relative hidden size-5 self-center stroke-current group-data-[selected]/option:inline sm:size-4"
165
- viewBox="0 0 16 16"
166
- fill="none"
167
- aria-hidden="true"
168
- >
169
- <path d="M4 8.5l3 3L12 4" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
170
- </svg>
171
- <span className={clsx(className, sharedClasses, 'col-start-2')}>{children}</span>
172
- </div>
173
- )
174
- }}
175
- </HeadlessListboxOption>
176
- )
177
- }
178
-
179
- export function ListboxLabel({ className, ...props }) {
180
- return <span className={clsx(className, 'ml-2.5 truncate first:ml-0 sm:ml-2 sm:first:ml-0')} {...props} />
181
- }
182
-
183
- export function ListboxDescription({ className, children, ...props }) {
184
- return (
185
- <span
186
- className={clsx(
187
- className,
188
- 'flex flex-1 overflow-hidden text-zinc-500 before:w-2 before:min-w-0 before:shrink group-data-[focus]/option:text-white dark:text-zinc-400'
189
- )}
190
- {...props}
191
- >
192
- <span className="flex-1 truncate">{children}</span>
193
- </span>
194
- )
195
- }
@@ -1,75 +0,0 @@
1
- import clsx from 'clsx'
2
-
3
- import { Button } from './button'
4
-
5
- export function Pagination({ 'aria-label': ariaLabel = 'Page navigation', className, ...props }) {
6
- return <nav aria-label={ariaLabel} {...props} className={clsx(className, 'flex gap-x-2')} />
7
- }
8
-
9
- export function PaginationPrevious({ href = null, children = 'Previous' }) {
10
- return (
11
- <span className="grow basis-0">
12
- <Button {...(href === null ? { disabled: true } : { href })} plain aria-label="Previous page">
13
- <svg className="stroke-current" data-slot="icon" viewBox="0 0 16 16" fill="none" aria-hidden="true">
14
- <path
15
- d="M2.75 8H13.25M2.75 8L5.25 5.5M2.75 8L5.25 10.5"
16
- strokeWidth={1.5}
17
- strokeLinecap="round"
18
- strokeLinejoin="round"
19
- />
20
- </svg>
21
- {children}
22
- </Button>
23
- </span>
24
- )
25
- }
26
-
27
- export function PaginationNext({ href = null, children = 'Next' }) {
28
- return (
29
- <span className="flex grow basis-0 justify-end">
30
- <Button {...(href === null ? { disabled: true } : { href })} plain aria-label="Next page">
31
- {children}
32
- <svg className="stroke-current" data-slot="icon" viewBox="0 0 16 16" fill="none" aria-hidden="true">
33
- <path
34
- d="M13.25 8L2.75 8M13.25 8L10.75 10.5M13.25 8L10.75 5.5"
35
- strokeWidth={1.5}
36
- strokeLinecap="round"
37
- strokeLinejoin="round"
38
- />
39
- </svg>
40
- </Button>
41
- </span>
42
- )
43
- }
44
-
45
- export function PaginationList({ children }) {
46
- return <span className="hidden items-baseline gap-x-2 sm:flex">{children}</span>
47
- }
48
-
49
- export function PaginationPage({ href, children, current = false }) {
50
- return (
51
- <Button
52
- href={href}
53
- plain
54
- aria-label={`Page ${children}`}
55
- aria-current={current ? 'page' : undefined}
56
- className={clsx(
57
- 'min-w-[2.25rem] before:absolute before:-inset-px before:rounded-lg',
58
- current && 'before:bg-zinc-950/5 dark:before:bg-white/10'
59
- )}
60
- >
61
- <span className="-mx-0.5">{children}</span>
62
- </Button>
63
- )
64
- }
65
-
66
- export function PaginationGap() {
67
- return (
68
- <div
69
- aria-hidden="true"
70
- className="w-[2.25rem] select-none text-center text-sm/6 font-semibold text-zinc-950 dark:text-white"
71
- >
72
- &hellip;
73
- </div>
74
- )
75
- }
@@ -1,144 +0,0 @@
1
- import { Field as HeadlessField, Radio as HeadlessRadio, RadioGroup as HeadlessRadioGroup } from '@headlessui/react'
2
- import { clsx } from 'clsx'
3
-
4
- export function RadioGroup({ className, ...props }) {
5
- return (
6
- <HeadlessRadioGroup
7
- data-slot="control"
8
- {...props}
9
- className={clsx(
10
- className,
11
-
12
- // Basic groups
13
- 'space-y-3 [&_[data-slot=label]]:font-normal',
14
-
15
- // With descriptions
16
- 'has-[[data-slot=description]]:space-y-6 [&_[data-slot=label]]:has-[[data-slot=description]]:font-medium'
17
- )}
18
- />
19
- )
20
- }
21
-
22
- export function RadioField({ className, ...props }) {
23
- return (
24
- <HeadlessField
25
- data-slot="field"
26
- {...props}
27
- className={clsx(
28
- className,
29
-
30
- // Base layout
31
- 'grid grid-cols-[1.125rem_1fr] items-center gap-x-4 gap-y-1 sm:grid-cols-[1rem_1fr]',
32
-
33
- // Control layout
34
- '[&>[data-slot=control]]:col-start-1 [&>[data-slot=control]]:row-start-1 [&>[data-slot=control]]:justify-self-center',
35
-
36
- // Label layout
37
- '[&>[data-slot=label]]:col-start-2 [&>[data-slot=label]]:row-start-1 [&>[data-slot=label]]:justify-self-start',
38
-
39
- // Description layout
40
- '[&>[data-slot=description]]:col-start-2 [&>[data-slot=description]]:row-start-2',
41
-
42
- // With description
43
- '[&_[data-slot=label]]:has-[[data-slot=description]]:font-medium'
44
- )}
45
- />
46
- )
47
- }
48
-
49
- const base = [
50
- // Basic layout
51
- 'relative isolate flex size-[1.1875rem] shrink-0 rounded-full sm:size-[1.0625rem]',
52
-
53
- // Background color + shadow applied to inset pseudo element, so shadow blends with border in light mode
54
- 'before:absolute before:inset-0 before:-z-10 before:rounded-full before:bg-white before:shadow',
55
-
56
- // Background color when checked
57
- 'before:group-data-[checked]:bg-[--radio-checked-bg]',
58
-
59
- // Background color is moved to control and shadow is removed in dark mode so hide `before` pseudo
60
- 'dark:before:hidden',
61
-
62
- // Background color applied to control in dark mode
63
- 'dark:bg-white/5 dark:group-data-[checked]:bg-[--radio-checked-bg]',
64
-
65
- // Border
66
- 'border border-zinc-950/15 group-data-[checked]:border-transparent group-data-[checked]:group-data-[hover]:border-transparent group-data-[hover]:border-zinc-950/30 group-data-[checked]:bg-[--radio-checked-border]',
67
- 'dark:border-white/15 dark:group-data-[checked]:border-white/5 dark:group-data-[checked]:group-data-[hover]:border-white/5 dark:group-data-[hover]:border-white/30',
68
-
69
- // Inner highlight shadow
70
- 'after:absolute after:inset-0 after:rounded-full after:shadow-[inset_0_1px_theme(colors.white/15%)]',
71
- 'dark:after:-inset-px dark:after:hidden dark:after:rounded-full dark:group-data-[checked]:after:block',
72
-
73
- // Indicator color (light mode)
74
- '[--radio-indicator:transparent] group-data-[checked]:[--radio-indicator:var(--radio-checked-indicator)] group-data-[checked]:group-data-[hover]:[--radio-indicator:var(--radio-checked-indicator)] group-data-[hover]:[--radio-indicator:theme(colors.zinc.900/10%)]',
75
-
76
- // Indicator color (dark mode)
77
- 'dark:group-data-[checked]:group-data-[hover]:[--radio-indicator:var(--radio-checked-indicator)] dark:group-data-[hover]:[--radio-indicator:theme(colors.zinc.700)]',
78
-
79
- // Focus ring
80
- 'group-data-[focus]:outline group-data-[focus]:outline-2 group-data-[focus]:outline-offset-2 group-data-[focus]:outline-blue-500',
81
-
82
- // Disabled state
83
- 'group-data-[disabled]:opacity-50',
84
- 'group-data-[disabled]:border-zinc-950/25 group-data-[disabled]:bg-zinc-950/5 group-data-[disabled]:[--radio-checked-indicator:theme(colors.zinc.950/50%)] group-data-[disabled]:before:bg-transparent',
85
- 'dark:group-data-[disabled]:border-white/20 dark:group-data-[disabled]:bg-white/[2.5%] dark:group-data-[disabled]:[--radio-checked-indicator:theme(colors.white/50%)] dark:group-data-[disabled]:group-data-[checked]:after:hidden',
86
- ]
87
-
88
- const colors = {
89
- 'dark/zinc': [
90
- '[--radio-checked-bg:theme(colors.zinc.900)] [--radio-checked-border:theme(colors.zinc.950/90%)] [--radio-checked-indicator:theme(colors.white)]',
91
- 'dark:[--radio-checked-bg:theme(colors.zinc.600)]',
92
- ],
93
- 'dark/white': [
94
- '[--radio-checked-bg:theme(colors.zinc.900)] [--radio-checked-border:theme(colors.zinc.950/90%)] [--radio-checked-indicator:theme(colors.white)]',
95
- 'dark:[--radio-checked-bg:theme(colors.white)] dark:[--radio-checked-border:theme(colors.zinc.950/15%)] dark:[--radio-checked-indicator:theme(colors.zinc.900)]',
96
- ],
97
- white:
98
- '[--radio-checked-bg:theme(colors.white)] [--radio-checked-border:theme(colors.zinc.950/15%)] [--radio-checked-indicator:theme(colors.zinc.900)]',
99
- dark: '[--radio-checked-bg:theme(colors.zinc.900)] [--radio-checked-border:theme(colors.zinc.950/90%)] [--radio-checked-indicator:theme(colors.white)]',
100
- zinc: '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.zinc.600)] [--radio-checked-border:theme(colors.zinc.700/90%)]',
101
- red: '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.red.600)] [--radio-checked-border:theme(colors.red.700/90%)]',
102
- orange:
103
- '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.orange.500)] [--radio-checked-border:theme(colors.orange.600/90%)]',
104
- amber:
105
- '[--radio-checked-bg:theme(colors.amber.400)] [--radio-checked-border:theme(colors.amber.500/80%)] [--radio-checked-indicator:theme(colors.amber.950)]',
106
- yellow:
107
- '[--radio-checked-bg:theme(colors.yellow.300)] [--radio-checked-border:theme(colors.yellow.400/80%)] [--radio-checked-indicator:theme(colors.yellow.950)]',
108
- lime: '[--radio-checked-bg:theme(colors.lime.300)] [--radio-checked-border:theme(colors.lime.400/80%)] [--radio-checked-indicator:theme(colors.lime.950)]',
109
- green:
110
- '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.green.600)] [--radio-checked-border:theme(colors.green.700/90%)]',
111
- emerald:
112
- '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.emerald.600)] [--radio-checked-border:theme(colors.emerald.700/90%)]',
113
- teal: '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.teal.600)] [--radio-checked-border:theme(colors.teal.700/90%)]',
114
- cyan: '[--radio-checked-bg:theme(colors.cyan.300)] [--radio-checked-border:theme(colors.cyan.400/80%)] [--radio-checked-indicator:theme(colors.cyan.950)]',
115
- sky: '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.sky.500)] [--radio-checked-border:theme(colors.sky.600/80%)]',
116
- blue: '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.blue.600)] [--radio-checked-border:theme(colors.blue.700/90%)]',
117
- indigo:
118
- '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.indigo.500)] [--radio-checked-border:theme(colors.indigo.600/90%)]',
119
- violet:
120
- '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.violet.500)] [--radio-checked-border:theme(colors.violet.600/90%)]',
121
- purple:
122
- '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.purple.500)] [--radio-checked-border:theme(colors.purple.600/90%)]',
123
- fuchsia:
124
- '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.fuchsia.500)] [--radio-checked-border:theme(colors.fuchsia.600/90%)]',
125
- pink: '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.pink.500)] [--radio-checked-border:theme(colors.pink.600/90%)]',
126
- rose: '[--radio-checked-indicator:theme(colors.white)] [--radio-checked-bg:theme(colors.rose.500)] [--radio-checked-border:theme(colors.rose.600/90%)]',
127
- }
128
-
129
- export function Radio({ color = 'dark/zinc', className, ...props }) {
130
- return (
131
- <HeadlessRadio data-slot="control" {...props} className={clsx(className, 'group inline-flex focus:outline-none')}>
132
- <span className={clsx([base, colors[color]])}>
133
- <span
134
- className={clsx(
135
- 'size-full rounded-full border-[4.5px] border-transparent bg-[--radio-indicator] bg-clip-padding',
136
-
137
- // Forced colors mode
138
- 'forced-colors:border-[Canvas] forced-colors:group-data-[checked]:border-[Highlight]'
139
- )}
140
- />
141
- </span>
142
- </HeadlessRadio>
143
- )
144
- }
@@ -1,78 +0,0 @@
1
- import { Select as HeadlessSelect } from '@headlessui/react'
2
- import { clsx } from 'clsx'
3
- import { forwardRef } from 'react'
4
-
5
- export const Select = forwardRef(function Select({ className, multiple, ...props }, ref) {
6
- return (
7
- <span
8
- data-slot="control"
9
- className={clsx([
10
- className,
11
-
12
- // Basic layout
13
- 'group relative block w-full',
14
-
15
- // Background color + shadow applied to inset pseudo element, so shadow blends with border in light mode
16
- 'before:absolute before:inset-px before:rounded-[calc(theme(borderRadius.lg)-1px)] before:bg-white before:shadow',
17
-
18
- // Background color is moved to control and shadow is removed in dark mode so hide `before` pseudo
19
- 'dark:before:hidden',
20
-
21
- // Focus ring
22
- 'after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:ring-inset after:ring-transparent sm:after:has-[[data-focus]]:ring-2 sm:after:has-[[data-focus]]:ring-blue-500',
23
-
24
- // Disabled state
25
- 'has-[[data-disabled]]:opacity-50 before:has-[[data-disabled]]:bg-zinc-950/5 before:has-[[data-disabled]]:shadow-none',
26
- ])}
27
- >
28
- <HeadlessSelect
29
- ref={ref}
30
- multiple={multiple}
31
- {...props}
32
- className={clsx([
33
- // Basic layout
34
- 'relative block w-full appearance-none rounded-lg py-[calc(theme(spacing[2.5])-1px)] sm:py-[calc(theme(spacing[1.5])-1px)]',
35
-
36
- // Horizontal padding
37
- multiple
38
- ? 'px-[calc(theme(spacing[3.5])-1px)] sm:px-[calc(theme(spacing.3)-1px)]'
39
- : 'pl-[calc(theme(spacing[3.5])-1px)] pr-[calc(theme(spacing.10)-1px)] sm:pl-[calc(theme(spacing.3)-1px)] sm:pr-[calc(theme(spacing.9)-1px)]',
40
-
41
- // Options (multi-select)
42
- '[&_optgroup]:font-semibold',
43
-
44
- // Typography
45
- 'text-base/6 text-zinc-950 placeholder:text-zinc-500 sm:text-sm/6 dark:text-white dark:*:text-white',
46
-
47
- // Border
48
- 'border border-zinc-950/10 data-[hover]:border-zinc-950/20 dark:border-white/10 dark:data-[hover]:border-white/20',
49
-
50
- // Background color
51
- 'bg-transparent dark:bg-white/5 dark:*:bg-zinc-800',
52
-
53
- // Hide default focus styles
54
- 'focus:outline-none',
55
-
56
- // Invalid state
57
- 'data-[invalid]:border-red-500 data-[invalid]:data-[hover]:border-red-500 data-[invalid]:dark:border-red-600 data-[invalid]:data-[hover]:dark:border-red-600',
58
-
59
- // Disabled state
60
- 'data-[disabled]:border-zinc-950/20 data-[disabled]:opacity-100 dark:data-[hover]:data-[disabled]:border-white/15 data-[disabled]:dark:border-white/15 data-[disabled]:dark:bg-white/[2.5%]',
61
- ])}
62
- />
63
- {!multiple && (
64
- <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
65
- <svg
66
- className="size-5 stroke-zinc-500 group-has-[[data-disabled]]:stroke-zinc-600 sm:size-4 dark:stroke-zinc-400 forced-colors:stroke-[CanvasText]"
67
- viewBox="0 0 16 16"
68
- aria-hidden="true"
69
- fill="none"
70
- >
71
- <path d="M5.75 10.75L8 13L10.25 10.75" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
72
- <path d="M10.25 5.25L8 3L5.75 5.25" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round" />
73
- </svg>
74
- </span>
75
- )}
76
- </span>
77
- )
78
- })