@vygruppen/spor-react 9.15.0 → 9.16.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @vygruppen/spor-react@9.15.0 build
2
+ > @vygruppen/spor-react@9.16.0 build
3
3
  > tsup src/index.tsx --dts --treeshake --format cjs,esm
4
4
 
5
5
  CLI Building entry: src/index.tsx
@@ -9,12 +9,12 @@
9
9
  CJS Build start
10
10
  ESM Build start
11
11
  DTS Build start
12
+ CJS dist/index.js 532.63 KB
13
+ CJS ⚡️ Build success in 2201ms
12
14
  ESM dist/index.mjs 2.16 KB
13
- ESM dist/CountryCodeSelect-BF22CLZQ.mjs 1.19 KB
14
- ESM dist/chunk-NTYAUO4O.mjs 419.34 KB
15
- ESM ⚡️ Build success in 2289ms
16
- CJS dist/index.js 532.15 KB
17
- CJS ⚡️ Build success in 2289ms
18
- DTS ⚡️ Build success in 15820ms
15
+ ESM dist/CountryCodeSelect-2DASZ3PQ.mjs 1.19 KB
16
+ ESM dist/chunk-MDMLROK2.mjs 419.77 KB
17
+ ESM ⚡️ Build success in 2201ms
18
+ DTS ⚡️ Build success in 15653ms
19
19
  DTS dist/index.d.ts 345.16 KB
20
20
  DTS dist/index.d.mts 345.16 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @vygruppen/spor-react
2
2
 
3
+ ## 9.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f7c43e4: Combobox & ListBox: Add semantics for accessibility
8
+
3
9
  ## 9.15.0
4
10
 
5
11
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- import { createTexts, useTranslation, InfoSelect, Item } from './chunk-NTYAUO4O.mjs';
1
+ import { createTexts, useTranslation, InfoSelect, Item } from './chunk-MDMLROK2.mjs';
2
2
  import React from 'react';
3
3
  import { getSupportedCallingCodes } from 'awesome-phonenumber';
4
4
 
