@khanacademy/wonder-blocks-dropdown 3.0.29 → 3.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @khanacademy/wonder-blocks-dropdown
2
2
 
3
+ ## 3.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d1a5796a: Added error prop
8
+
3
9
  ## 3.0.29
4
10
 
5
11
  ### Patch Changes
@@ -3,7 +3,7 @@ import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
3
3
  import DropdownOpener from "./dropdown-opener";
4
4
  import SelectOpener from "./select-opener";
5
5
  import OptionItem from "./option-item";
6
- import type { DropdownItem, OpenerProps } from "../util/types";
6
+ import type { DropdownItem, OpenerProps, OptionItemComponentArray } from "../util/types";
7
7
  export type Labels = {
8
8
  /**
9
9
  * Label for describing the dismiss icon on the search filter.
@@ -49,6 +49,10 @@ type DefaultProps = Readonly<{
49
49
  * and does not support interaction. Defaults to false.
50
50
  */
51
51
  disabled: boolean;
52
+ /**
53
+ * Whether this component is in an error state. Defaults to false.
54
+ */
55
+ error: boolean;
52
56
  /**
53
57
  * Whether to display the "light" version of this component instead, for
54
58
  * use when the component is used on a dark background.
@@ -185,14 +189,14 @@ export default class MultiSelect extends React.Component<Props, State> {
185
189
  handleToggle: (selectedValue: string) => void;
186
190
  handleSelectAll: () => void;
187
191
  handleSelectNone: () => void;
188
- getMenuText(children: Array<React.ReactElement<React.ComponentProps<typeof OptionItem>>>): string;
189
- getShortcuts(numOptions: number): Array<DropdownItem>;
190
- getMenuItems(children: Array<React.ReactElement<React.ComponentProps<typeof OptionItem>>>): Array<DropdownItem>;
192
+ getMenuText(children: OptionItemComponentArray): string;
193
+ getShortcuts(numOptions: number): DropdownItem[];
194
+ getMenuItems(children: OptionItemComponentArray): DropdownItem[];
191
195
  mapOptionItemToDropdownItem: (option: React.ReactElement<React.ComponentProps<typeof OptionItem>>) => DropdownItem;
192
196
  handleOpenerRef: (node?: any) => void;
193
197
  handleSearchTextChanged: (searchText: string) => void;
194
198
  handleClick: (e: React.SyntheticEvent) => void;
195
- renderOpener(allChildren: Array<React.ReactElement<React.ComponentProps<typeof OptionItem>>>): React.ReactElement<React.ComponentProps<typeof DropdownOpener>> | React.ReactElement<React.ComponentProps<typeof SelectOpener>>;
199
+ renderOpener(allChildren: React.ReactElement<React.ComponentProps<typeof OptionItem>>[]): React.ReactElement<React.ComponentProps<typeof DropdownOpener>> | React.ReactElement<React.ComponentProps<typeof SelectOpener>>;
196
200
  render(): React.ReactNode;
197
201
  }
198
202
  export {};
@@ -10,6 +10,10 @@ type SelectOpenerProps = AriaProps & {
10
10
  * Default false.
11
11
  */
12
12
  disabled: boolean;
13
+ /**
14
+ * Whether or not the input is in an error state. Defaults to false.
15
+ */
16
+ error: boolean;
13
17
  /**
14
18
  * Auto-populated by parent. Used for accessibility purposes, where the label
15
19
  * id should match the field id.
@@ -25,10 +29,6 @@ type SelectOpenerProps = AriaProps & {
25
29
  * use when the item is used on a dark background.
26
30
  */
27
31
  light: boolean;
28
- /**
29
- * Test ID used for e2e testing.
30
- */
31
- testId?: string;
32
32
  /**
33
33
  * Callback for when the SelectOpener is pressed.
34
34
  */
@@ -37,9 +37,14 @@ type SelectOpenerProps = AriaProps & {
37
37
  * Whether the dropdown is open.
38
38
  */
39
39
  open: boolean;
40
+ /**
41
+ * Test ID used for e2e testing.
42
+ */
43
+ testId?: string;
40
44
  };
41
45
  type DefaultProps = {
42
46
  disabled: SelectOpenerProps["disabled"];
47
+ error: SelectOpenerProps["error"];
43
48
  light: SelectOpenerProps["light"];
44
49
  isPlaceholder: SelectOpenerProps["isPlaceholder"];
45
50
  };
@@ -3,7 +3,7 @@ import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
3
3
  import DropdownOpener from "./dropdown-opener";
4
4
  import SelectOpener from "./select-opener";
5
5
  import OptionItem from "./option-item";
6
- import type { DropdownItem, OpenerProps } from "../util/types";
6
+ import type { DropdownItem, OpenerProps, OptionItemComponentArray } from "../util/types";
7
7
  export type SingleSelectLabels = {
8
8
  /**
9
9
  * Label for describing the dismiss icon on the search filter.
@@ -32,6 +32,11 @@ type DefaultProps = Readonly<{
32
32
  * Whether to auto focus an option. Defaults to true.
33
33
  */
34
34
  autoFocus: boolean;
35
+ /**
36
+ * Whether this component is disabled. A disabled dropdown may not be opened
37
+ * and does not support interaction. Defaults to false.
38
+ */
39
+ disabled: boolean;
35
40
  /**
36
41
  * Whether to enable the type-ahead suggestions feature. Defaults to true.
37
42
  *
@@ -47,10 +52,9 @@ type DefaultProps = Readonly<{
47
52
  */
48
53
  enableTypeAhead: boolean;
49
54
  /**
50
- * Whether this component is disabled. A disabled dropdown may not be opened
51
- * and does not support interaction. Defaults to false.
55
+ * Whether or not the input in is an error state. Defaults to false.
52
56
  */
53
- disabled: boolean;
57
+ error: boolean;
54
58
  /**
55
59
  * Whether to display the "light" version of this component instead, for
56
60
  * use when the component is used on a dark background.
@@ -194,9 +198,9 @@ export default class SingleSelect extends React.Component<Props, State> {
194
198
  static getDerivedStateFromProps(props: Props, state: State): Partial<State> | null;
195
199
  handleOpenChanged: (opened: boolean) => void;
196
200
  handleToggle: (selectedValue: string) => void;
197
- mapOptionItemsToDropdownItems: (children: Array<React.ReactElement<React.ComponentProps<typeof OptionItem>>>) => Array<DropdownItem>;
198
- filterChildren(children: Array<React.ReactElement<React.ComponentProps<typeof OptionItem>>>): Array<React.ReactElement<React.ComponentProps<typeof OptionItem>>>;
199
- getMenuItems(children: Array<React.ReactElement<React.ComponentProps<typeof OptionItem>>>): Array<DropdownItem>;
201
+ mapOptionItemsToDropdownItems: (children: OptionItemComponentArray) => DropdownItem[];
202
+ filterChildren(children: OptionItemComponentArray): OptionItemComponentArray;
203
+ getMenuItems(children: OptionItemComponentArray): DropdownItem[];
200
204
  handleSearchTextChanged: (searchText: string) => void;
201
205
  handleOpenerRef: (node?: any) => void;
202
206
  handleClick: (e: React.SyntheticEvent) => void;
package/dist/es/index.js CHANGED
@@ -7,6 +7,7 @@ import Spacing from '@khanacademy/wonder-blocks-spacing';
7
7
  import { LabelMedium, LabelLarge } from '@khanacademy/wonder-blocks-typography';
8
8
  import { getClickableBehavior, isClientSideUrl, ClickableBehavior } from '@khanacademy/wonder-blocks-clickable';
9
9
  import { addStyle, View } from '@khanacademy/wonder-blocks-core';
10
+ import { tokens } from '@khanacademy/wonder-blocks-theming';
10
11
  import Icon, { icons } from '@khanacademy/wonder-blocks-icon';
11
12
  import * as ReactDOM from 'react-dom';
12
13
  import SearchField from '@khanacademy/wonder-blocks-search-field';
@@ -40,8 +41,8 @@ const keyCodes = {
40
41
  down: 40
41
42
  };
42
43
  const selectDropdownStyle = {
43
- marginTop: Spacing.xSmall_8,
44
- marginBottom: Spacing.xSmall_8
44
+ marginTop: tokens.spacing.xSmall_8,
45
+ marginBottom: tokens.spacing.xSmall_8
45
46
  };
46
47
  const filterableDropdownStyle = {
47
48
  minHeight: 100
@@ -61,10 +62,10 @@ const defaultLabels = {
61
62
  };
62
63
 
63
64
  const {
64
- blue: blue$3,
65
- white: white$4,
66
- offBlack: offBlack$3,
67
- offBlack32: offBlack32$4
65
+ blue: blue$2,
66
+ white: white$3,
67
+ offBlack: offBlack$2,
68
+ offBlack32: offBlack32$3
68
69
  } = Color;
69
70
  const StyledAnchor = addStyle("a");
70
71
  const StyledButton$2 = addStyle("button");
@@ -139,8 +140,8 @@ ActionItem.defaultProps = {
139
140
  ActionItem.__IS_ACTION_ITEM__ = true;
140
141
  const styles$8 = StyleSheet.create({
141
142
  shared: {
142
- background: white$4,
143
- color: offBlack$3,
143
+ background: white$3,
144
+ color: offBlack$2,
144
145
  textDecoration: "none",
145
146
  border: "none",
146
147
  outline: "none",
@@ -161,15 +162,15 @@ const styles$8 = StyleSheet.create({
161
162
  marginLeft: Spacing.medium_16
162
163
  },
163
164
  focus: {
164
- color: white$4,
165
- background: blue$3
165
+ color: white$3,
166
+ background: blue$2
166
167
  },
167
168
  active: {
168
- color: mix(fade(blue$3, 0.32), white$4),
169
- background: mix(offBlack32$4, blue$3)
169
+ color: mix(fade(blue$2, 0.32), white$3),
170
+ background: mix(offBlack32$3, blue$2)
170
171
  },
171
172
  disabled: {
172
- color: offBlack32$4,
173
+ color: offBlack32$3,
173
174
  cursor: "default"
174
175
  }
175
176
  });
@@ -188,9 +189,9 @@ function _objectWithoutPropertiesLoose(source, excluded) {
188
189
  }
189
190
 
190
191
  const {
191
- offBlack: offBlack$2,
192
- offBlack32: offBlack32$3,
193
- white: white$3
192
+ offBlack: offBlack$1,
193
+ offBlack32: offBlack32$2,
194
+ white: white$2
194
195
  } = Color;
195
196
  const Check = function Check(props) {
196
197
  const {
@@ -203,7 +204,7 @@ const Check = function Check(props) {
203
204
  return React.createElement(Icon, {
204
205
  icon: icons.check,
205
206
  size: "small",
206
- color: disabled ? offBlack32$3 : pressed || hovered || focused ? white$3 : offBlack$2,
207
+ color: disabled ? offBlack32$2 : pressed || hovered || focused ? white$2 : offBlack$1,
207
208
  style: [styles$7.bounds, !selected && styles$7.hide]
208
209
  });
209
210
  };
@@ -221,10 +222,10 @@ const checkboxCheck = {
221
222
  small: "M11.263 4.324a1 1 0 1 1 1.474 1.352l-5.5 6a1 1 0 0 1-1.505-.036l-2.5-3a1 1 0 1 1 1.536-1.28L6.536 9.48l4.727-5.157z"
222
223
  };
223
224
  const {
224
- blue: blue$2,
225
- white: white$2,
226
- offBlack16: offBlack16$1,
227
- offBlack32: offBlack32$2,
225
+ blue: blue$1,
226
+ white: white$1,
227
+ offBlack16,
228
+ offBlack32: offBlack32$1,
228
229
  offBlack50,
229
230
  offWhite
230
231
  } = Color;
@@ -236,10 +237,10 @@ const Checkbox = function Checkbox(props) {
236
237
  hovered,
237
238
  focused
238
239
  } = props;
239
- const activeBlue = mix(offBlack32$2, blue$2);
240
+ const activeBlue = mix(offBlack32$1, blue$1);
240
241
  const clickInteraction = pressed || hovered || focused;
241
- const bgColor = disabled ? offWhite : selected && !clickInteraction ? blue$2 : white$2;
242
- const checkColor = disabled ? offBlack32$2 : clickInteraction ? pressed ? activeBlue : blue$2 : white$2;
242
+ const bgColor = disabled ? offWhite : selected && !clickInteraction ? blue$1 : white$1;
243
+ const checkColor = disabled ? offBlack32$1 : clickInteraction ? pressed ? activeBlue : blue$1 : white$1;
243
244
  return React.createElement(View, {
244
245
  style: [styles$6.checkbox, (clickInteraction || selected && !disabled) && styles$6.noBorder, disabled && styles$6.disabledCheckbox, {
245
246
  backgroundColor: bgColor
@@ -264,7 +265,7 @@ const styles$6 = StyleSheet.create({
264
265
  borderWidth: 0
265
266
  },
266
267
  disabledCheckbox: {
267
- borderColor: offBlack16$1,
268
+ borderColor: offBlack16,
268
269
  backgroundColor: offWhite
269
270
  },
270
271
  disabledCheckFormatting: {
@@ -350,16 +351,16 @@ OptionItem.defaultProps = {
350
351
  };
351
352
  OptionItem.__IS_OPTION_ITEM__ = true;
352
353
  const {
353
- blue: blue$1,
354
- white: white$1,
355
- offBlack: offBlack$1,
356
- offBlack32: offBlack32$1
354
+ blue,
355
+ white,
356
+ offBlack,
357
+ offBlack32
357
358
  } = Color;
358
359
  const styles$5 = StyleSheet.create({
359
360
  itemContainer: {
360
361
  flexDirection: "row",
361
- background: white$1,
362
- color: offBlack$1,
362
+ background: white,
363
+ color: offBlack,
363
364
  alignItems: "center",
364
365
  height: DROPDOWN_ITEM_HEIGHT,
365
366
  minHeight: DROPDOWN_ITEM_HEIGHT,
@@ -371,16 +372,16 @@ const styles$5 = StyleSheet.create({
371
372
  cursor: "default"
372
373
  },
373
374
  focus: {
374
- color: white$1,
375
- background: blue$1
375
+ color: white,
376
+ background: blue
376
377
  },
377
378
  active: {
378
- color: mix(fade(blue$1, 0.32), white$1),
379
- background: mix(offBlack32$1, blue$1)
379
+ color: mix(fade(blue, 0.32), white),
380
+ background: mix(offBlack32, blue)
380
381
  },
381
382
  disabled: {
382
- color: offBlack32$1,
383
- background: white$1
383
+ color: offBlack32,
384
+ background: white
384
385
  },
385
386
  label: {
386
387
  whiteSpace: "nowrap",
@@ -1109,9 +1110,13 @@ class DropdownCore extends React.Component {
1109
1110
  }
1110
1111
  renderDropdownMenu(listRenderer, isReferenceHidden) {
1111
1112
  const {
1113
+ "aria-invalid": ariaInvalid,
1114
+ "aria-required": ariaRequired,
1112
1115
  dropdownStyle,
1116
+ isFilterable,
1113
1117
  light,
1114
- openerElement
1118
+ openerElement,
1119
+ role
1115
1120
  } = this.props;
1116
1121
  const openerStyle = openerElement && window.getComputedStyle(openerElement);
1117
1122
  const minDropdownWidth = openerStyle ? openerStyle.getPropertyValue("width") : 0;
@@ -1120,9 +1125,11 @@ class DropdownCore extends React.Component {
1120
1125
  onMouseUp: this.handleDropdownMouseUp,
1121
1126
  style: [styles$3.dropdown, light && styles$3.light, isReferenceHidden && styles$3.hidden, dropdownStyle],
1122
1127
  testId: "dropdown-core-container"
1123
- }, this.props.isFilterable && this.renderSearchField(), React.createElement(View, {
1124
- role: this.props.role,
1125
- style: [styles$3.listboxOrMenu, generateDropdownMenuStyles(minDropdownWidth, maxDropdownHeight)]
1128
+ }, isFilterable && this.renderSearchField(), React.createElement(View, {
1129
+ role: role,
1130
+ style: [styles$3.listboxOrMenu, generateDropdownMenuStyles(minDropdownWidth, maxDropdownHeight)],
1131
+ "aria-invalid": role === "listbox" ? ariaInvalid : undefined,
1132
+ "aria-required": role === "listbox" ? ariaRequired : undefined
1126
1133
  }, listRenderer), this.maybeRenderNoResults());
1127
1134
  }
1128
1135
  renderDropdown() {
@@ -1509,17 +1516,8 @@ const styles$1 = StyleSheet.create({
1509
1516
  }
1510
1517
  });
1511
1518
 
1512
- const _excluded$2 = ["children", "disabled", "id", "isPlaceholder", "light", "open", "testId", "onOpenChanged"];
1519
+ const _excluded$2 = ["children", "disabled", "error", "id", "isPlaceholder", "light", "open", "testId", "onOpenChanged"];
1513
1520
  const StyledButton = addStyle("button");
1514
- const {
1515
- blue,
1516
- white,
1517
- white50,
1518
- offBlack,
1519
- offBlack16,
1520
- offBlack32,
1521
- offBlack64
1522
- } = Color;
1523
1521
  class SelectOpener extends React.Component {
1524
1522
  constructor(...args) {
1525
1523
  super(...args);
@@ -1535,6 +1533,7 @@ class SelectOpener extends React.Component {
1535
1533
  {
1536
1534
  children,
1537
1535
  disabled,
1536
+ error,
1538
1537
  id,
1539
1538
  isPlaceholder,
1540
1539
  light,
@@ -1547,13 +1546,13 @@ class SelectOpener extends React.Component {
1547
1546
  disabled: disabled,
1548
1547
  onClick: this.handleClick
1549
1548
  }, (state, childrenProps) => {
1550
- const stateStyles = _generateStyles(light, isPlaceholder);
1549
+ const stateStyles = _generateStyles(light, isPlaceholder, error);
1551
1550
  const {
1552
1551
  hovered,
1553
1552
  focused,
1554
1553
  pressed
1555
1554
  } = state;
1556
- const iconColor = light ? disabled || pressed ? "currentColor" : white : disabled ? offBlack32 : offBlack64;
1555
+ const iconColor = light ? disabled || pressed ? "currentColor" : tokens.color.white : disabled ? tokens.color.offBlack32 : tokens.color.offBlack64;
1557
1556
  const style = [styles.shared, stateStyles.default, disabled && stateStyles.disabled, !disabled && (pressed ? stateStyles.active : (hovered || focused) && stateStyles.focus)];
1558
1557
  return React.createElement(StyledButton, _extends({}, sharedProps, {
1559
1558
  "aria-expanded": open ? "true" : "false",
@@ -1580,22 +1579,22 @@ class SelectOpener extends React.Component {
1580
1579
  }
1581
1580
  SelectOpener.defaultProps = {
1582
1581
  disabled: false,
1582
+ error: false,
1583
1583
  light: false,
1584
1584
  isPlaceholder: false
1585
1585
  };
1586
- const buttonRadius = 4;
1587
1586
  const styles = StyleSheet.create({
1588
1587
  shared: {
1589
1588
  position: "relative",
1590
1589
  display: "inline-flex",
1591
1590
  alignItems: "center",
1592
1591
  justifyContent: "space-between",
1593
- color: offBlack,
1592
+ color: tokens.color.offBlack,
1594
1593
  height: DROPDOWN_ITEM_HEIGHT,
1595
- paddingLeft: 16,
1596
- paddingRight: 12,
1594
+ paddingLeft: tokens.spacing.medium_16,
1595
+ paddingRight: tokens.spacing.small_12,
1597
1596
  borderWidth: 0,
1598
- borderRadius: buttonRadius,
1597
+ borderRadius: tokens.border.radius.medium_4,
1599
1598
  borderStyle: "solid",
1600
1599
  outline: "none",
1601
1600
  textDecoration: "none",
@@ -1604,7 +1603,7 @@ const styles = StyleSheet.create({
1604
1603
  touchAction: "manipulation"
1605
1604
  },
1606
1605
  text: {
1607
- marginRight: Spacing.xSmall_8,
1606
+ marginRight: tokens.spacing.xSmall_8,
1608
1607
  whiteSpace: "nowrap",
1609
1608
  userSelect: "none",
1610
1609
  overflow: "hidden",
@@ -1614,11 +1613,11 @@ const styles = StyleSheet.create({
1614
1613
  minWidth: 16
1615
1614
  }
1616
1615
  });
1617
- const adjustedPaddingLeft = 16 - 1;
1618
- const adjustedPaddingRight = 12 - 1;
1616
+ const adjustedPaddingLeft = tokens.spacing.medium_16 - 1;
1617
+ const adjustedPaddingRight = tokens.spacing.small_12 - 1;
1619
1618
  const stateStyles = {};
1620
- const _generateStyles = (light, placeholder) => {
1621
- const styleKey = `${String(light)}-${String(placeholder)}`;
1619
+ const _generateStyles = (light, placeholder, error) => {
1620
+ const styleKey = `${light}-${placeholder}-${error}`;
1622
1621
  if (stateStyles[styleKey]) {
1623
1622
  return stateStyles[styleKey];
1624
1623
  }
@@ -1626,56 +1625,57 @@ const _generateStyles = (light, placeholder) => {
1626
1625
  if (light) {
1627
1626
  newStyles = {
1628
1627
  default: {
1629
- background: "transparent",
1630
- color: placeholder ? white50 : white,
1631
- borderColor: white50,
1632
- borderWidth: 1
1628
+ background: error ? tokens.color.fadedRed8 : "transparent",
1629
+ color: placeholder ? tokens.color.white50 : tokens.color.white,
1630
+ borderColor: error ? tokens.color.red : tokens.color.white50,
1631
+ borderWidth: tokens.border.width.hairline
1633
1632
  },
1634
1633
  focus: {
1635
- borderColor: white,
1636
- borderWidth: 2,
1634
+ borderColor: error ? tokens.color.fadedRed8 : tokens.color.white,
1635
+ borderWidth: tokens.spacing.xxxxSmall_2,
1637
1636
  paddingLeft: adjustedPaddingLeft,
1638
1637
  paddingRight: adjustedPaddingRight
1639
1638
  },
1640
1639
  active: {
1641
1640
  paddingLeft: adjustedPaddingLeft,
1642
1641
  paddingRight: adjustedPaddingRight,
1643
- borderColor: mix(fade(blue, 0.32), white),
1644
- borderWidth: 2,
1645
- color: placeholder ? mix(fade(white, 0.32), blue) : mix(fade(blue, 0.32), white),
1646
- backgroundColor: mix(offBlack32, blue)
1642
+ borderColor: error ? tokens.color.red : tokens.color.fadedBlue,
1643
+ borderWidth: tokens.border.width.thin,
1644
+ color: placeholder ? mix(tokens.color.white32, tokens.color.blue) : tokens.color.fadedBlue,
1645
+ backgroundColor: error ? tokens.color.fadedRed : tokens.color.activeBlue
1647
1646
  },
1648
1647
  disabled: {
1649
- borderColor: mix(fade(white, 0.32), blue),
1650
- color: mix(fade(white, 0.32), blue),
1648
+ background: "transparent",
1649
+ borderColor: mix(tokens.color.white32, tokens.color.blue),
1650
+ color: mix(tokens.color.white32, tokens.color.blue),
1651
1651
  cursor: "auto"
1652
1652
  }
1653
1653
  };
1654
1654
  } else {
1655
1655
  newStyles = {
1656
1656
  default: {
1657
- background: white,
1658
- borderColor: offBlack16,
1659
- borderWidth: 1,
1660
- color: placeholder ? offBlack64 : offBlack
1657
+ background: error ? tokens.color.fadedRed8 : tokens.color.white,
1658
+ borderColor: error ? tokens.color.red : tokens.color.offBlack16,
1659
+ borderWidth: tokens.border.width.hairline,
1660
+ color: placeholder ? tokens.color.offBlack64 : tokens.color.offBlack
1661
1661
  },
1662
1662
  focus: {
1663
- borderColor: blue,
1664
- borderWidth: 2,
1663
+ borderColor: error ? tokens.color.red : tokens.color.blue,
1664
+ borderWidth: tokens.border.width.thin,
1665
1665
  paddingLeft: adjustedPaddingLeft,
1666
1666
  paddingRight: adjustedPaddingRight
1667
1667
  },
1668
1668
  active: {
1669
- background: mix(fade(blue, 0.32), white),
1670
- borderColor: mix(offBlack32, blue),
1671
- borderWidth: 2,
1669
+ background: error ? tokens.color.fadedRed : tokens.color.fadedBlue,
1670
+ borderColor: error ? tokens.color.red : tokens.color.activeBlue,
1671
+ borderWidth: tokens.border.width.thin,
1672
1672
  paddingLeft: adjustedPaddingLeft,
1673
1673
  paddingRight: adjustedPaddingRight
1674
1674
  },
1675
1675
  disabled: {
1676
- background: Color.offWhite,
1677
- borderColor: offBlack16,
1678
- color: offBlack64,
1676
+ background: tokens.color.offWhite,
1677
+ borderColor: tokens.color.offBlack16,
1678
+ color: tokens.color.offBlack64,
1679
1679
  cursor: "auto"
1680
1680
  }
1681
1681
  };
@@ -1684,7 +1684,7 @@ const _generateStyles = (light, placeholder) => {
1684
1684
  return stateStyles[styleKey];
1685
1685
  };
1686
1686
 
1687
- const _excluded$1 = ["children", "disabled", "id", "light", "opener", "placeholder", "selectedValue", "testId", "alignment", "autoFocus", "dropdownStyle", "enableTypeAhead", "isFilterable", "labels", "onChange", "onToggle", "opened", "style", "className"];
1687
+ const _excluded$1 = ["children", "disabled", "error", "id", "light", "opener", "placeholder", "selectedValue", "testId", "alignment", "autoFocus", "dropdownStyle", "enableTypeAhead", "isFilterable", "labels", "onChange", "onToggle", "opened", "style", "className", "aria-invalid", "aria-required"];
1688
1688
  class SingleSelect extends React.Component {
1689
1689
  constructor(props) {
1690
1690
  super(props);
@@ -1786,6 +1786,7 @@ class SingleSelect extends React.Component {
1786
1786
  {
1787
1787
  children,
1788
1788
  disabled,
1789
+ error,
1789
1790
  id,
1790
1791
  light,
1791
1792
  opener,
@@ -1794,7 +1795,8 @@ class SingleSelect extends React.Component {
1794
1795
  testId
1795
1796
  } = _this$props,
1796
1797
  sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$1);
1797
- const selectedItem = React.Children.toArray(children).find(option => option.props.value === selectedValue);
1798
+ const items = React.Children.toArray(children);
1799
+ const selectedItem = items.find(option => option.props.value === selectedValue);
1798
1800
  const menuText = selectedItem ? selectedItem.props.label : placeholder;
1799
1801
  const dropdownOpener = opener ? React.createElement(DropdownOpener, {
1800
1802
  onClick: this.handleClick,
@@ -1804,6 +1806,7 @@ class SingleSelect extends React.Component {
1804
1806
  }, opener) : React.createElement(SelectOpener, _extends({}, sharedProps, {
1805
1807
  disabled: numItems === 0 || disabled,
1806
1808
  id: id,
1809
+ error: error,
1807
1810
  isPlaceholder: !selectedItem,
1808
1811
  light: light,
1809
1812
  onOpenChanged: this.handleOpenChanged,
@@ -1824,7 +1827,9 @@ class SingleSelect extends React.Component {
1824
1827
  isFilterable,
1825
1828
  labels,
1826
1829
  light,
1827
- style
1830
+ style,
1831
+ "aria-invalid": ariaInvalid,
1832
+ "aria-required": ariaRequired
1828
1833
  } = this.props;
1829
1834
  const {
1830
1835
  searchText
@@ -1851,7 +1856,9 @@ class SingleSelect extends React.Component {
1851
1856
  isFilterable: isFilterable,
1852
1857
  onSearchTextChanged: isFilterable ? this.handleSearchTextChanged : undefined,
1853
1858
  searchText: isFilterable ? searchText : "",
1854
- labels: labels
1859
+ labels: labels,
1860
+ "aria-invalid": ariaInvalid,
1861
+ "aria-required": ariaRequired
1855
1862
  });
1856
1863
  }
1857
1864
  }
@@ -1860,6 +1867,7 @@ SingleSelect.defaultProps = {
1860
1867
  autoFocus: true,
1861
1868
  disabled: false,
1862
1869
  enableTypeAhead: true,
1870
+ error: false,
1863
1871
  light: false,
1864
1872
  labels: {
1865
1873
  clearSearch: defaultLabels.clearSearch,
@@ -1869,7 +1877,7 @@ SingleSelect.defaultProps = {
1869
1877
  }
1870
1878
  };
1871
1879
 
1872
- const _excluded = ["disabled", "id", "light", "opener", "testId", "alignment", "dropdownStyle", "implicitAllEnabled", "isFilterable", "labels", "onChange", "onToggle", "opened", "selectedValues", "shortcuts", "style", "className"];
1880
+ const _excluded = ["disabled", "id", "light", "opener", "testId", "alignment", "dropdownStyle", "implicitAllEnabled", "isFilterable", "labels", "onChange", "onToggle", "opened", "selectedValues", "shortcuts", "style", "className", "aria-invalid", "aria-required"];
1873
1881
  class MultiSelect extends React.Component {
1874
1882
  constructor(props) {
1875
1883
  super(props);
@@ -2106,7 +2114,9 @@ class MultiSelect extends React.Component {
2106
2114
  className,
2107
2115
  dropdownStyle,
2108
2116
  children,
2109
- isFilterable
2117
+ isFilterable,
2118
+ "aria-invalid": ariaInvalid,
2119
+ "aria-required": ariaRequired
2110
2120
  } = this.props;
2111
2121
  const {
2112
2122
  open,
@@ -2143,13 +2153,16 @@ class MultiSelect extends React.Component {
2143
2153
  filter,
2144
2154
  noResults,
2145
2155
  someResults: someSelected
2146
- }
2156
+ },
2157
+ "aria-invalid": ariaInvalid,
2158
+ "aria-required": ariaRequired
2147
2159
  });
2148
2160
  }
2149
2161
  }
2150
2162
  MultiSelect.defaultProps = {
2151
2163
  alignment: "left",
2152
2164
  disabled: false,
2165
+ error: false,
2153
2166
  light: false,
2154
2167
  shortcuts: false,
2155
2168
  selectedValues: []