@womp/kookie-ui 0.28.0 → 0.29.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 (58) hide show
  1. package/components.css +246 -42
  2. package/dist/cjs/components/index.js +2 -2
  3. package/dist/cjs/components/index.js.map +3 -3
  4. package/dist/cjs/components/segmented-control.js +1 -1
  5. package/dist/cjs/components/segmented-control.js.map +3 -3
  6. package/dist/cjs/components/segmented-control.props.d.ts +6 -0
  7. package/dist/cjs/components/segmented-control.props.d.ts.map +1 -1
  8. package/dist/cjs/components/segmented-control.props.js +1 -1
  9. package/dist/cjs/components/segmented-control.props.js.map +3 -3
  10. package/dist/cjs/components/text-field.d.ts +11 -3
  11. package/dist/cjs/components/text-field.d.ts.map +1 -1
  12. package/dist/cjs/components/text-field.js +2 -2
  13. package/dist/cjs/components/text-field.js.map +3 -3
  14. package/dist/cjs/components/text-field.props.d.ts +30 -1
  15. package/dist/cjs/components/text-field.props.d.ts.map +1 -1
  16. package/dist/cjs/components/text-field.props.js +1 -1
  17. package/dist/cjs/components/text-field.props.js.map +3 -3
  18. package/dist/cjs/index.js +4 -4
  19. package/dist/cjs/index.js.map +3 -3
  20. package/dist/cjs/props/index.js +1 -1
  21. package/dist/cjs/props/index.js.map +3 -3
  22. package/dist/esm/chunk-A252TSYI.js +2 -0
  23. package/dist/esm/chunk-A252TSYI.js.map +7 -0
  24. package/dist/esm/chunk-FIMFM25N.js +2 -0
  25. package/dist/esm/chunk-FIMFM25N.js.map +7 -0
  26. package/dist/esm/chunk-GPZHRZBE.js +6 -0
  27. package/dist/esm/chunk-GPZHRZBE.js.map +7 -0
  28. package/dist/esm/chunk-TSS4K2U5.js +3 -0
  29. package/dist/esm/{chunk-W4Z6ORYO.js.map → chunk-TSS4K2U5.js.map} +3 -3
  30. package/dist/esm/components/index.js +1 -1
  31. package/dist/esm/components/segmented-control.js +1 -1
  32. package/dist/esm/components/segmented-control.props.d.ts +6 -0
  33. package/dist/esm/components/segmented-control.props.d.ts.map +1 -1
  34. package/dist/esm/components/segmented-control.props.js +1 -1
  35. package/dist/esm/components/text-field.d.ts +11 -3
  36. package/dist/esm/components/text-field.d.ts.map +1 -1
  37. package/dist/esm/components/text-field.js +1 -1
  38. package/dist/esm/components/text-field.props.d.ts +30 -1
  39. package/dist/esm/components/text-field.props.d.ts.map +1 -1
  40. package/dist/esm/components/text-field.props.js +1 -1
  41. package/dist/esm/index.js +1 -1
  42. package/dist/esm/props/index.js +1 -1
  43. package/package.json +1 -1
  44. package/src/components/segmented-control.css +43 -0
  45. package/src/components/segmented-control.props.tsx +5 -0
  46. package/src/components/shell.css +7 -7
  47. package/src/components/sidebar.css +22 -9
  48. package/src/components/text-field.css +138 -0
  49. package/src/components/text-field.props.tsx +16 -1
  50. package/src/components/text-field.tsx +48 -4
  51. package/styles.css +246 -42
  52. package/dist/esm/chunk-2ZLMWYJ6.js +0 -2
  53. package/dist/esm/chunk-2ZLMWYJ6.js.map +0 -7
  54. package/dist/esm/chunk-BP64M73W.js +0 -2
  55. package/dist/esm/chunk-BP64M73W.js.map +0 -7
  56. package/dist/esm/chunk-W4Z6ORYO.js +0 -3
  57. package/dist/esm/chunk-ZOUIIO4C.js +0 -6
  58. package/dist/esm/chunk-ZOUIIO4C.js.map +0 -7