@@ -1050,12 +1050,12 @@ function Combobox({
1050
1050
  const inputRef = externalInputRef ?? fallbackInputRef;
1051
1051
  const listBoxRef = useRef(null);
1052
1052
  const popoverRef = useRef(null);
1053
+ const listboxId = `${useId()}-listbox`;
1053
1054
  const inputWidth = useInputWidth(inputRef);
1054
1055
  const state2 = useComboBoxState({
1055
1056
  allowsEmptyCollection: Boolean(emptyContent),
1056
1057
  defaultFilter: contains2,
1057
1058
  shouldCloseOnBlur: true,
1058
- label,
1059
1059
  ...rest
1060
1060
  });
1061
1061
  const comboBoxProps = {
@@ -1083,7 +1083,8 @@ function Combobox({
1083
1083
  ...rest,
1084
1084
  inputRef,
1085
1085
  listBoxRef,
1086
- popoverRef
1086
+ popoverRef,
1087
+ label
1087
1088
  },
1088
1089
  state2
1089
1090
  );
@@ -1093,7 +1094,11 @@ function Combobox({
1093
1094
  ...styleProps(comboBoxProps),
1094
1095
  "aria-haspopup": "listbox",
1095
1096
  ref: inputRef,
1097
+ role: "combobox",
1096
1098
  label,
1099
+ "aria-expanded": state2.isOpen,
1100
+ "aria-autocomplete": "list",
1101
+ "aria-controls": listboxId,
1097
1102
  borderBottomLeftRadius: state2.isOpen && !isLoading ? 0 : borderBottomLeftRadius,
1098
1103
  borderBottomRightRadius: state2.isOpen && !isLoading ? 0 : borderBottomRightRadius,
1099
1104
  ...inputProps,
@@ -1112,7 +1117,7 @@ function Combobox({
1112
1117
  }
1113
1118
  ) : rightIcon
1114
1119
  }
1115
- ), state2.isOpen && !isLoading && /* @__PURE__ */ React86__default.createElement(
1120
+ ), /* @__PURE__ */ React86__default.createElement("span", { "aria-hidden": "true", "data-trigger": "multiselect" }), state2.isOpen && !isLoading && /* @__PURE__ */ React86__default.createElement(
1116
1121
  Popover,
1117
1122
  {
1118
1123
  state: state2,
@@ -1129,6 +1134,7 @@ function Combobox({
1129
1134
  {
1130
1135
  ...listBoxProps,
1131
1136
  state: state2,
1137
+ id: listboxId,
1132
1138
  listBoxRef,
1133
1139
  emptyContent,
1134
1140
  maxWidth: inputWidth
@@ -1269,6 +1275,7 @@ function Option({ item, state: state2 }) {
1269
1275
  optionProps,
1270
1276
  isSelected,
1271
1277
  isDisabled,
1278
+ isFocusVisible,
1272
1279
  isFocused,
1273
1280
  labelProps,
1274
1281
  descriptionProps
@@ -1284,6 +1291,9 @@ function Option({ item, state: state2 }) {
1284
1291
  if (isFocused) {
1285
1292
  dataFields["data-focus"] = true;
1286
1293
  }
1294
+ if (isFocusVisible) {
1295
+ dataFields["data-focus-visible"] = true;
1296
+ }
1287
1297
  useEffect(() => {
1288
1298
  var _a6;
1289
1299
  (_a6 = ref == null ? void 0 : ref.current) == null ? void 0 : _a6.addEventListener(
@@ -1449,6 +1459,7 @@ var Input = forwardRef(
1449
1459
  paddingRight: rightIcon ? 7 : void 0,
1450
1460
  ...props,
1451
1461
  id: inputId,
1462
+ "aria-labelledby": inputId,
1452
1463
  ref,
1453
1464
  placeholder: " "
1454
1465
  }
@@ -1758,7 +1769,7 @@ var texts4 = createTexts({
1758
1769
  sv: "Landskod"
1759
1770
  }
1760
1771
  });
1761
- var LazyCountryCodeSelect = React86__default.lazy(() => import('./CountryCodeSelect-BF22CLZQ.mjs'));
1772
+ var LazyCountryCodeSelect = React86__default.lazy(() => import('./CountryCodeSelect-2DASZ3PQ.mjs'));
1762
1773
  var Radio = forwardRef((props, ref) => {
1763
1774
  return /* @__PURE__ */ React86__default.createElement(Radio$1, { ...props, ref });
1764
1775
  });
@@ -12850,6 +12861,27 @@ var baseStyle44 = definePartsStyle28({
12850
12861
  var list_default = defineMultiStyleConfig28({
12851
12862
  baseStyle: baseStyle44
12852
12863
  });
12864
+ function outlineBorder(state2, props) {
12865
+ switch (state2) {
12866
+ case "error":
12867
+ return {
12868
+ outlineColor: mode("outline.error.light", "outline.error.dark")(props)
12869
+ };
12870
+ case "focus":
12871
+ return {
12872
+ outlineColor: mode("outline.focus.light", "outline.focus.dark")(props)
12873
+ };
12874
+ default:
12875
+ return {
12876
+ outlineColor: mode(
12877
+ "outline.default.light",
12878
+ "outline.default.dark"
12879
+ )(props)
12880
+ };
12881
+ }
12882
+ }
12883
+
12884
+ // src/theme/components/listbox.ts
12853
12885
  var parts11 = anatomy("ListBox").parts(
12854
12886
  "container",
12855
12887
  "item",
@@ -12881,12 +12913,12 @@ var config25 = helpers16.defineMultiStyleConfig({
12881
12913
  _active: {
12882
12914
  ...ghostBackground("active", props)
12883
12915
  },
12916
+ _focusVisible: {
12917
+ ...outlineBorder("focus", props)
12918
+ },
12884
12919
  _hover: {
12885
12920
  ...ghostBackground("hover", props)
12886
12921
  },
12887
- _focus: {
12888
- ...ghostBackground("selected", props)
12889
- },
12890
12922
  _selected: {
12891
12923
  ...ghostBackground("active", props)
12892
12924
  }
@@ -13326,27 +13358,6 @@ var config32 = helpers23.defineMultiStyleConfig({
13326
13358
  }
13327
13359
  });
13328
13360
  var progress_indicator_default = config32;
13329
- function outlineBorder(state2, props) {
13330
- switch (state2) {
13331
- case "error":
13332
- return {
13333
- outlineColor: mode("outline.error.light", "outline.error.dark")(props)
13334
- };
13335
- case "focus":
13336
- return {
13337
- outlineColor: mode("outline.focus.light", "outline.focus.dark")(props)
13338
- };
13339
- default:
13340
- return {
13341
- outlineColor: mode(
13342
- "outline.default.light",
13343
- "outline.default.dark"
13344
- )(props)
13345
- };
13346
- }
13347
- }
13348
-
13349
- // src/theme/components/radio-card.ts
13350
13361
  var parts17 = anatomy$1("radio-card").parts(
13351
13362
  "container",
13352
13363
  "checked",
package/dist/index.d.mts CHANGED
@@ -5403,10 +5403,10 @@ declare const theme: {
5403
5403
  _active: {
5404
5404
  backgroundColor: string;
5405
5405
  };
5406
- _hover: {
5407
- backgroundColor: string;
5406
+ _focusVisible: {
5407
+ outlineColor: string;
5408
5408
  };
5409
- _focus: {
5409
+ _hover: {
5410
5410
  backgroundColor: string;
5411
5411
  };
5412
5412
  _selected: {
package/dist/index.d.ts CHANGED
@@ -5403,10 +5403,10 @@ declare const theme: {
5403
5403
  _active: {
5404
5404
  backgroundColor: string;
5405
5405
  };
5406
- _hover: {
5407
- backgroundColor: string;
5406
+ _focusVisible: {
5407
+ outlineColor: string;
5408
5408
  };
5409
- _focus: {
5409
+ _hover: {
5410
5410
  backgroundColor: string;
5411
5411
  };
5412
5412
  _selected: {
package/dist/index.js CHANGED
@@ -1147,12 +1147,12 @@ function Combobox({
1147
1147
  const inputRef = externalInputRef ?? fallbackInputRef;
1148
1148
  const listBoxRef = React87.useRef(null);
1149
1149
  const popoverRef = React87.useRef(null);
1150
+ const listboxId = `${React87.useId()}-listbox`;
1150
1151
  const inputWidth = useInputWidth(inputRef);
1151
1152
  const state2 = reactStately.useComboBoxState({
1152
1153
  allowsEmptyCollection: Boolean(emptyContent),
1153
1154
  defaultFilter: contains2,
1154
1155
  shouldCloseOnBlur: true,
1155
- label,
1156
1156
  ...rest
1157
1157
  });
1158
1158
  const comboBoxProps = {
@@ -1180,7 +1180,8 @@ function Combobox({
1180
1180
  ...rest,
1181
1181
  inputRef,
1182
1182
  listBoxRef,
1183
- popoverRef
1183
+ popoverRef,
1184
+ label
1184
1185
  },
1185
1186
  state2
1186
1187
  );
@@ -1190,7 +1191,11 @@ function Combobox({
1190
1191
  ...styleProps(comboBoxProps),
1191
1192
  "aria-haspopup": "listbox",
1192
1193
  ref: inputRef,
1194
+ role: "combobox",
1193
1195
  label,
1196
+ "aria-expanded": state2.isOpen,
1197
+ "aria-autocomplete": "list",
1198
+ "aria-controls": listboxId,
1194
1199
  borderBottomLeftRadius: state2.isOpen && !isLoading ? 0 : borderBottomLeftRadius,
1195
1200
  borderBottomRightRadius: state2.isOpen && !isLoading ? 0 : borderBottomRightRadius,
1196
1201
  ...inputProps,
@@ -1209,7 +1214,7 @@ function Combobox({
1209
1214
  }
1210
1215
  ) : rightIcon
1211
1216
  }
1212
- ), state2.isOpen && !isLoading && /* @__PURE__ */ React87__namespace.default.createElement(
1217
+ ), /* @__PURE__ */ React87__namespace.default.createElement("span", { "aria-hidden": "true", "data-trigger": "multiselect" }), state2.isOpen && !isLoading && /* @__PURE__ */ React87__namespace.default.createElement(
1213
1218
  Popover,
1214
1219
  {
1215
1220
  state: state2,
@@ -1226,6 +1231,7 @@ function Combobox({
1226
1231
  {
1227
1232
  ...listBoxProps,
1228
1233
  state: state2,
1234
+ id: listboxId,
1229
1235
  listBoxRef,
1230
1236
  emptyContent,
1231
1237
  maxWidth: inputWidth
@@ -1388,6 +1394,7 @@ function Option({ item, state: state2 }) {
1388
1394
  optionProps,
1389
1395
  isSelected,
1390
1396
  isDisabled,
1397
+ isFocusVisible,
1391
1398
  isFocused,
1392
1399
  labelProps,
1393
1400
  descriptionProps
@@ -1403,6 +1410,9 @@ function Option({ item, state: state2 }) {
1403
1410
  if (isFocused) {
1404
1411
  dataFields["data-focus"] = true;
1405
1412
  }
1413
+ if (isFocusVisible) {
1414
+ dataFields["data-focus-visible"] = true;
1415
+ }
1406
1416
  React87.useEffect(() => {
1407
1417
  var _a6;
1408
1418
  (_a6 = ref == null ? void 0 : ref.current) == null ? void 0 : _a6.addEventListener(
@@ -1582,6 +1592,7 @@ var init_Input = __esm({
1582
1592
  paddingRight: rightIcon ? 7 : void 0,
1583
1593
  ...props,
1584
1594
  id: inputId,
1595
+ "aria-labelledby": inputId,
1585
1596
  ref,
1586
1597
  placeholder: " "
1587
1598
  }
@@ -14520,6 +14531,29 @@ var init_list2 = __esm({
14520
14531
  });
14521
14532
  }
14522
14533
  });
14534
+ function outlineBorder(state2, props) {
14535
+ switch (state2) {
14536
+ case "error":
14537
+ return {
14538
+ outlineColor: themeTools.mode("outline.error.light", "outline.error.dark")(props)
14539
+ };
14540
+ case "focus":
14541
+ return {
14542
+ outlineColor: themeTools.mode("outline.focus.light", "outline.focus.dark")(props)
14543
+ };
14544
+ default:
14545
+ return {
14546
+ outlineColor: themeTools.mode(
14547
+ "outline.default.light",
14548
+ "outline.default.dark"
14549
+ )(props)
14550
+ };
14551
+ }
14552
+ }
14553
+ var init_outline_utils = __esm({
14554
+ "src/theme/utils/outline-utils.ts"() {
14555
+ }
14556
+ });
14523
14557
  var parts11, helpers16, config25, listbox_default;
14524
14558
  var init_listbox = __esm({
14525
14559
  "src/theme/components/listbox.ts"() {
@@ -14527,6 +14561,7 @@ var init_listbox = __esm({
14527
14561
  init_base_utils();
14528
14562
  init_ghost_utils();
14529
14563
  init_surface_utils();
14564
+ init_outline_utils();
14530
14565
  parts11 = anatomy("ListBox").parts(
14531
14566
  "container",
14532
14567
  "item",
@@ -14558,12 +14593,12 @@ var init_listbox = __esm({
14558
14593
  _active: {
14559
14594
  ...ghostBackground("active", props)
14560
14595
  },
14596
+ _focusVisible: {
14597
+ ...outlineBorder("focus", props)
14598
+ },
14561
14599
  _hover: {
14562
14600
  ...ghostBackground("hover", props)
14563
14601
  },
14564
- _focus: {
14565
- ...ghostBackground("selected", props)
14566
- },
14567
14602
  _selected: {
14568
14603
  ...ghostBackground("active", props)
14569
14604
  }
@@ -15057,29 +15092,6 @@ var init_progress_indicator2 = __esm({
15057
15092
  progress_indicator_default = config32;
15058
15093
  }
15059
15094
  });
15060
- function outlineBorder(state2, props) {
15061
- switch (state2) {
15062
- case "error":
15063
- return {
15064
- outlineColor: themeTools.mode("outline.error.light", "outline.error.dark")(props)
15065
- };
15066
- case "focus":
15067
- return {
15068
- outlineColor: themeTools.mode("outline.focus.light", "outline.focus.dark")(props)
15069
- };
15070
- default:
15071
- return {
15072
- outlineColor: themeTools.mode(
15073
- "outline.default.light",
15074
- "outline.default.dark"
15075
- )(props)
15076
- };
15077
- }
15078
- }
15079
- var init_outline_utils = __esm({
15080
- "src/theme/utils/outline-utils.ts"() {
15081
- }
15082
- });
15083
15095
  var parts17, helpers24, config33, radio_card_default;
15084
15096
  var init_radio_card = __esm({
15085
15097
  "src/theme/components/radio-card.ts"() {
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, AttachedInputs, Badge, Box, Brand, Breadcrumb, BreadcrumbItem, BreadcrumbLink, Button, ButtonGroup, Card, CardSelect, CargonetLogo, Center, Checkbox, CheckboxGroup, ChoiceChip, ClosableAlert, CloseButton, Code, Collapse, ColorInlineLoader, ColorSpinner, Combobox, Container, ContentLoader, DarkFullScreenLoader, DarkInlineLoader, DarkMode, DarkSpinner, DatePicker, DateRangePicker, Divider, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerFooter, ModalHeader as DrawerHeader, DrawerOverlay, Expandable, ExpandableAlert, ExpandableItem, Fade, Flex, FloatingActionButton, FormControl, FormErrorMessage, FormHelperText, FormLabel, FullScreenDrawer, Grid, GridItem, HStack, Heading, IconButton, Image, Img, InfoSelect, InfoTag, Input, InputGroup, InputLeftElement, InputRightElement, Item, ItemDescription, ItemLabel, JumpButton, Language, LanguageProvider, LightFullScreenLoader, LightInlineLoader, LightMode, LightSpinner, LineIcon, ListBox, ListItem, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, NativeSelect, Nudge, NumericStepper, OrderedList, Pagination, PasswordInput, PhoneNumberInput, PlayPauseButton, Portal, PressableCard, ProgressBar, ProgressIndicator, ProgressLoader, Radio, RadioCard, RadioCardGroup, RadioCardGroupContext, RadioGroup, ScaleFade, SearchInput, Section, SimpleDrawer, SimpleGrid, Skeleton, SkeletonCircle, SkeletonText, SkipButton, Slide, SlideFade, Spacer, SporProvider, Stack, StaticAlert, StaticCard, Stepper, StepperStep, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableCaption, Tabs, Tbody, Td, Text, TextLink, Textarea, Tfoot, Th, Thead, Time, TimePicker, Tooltip, Tr, TravelTag, UnorderedList, VStack, VyLogo, VyLogoPride, WizardNudge, Wrap, WrapItem, brandTheme, createTexts, defineStyleConfig, extendTheme, fontFaces, slugify, theme, tokens, useBreakpointValue, useClipboard, useColorMode, useColorModePreference, useColorModeValue, useControllableProp, useDisclosure, useMediaQuery, useMergeRefs, useOutsideClick, usePrefersReducedMotion, useSize, useTheme, useToast, useToken, useTranslation } from './chunk-NTYAUO4O.mjs';
1
+ export { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, AttachedInputs, Badge, Box, Brand, Breadcrumb, BreadcrumbItem, BreadcrumbLink, Button, ButtonGroup, Card, CardSelect, CargonetLogo, Center, Checkbox, CheckboxGroup, ChoiceChip, ClosableAlert, CloseButton, Code, Collapse, ColorInlineLoader, ColorSpinner, Combobox, Container, ContentLoader, DarkFullScreenLoader, DarkInlineLoader, DarkMode, DarkSpinner, DatePicker, DateRangePicker, Divider, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerFooter, ModalHeader as DrawerHeader, DrawerOverlay, Expandable, ExpandableAlert, ExpandableItem, Fade, Flex, FloatingActionButton, FormControl, FormErrorMessage, FormHelperText, FormLabel, FullScreenDrawer, Grid, GridItem, HStack, Heading, IconButton, Image, Img, InfoSelect, InfoTag, Input, InputGroup, InputLeftElement, InputRightElement, Item, ItemDescription, ItemLabel, JumpButton, Language, LanguageProvider, LightFullScreenLoader, LightInlineLoader, LightMode, LightSpinner, LineIcon, ListBox, ListItem, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, NativeSelect, Nudge, NumericStepper, OrderedList, Pagination, PasswordInput, PhoneNumberInput, PlayPauseButton, Portal, PressableCard, ProgressBar, ProgressIndicator, ProgressLoader, Radio, RadioCard, RadioCardGroup, RadioCardGroupContext, RadioGroup, ScaleFade, SearchInput, Section, SimpleDrawer, SimpleGrid, Skeleton, SkeletonCircle, SkeletonText, SkipButton, Slide, SlideFade, Spacer, SporProvider, Stack, StaticAlert, StaticCard, Stepper, StepperStep, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableCaption, Tabs, Tbody, Td, Text, TextLink, Textarea, Tfoot, Th, Thead, Time, TimePicker, Tooltip, Tr, TravelTag, UnorderedList, VStack, VyLogo, VyLogoPride, WizardNudge, Wrap, WrapItem, brandTheme, createTexts, defineStyleConfig, extendTheme, fontFaces, slugify, theme, tokens, useBreakpointValue, useClipboard, useColorMode, useColorModePreference, useColorModeValue, useControllableProp, useDisclosure, useMediaQuery, useMergeRefs, useOutsideClick, usePrefersReducedMotion, useSize, useTheme, useToast, useToken, useTranslation } from './chunk-MDMLROK2.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vygruppen/spor-react",
3
- "version": "9.15.0",
3
+ "version": "9.16.0",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef, useState } from "react";
1
+ import React, { useEffect, useId, useRef, useState } from "react";
2
2
  import { AriaComboBoxProps, useComboBox, useFilter } from "react-aria";
3
3
  import { useComboBoxState } from "react-stately";
4
4
  import { ColorSpinner, Input, InputProps, ListBox } from "..";
@@ -93,16 +93,17 @@ export function Combobox<T extends object>({
93
93
 
94
94
  const fallbackInputRef = useRef<HTMLInputElement>(null);
95
95
  const inputRef = externalInputRef ?? fallbackInputRef;
96
- const listBoxRef = useRef(null);
96
+ const listBoxRef = useRef<HTMLUListElement>(null);
97
97
  const popoverRef = useRef(null);
98
98
 
99
+ const listboxId = `${useId()}-listbox`;
100
+
99
101
  const inputWidth = useInputWidth(inputRef);
100
102
 
101
103
  const state = useComboBoxState({
102
104
  allowsEmptyCollection: Boolean(emptyContent),
103
105
  defaultFilter: contains,
104
106
  shouldCloseOnBlur: true,
105
- label,
106
107
  ...rest,
107
108
  });
108
109
 
@@ -133,6 +134,7 @@ export function Combobox<T extends object>({
133
134
  inputRef,
134
135
  listBoxRef,
135
136
  popoverRef,
137
+ label,
136
138
  },
137
139
  state,
138
140
  );
@@ -143,7 +145,11 @@ export function Combobox<T extends object>({
143
145
  {...styleProps(comboBoxProps)}
144
146
  aria-haspopup="listbox"
145
147
  ref={inputRef}
148
+ role="combobox"
146
149
  label={label}
150
+ aria-expanded={state.isOpen}
151
+ aria-autocomplete="list"
152
+ aria-controls={listboxId}
147
153
  borderBottomLeftRadius={
148
154
  state.isOpen && !isLoading ? 0 : borderBottomLeftRadius
149
155
  }
@@ -169,7 +175,7 @@ export function Combobox<T extends object>({
169
175
  )
170
176
  }
171
177
  />
172
-
178
+ <span aria-hidden="true" data-trigger="multiselect"></span>
173
179
  {state.isOpen && !isLoading && (
174
180
  <Popover
175
181
  state={state}
@@ -186,6 +192,7 @@ export function Combobox<T extends object>({
186
192
  <ListBox
187
193
  {...listBoxProps}
188
194
  state={state}
195
+ id={listboxId}
189
196
  listBoxRef={listBoxRef}
190
197
  emptyContent={emptyContent}
191
198
  maxWidth={inputWidth}
@@ -49,6 +49,7 @@ export const Input = forwardRef<InputProps, "input">(
49
49
  paddingRight={rightIcon ? 7 : undefined}
50
50
  {...props}
51
51
  id={inputId}
52
+ aria-labelledby={inputId}
52
53
  ref={ref}
53
54
  placeholder=" " // This is needed to make the label work as expected
54
55
  />
@@ -135,6 +135,7 @@ function Option({ item, state }: OptionProps) {
135
135
  optionProps,
136
136
  isSelected,
137
137
  isDisabled,
138
+ isFocusVisible,
138
139
  isFocused,
139
140
  labelProps,
140
141
  descriptionProps,
@@ -151,6 +152,9 @@ function Option({ item, state }: OptionProps) {
151
152
  if (isFocused) {
152
153
  dataFields["data-focus"] = true;
153
154
  }
155
+ if (isFocusVisible) {
156
+ dataFields["data-focus-visible"] = true;
157
+ }
154
158
 
155
159
  /*
156
160
  Workaround to fix click througs on mobile devices
@@ -4,6 +4,7 @@ import { mode } from "@chakra-ui/theme-tools";
4
4
  import { baseBorder } from "../utils/base-utils";
5
5
  import { ghostBackground, ghostText } from "../utils/ghost-utils";
6
6
  import { surface } from "../utils/surface-utils";
7
+ import { outlineBorder } from "../utils/outline-utils";
7
8
 
8
9
  const parts = anatomy("ListBox").parts(
9
10
  "container",
@@ -38,12 +39,12 @@ const config = helpers.defineMultiStyleConfig({
38
39
  _active: {
39
40
  ...ghostBackground("active", props),
40
41
  },
42
+ _focusVisible: {
43
+ ...outlineBorder("focus", props),
44
+ },
41
45
  _hover: {
42
46
  ...ghostBackground("hover", props),
43
47
  },
44
- _focus: {
45
- ...ghostBackground("selected", props),
46
- },
47
48
  _selected: {
48
49
  ...ghostBackground("active", props),
49
50
  },