nitro-web 0.0.31 → 0.0.33

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.
package/client/index.ts CHANGED
@@ -42,13 +42,12 @@ export { Checkbox } from '../components/partials/form/checkbox'
42
42
  export { Drop } from '../components/partials/form/drop'
43
43
  export { DropHandler } from '../components/partials/form/drop-handler'
44
44
  export { FormError } from '../components/partials/form/form-error'
45
- export { Field } from '../components/partials/form/input'
46
- export { FieldColor, type FieldColorProps } from '../components/partials/form/input-color'
47
- export { FieldCurrency, type FieldCurrencyProps } from '../components/partials/form/input-currency'
48
- export { FieldDate, type FieldDateProps } from '../components/partials/form/input-date'
45
+ export { Field } from '../components/partials/form/field'
46
+ export { FieldColor, type FieldColorProps } from '../components/partials/form/field-color'
47
+ export { FieldCurrency, type FieldCurrencyProps } from '../components/partials/form/field-currency'
48
+ export { FieldDate, type FieldDateProps } from '../components/partials/form/field-date'
49
49
  export { Location } from '../components/partials/form/location'
50
50
  export { Select, getSelectStyle } from '../components/partials/form/select'
51
- export { Toggle } from '../components/partials/form/toggle'
52
51
 
53
52
  // Component Other
54
53
  export { IsFirstRender } from '../components/partials/is-first-render'