@@ -305,7 +305,7 @@
305
305
 
306
306
  /*
307
307
  * How tall the floating row is: one control row plus the row's padding on both sides, worked
308
- * out in CSS so the first paint is right. The padding is the pane's surface padding at the
308
+ * out in CSS so the first paint is right. The padding is the pane's panel padding at the
309
309
  * Shell's index, the same the row itself pads by. A Toolbar in the row publishes its own control
310
310
  * height as the band (one step above the Shell's when it states no size).
311
311
  */
@@ -316,7 +316,7 @@
316
316
  .kui-ShellBottomContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-1)),
317
317
  .kui-ShellContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-1)) {
318
318
  --kui-pane-row-start: var(--control-height-1);
319
- --kui-pane-pad-start: var(--surface-p-1);
319
+ --kui-pane-pad-start: var(--panel-p-1);
320
320
  }
321
321
  .kui-ShellRailContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-2)),
322
322
  .kui-ShellPanelContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-2)),
@@ -325,7 +325,7 @@
325
325
  .kui-ShellBottomContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-2)),
326
326
  .kui-ShellContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-2)) {
327
327
  --kui-pane-row-start: var(--control-height-2);
328
- --kui-pane-pad-start: var(--surface-p-2);
328
+ --kui-pane-pad-start: var(--panel-p-2);
329
329
  }
330
330
  .kui-ShellRailContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-3)),
331
331
  .kui-ShellPanelContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-3)),
@@ -334,7 +334,7 @@
334
334
  .kui-ShellBottomContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-3)),
335
335
  .kui-ShellContent:has(> .kui-ShellPaneHeader[data-float]:where(.kui-r-size-3)) {
336
336
  --kui-pane-row-start: var(--control-height-3);
337
- --kui-pane-pad-start: var(--surface-p-3);
337
+ --kui-pane-pad-start: var(--panel-p-3);
338
338
  }
339
339
  .kui-ShellRailContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-1)),
340
340
  .kui-ShellPanelContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-1)),
@@ -343,7 +343,7 @@
343
343
  .kui-ShellBottomContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-1)),
344
344
  .kui-ShellContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-1)) {
345
345
  --kui-pane-row-end: var(--control-height-1);
346
- --kui-pane-pad-end: var(--surface-p-1);
346
+ --kui-pane-pad-end: var(--panel-p-1);
347
347
  }
348
348
  .kui-ShellRailContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-2)),
349
349
  .kui-ShellPanelContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-2)),
@@ -352,7 +352,7 @@
352
352
  .kui-ShellBottomContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-2)),
353
353
  .kui-ShellContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-2)) {
354
354
  --kui-pane-row-end: var(--control-height-2);
355
- --kui-pane-pad-end: var(--surface-p-2);
355
+ --kui-pane-pad-end: var(--panel-p-2);
356
356
  }
357
357
  .kui-ShellRailContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-3)),
358
358
  .kui-ShellPanelContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-3)),
@@ -361,7 +361,7 @@
361
361
  .kui-ShellBottomContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-3)),
362
362
  .kui-ShellContent:has(> .kui-ShellPaneFooter[data-float]:where(.kui-r-size-3)) {
363
363
  --kui-pane-row-end: var(--control-height-3);
364
- --kui-pane-pad-end: var(--surface-p-3);
364
+ --kui-pane-pad-end: var(--panel-p-3);
365
365
  }
366
366
  .kui-ShellRailContent:has(> .kui-ShellPaneHeader[data-float] > .kui-Toolbar:where(.kui-r-size-1)),
367
367
  .kui-ShellPanelContent:has(> .kui-ShellPaneHeader[data-float] > .kui-Toolbar:where(.kui-r-size-1)),
@@ -344,6 +344,12 @@
344
344
  }
345
345
  }
346
346
 
