@leafygreen-ui/combobox 1.2.2 → 2.0.2

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 (41) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/Chip.d.ts.map +1 -1
  3. package/dist/Combobox.d.ts.map +1 -1
  4. package/dist/Combobox.styles.d.ts +39 -39
  5. package/dist/Combobox.styles.d.ts.map +1 -1
  6. package/dist/Combobox.types.d.ts +5 -0
  7. package/dist/Combobox.types.d.ts.map +1 -1
  8. package/dist/ComboboxContext.d.ts +5 -1
  9. package/dist/ComboboxContext.d.ts.map +1 -1
  10. package/dist/ComboboxGroup.d.ts.map +1 -1
  11. package/dist/ComboboxMenu/ComboboxMenu.d.ts +10 -0
  12. package/dist/ComboboxMenu/ComboboxMenu.d.ts.map +1 -0
  13. package/dist/ComboboxMenu/Menu.styles.d.ts +25 -0
  14. package/dist/ComboboxMenu/Menu.styles.d.ts.map +1 -0
  15. package/dist/ComboboxOption.d.ts.map +1 -1
  16. package/dist/ComboboxTestUtils.d.ts.map +1 -1
  17. package/dist/Menu.styles.d.ts +21 -0
  18. package/dist/Menu.styles.d.ts.map +1 -0
  19. package/dist/esm/index.js +1 -1
  20. package/dist/esm/index.js.map +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/utils/wrapJSX.d.ts.map +1 -1
  24. package/package.json +12 -9
  25. package/src/Chip.tsx +125 -91
  26. package/src/Combobox.spec.tsx +3 -1
  27. package/src/Combobox.story.tsx +4 -2
  28. package/src/Combobox.styles.ts +250 -299
  29. package/src/Combobox.tsx +162 -190
  30. package/src/Combobox.types.ts +7 -0
  31. package/src/ComboboxContext.tsx +16 -1
  32. package/src/ComboboxGroup.tsx +27 -17
  33. package/src/ComboboxMenu/ComboboxMenu.tsx +161 -0
  34. package/src/ComboboxMenu/Menu.styles.ts +131 -0
  35. package/src/ComboboxOption.tsx +120 -32
  36. package/src/ComboboxTestUtils.tsx +3 -2
  37. package/src/Menu.styles.ts +110 -0
  38. package/src/utils/ComboboxUtils.spec.tsx +23 -0
  39. package/src/utils/wrapJSX.tsx +3 -1
  40. package/tsconfig.json +0 -3
  41. package/tsconfig.tsbuildinfo +1 -1