@@ -27,6 +27,6 @@ export function Dashboard() {
27
27
 
28
28
  const style = css`
29
29
  .example-usage-of-tailwind-variable {
30
- color: ${theme('colors.dark')};
30
+ color: ${theme('colors.primary')};
31
31
  }
32
32
  `
@@ -80,7 +80,7 @@ export function Accordion({ children, className, expanded, onChange }: Accordion
80
80
  return (
81
81
  <div
82
82
  ref={el}
83
- class={['accordion', className, state ? 'is-expanded' : ''].filter(o => o).join(' ')}
83
+ class={['accordion', className, state ? 'is-expanded' : ''].filter(o => o).join(' nitro-accordion')}
84
84
  onClick={onClick}
85
85
  css={style}
86
86
  >
@@ -13,7 +13,7 @@ type AvatarProps = {
13
13
  }
14
14
 
15
15
  export function Avatar({ awsUrl, isRound, user, showPlaceholderImage, className }: AvatarProps) {
16
- const classes = 'rounded-full w-[30px] h-[30px] object-cover transition-all duration-150 ease ' + (className || '')
16
+ const classes = 'rounded-full w-[30px] h-[30px] object-cover transition-all duration-150 ease nitro-avatar ' + (className || '')
17
17
 
18
18
  function getInitials(user: User) {
19
19
  const text = (user.firstName ? [user.firstName, user.lastName] : (user?.name||'').split(' ')).map((o) => o?.charAt(0))
@@ -41,10 +41,10 @@ export function Button({
41
41
 
42
42
  // Button sizes
43
43
  const sizes = {
44
- xs: 'px-2 py-1 text-xs rounded',
45
- sm: 'px-2.5 py-1.5 text-sm rounded-md',
46
- md: 'px-3 py-2 text-sm rounded-md',
47
- lg: 'px-3.5 py-2.5 text-sm rounded-md',
44
+ xs: 'px-2 py-1 px-button-x-xs py-button-y-xs text-xs rounded',
45
+ sm: 'px-2.5 py-1.5 px-button-x-sm py-button-y-sm text-sm rounded-md',
46
+ md: 'px-3 py-2 px-button-x py-button-y text-sm rounded-md',
47
+ lg: 'px-3.5 py-2.5 px-button-x-lg py-button-y-lg text-sm rounded-md',
48
48
  }
49
49
 
50
50
  const contentLayout = `w-full gap-x-1.5 ${iconPosition == 'none' ? '' : 'inline-flex items-center justify-center'}`
@@ -57,7 +57,7 @@ export function Button({
57
57
  }
58
58
 
59
59
  return (
60
- <button class={twMerge(`${base} ${colors[color]} ${sizes[size]} ${contentLayout} ${loading} ${className||''}`)} {...props}>
60
+ <button class={twMerge(`${base} ${colors[color]} ${sizes[size]} ${contentLayout} ${loading} nitro-button ${className||''}`)} {...props}>
61
61
  {IconLeft && getIcon(IconLeft)}
62
62
  {IconLeftEnd && getIcon(IconLeftEnd)}
63
63
  <span class={`${iconPosition == 'leftEnd' || iconPosition == 'rightEnd' ? 'flex-1' : ''}`}>{children}</span>
@@ -83,12 +83,12 @@ export function Calendar({ mode='single', onChange, value, numberOfMonths, month
83
83
  range_middle: `${d.range_middle} rangemiddle`,
84
84
  },
85
85
  classNames: {
86
- root: `${d.root} flex`,
86
+ root: `${d.root} flex nitro-calendar`,
87
87
  months: `${d.months} flex-nowrap`,
88
88
  month_caption: `${d.month_caption} text-2xs pl-2`,
89
89
  caption_label: `${d.caption_label} z-auto`,
90
- button_previous: `${d.button_previous} size-8`,// [&:hover>svg]:fill-primary-dark`,
91
- button_next: `${d.button_next} size-8`,// [&:hover>svg]:fill-primary-dark`,
90
+ button_previous: `${d.button_previous} size-8`,// [&:hover>svg]:fill-input-border-focus`,
91
+ button_next: `${d.button_next} size-8`,// [&:hover>svg]:fill-input-border-focus`,
92
92
  chevron: `${d.chevron} fill-black size-[18px]`,
93
93
 
94
94
  // Days
@@ -98,12 +98,12 @@ export function Calendar({ mode='single', onChange, value, numberOfMonths, month
98
98
 
99
99
  // States
100
100
  focused: `${d.focused} [&>button]:bg-gray-200 [&>button]:border-gray-200`,
101
- range_start: `${d.range_start} [&>button]:!bg-primary-dark [&>button]:!border-primary-dark`,
102
- range_end: `${d.range_end} [&>button]:!bg-primary-dark [&>button]:!border-primary-dark`,
101
+ range_start: `${d.range_start} [&>button]:!bg-input-border-focus [&>button]:!border-input-border-focus`,
102
+ range_end: `${d.range_end} [&>button]:!bg-input-border-focus [&>button]:!border-input-border-focus`,
103
103
  selected: `${d.selected} font-normal `
104
104
  + '[&:not(.rangemiddle)>button]:!text-white '
105
- + '[&:not(.rangemiddle)>button]:!bg-primary-dark '
106
- + '[&:not(.rangemiddle)>button]:!border-primary-dark ',
105
+ + '[&:not(.rangemiddle)>button]:!bg-input-border-focus '
106
+ + '[&:not(.rangemiddle)>button]:!border-input-border-focus ',
107
107
  },
108
108
  }
109
109
 
@@ -91,6 +91,7 @@ export const Dropdown = forwardRef(function Dropdown({
91
91
  (isHoverable ? ' is-hoverable' : '') +
92
92
  (isActive ? ' is-active' : '') +
93
93
  (!animate ? ' no-animation' : '') +
94
+ ' nitro-dropdown' +
94
95
  (className ? ` ${className}` : '')
95
96
  }
96
97
  onClick={(e) => e.stopPropagation()} // required for dropdowns inside row links
@@ -9,7 +9,7 @@ export function GithubLink({ filename }: { filename: string }) {
9
9
 
10
10
  return (
11
11
  // <a href={link}>Go to Github</a>
12
- <a href={link} className="fixed top-0 right-0">
12
+ <a href={link} className="fixed top-0 right-0 nitro-github">
13
13
  <GithubIcon />
14
14
  </a>
15
15
  )
@@ -20,6 +20,7 @@ export function Initials({ icon, isBig, isMedium, isSmall, isRound, className }:
20
20
  (isSmall ? ' is-small' : '') +
21
21
  (isRound ? ' is-round' : '') +
22
22
  (icon ? '' : ' is-empty') +
23
+ ' nitro-initials' +
23
24
  (className ? ' ' + className : '')
24
25
  }
25
26
  style={icon ? {backgroundColor: icon?.hex + '15', color: icon?.hex} : {}}
@@ -82,7 +82,7 @@ export function Message() {
82
82
  {/* Global notification live region, render this permanently at the end of the document */}
83
83
  <div
84
84
  aria-live="assertive"
85
- className="pointer-events-none fixed inset-0 flex items-end px-4 py-6 sm:items-start sm:p-6 z-20"
85
+ className="pointer-events-none fixed inset-0 flex items-end px-4 py-6 sm:items-start sm:p-6 z-20 nitro-message"
86
86
  >
87
87
  <div className="flex w-full flex-col items-center space-y-4 sm:items-end">
88
88
  {/* Notification panel, dynamically insert this into the live region when it needs to be displayed */}
@@ -64,7 +64,7 @@ export function Modal({ show, setShow, children, maxWidth, minHeight, dismissabl
64
64
  return (
65
65
  <div
66
66
  onClick={(e) => e.stopPropagation()}
67
- class={`fixed top-0 w-[100vw] h-[100vh] z-[700] ${_state.root}`}
67
+ class={`fixed top-0 w-[100vw] h-[100vh] z-[700] nitro-modal ${_state.root}`}
68
68
  >
69
69
  <div class={`!absolute inset-0 box-content bg-gray-500/70 transition-opacity ${_state.bg}`}></div>
70
70
  <div class={`relative h-[100vh] overflow-y-auto transition-[opacity,transform] ${_state.container}`}>
@@ -10,6 +10,7 @@ import {
10
10
  ArrowLeftCircleIcon,
11
11
  PaintBrushIcon,
12
12
  } from '@heroicons/react/24/outline'
13
+
13
14
  const sidebarWidth = 'lg:w-80'
14
15
 
15
16
  export type SidebarProps = {
@@ -27,7 +28,7 @@ export function Sidebar({ Logo, menu, links }: SidebarProps) {
27
28
  return (
28
29
  <>
29
30
  {/* mobile sidebar opened */}
30
- <Dialog open={sidebarOpen} onClose={setSidebarOpen} className="relative z-50 lg:hidden">
31
+ <Dialog open={sidebarOpen} onClose={setSidebarOpen} className="relative z-50 lg:hidden nitro-sidebar">
31
32
  <DialogBackdrop
32
33
  transition
33
34
  className="fixed inset-0 bg-gray-900/80 transition-opacity duration-300 ease-linear data-[closed]:opacity-0"
@@ -11,7 +11,7 @@ type TooltipProps = {
11
11
 
12
12
  export function Tooltip({ text, children, className, classNamePopup, isSmall }: TooltipProps) {
13
13
  return (
14
- <div class={`${className} relative inline-block align-middle`} css={style}>
14
+ <div class={`${className} relative inline-block align-middle nitro-tooltip`} css={style}>
15
15
  {
16
16
  text
17
17
  ? <>
@@ -1,27 +1,15 @@
1
1
  type TopbarProps = {
2
2
  title: React.ReactNode
3
3
  subtitle?: React.ReactNode
4
- submenu?: React.ReactNode
5
- btns?: React.ReactNode
6
4
  className?: string
7
5
  }
8
6
 
9
- export function Topbar({ title, subtitle, submenu, btns, className }: TopbarProps) {
7
+ export function Topbar({ title, subtitle, className }: TopbarProps) {
10
8
  return (
11
- <div class={`flex justify-between items-end mb-6 ${className||''}`}>
12
- <div class="flex flex-col min-h-12">
13
- { subtitle && <div class="py-2 text-sm">{subtitle}</div>}
14
- <div class="flex items-center py-2">
15
- <h1 class="h1 mb-0">{title}</h1>
16
- </div>
17
- {
18
- submenu &&
19
- <div class="pt-2 text-large weight-500">{submenu}</div>
20
- }
21
- </div>
22
- <div class="">
23
- {btns}
24
- </div>
9
+ <div class={`flex flex-col min-h-12 gap-0.5 mb-6 nitro-topbar ${className||''}`}>
10
+ <div class="text-2xl font-bold">{title}</div>
11
+ { subtitle && <div class="text-sm text-muted-foreground">{subtitle}</div>}
12
+ {/* { submenu && <div class="pt-2 text-large weight-500">{submenu}</div> } */}
25
13
  </div>
26
14
  )
27
15
  }
@@ -32,7 +32,7 @@ export function Checkbox({ name, id, size='sm', subtext, text, type='checkbox',
32
32
  const _size = sizeMap[size]
33
33
 
34
34
  return (
35
- <div className={`mt-input-before mb-input-after flex gap-3 ${props.className || ''}`}>
35
+ <div className={`mt-2.5 mb-6 mt-input-before mb-input-after flex gap-3 nitro-checkbox ${props.className || ''}`}>
36
36
  <div className="flex shrink-0 mt-[2px]">
37
37
  {
38
38
  type !== 'toggle'
@@ -42,7 +42,13 @@ export function Checkbox({ name, id, size='sm', subtext, text, type='checkbox',
42
42
  id={id}
43
43
  name={name}
44
44
  type={type}
45
- className={`${type === 'radio' ? 'rounded-full' : 'rounded'} col-start-1 row-start-1 appearance-none border border-gray-300 bg-white checked:border-primary checked:bg-primary indeterminate:border-primary indeterminate:bg-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto`}
45
+ className={
46
+ `${type === 'radio' ? 'rounded-full' : 'rounded'} col-start-1 row-start-1 appearance-none border border-gray-300 bg-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto ` +
47
+ // Default
48
+ 'checked:border-blue-600 checked:bg-blue-600 indeterminate:border-blue-600 indeterminate:bg-blue-600 focus-visible:outline-blue-600 ' +
49
+ // Variable-selected color defined?
50
+ 'checked:!border-variable-selected checked:!bg-variable-selected indeterminate:!border-variable-selected indeterminate:!bg-variable-selected focus-visible:!outline-variable-selected'
51
+ }
46
52
  />
47
53
  <svg
48
54
  fill="none"
@@ -89,7 +95,15 @@ export function Checkbox({ name, id, size='sm', subtext, text, type='checkbox',
89
95
  />
90
96
  <label
91
97
  for={id}
92
- className={`col-start-1 row-start-1 relative ${_size.toggleWidth} ${_size.toggleHeight} bg-gray-200 peer-focus-visible:outline-none peer-focus-visible:ring-4 peer-focus-visible:ring-blue-300 dark:peer-focus-visible:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full ${_size.toggleAfterSize} after:transition-all dark:border-gray-600 peer-checked:bg-blue-600`}
98
+ className={
99
+ `col-start-1 row-start-1 relative ${_size.toggleWidth} ${_size.toggleHeight} bg-gray-200 peer-focus-visible:outline-none peer-focus-visible:ring-4 rounded-full peer peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full ${_size.toggleAfterSize} after:transition-all ` +
100
+ // Default
101
+ 'peer-focus-visible:ring-blue-300 peer-checked:bg-blue-600 ' +
102
+ // Variable-selected color defined?
103
+ 'peer-focus-visible:!ring-variable-selected peer-checked:!bg-variable-selected '
104
+ // Dark mode not used yet...
105
+ // 'dark:peer-focus-visible:ring-blue-800 dark:bg-gray-700 dark:border-gray-600 '
106
+ }
93
107
  />
94
108
  </div>
95
109
  }
@@ -99,7 +99,7 @@ export function Drop({ awsUrl, className, id, name, onChange, multiple, state, .
99
99
  // }
100
100
 
101
101
  return (
102
- <div class={`mt-input-before mb-input-after ${className || ''}`}>
102
+ <div class={`mt-2.5 mb-6 mt-input-before mb-input-after nitro-field nitro-drop ${className || ''}`}>
103
103
  <input
104
104
  {...props}
105
105
  id={inputId}
@@ -148,7 +148,7 @@ export function FieldCurrency({ config, currency='nzd', onChange, value, default
148
148
  defaultValue={defaultValue}
149
149
  />
150
150
  <span
151
- class={`absolute top-[1px] bottom-0 left-3 inline-flex items-center select-none text-gray-500 text-sm sm:text-sm/6 ${dollars !== null && settings.prefix == '$' ? 'text-dark' : ''}`}
151
+ class={`absolute top-[1px] bottom-0 left-3 inline-flex items-center select-none text-gray-500 text-sm sm:text-sm/6 ${dollars !== null && settings.prefix == '$' ? 'text-foreground' : ''}`}
152
152
  >
153
153
  {settings.prefix || settings.suffix}
154
154
  </span>
@@ -179,7 +179,7 @@ function TimePicker({ date, onChange }: TimePickerProps) {
179
179
  key={item}
180
180
  className={
181
181
  'size-[33px] rounded-full flex justify-center items-center group-hover:bg-gray-100 '
182
- + (item === currentValue ? '!bg-primary-dark text-white' : '')
182
+ + (item === currentValue ? '!bg-input-border-focus text-white' : '')
183
183
  }
184
184
  onClick={() => handleTimeChange(type, item)}
185
185
  >
@@ -46,7 +46,7 @@ export function Field({ state, icon, iconPos: ip, ...props }: FieldProps) {
46
46
  const iconPos = ip == 'left' || (type == 'color' && !ip) ? 'left' : 'right'
47
47
 
48
48
  if (!props.name) {
49
- throw new Error('Input component requires a `name` prop')
49
+ throw new Error('Field component requires a `name` prop')
50
50
  }
51
51
 
52
52
  // Input type
@@ -58,7 +58,7 @@ export function Field({ state, icon, iconPos: ip, ...props }: FieldProps) {
58
58
  if (props.value) value = props.value as string
59
59
  else if (typeof state == 'object') value = util.deepFind(state, props.name) ?? ''
60
60
 
61
- // Errors: find any that match this input path
61
+ // Errors: find any that match this field path
62
62
  for (const item of (state?.errors || [])) {
63
63
  if (util.isRegex(props.name) && (item.title || '').match(props.name)) error = item
64
64
  else if (item.title == props.name) error = item
@@ -126,22 +126,28 @@ export function Field({ state, icon, iconPos: ip, ...props }: FieldProps) {
126
126
 
127
127
  function FieldContainer({ children, className, error }: { children: React.ReactNode, className?: string, error?: Error }) {
128
128
  return (
129
- <div css={style} className={`mt-input-before mb-input-after grid grid-cols-1 ${className || ''}`}>
129
+ <div css={style} className={`mt-2.5 mb-6 mt-input-before mb-input-after grid grid-cols-1 nitro-field ${className || ''}`}>
130
130
  {children}
131
- {error && <div class="mt-1.5 text-xs text-danger">{error.detail}</div>}
131
+ {error && <div class="mt-1.5 text-xs text-danger nitro-error">{error.detail}</div>}
132
132
  </div>
133
133
  )
134
134
  }
135
135
 
136
136
  function getInputClasses({ error, Icon, iconPos, type }: { error: Error, Icon?: React.ReactNode, iconPos: string, type?: string }) {
137
- const paddingLeft = type == 'color' ? 'sm:pl-9 pl-9' : 'sm:pl-8 pl-8'
138
- const paddingRight = type == 'color' ? 'sm:pr-9 pr-9' : 'sm:pr-8 pr-8'
137
+ const pl = 'pl-3 pl-input-x'
138
+ const pr = 'pr-3 pr-input-x'
139
+ const py = 'py-2 py-input-y'
140
+ const plWithIcon = type == 'color' ? 'pl-9' : 'pl-8' // was sm:pl-8 pl-8, etc
141
+ const prWithIcon = type == 'color' ? 'pr-9' : 'pr-8'
139
142
  return (
140
- 'col-start-1 row-start-1 block w-full rounded-md bg-white py-2 text-sm leading-[1.65] outline outline-1 -outline-offset-1 ' +
143
+ `block ${py} col-start-1 row-start-1 w-full rounded-md bg-white text-sm leading-[1.65] outline outline-1 -outline-offset-1 ` +
141
144
  'placeholder:text-input-placeholder focus:outline focus:outline-2 focus:-outline-offset-2 ' +
142
- (iconPos == 'right' && Icon ? `${paddingRight} pl-3 ` : (Icon ? `${paddingLeft} pr-3 ` : 'px-3 ')) +
143
- (error ? 'text-red-900 outline-danger focus:outline-danger ' : 'text-input outline-input-border focus:outline-primary ') +
144
- (iconPos == 'right' ? 'justify-self-start ' : 'justify-self-end ')
145
+ (iconPos == 'right' && Icon ? `${pl} ${prWithIcon} ` : (Icon ? `${plWithIcon} ${pr} ` : `${pl} ${pr} `)) +
146
+ (error
147
+ ? 'text-red-900 outline-danger focus:outline-danger '
148
+ : 'text-input outline-input-border focus:outline-input-border-focus ') +
149
+ (iconPos == 'right' ? 'justify-self-start ' : 'justify-self-end ') +
150
+ 'nitro-input'
145
151
  )
146
152
  }
147
153
 
@@ -18,7 +18,7 @@ export function FormError({ state, fields, className }: FormError) {
18
18
  return (
19
19
  <>
20
20
  {error ? (
21
- <div class={`text-danger mt-1 text-sm ${className||''}`}>
21
+ <div class={`text-danger mt-1 text-sm nitro-error ${className||''}`}>
22
22
  {error.detail}
23
23
  </div>
24
24
  ) : null}
@@ -58,7 +58,7 @@ export function Select({ inputId, minMenuWidth, name, prefix='', onChange, optio
58
58
  }
59
59
 
60
60
  return (
61
- <div css={style} class="mt-input-before mb-input-after">
61
+ <div css={style} class="mt-2.5 mb-6 mt-input-before mb-input-after nitro-select">
62
62
  <ReactSelect
63
63
  /**
64
64
  * react-select prop quick reference (https://react-select.com/props#api):
@@ -238,10 +238,10 @@ const selectStyles = {
238
238
  // Input container
239
239
  control: {
240
240
  base: 'rounded-md bg-white hover:cursor-pointer text-sm leading-[1.65] outline outline-1 -outline-offset-1 outline-input-border',
241
- focus: 'outline-2 -outline-offset-2 outline-primary',
241
+ focus: 'outline-2 -outline-offset-2 outline-input-border-focus',
242
242
  error: 'outline-danger',
243
243
  },
244
- valueContainer: 'py-2 px-3 gap-1',
244
+ valueContainer: 'py-2 px-3 py-input-y px-input-x gap-1',
245
245
  // Input container objects
246
246
  input: {
247
247
  base: 'text-input',
@@ -249,7 +249,7 @@ const selectStyles = {
249
249
  },
250
250
  multiValue: 'bg-primary text-white rounded items-center pl-2 pr-1.5 gap-1.5',
251
251
  multiValueLabel: '',
252
- multiValueRemove: 'border border-black/10 bg-clip-content bg-white rounded-md text-dark hover:bg-red-50',
252
+ multiValueRemove: 'border border-black/10 bg-clip-content bg-white rounded-md text-foreground hover:bg-red-50',
253
253
  placeholder: 'text-input-placeholder',
254
254
  singleValue: {
255
255
  base: 'text-input',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitro-web",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "repository": "github:boycce/nitro-web",
5
5
  "homepage": "https://boycce.github.io/nitro-web/",
6
6
  "description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
@@ -1,54 +0,0 @@
1
- type ToggleProps = {
2
- className?: string
3
- id?: string
4
- name: string
5
- subtext?: string
6
- text?: string
7
- type?: 'checkbox'
8
- }
9
-
10
- export function Toggle({ name, id, subtext, text, type='checkbox', ...props }: ToggleProps) {
11
- id = id || name
12
- // https://tailwindui.com/components/application-ui/forms/checkboxes#component-744ed4fa65ba36b925701eb4da5c6e31
13
- return (
14
- <div className={`mt-input-before mb-input-after flex gap-3 ${props.className || ''}`}>
15
- <div className="flex h-6 shrink-0 items-center">
16
- <div className="group grid size-4 grid-cols-1">
17
- <input
18
- {...props}
19
- id={id}
20
- name={name}
21
- type={type}
22
- className="col-start-1 row-start-1 appearance-none rounded border border-gray-300 bg-white checked:border-indigo-600 checked:bg-indigo-600 indeterminate:border-indigo-600 indeterminate:bg-indigo-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto"
23
- />
24
- <svg
25
- fill="none"
26
- viewBox="0 0 14 14"
27
- className="pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-[:disabled]:stroke-gray-950/25"
28
- >
29
- <path
30
- d="M3 8L6 11L11 3.5"
31
- strokeWidth={2}
32
- strokeLinecap="round"
33
- strokeLinejoin="round"
34
- className="opacity-0 group-has-[:checked]:opacity-100"
35
- />
36
- <path
37
- d="M3 7H11"
38
- strokeWidth={2}
39
- strokeLinecap="round"
40
- strokeLinejoin="round"
41
- className="opacity-0 group-has-[:indeterminate]:opacity-100"
42
- />
43
- </svg>
44
- </div>
45
- </div>
46
- {text && <div className="text-sm/6">
47
- <label for={id}>
48
- <span className="font-medium text-gray-900">{text}</span>
49
- <span className="ml-2 text-gray-500">{subtext}</span>
50
- </label>
51
- </div>}
52
- </div>
53
- )
54
- }
File without changes