347
+ /* A header or footer beside the pane's list shares one inset with it: the list already pads
348
+ by the same amount, so the row drops its padding on that side instead of doubling it. */
349
+ .kui-SidebarHeader:where(.kui-SidebarHeader--container:not([data-float]):has(+ .kui-ShellScroll)) {
350
+ padding-bottom: 0;
351
+ }
352
+
347
353
  .kui-SidebarFooter:where(.kui-SidebarFooter--container) {
348
354
  display: flex;
349
355
  flex-direction: row;
@@ -363,6 +369,11 @@
363
369
  }
364
370
  }
365
371
 
372
+ /* Second half of the shared inset above; after the footer's own padding, at its specificity. */
373
+ :where(.kui-ShellScroll) + .kui-SidebarFooter:where(.kui-SidebarFooter--container:not([data-float])) {
374
+ padding-top: 0;
375
+ }
376
+
366
377
  /* Header/Footer Menu Button Support */
367
378
  .kui-SidebarHeader :where(.kui-SidebarMenuButton),
368
379
  .kui-SidebarFooter :where(.kui-SidebarMenuButton) {
@@ -416,18 +427,20 @@
416
427
  TextField of size N, with the row family's pill padding, gap and icon box. Content is a
417
428
  BaseMenuContent, so it takes every other size value from base-menu.css. Header and
418
429
  Footer are not, so they restate base-menu's values here; keep the two in step. */
419
- /* A Shell pane is a surface: its header, footer, search and scrolling list all pad by the
420
- surface padding at the Shell's index, so every row and every control in the pane starts on
421
- one line. The Rail is left out: its tiles keep their own tight padding (above). */
430
+ /* A Shell pane's header, footer, search and scrolling list all pad by the panel padding at
431
+ the Shell's index, so every row and every control in the pane starts on one line. Panel,
432
+ not surface: a pane is chrome that holds rows, like a menu, and a card's 24px around a
433
+ 32px control row read as padded twice (docs/LOG.md, 2026-10-27). The Rail is left out:
434
+ its tiles keep their own tight padding (above). */
422
435
  .kui-ShellPaneChrome {
423
436
  &:where(.kui-r-size-1) {
424
- --sidebar-base-padding: var(--surface-p-1);
437
+ --sidebar-base-padding: var(--panel-p-1);
425
438
  }
426
439
  &:where(.kui-r-size-2) {
427
- --sidebar-base-padding: var(--surface-p-2);
440
+ --sidebar-base-padding: var(--panel-p-2);
428
441
  }
429
442
  &:where(.kui-r-size-3) {
430
- --sidebar-base-padding: var(--surface-p-3);
443
+ --sidebar-base-padding: var(--panel-p-3);
431
444
  }
432
445
  }
433
446
 
@@ -435,13 +448,13 @@
435
448
  /* stylelint-disable selector-max-specificity */
436
449
  .kui-SidebarContent.kui-ShellPaneChrome:not(.kui-ShellRailContent *) {
437
450
  &:where(.kui-r-size-1) {
438
- --base-menu-content-padding: var(--surface-p-1);
451
+ --base-menu-content-padding: var(--panel-p-1);
439
452
  }
440
453
  &:where(.kui-r-size-2) {
441
- --base-menu-content-padding: var(--surface-p-2);
454
+ --base-menu-content-padding: var(--panel-p-2);
442
455
  }
443
456
  &:where(.kui-r-size-3) {
444
- --base-menu-content-padding: var(--surface-p-3);
457
+ --base-menu-content-padding: var(--panel-p-3);
445
458
  }
446
459
  }
447
460
  /* stylelint-enable selector-max-specificity */
@@ -738,3 +738,141 @@
738
738
  filter: none;
739
739
  }
740
740
  }