package/src/Combobox.tsx CHANGED
@@ -1,3 +1,9 @@
1
+ import clone from 'lodash/clone';
2
+ import isArray from 'lodash/isArray';
3
+ import isEqual from 'lodash/isEqual';
4
+ import isNull from 'lodash/isNull';
5
+ import isString from 'lodash/isString';
6
+ import isUndefined from 'lodash/isUndefined';
1
7
  import React, {
2
8
  useCallback,
3
9
  useEffect,
@@ -5,11 +11,8 @@ import React, {
5
11
  useRef,
6
12
  useState,
7
13
  } from 'react';
8
- import { clone, isArray, isEqual, isNull, isString, isUndefined } from 'lodash';
9
14
  import { Description, Label } from '@leafygreen-ui/typography';
10
- import Popover from '@leafygreen-ui/popover';
11
15
  import {
12
- useAvailableSpace,
13
16
  useDynamicRefs,
14
17
  useEventListener,
15
18
  useIdAllocator,
@@ -17,8 +20,8 @@ import {
17
20
  } from '@leafygreen-ui/hooks';
18
21
  import Icon from '@leafygreen-ui/icon';
19
22
  import IconButton from '@leafygreen-ui/icon-button';
20
- import { css, cx } from '@leafygreen-ui/emotion';
21
- import { uiColors } from '@leafygreen-ui/palette';
23
+ import { cx } from '@leafygreen-ui/emotion';
24
+ import { palette } from '@leafygreen-ui/palette';
22
25
  import { consoleOnce, isComponentType, keyMap } from '@leafygreen-ui/lib';
23
26
  import {
24
27
  ComboboxProps,
@@ -28,28 +31,8 @@ import {
28
31
  OptionObject,
29
32
  ComboboxElement,
30
33
  ComboboxSize,
34
+ State,
31
35
  } from './Combobox.types';
32
- import { ComboboxContext } from './ComboboxContext';
33
- import { InternalComboboxOption } from './ComboboxOption';
34
- import { Chip } from './Chip';
35
- import {
36
- clearButtonStyle,
37
- clearButtonFocusOverrideStyles,
38
- comboboxFocusStyle,
39
- comboboxParentStyle,
40
- comboboxStyle,
41
- endIcon,
42
- errorMessageStyle,
43
- inputElementStyle,
44
- inputWrapperStyle,
45
- loadingIconStyle,
46
- menuList,
47
- menuMessage,
48
- menuStyle,
49
- menuWrapperStyle,
50
- _tempLabelDescriptionOverrideStyle,
51
- } from './Combobox.styles';
52
- import { InternalComboboxGroup } from './ComboboxGroup';
53
36
  import {
54
37
  flattenChildren,
55
38
  getOptionObjectFromValue,
@@ -57,6 +40,32 @@ import {
57
40
  getValueForDisplayName,
58
41
  getNameAndValue,
59
42
  } from './utils';
43
+ import { ComboboxContext, useDarkMode } from './ComboboxContext';
44
+ import { InternalComboboxGroup } from './ComboboxGroup';
45
+ import { InternalComboboxOption } from './ComboboxOption';
46
+ import { Chip } from './Chip';
47
+ import {
48
+ comboboxFocusStyle,
49
+ inputWrapperStyle,
50
+ baseComboboxStyles,
51
+ comboboxThemeStyles,
52
+ comboboxSizeStyles,
53
+ comboboxDisabledStyles,
54
+ comboboxErrorStyles,
55
+ comboboxParentStyle,
56
+ baseInputElementStyle,
57
+ inputElementSizeStyle,
58
+ inputElementTransitionStyles,
59
+ multiselectInputElementStyle,
60
+ clearButtonStyle,
61
+ endIconStyle,
62
+ errorMessageThemeStyle,
63
+ errorMessageSizeStyle,
64
+ multiselectInputElementPadding,
65
+ labelDescriptionContainerStyle,
66
+ inputElementThemeStyle,
67
+ } from './Combobox.styles';
68
+ import { ComboboxMenu } from './ComboboxMenu/ComboboxMenu';
60
69
 
61
70
  /**
62
71
  * Combobox is a combination of a Select and TextInput,
@@ -97,6 +106,7 @@ export default function Combobox<M extends boolean>({
97
106
  popoverZIndex,
98
107
  ...rest
99
108
  }: ComboboxProps<M>) {
109
+ const theme = useDarkMode(darkMode);
100
110
  const getOptionRef = useDynamicRefs<HTMLLIElement>({ prefix: 'option' });
101
111
  const getChipRef = useDynamicRefs<HTMLSpanElement>({ prefix: 'chip' });
102
112
 
@@ -357,6 +367,8 @@ export default function Combobox<M extends boolean>({
357
367
  const [focusedElementName, trackFocusedElement] = useState<
358
368
  ComboboxElement | undefined
359
369
  >();
370
+ const isElementFocused = (elementName: ComboboxElement) =>
371
+ elementName === focusedElementName;
360
372
 
361
373
  type Direction = 'next' | 'prev' | 'first' | 'last';
362
374
 
@@ -595,74 +607,75 @@ export default function Combobox<M extends boolean>({
595
607
  */
596
608
 
597
609
  /**
598
- * Callback to render the children as <InternalComboboxOption> elements
610
+ * Callback to render a child as an <InternalComboboxOption> element
599
611
  */
600
- const renderInternalOptions = useCallback(
601
- (_children: React.ReactNode) => {
602
- return React.Children.map(_children, child => {
603
- if (isComponentType(child, 'ComboboxOption')) {
604
- const { value, displayName } = getNameAndValue(child.props);
605
-
606
- if (shouldOptionBeVisible(value)) {
607
- const { className, glyph, disabled } = child.props;
608
- const index = allOptions.findIndex(opt => opt.value === value);
609
-
610
- const isFocused = highlightedOption === value;
611
- const isSelected = isMultiselect(selection)
612
- ? selection.includes(value)
613
- : selection === value;
614
-
615
- const setSelected = () => {
616
- sethighlightedOption(value);
617
- updateSelection(value);
618
- setInputFocus();
619
-
620
- if (value === selection) {
621
- closeMenu();
622
- }
623
- };
624
-
625
- const optionRef = getOptionRef(value);
626
-
627
- return (
628
- <InternalComboboxOption
629
- value={value}
630
- displayName={displayName}
631
- isFocused={isFocused}
632
- isSelected={isSelected}
633
- disabled={disabled}
634
- setSelected={setSelected}
635
- glyph={glyph}
636
- className={className}
637
- index={index}
638
- ref={optionRef}
639
- />
640
- );
641
- }
642
- } else if (isComponentType(child, 'ComboboxGroup')) {
643
- const nestedChildren = renderInternalOptions(child.props.children);
644
-
645
- if (nestedChildren && nestedChildren?.length > 0) {
646
- return (
647
- <InternalComboboxGroup
648
- label={child.props.label}
649
- className={child.props.className}
650
- >
651
- {renderInternalOptions(nestedChildren)}
652
- </InternalComboboxGroup>
653
- );
654
- }
612
+ const renderOption = useCallback(
613
+ (child: React.ReactNode) => {
614
+ if (isComponentType(child, 'ComboboxOption')) {
615
+ const { value, displayName } = getNameAndValue(child.props);
616
+
617
+ if (shouldOptionBeVisible(value)) {
618
+ const { className, glyph, disabled } = child.props;
619
+ const index = allOptions.findIndex(opt => opt.value === value);
620
+
621
+ const isFocused = highlightedOption === value;
622
+ const isSelected = isMultiselect(selection)
623
+ ? selection.includes(value)
624
+ : selection === value;
625
+
626
+ const setSelected = () => {
627
+ sethighlightedOption(value);
628
+ updateSelection(value);
629
+ setInputFocus();
630
+
631
+ if (value === selection) {
632
+ closeMenu();
633
+ }
634
+ };
635
+
636
+ const optionRef = getOptionRef(value);
637
+
638
+ return (
639
+ <InternalComboboxOption
640
+ value={value}
641
+ displayName={displayName}
642
+ isFocused={isFocused}
643
+ isSelected={isSelected}
644
+ disabled={disabled}
645
+ setSelected={setSelected}
646
+ glyph={glyph}
647
+ className={className}
648
+ index={index}
649
+ ref={optionRef}
650
+ />
651
+ );
655
652
  }
656
- });
653
+ } else if (isComponentType(child, 'ComboboxGroup')) {
654
+ const nestedChildren = React.Children.map(
655
+ child.props.children,
656
+ renderOption,
657
+ );
658
+
659
+ if (nestedChildren && nestedChildren?.length > 0) {
660
+ return (
661
+ <InternalComboboxGroup
662
+ label={child.props.label}
663
+ className={child.props.className}
664
+ >
665
+ {React.Children.map(nestedChildren, renderOption)}
666
+ </InternalComboboxGroup>
667
+ );
668
+ }
669
+ }
657
670
  },
658
671
  [
659
672
  allOptions,
660
- highlightedOption,
661
673
  getOptionRef,
674
+ highlightedOption,
662
675
  isMultiselect,
663
- shouldOptionBeVisible,
664
676
  selection,
665
677
  setInputFocus,
678
+ shouldOptionBeVisible,
666
679
  updateSelection,
667
680
  ],
668
681
  );
@@ -671,8 +684,8 @@ export default function Combobox<M extends boolean>({
671
684
  * The rendered JSX elements for the options
672
685
  */
673
686
  const renderedOptionsJSX = useMemo(
674
- () => renderInternalOptions(children),
675
- [children, renderInternalOptions],
687
+ () => React.Children.map(children, renderOption),
688
+ [children, renderOption],
676
689
  );
677
690
 
678
691
  /**
@@ -752,15 +765,20 @@ export default function Combobox<M extends boolean>({
752
765
  ref={clearButtonRef}
753
766
  onClick={handleClearButtonClick}
754
767
  onFocus={handleClearButtonFocus}
755
- className={cx(clearButtonStyle, clearButtonFocusOverrideStyles)}
768
+ className={cx(clearButtonStyle)}
769
+ darkMode={darkMode}
756
770
  >
757
771
  <Icon glyph="XWithCircle" />
758
772
  </IconButton>
759
773
  )}
760
774
  {state === 'error' ? (
761
- <Icon glyph="Warning" color={uiColors.red.base} className={endIcon} />
775
+ <Icon
776
+ glyph="Warning"
777
+ color={darkMode ? palette.red.light1 : palette.red.base}
778
+ className={endIconStyle(size)}
779
+ />
762
780
  ) : (
763
- <Icon glyph="CaretDown" className={endIcon} />
781
+ <Icon glyph="CaretDown" className={endIconStyle(size)} />
764
782
  )}
765
783
  </>
766
784
  );
@@ -769,6 +787,8 @@ export default function Combobox<M extends boolean>({
769
787
  doesSelectionExist,
770
788
  disabled,
771
789
  state,
790
+ darkMode,
791
+ size,
772
792
  updateSelection,
773
793
  onClear,
774
794
  onFilter,
@@ -906,62 +926,11 @@ export default function Combobox<M extends boolean>({
906
926
  setMenuWidth(comboboxRef.current?.clientWidth ?? 0);
907
927
  }, [comboboxRef, isOpen, highlightedOption, selection]);
908
928
 
909
- // Handler fired when the manu has finished transitioning in/out
929
+ // Handler fired when the menu has finished transitioning in/out
910
930
  const handleTransitionEnd = () => {
911
931
  setMenuWidth(comboboxRef.current?.clientWidth ?? 0);
912
932
  };
913
933
 
914
- /**
915
- * The rendered menu JSX contents
916
- * Includes error, empty, search and default states
917
- */
918
- const renderedMenuContents = useMemo((): JSX.Element => {
919
- switch (searchState) {
920
- case 'loading': {
921
- return (
922
- <span className={menuMessage}>
923
- <Icon
924
- glyph="Refresh"
925
- color={uiColors.blue.base}
926
- className={loadingIconStyle}
927
- />
928
- {searchLoadingMessage}
929
- </span>
930
- );
931
- }
932
-
933
- case 'error': {
934
- return (
935
- <span className={menuMessage}>
936
- <Icon glyph="Warning" color={uiColors.red.base} />
937
- {searchErrorMessage}
938
- </span>
939
- );
940
- }
941
-
942
- case 'unset':
943
- default: {
944
- if (renderedOptionsJSX && renderedOptionsJSX.length > 0) {
945
- return <ul className={menuList}>{renderedOptionsJSX}</ul>;
946
- }
947
-
948
- return <span className={menuMessage}>{searchEmptyMessage}</span>;
949
- }
950
- }
951
- }, [
952
- renderedOptionsJSX,
953
- searchEmptyMessage,
954
- searchErrorMessage,
955
- searchLoadingMessage,
956
- searchState,
957
- ]);
958
-
959
- /** The max height of the menu element */
960
- const availableSpace = useAvailableSpace(comboboxRef);
961
- const maxHeightValue = !isUndefined(availableSpace)
962
- ? `${Math.min(availableSpace, 256)}px`
963
- : 'unset';
964
-
965
934
  /**
966
935
  *
967
936
  * Event Handlers
@@ -1214,32 +1183,26 @@ export default function Combobox<M extends boolean>({
1214
1183
  size,
1215
1184
  withIcons,
1216
1185
  disabled,
1186
+ isOpen,
1187
+ state,
1188
+ searchState,
1217
1189
  chipTruncationLocation,
1218
1190
  chipCharacterLimit,
1219
1191
  inputValue,
1220
1192
  }}
1221
1193
  >
1222
1194
  <div
1223
- className={cx(
1224
- comboboxParentStyle({ darkMode, size, overflow }),
1225
- className,
1226
- )}
1195
+ className={cx(comboboxParentStyle(size, overflow), className)}
1227
1196
  {...rest}
1228
1197
  >
1229
- <div>
1198
+ <div className={labelDescriptionContainerStyle}>
1230
1199
  {label && (
1231
- <Label
1232
- id={labelId}
1233
- htmlFor={inputId}
1234
- className={_tempLabelDescriptionOverrideStyle}
1235
- >
1200
+ <Label id={labelId} htmlFor={inputId} darkMode={darkMode}>
1236
1201
  {label}
1237
1202
  </Label>
1238
1203
  )}
1239
1204
  {description && (
1240
- <Description className={_tempLabelDescriptionOverrideStyle}>
1241
- {description}
1242
- </Description>
1205
+ <Description darkMode={darkMode}>{description}</Description>
1243
1206
  )}
1244
1207
  </div>
1245
1208
 
@@ -1252,25 +1215,29 @@ export default function Combobox<M extends boolean>({
1252
1215
  aria-controls={menuId}
1253
1216
  aria-owns={menuId}
1254
1217
  tabIndex={-1}
1255
- className={cx(comboboxStyle, {
1256
- [comboboxFocusStyle]: focusedElementName === ComboboxElement.Input,
1257
- })}
1258
1218
  onMouseDown={handleInputWrapperMousedown}
1259
1219
  onClick={handleComboboxClick}
1260
1220
  onFocus={handleComboboxFocus}
1261
1221
  onKeyDown={handleKeyDown}
1262
1222
  onTransitionEnd={handleTransitionEnd}
1263
- data-disabled={disabled}
1264
- data-state={state}
1223
+ className={cx(
1224
+ baseComboboxStyles,
1225
+ comboboxThemeStyles[theme],
1226
+ comboboxSizeStyles(size),
1227
+ {
1228
+ [comboboxDisabledStyles[theme]]: disabled,
1229
+ [comboboxErrorStyles[theme]]: state === State.error,
1230
+ [comboboxFocusStyle[theme]]: isElementFocused(
1231
+ ComboboxElement.Input,
1232
+ ),
1233
+ },
1234
+ )}
1265
1235
  >
1266
1236
  <div
1267
1237
  ref={inputWrapperRef}
1268
1238
  className={inputWrapperStyle({
1269
- overflow,
1270
- isOpen,
1271
- selection,
1272
1239
  size,
1273
- value: inputValue,
1240
+ overflow,
1274
1241
  })}
1275
1242
  >
1276
1243
  {renderedChips}
@@ -1281,7 +1248,18 @@ export default function Combobox<M extends boolean>({
1281
1248
  aria-labelledby={labelId}
1282
1249
  ref={inputRef}
1283
1250
  id={inputId}
1284
- className={inputElementStyle}
1251
+ className={cx(
1252
+ baseInputElementStyle,
1253
+ inputElementSizeStyle[size],
1254
+ inputElementThemeStyle[theme],
1255
+ inputElementTransitionStyles(isOpen, overflow),
1256
+ {
1257
+ [multiselectInputElementStyle(size, inputValue)]:
1258
+ isMultiselect(selection),
1259
+ [multiselectInputElementPadding(selection)]:
1260
+ isMultiselect(selection),
1261
+ },
1262
+ )}
1285
1263
  placeholder={placeholderValue}
1286
1264
  disabled={disabled ?? undefined}
1287
1265
  onChange={handleInputChange}
@@ -1293,39 +1271,33 @@ export default function Combobox<M extends boolean>({
1293
1271
  </div>
1294
1272
 
1295
1273
  {state === 'error' && errorMessage && (
1296
- <div className={errorMessageStyle}>{errorMessage}</div>
1274
+ <div
1275
+ className={cx(
1276
+ errorMessageThemeStyle[theme],
1277
+ errorMessageSizeStyle[size],
1278
+ )}
1279
+ >
1280
+ {errorMessage}
1281
+ </div>
1297
1282
  )}
1298
1283
 
1299
1284
  {/******* /
1300
1285
  * Menu *
1301
1286
  / *******/}
1302
- <Popover
1303
- active={isOpen && !disabled}
1304
- spacing={4}
1305
- align="bottom"
1306
- justify="middle"
1287
+
1288
+ <ComboboxMenu
1289
+ id={menuId}
1290
+ labelId={labelId}
1307
1291
  refEl={comboboxRef}
1308
- adjustOnMutation={true}
1309
- className={menuWrapperStyle({ darkMode, size, width: menuWidth })}
1292
+ ref={menuRef}
1293
+ menuWidth={menuWidth}
1294
+ searchLoadingMessage={searchLoadingMessage}
1295
+ searchErrorMessage={searchErrorMessage}
1296
+ searchEmptyMessage={searchEmptyMessage}
1310
1297
  {...popoverProps}
1311
1298
  >
1312
- <div
1313
- id={menuId}
1314
- role="listbox"
1315
- aria-labelledby={labelId}
1316
- aria-expanded={isOpen}
1317
- ref={menuRef}
1318
- className={cx(
1319
- menuStyle,
1320
- css`
1321
- max-height: ${maxHeightValue};
1322
- `,
1323
- )}
1324
- onMouseDownCapture={e => e.preventDefault()}
1325
- >
1326
- {renderedMenuContents}
1327
- </div>
1328
- </Popover>
1299
+ {renderedOptionsJSX}
1300
+ </ComboboxMenu>
1329
1301
  </div>
1330
1302
  </ComboboxContext.Provider>
1331
1303
  );
@@ -1,6 +1,13 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
2
  import { Either } from '@leafygreen-ui/lib';
3
3
 
4
+ export const Theme = {
5
+ Dark: 'dark',
6
+ Light: 'light',
7
+ } as const;
8
+
9
+ export type Theme = typeof Theme[keyof typeof Theme];
10
+
4
11
  /**
5
12
  * Prop Enums & Types
6
13
  */
@@ -1,5 +1,11 @@
1
1
  import { createContext } from 'react';
2
- import { ComboboxSize, TrunctationLocation } from './Combobox.types';
2
+ import {
3
+ ComboboxSize,
4
+ SearchState,
5
+ State,
6
+ Theme,
7
+ TrunctationLocation,
8
+ } from './Combobox.types';
3
9
 
4
10
  interface ComboboxData {
5
11
  multiselect: boolean;
@@ -7,6 +13,9 @@ interface ComboboxData {
7
13
  size: ComboboxSize;
8
14
  withIcons: boolean;
9
15
  disabled: boolean;
16
+ isOpen: boolean;
17
+ state: State;
18
+ searchState: SearchState;
10
19
  chipTruncationLocation?: TrunctationLocation;
11
20
  chipCharacterLimit?: number;
12
21
  inputValue?: string;
@@ -18,4 +27,10 @@ export const ComboboxContext = createContext<ComboboxData>({
18
27
  size: ComboboxSize.Default,
19
28
  withIcons: false,
20
29
  disabled: false,
30
+ isOpen: false,
31
+ state: State.none,
32
+ searchState: SearchState.unset,
21
33
  });
34
+
35
+ export const useDarkMode = (darkMode: boolean) =>
36
+ darkMode ? Theme.Dark : Theme.Light;
@@ -1,20 +1,18 @@
1
1
  import { css, cx } from '@leafygreen-ui/emotion';
2
2
  import { useIdAllocator } from '@leafygreen-ui/hooks';
3
- import { uiColors } from '@leafygreen-ui/palette';
3
+ import { palette } from '@leafygreen-ui/palette';
4
4
  import React, { useContext } from 'react';
5
- import { ComboboxGroupProps } from './Combobox.types';
6
- import { ComboboxContext } from './ComboboxContext';
7
-
8
- const comboboxGroupStyle = (darkMode: boolean) => css`
9
- --lg-combobox-group-label-color: ${darkMode
10
- ? uiColors.gray.light1
11
- : uiColors.gray.dark1};
12
- --lg-combobox-group-border-color: ${darkMode
13
- ? uiColors.gray.dark1
14
- : uiColors.gray.light1};
15
- padding-top: 8px;
16
- border-bottom: 1px solid var(--lg-combobox-group-border-color);
17
- `;
5
+ import { ComboboxGroupProps, Theme } from './Combobox.types';
6
+ import { ComboboxContext, useDarkMode } from './ComboboxContext';
7
+
8
+ const comboboxGroupStyle: Record<Theme, string> = {
9
+ [Theme.Light]: css`
10
+ padding-top: 8px;
11
+ `,
12
+ [Theme.Dark]: css`
13
+ padding-top: 8px;
14
+ `,
15
+ };
18
16
 
19
17
  const comboboxGroupLabel = css`
20
18
  cursor: default;
@@ -27,22 +25,34 @@ const comboboxGroupLabel = css`
27
25
  font-weight: bold;
28
26
  text-transform: uppercase;
29
27
  letter-spacing: 0.4px;
30
- color: var(--lg-combobox-group-label-color);
31
28
  `;
32
29
 
30
+ const comboboxGroupLabelThemeStyle: Record<Theme, string> = {
31
+ [Theme.Light]: css`
32
+ color: ${palette.gray.dark1};
33
+ `,
34
+ [Theme.Dark]: css`
35
+ color: ${palette.gray.light1};
36
+ `,
37
+ };
38
+
33
39
  export function InternalComboboxGroup({
34
40
  label,
35
41
  className,
36
42
  children,
37
43
  }: ComboboxGroupProps): JSX.Element {
38
44
  const { darkMode } = useContext(ComboboxContext);
45
+ const theme = useDarkMode(darkMode);
39
46
 
40
47
  const groupId = useIdAllocator({ prefix: 'combobox-group' });
41
48
  const childCount = React.Children.count(children);
42
49
 
43
50
  return childCount > 0 ? (
44
- <div className={cx(comboboxGroupStyle(darkMode), className)}>
45
- <div className={comboboxGroupLabel} id={groupId}>
51
+ <div className={cx(comboboxGroupStyle[theme], className)}>
52
+ <div
53
+ className={cx(comboboxGroupLabel, comboboxGroupLabelThemeStyle[theme])}
54
+ id={groupId}
55
+ >
46
56
  {label}
47
57
  </div>
48
58
  <div role="group" aria-labelledby={groupId}>