@primer/components 0.0.0-20211011154552 → 0.0.0-20211011162723

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,6 +1,6 @@
1
1
  # @primer/components
2
2
 
3
- ## 0.0.0-20211011154552
3
+ ## 0.0.0-20211011162723
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  ### Patch Changes
12
12
 
13
- - [#1599](https://github.com/primer/react/pull/1599) [`86e7cc84`](https://github.com/primer/react/commit/86e7cc843842e9c0374be6b566a552247826742c) Thanks [@siddharthkp](https://github.com/siddharthkp)! - ActionList: Better labels and description for accessible ActionList.Item
13
+ - [#1603](https://github.com/primer/react/pull/1603) [`f96d2abf`](https://github.com/primer/react/commit/f96d2abf45701466054f8f8306b1285bc39c2a0f) Thanks [@siddharthkp](https://github.com/siddharthkp)! - ActionList: Improve keyboard accessibility with focus styles cross browser
14
14
 
15
15
  * [#1583](https://github.com/primer/react/pull/1583) [`24b1ebbc`](https://github.com/primer/react/commit/24b1ebbc21ca2eaa92bd6b5b8c15ab0e7577f5a0) Thanks [@pksjce](https://github.com/pksjce)! - Add a utility to provide useIsoMorphicEffect function and use that instead of useLayoutEffect everywhere
16
16
 
@@ -82,9 +82,7 @@ const Item = /*#__PURE__*/_react.default.forwardRef(({
82
82
  onSelect = () => null,
83
83
  sx: sxProp = {},
84
84
  id,
85
- _PrivateItemWrapper = ({
86
- children
87
- }) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children),
85
+ _PrivateItemWrapper,
88
86
  ...props
89
87
  }, forwardedRef) => {
90
88
  const {
@@ -102,9 +100,9 @@ const Item = /*#__PURE__*/_react.default.forwardRef(({
102
100
  paddingY: '6px',
103
101
  // custom value off the scale
104
102
  lineHeight: TEXT_ROW_HEIGHT,
105
- marginX: listVariant === 'inset' ? 2 : 0,
106
103
  minHeight: 5,
107
- borderRadius: 2,
104
+ marginX: listVariant === 'inset' ? 2 : 0,
105
+ borderRadius: listVariant === 'inset' ? 2 : 0,
108
106
  transition: 'background 33.333ms linear',
109
107
  color: getVariantStyles(variant, disabled).color,
110
108
  textDecoration: 'none',
@@ -117,11 +115,17 @@ const Item = /*#__PURE__*/_react.default.forwardRef(({
117
115
  backgroundColor: `actionListItem.${variant}.hoverBg`,
118
116
  color: getVariantStyles(variant, disabled).hoverColor
119
117
  },
120
- ':focus:not([aria-disabled])': {
118
+ ':focus:not([data-focus-visible-added])': {
121
119
  backgroundColor: `actionListItem.${variant}.selectedBg`,
122
120
  color: getVariantStyles(variant, disabled).hoverColor,
123
121
  outline: 'none'
124
122
  },
123
+ '&[data-focus-visible-added]': {
124
+ // we don't use :focus-visible because not all browsers (safari) have it yet
125
+ outline: 'none',
126
+ border: `2 solid`,
127
+ boxShadow: `0 0 0 2px ${theme === null || theme === void 0 ? void 0 : theme.colors.accent.emphasis}`
128
+ },
125
129
  ':active:not([aria-disabled])': {
126
130
  backgroundColor: `actionListItem.${variant}.activeBg`,
127
131
  color: getVariantStyles(variant, disabled).hoverColor
@@ -143,7 +147,7 @@ const Item = /*#__PURE__*/_react.default.forwardRef(({
143
147
  borderColor: 'var(--divider-color, transparent)'
144
148
  },
145
149
  // show between 2 items
146
- ':not(:first-of-type):not([aria-selected=true])': {
150
+ ':not(:first-of-type)': {
147
151
  '--divider-color': theme === null || theme === void 0 ? void 0 : theme.colors.actionListItem.inlineDivider
148
152
  },
149
153
  // hide divider after dividers & group header, with higher importance!
@@ -151,14 +155,10 @@ const Item = /*#__PURE__*/_react.default.forwardRef(({
151
155
  '--divider-color': 'transparent !important'
152
156
  },
153
157
  // hide border on current and previous item
154
- '&:hover:not([aria-disabled]), &:focus:not([aria-disabled])': {
155
- '--divider-color': 'transparent'
156
- },
157
- '&:hover:not([aria-disabled]) + &, &:focus:not([aria-disabled]) + &': {
158
+ '&:hover:not([aria-disabled]), &:focus:not([aria-disabled]), &[data-focus-visible-added]:not([aria-disabled])': {
158
159
  '--divider-color': 'transparent'
159
160
  },
160
- // hide border around selected item
161
- '&[aria-selected=true] + &': {
161
+ '&:hover:not([aria-disabled]) + &, &:focus:not([aria-disabled]) + &, &[data-focus-visible-added] + li': {
162
162
  '--divider-color': 'transparent'
163
163
  }
164
164
  };
@@ -166,12 +166,21 @@ const Item = /*#__PURE__*/_react.default.forwardRef(({
166
166
  const clickHandler = _react.default.useCallback(event => {
167
167
  if (disabled) return;
168
168
  if (!event.defaultPrevented) onSelect(event);
169
+ }, [onSelect, disabled]);
170
+
171
+ const keyPressHandler = _react.default.useCallback(event => {
172
+ if (disabled) return;
173
+
174
+ if (!event.defaultPrevented && [' ', 'Enter'].includes(event.key)) {
175
+ onSelect(event);
176
+ }
169
177
  }, [onSelect, disabled]); // use props.id if provided, otherwise generate one.
170
178
 
171
179
 
172
180
  const labelId = (0, _ssr.useSSRSafeId)(id);
173
181
  const inlineDescriptionId = (0, _ssr.useSSRSafeId)(id && `${id}--inline-description`);
174
182
  const blockDescriptionId = (0, _ssr.useSSRSafeId)(id && `${id}--block-description`);
183
+ const ItemWrapper = _PrivateItemWrapper || _react.default.Fragment;
175
184
  return /*#__PURE__*/_react.default.createElement(Slots, {
176
185
  context: {
177
186
  variant,
@@ -183,12 +192,13 @@ const Item = /*#__PURE__*/_react.default.forwardRef(({
183
192
  ref: forwardedRef,
184
193
  sx: (0, _sx.merge)(styles, sxProp),
185
194
  onClick: clickHandler,
195
+ onKeyPress: keyPressHandler,
186
196
  "aria-selected": selected,
187
197
  "aria-disabled": disabled ? true : undefined,
188
- tabIndex: disabled ? undefined : -1,
189
- "aria-labelledby": `${labelId} ${slots.InlineDescription ? inlineDescriptionId : ''}`,
190
- "aria-describedby": slots.BlockDescription ? blockDescriptionId : undefined
191
- }, props), /*#__PURE__*/_react.default.createElement(_PrivateItemWrapper, null, /*#__PURE__*/_react.default.createElement(_Selection.Selection, {
198
+ tabIndex: disabled || _PrivateItemWrapper ? undefined : 0,
199
+ "aria-labelledby": labelId,
200
+ "aria-describedby": [slots.InlineDescription && inlineDescriptionId, slots.BlockDescription && blockDescriptionId].filter(Boolean).join(' ')
201
+ }, props), /*#__PURE__*/_react.default.createElement(ItemWrapper, null, /*#__PURE__*/_react.default.createElement(_Selection.Selection, {
192
202
  selected: selected,
193
203
  disabled: disabled
194
204
  }), slots.LeadingVisual, /*#__PURE__*/_react.default.createElement(_Box.default, {
@@ -54,9 +54,7 @@ export const Item = /*#__PURE__*/React.forwardRef(({
54
54
  onSelect = () => null,
55
55
  sx: sxProp = {},
56
56
  id,
57
- _PrivateItemWrapper = ({
58
- children
59
- }) => /*#__PURE__*/React.createElement(React.Fragment, null, children),
57
+ _PrivateItemWrapper,
60
58
  ...props
61
59
  }, forwardedRef) => {
62
60
  const {
@@ -73,9 +71,9 @@ export const Item = /*#__PURE__*/React.forwardRef(({
73
71
  paddingY: '6px',
74
72
  // custom value off the scale
75
73
  lineHeight: TEXT_ROW_HEIGHT,
76
- marginX: listVariant === 'inset' ? 2 : 0,
77
74
  minHeight: 5,
78
- borderRadius: 2,
75
+ marginX: listVariant === 'inset' ? 2 : 0,
76
+ borderRadius: listVariant === 'inset' ? 2 : 0,
79
77
  transition: 'background 33.333ms linear',
80
78
  color: getVariantStyles(variant, disabled).color,
81
79
  textDecoration: 'none',
@@ -88,11 +86,17 @@ export const Item = /*#__PURE__*/React.forwardRef(({
88
86
  backgroundColor: `actionListItem.${variant}.hoverBg`,
89
87
  color: getVariantStyles(variant, disabled).hoverColor
90
88
  },
91
- ':focus:not([aria-disabled])': {
89
+ ':focus:not([data-focus-visible-added])': {
92
90
  backgroundColor: `actionListItem.${variant}.selectedBg`,
93
91
  color: getVariantStyles(variant, disabled).hoverColor,
94
92
  outline: 'none'
95
93
  },
94
+ '&[data-focus-visible-added]': {
95
+ // we don't use :focus-visible because not all browsers (safari) have it yet
96
+ outline: 'none',
97
+ border: `2 solid`,
98
+ boxShadow: `0 0 0 2px ${theme === null || theme === void 0 ? void 0 : theme.colors.accent.emphasis}`
99
+ },
96
100
  ':active:not([aria-disabled])': {
97
101
  backgroundColor: `actionListItem.${variant}.activeBg`,
98
102
  color: getVariantStyles(variant, disabled).hoverColor
@@ -114,7 +118,7 @@ export const Item = /*#__PURE__*/React.forwardRef(({
114
118
  borderColor: 'var(--divider-color, transparent)'
115
119
  },
116
120
  // show between 2 items
117
- ':not(:first-of-type):not([aria-selected=true])': {
121
+ ':not(:first-of-type)': {
118
122
  '--divider-color': theme === null || theme === void 0 ? void 0 : theme.colors.actionListItem.inlineDivider
119
123
  },
120
124
  // hide divider after dividers & group header, with higher importance!
@@ -122,25 +126,29 @@ export const Item = /*#__PURE__*/React.forwardRef(({
122
126
  '--divider-color': 'transparent !important'
123
127
  },
124
128
  // hide border on current and previous item
125
- '&:hover:not([aria-disabled]), &:focus:not([aria-disabled])': {
126
- '--divider-color': 'transparent'
127
- },
128
- '&:hover:not([aria-disabled]) + &, &:focus:not([aria-disabled]) + &': {
129
+ '&:hover:not([aria-disabled]), &:focus:not([aria-disabled]), &[data-focus-visible-added]:not([aria-disabled])': {
129
130
  '--divider-color': 'transparent'
130
131
  },
131
- // hide border around selected item
132
- '&[aria-selected=true] + &': {
132
+ '&:hover:not([aria-disabled]) + &, &:focus:not([aria-disabled]) + &, &[data-focus-visible-added] + li': {
133
133
  '--divider-color': 'transparent'
134
134
  }
135
135
  };
136
136
  const clickHandler = React.useCallback(event => {
137
137
  if (disabled) return;
138
138
  if (!event.defaultPrevented) onSelect(event);
139
+ }, [onSelect, disabled]);
140
+ const keyPressHandler = React.useCallback(event => {
141
+ if (disabled) return;
142
+
143
+ if (!event.defaultPrevented && [' ', 'Enter'].includes(event.key)) {
144
+ onSelect(event);
145
+ }
139
146
  }, [onSelect, disabled]); // use props.id if provided, otherwise generate one.
140
147
 
141
148
  const labelId = useSSRSafeId(id);
142
149
  const inlineDescriptionId = useSSRSafeId(id && `${id}--inline-description`);
143
150
  const blockDescriptionId = useSSRSafeId(id && `${id}--block-description`);
151
+ const ItemWrapper = _PrivateItemWrapper || React.Fragment;
144
152
  return /*#__PURE__*/React.createElement(Slots, {
145
153
  context: {
146
154
  variant,
@@ -152,12 +160,13 @@ export const Item = /*#__PURE__*/React.forwardRef(({
152
160
  ref: forwardedRef,
153
161
  sx: merge(styles, sxProp),
154
162
  onClick: clickHandler,
163
+ onKeyPress: keyPressHandler,
155
164
  "aria-selected": selected,
156
165
  "aria-disabled": disabled ? true : undefined,
157
- tabIndex: disabled ? undefined : -1,
158
- "aria-labelledby": `${labelId} ${slots.InlineDescription ? inlineDescriptionId : ''}`,
159
- "aria-describedby": slots.BlockDescription ? blockDescriptionId : undefined
160
- }, props), /*#__PURE__*/React.createElement(_PrivateItemWrapper, null, /*#__PURE__*/React.createElement(Selection, {
166
+ tabIndex: disabled || _PrivateItemWrapper ? undefined : 0,
167
+ "aria-labelledby": labelId,
168
+ "aria-describedby": [slots.InlineDescription && inlineDescriptionId, slots.BlockDescription && blockDescriptionId].filter(Boolean).join(' ')
169
+ }, props), /*#__PURE__*/React.createElement(ItemWrapper, null, /*#__PURE__*/React.createElement(Selection, {
161
170
  selected: selected,
162
171
  disabled: disabled
163
172
  }), slots.LeadingVisual, /*#__PURE__*/React.createElement(Box, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/components",
3
- "version": "0.0.0-20211011154552",
3
+ "version": "0.0.0-20211011162723",
4
4
  "description": "Primer react components",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib-esm/index.js",