741
+
742
+ /***************************************************************************************************
743
+ * *
744
+ * GROUP *
745
+ * *
746
+ ***************************************************************************************************/
747
+
748
+ /*
749
+ * TextField.Group joins its fields into one control, such as X, Y and Z. The group draws the
750
+ * variant's edge once, over the fields, so a field's fill never covers it. Each field keeps its
751
+ * fill, hover and focus ring; its own edge goes, its inner corners are square, and a hairline
752
+ * divides it from the one before.
753
+ */
754
+
755
+ /* stylelint-disable selector-max-specificity */
756
+
757
+ .kui-TextFieldGroup {
758
+ display: grid;
759
+ grid-auto-flow: column;
760
+ grid-auto-columns: minmax(0, 1fr);
761
+ position: relative;
762
+ isolation: isolate;
763
+ border-radius: var(--text-field-border-radius);
764
+
765
+ &::after {
766
+ content: '';
767
+ position: absolute;
768
+ inset: 0;
769
+ z-index: 2;
770
+ border-radius: inherit;
771
+ box-shadow: var(--text-field-group-edge);
772
+ pointer-events: none;
773
+ }
774
+ }
775
+
776
+ @breakpoints {
777
+ .kui-TextFieldGroup {
778
+ &:where(.kui-r-size-1) {
779
+ --text-field-border-radius: var(--radius-control-1);
780
+ }
781
+ &:where(.kui-r-size-2) {
782
+ --text-field-border-radius: var(--radius-control-2);
783
+ }
784
+ &:where(.kui-r-size-3) {
785
+ --text-field-border-radius: var(--radius-control-3);
786
+ }
787
+ &:where(.kui-r-size-4) {
788
+ --text-field-border-radius: var(--radius-control-4);
789
+ }
790
+ }
791
+ }
792
+
793
+ /* Each variant's edge and divider are the ones its single field draws. */
794
+ .kui-TextFieldGroup:where(.kui-variant-raised) {
795
+ --text-field-group-edge: var(--control-chrome);
796
+ --text-field-group-divider: var(--neutral-a4);
797
+
798
+ &:where([data-disabled]) {
799
+ --text-field-group-edge: inset 0 0 0 1px var(--field-edge-disabled);
800
+ }
801
+ }
802
+
803
+ .kui-TextFieldGroup:where(.kui-variant-outline, .kui-variant-surface) {
804
+ --text-field-group-edge: inset 0 0 0 1px var(--accent-6);
805
+ --text-field-group-divider: var(--accent-6);
806
+
807
+ &:where([data-disabled]) {
808
+ --text-field-group-edge: inset 0 0 0 1px var(--neutral-a6);
809
+ --text-field-group-divider: var(--neutral-a6);
810
+ }
811
+ }
812
+
813
+ .kui-TextFieldGroup:where(.kui-variant-soft) {
814
+ --text-field-group-edge: none;
815
+ --text-field-group-divider: var(--accent-a5);
816
+ }
817
+
818
+ /* ghost: the dividers alone. Each field keeps its ghost hover and focus fill. */
819
+ .kui-TextFieldGroup:where(.kui-variant-ghost) {
820
+ --text-field-group-edge: none;
821
+ --text-field-group-divider: var(--neutral-a5);
822
+ }
823
+
824
+ .kui-TextFieldGroup > .kui-TextFieldWrapper > .kui-TextFieldRoot {
825
+ position: relative;
826
+ border-radius: 0;
827
+ box-shadow: none;
828
+
829
+ /* The focus ring and an invalid edge draw above the group's edge. */
830
+ &:focus-within {
831
+ z-index: 3;
832
+ }
833
+ }
834
+
835
+ .kui-TextFieldGroup > .kui-TextFieldWrapper:first-child > .kui-TextFieldRoot {
836
+ border-start-start-radius: var(--text-field-border-radius);
837
+ border-end-start-radius: var(--text-field-border-radius);
838
+ }
839
+
840
+ .kui-TextFieldGroup > .kui-TextFieldWrapper:last-child > .kui-TextFieldRoot {
841
+ border-start-end-radius: var(--text-field-border-radius);
842
+ border-end-end-radius: var(--text-field-border-radius);
843
+ }
844
+
845
+ .kui-TextFieldGroup > .kui-TextFieldWrapper + .kui-TextFieldWrapper > .kui-TextFieldRoot::before {
846
+ content: '';
847
+ position: absolute;
848
+ z-index: 1;
849
+ inset-block: 0;
850
+ inset-inline-start: 0;
851
+ width: 1px;
852
+ background-color: var(--text-field-group-divider);
853
+ pointer-events: none;
854
+ }
855
+
856
+ /* A focused field's ring is its edge, so the hairlines on either side of it step back. */
857
+ .kui-TextFieldGroup > .kui-TextFieldWrapper > .kui-TextFieldRoot:focus-within::before,
858
+ .kui-TextFieldGroup > .kui-TextFieldWrapper:has(> .kui-TextFieldRoot:focus-within) + .kui-TextFieldWrapper > .kui-TextFieldRoot::before {
859
+ opacity: 0;
860
+ }
861
+
862
+ /* An invalid field keeps its red edge, on its own segment only. */
863
+ .kui-TextFieldGroup > .kui-TextFieldWrapper > .kui-TextFieldRoot:has(> .kui-TextFieldInput[aria-invalid='true']) {
864
+ z-index: 3;
865
+ box-shadow: inset 0 0 0 1px var(--red-6);
866
+ }
867
+
868
+
869
+ @media (forced-colors: active) {
870
+ .kui-TextFieldGroup {
871
+ border: 1px solid CanvasText;
872
+ }
873
+ .kui-TextFieldGroup > .kui-TextFieldWrapper > .kui-TextFieldRoot {
874
+ border: none;
875
+ }
876
+ }
877
+
878
+ /* stylelint-enable selector-max-specificity */
@@ -30,6 +30,21 @@ const textFieldRootPropDefs = {
30
30
  'aria-labelledby': PropDef<string | undefined>;
31
31
  };
32
32
 
33
+ // Ghost is the dividers alone: no fill, no edge.
34
+ const groupVariants = ['raised', 'surface', 'soft', 'outline', 'ghost'] as const;
35
+
36
+ const textFieldGroupPropDefs = {
37
+ size: { type: 'enum', className: 'kui-r-size', values: sizes, default: '2', responsive: true },
38
+ variant: { type: 'enum', className: 'kui-variant', values: groupVariants, default: 'raised' },
39
+ disabled: { type: 'boolean', default: false },
40
+ ...colorPropDef,
41
+ ...radiusPropDef,
42
+ } satisfies {
43
+ size: PropDef<(typeof sizes)[number]>;
44
+ variant: PropDef<(typeof groupVariants)[number]>;
45
+ disabled: PropDef<boolean>;
46
+ };
47
+
33
48
  const sides = ['left', 'right'] as const;
34
49
 
35
50
  const textFieldSlotPropDefs = {
@@ -75,4 +90,4 @@ interface TextFieldSlotScrubProps {
75
90
 
76
91
  export type { TextFieldSlotScrubProps };
77
92
 
78
- export { textFieldRootPropDefs, textFieldSlotPropDefs };
93
+ export { textFieldRootPropDefs, textFieldGroupPropDefs, textFieldSlotPropDefs };
@@ -5,7 +5,7 @@ import * as ReactDOM from 'react-dom';
5
5
  import classNames from 'classnames';
6
6
  import { composeEventHandlers, composeRefs, useLayoutEffect } from 'radix-ui/internal';
7
7
 
8
- import { textFieldRootPropDefs, textFieldSlotPropDefs, type TextFieldSlotScrubProps } from './text-field.props.js';
8
+ import { textFieldRootPropDefs, textFieldGroupPropDefs, textFieldSlotPropDefs, type TextFieldSlotScrubProps } from './text-field.props.js';
9
9
  import { extractProps } from '../helpers/extract-props.js';
10
10
  import { mergeStyles } from '../helpers/merge-styles.js';
11
11
  import { useThemeSizeProps } from '../hooks/theme-size.js';
@@ -31,7 +31,23 @@ const TextFieldContext = React.createContext<TextFieldContextValue | null>(null)
31
31
  // list, not a tag list. `[tabindex]` catches role-based widgets; `label` already redirects a click.
32
32
  const FOCUSABLE_IN_SLOT = 'button, a, input, select, textarea, label, [tabindex], [contenteditable]';
33
33
 
34
- const TextFieldRoot = React.forwardRef<TextFieldRootElement, TextFieldRootProps>((ownProps, forwardedRef) => {
34
+ // A Group decides the look of its fields: their size, variant and radius come from it. A field
35
+ // can still take its own color, and is disabled when either it or the group is.
36
+ type TextFieldGroupContextValue = Pick<TextFieldGroupOwnProps, 'size' | 'variant' | 'radius' | 'color' | 'disabled'>;
37
+ const TextFieldGroupContext = React.createContext<TextFieldGroupContextValue | null>(null);
38
+
39
+ const TextFieldRoot = React.forwardRef<TextFieldRootElement, TextFieldRootProps>((fieldProps, forwardedRef) => {
40
+ const group = React.useContext(TextFieldGroupContext);
41
+ const ownProps = group
42
+ ? {
43
+ ...fieldProps,
44
+ size: group.size,
45
+ variant: group.variant,
46
+ radius: group.radius,
47
+ color: fieldProps.color ?? group.color,
48
+ disabled: Boolean(group.disabled || fieldProps.disabled),
49
+ }
50
+ : fieldProps;
35
51
  // The caller's className and style are kept apart from the size and variant classes: with an
36
52
  // error message they go on the wrapper, which is then the one box the parent lays out.
37
53
  const { className: ownClassName, style: ownStyle, ...themedProps } = useThemeSizeProps(ownProps, textFieldRootPropDefs.size);
@@ -137,6 +153,34 @@ const TextFieldRoot = React.forwardRef<TextFieldRootElement, TextFieldRootProps>
137
153
  });
138
154
  TextFieldRoot.displayName = 'TextField.Root';
139
155
 
156
+ type TextFieldGroupOwnProps = GetPropDefTypes<typeof textFieldGroupPropDefs>;
157
+ interface TextFieldGroupProps extends ComponentPropsWithout<'div', RemovedProps>, TextFieldGroupOwnProps {}
158
+
159
+ /**
160
+ * Joins two or more fields into one, such as X, Y and Z: one edge, square inner corners and a
161
+ * hairline between the fields. The group draws the edge, so each field keeps only its fill.
162
+ */
163
+ const TextFieldGroup = React.forwardRef<HTMLDivElement, TextFieldGroupProps>((ownProps, forwardedRef) => {
164
+ const props = useThemeSizeProps(ownProps, textFieldGroupPropDefs.size);
165
+ const { size, variant, radius, color, disabled } = props;
166
+ const { className, children, radius: _radius, color: _color, disabled: _disabled, ...domProps } = extractProps(props, textFieldGroupPropDefs);
167
+ const contextValue = React.useMemo(() => ({ size, variant, radius, color, disabled }), [size, variant, radius, color, disabled]);
168
+ return (
169
+ <div
170
+ role="group"
171
+ data-accent-color={color}
172
+ data-radius={radius}
173
+ data-disabled={disabled || undefined}
174
+ {...domProps}
175
+ ref={forwardedRef}
176
+ className={classNames('kui-TextFieldGroup', className)}
177
+ >
178
+ <TextFieldGroupContext.Provider value={contextValue}>{children}</TextFieldGroupContext.Provider>
179
+ </div>
180
+ );
181
+ });
182
+ TextFieldGroup.displayName = 'TextField.Group';
183
+
140
184
  type TextFieldSlotElement = React.ElementRef<'div'>;
141
185
  type TextFieldSlotOwnProps = GetPropDefTypes<typeof textFieldSlotPropDefs> & TextFieldSlotScrubProps;
142
186
  interface TextFieldSlotProps extends ComponentPropsWithout<'div', RemovedProps>, TextFieldSlotOwnProps {}
@@ -478,5 +522,5 @@ const TextFieldSlot = React.forwardRef<TextFieldSlotElement, TextFieldSlotProps>
478
522
  });
479
523
  TextFieldSlot.displayName = 'TextField.Slot';
480
524
 
481
- export { TextFieldRoot as Root, TextFieldSlot as Slot };
482
- export type { TextFieldRootProps as RootProps, TextFieldSlotProps as SlotProps };
525
+ export { TextFieldRoot as Root, TextFieldGroup as Group, TextFieldSlot as Slot };
526
+ export type { TextFieldRootProps as RootProps, TextFieldGroupProps as GroupProps, TextFieldSlotProps as SlotProps };