@instructure/ui-options 8.19.1-snapshot.8 → 8.20.1-snapshot.18
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 +7 -0
- package/es/Options/Item/__examples__/Item.examples.js +5 -0
- package/es/Options/Item/index.js +16 -9
- package/es/Options/Item/props.js +3 -2
- package/es/Options/Item/styles.js +18 -1
- package/es/Options/Item/theme.js +1 -1
- package/es/Options/index.js +2 -2
- package/es/Options/theme.js +3 -5
- package/es/index.js +1 -1
- package/lib/Options/Item/__examples__/Item.examples.js +5 -0
- package/lib/Options/Item/index.js +15 -8
- package/lib/Options/Item/props.js +3 -2
- package/lib/Options/Item/styles.js +18 -1
- package/lib/Options/Item/theme.js +1 -1
- package/lib/Options/index.js +2 -2
- package/lib/Options/theme.js +3 -7
- package/lib/index.js +0 -6
- package/package.json +14 -14
- package/src/Options/Item/__examples__/Item.examples.ts +10 -0
- package/src/Options/Item/index.tsx +31 -4
- package/src/Options/Item/props.ts +22 -3
- package/src/Options/Item/styles.ts +17 -1
- package/src/Options/Item/theme.ts +1 -1
- package/src/Options/README.md +61 -0
- package/src/Options/index.tsx +8 -2
- package/src/Options/theme.ts +1 -10
- package/src/index.ts +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/Options/Item/__examples__/Item.examples.d.ts.map +1 -1
- package/types/Options/Item/index.d.ts +6 -4
- package/types/Options/Item/index.d.ts.map +1 -1
- package/types/Options/Item/props.d.ts +8 -3
- package/types/Options/Item/props.d.ts.map +1 -1
- package/types/Options/Item/styles.d.ts.map +1 -1
- package/types/Options/index.d.ts.map +1 -1
- package/types/Options/theme.d.ts +1 -2
- package/types/Options/theme.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
|
@@ -31,18 +31,24 @@ import type {
|
|
|
31
31
|
OptionsItemTheme,
|
|
32
32
|
OtherHTMLAttributes
|
|
33
33
|
} from '@instructure/shared-types'
|
|
34
|
+
import type { WithDeterministicIdProps } from '@instructure/ui-react-utils'
|
|
34
35
|
import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
|
|
35
36
|
|
|
36
37
|
type ItemProps = {
|
|
37
38
|
children?: React.ReactNode | (() => React.ReactNode)
|
|
38
39
|
/**
|
|
39
|
-
* Element type to render as
|
|
40
|
+
* Element type to render as. Will be set to `<a>` if href is provided.
|
|
40
41
|
*/
|
|
41
42
|
as?: AsElementType
|
|
42
43
|
/**
|
|
43
44
|
* The style variant of the item
|
|
44
45
|
*/
|
|
45
|
-
variant?:
|
|
46
|
+
variant?:
|
|
47
|
+
| 'default'
|
|
48
|
+
| 'highlighted'
|
|
49
|
+
| 'selected'
|
|
50
|
+
| 'disabled'
|
|
51
|
+
| 'highlighted-disabled'
|
|
46
52
|
/**
|
|
47
53
|
* The ARIA role of the element
|
|
48
54
|
*/
|
|
@@ -76,6 +82,10 @@ type OptionsItemOwnProps = ItemProps & {
|
|
|
76
82
|
* The ARIA role of the description element
|
|
77
83
|
*/
|
|
78
84
|
descriptionRole?: string
|
|
85
|
+
/**
|
|
86
|
+
* Providing href will render the option as `<a>`.
|
|
87
|
+
*/
|
|
88
|
+
href?: string
|
|
79
89
|
/**
|
|
80
90
|
* provides a reference to the underlying html root element
|
|
81
91
|
*/
|
|
@@ -88,6 +98,7 @@ type AllowedPropKeys = Readonly<Array<PropKeys>>
|
|
|
88
98
|
|
|
89
99
|
type OptionsItemProps = OptionsItemOwnProps &
|
|
90
100
|
WithStyleProps<OptionsItemTheme, OptionsItemStyle> &
|
|
101
|
+
WithDeterministicIdProps &
|
|
91
102
|
OtherHTMLAttributes<OptionsItemOwnProps>
|
|
92
103
|
|
|
93
104
|
type OptionsItemStyle = ComponentStyle<
|
|
@@ -101,7 +112,13 @@ type OptionsItemStyle = ComponentStyle<
|
|
|
101
112
|
|
|
102
113
|
const propTypes: PropValidators<PropKeys> = {
|
|
103
114
|
as: PropTypes.elementType,
|
|
104
|
-
variant: PropTypes.oneOf([
|
|
115
|
+
variant: PropTypes.oneOf([
|
|
116
|
+
'default',
|
|
117
|
+
'highlighted',
|
|
118
|
+
'selected',
|
|
119
|
+
'disabled',
|
|
120
|
+
'highlighted-disabled'
|
|
121
|
+
]),
|
|
105
122
|
role: PropTypes.string,
|
|
106
123
|
renderBeforeLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
107
124
|
renderAfterLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
@@ -109,6 +126,7 @@ const propTypes: PropValidators<PropKeys> = {
|
|
|
109
126
|
afterLabelContentVAlign: PropTypes.oneOf(['start', 'center', 'end']),
|
|
110
127
|
description: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
111
128
|
descriptionRole: PropTypes.string,
|
|
129
|
+
href: PropTypes.string,
|
|
112
130
|
elementRef: PropTypes.func,
|
|
113
131
|
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func])
|
|
114
132
|
}
|
|
@@ -123,6 +141,7 @@ const allowedProps: AllowedPropKeys = [
|
|
|
123
141
|
'afterLabelContentVAlign',
|
|
124
142
|
'description',
|
|
125
143
|
'descriptionRole',
|
|
144
|
+
'href',
|
|
126
145
|
'elementRef',
|
|
127
146
|
'children'
|
|
128
147
|
]
|
|
@@ -63,6 +63,12 @@ const generateStyle = (
|
|
|
63
63
|
color: componentTheme.highlightedLabelColor
|
|
64
64
|
},
|
|
65
65
|
disabled: { cursor: 'not-allowed', opacity: 0.5 },
|
|
66
|
+
['highlighted-disabled']: {
|
|
67
|
+
background: componentTheme.highlightedBackground,
|
|
68
|
+
color: componentTheme.highlightedLabelColor,
|
|
69
|
+
cursor: 'not-allowed',
|
|
70
|
+
opacity: 0.5
|
|
71
|
+
},
|
|
66
72
|
default: {}
|
|
67
73
|
}
|
|
68
74
|
|
|
@@ -92,6 +98,8 @@ const generateStyle = (
|
|
|
92
98
|
}[vAlign!]
|
|
93
99
|
}
|
|
94
100
|
|
|
101
|
+
const linkStyles = { textDecoration: 'none', color: 'currentColor' }
|
|
102
|
+
|
|
95
103
|
const transition = 'background 200ms'
|
|
96
104
|
|
|
97
105
|
return {
|
|
@@ -143,7 +151,15 @@ const generateStyle = (
|
|
|
143
151
|
hasContentAfterLabel && {
|
|
144
152
|
paddingInlineEnd: `calc(${componentTheme.iconPadding} * 2 + 1em)`,
|
|
145
153
|
paddingInlineStart: `calc(${componentTheme.iconPadding} * 2 + 1em)`
|
|
146
|
-
})
|
|
154
|
+
}),
|
|
155
|
+
|
|
156
|
+
// NOTE: needs separate groups for `:is()` and `:-webkit-any()` because of css selector group validation (see https://www.w3.org/TR/selectors-3/#grouping)
|
|
157
|
+
'&:is(a)': {
|
|
158
|
+
'&, &:link, &:visited, &:active, &:hover, &:focus': linkStyles
|
|
159
|
+
},
|
|
160
|
+
'&:-webkit-any(a)': {
|
|
161
|
+
'&, &:link, &:visited, &:active, &:hover, &:focus': linkStyles
|
|
162
|
+
}
|
|
147
163
|
},
|
|
148
164
|
content: {
|
|
149
165
|
label: 'optionItem__content',
|
|
@@ -55,7 +55,7 @@ const generateComponentTheme = (theme: Theme): OptionsItemTheme => {
|
|
|
55
55
|
|
|
56
56
|
padding: `${spacing?.xSmall} ${spacing?.small}`,
|
|
57
57
|
iconPadding: spacing?.small,
|
|
58
|
-
nestedPadding: spacing?.
|
|
58
|
+
nestedPadding: spacing?.small,
|
|
59
59
|
|
|
60
60
|
beforeLabelContentVOffset: '0.625rem',
|
|
61
61
|
afterLabelContentVOffset: '0.625rem',
|
package/src/Options/README.md
CHANGED
|
@@ -24,6 +24,9 @@ example: true
|
|
|
24
24
|
<Options.Item variant="disabled">
|
|
25
25
|
Disabled option
|
|
26
26
|
</Options.Item>
|
|
27
|
+
<Options.Item variant="highlighted-disabled">
|
|
28
|
+
Highlighted disabled option
|
|
29
|
+
</Options.Item>
|
|
27
30
|
</Options>
|
|
28
31
|
</View>
|
|
29
32
|
```
|
|
@@ -372,3 +375,61 @@ class Example extends React.Component {
|
|
|
372
375
|
|
|
373
376
|
render(<Example />)
|
|
374
377
|
```
|
|
378
|
+
|
|
379
|
+
Providing a `href` prop will render the option as `<a>` link element.
|
|
380
|
+
|
|
381
|
+
**WARNING!** Since `Options` is a view-only component, you have to make sure it is accessible, and if set the variant to disabled, disable the links as well!
|
|
382
|
+
|
|
383
|
+
```js
|
|
384
|
+
---
|
|
385
|
+
render: false
|
|
386
|
+
example: true
|
|
387
|
+
---
|
|
388
|
+
class Example extends React.Component {
|
|
389
|
+
constructor(props) {
|
|
390
|
+
super(props)
|
|
391
|
+
|
|
392
|
+
this.state = {
|
|
393
|
+
highlighted: -1
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
handleMouseOver = (index) => {
|
|
398
|
+
this.setState({ highlighted: index })
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
render() {
|
|
402
|
+
return (
|
|
403
|
+
<View display="block" width="300px">
|
|
404
|
+
<Options onMouseOut={(e) => this.setState({ highlighted: -1 })}>
|
|
405
|
+
<Options.Item
|
|
406
|
+
onMouseOver={(e) => this.handleMouseOver(1)}
|
|
407
|
+
variant={this.state.highlighted === 1 ? 'highlighted' : 'default'}
|
|
408
|
+
href="/"
|
|
409
|
+
>
|
|
410
|
+
Link one
|
|
411
|
+
</Options.Item>
|
|
412
|
+
<Options.Item
|
|
413
|
+
onMouseOver={(e) => this.handleMouseOver(2)}
|
|
414
|
+
variant={this.state.highlighted === 2 ? 'highlighted' : 'default'}
|
|
415
|
+
href="/"
|
|
416
|
+
>
|
|
417
|
+
Link two
|
|
418
|
+
</Options.Item>
|
|
419
|
+
<Options.Item
|
|
420
|
+
onMouseOver={(e) => this.handleMouseOver(3)}
|
|
421
|
+
variant={this.state.highlighted === 3 ? 'highlighted' : 'default'}
|
|
422
|
+
variant="disabled"
|
|
423
|
+
onClick={(e) => { e.preventDefault() }}
|
|
424
|
+
href="/"
|
|
425
|
+
>
|
|
426
|
+
Link three
|
|
427
|
+
</Options.Item>
|
|
428
|
+
</Options>
|
|
429
|
+
</View>
|
|
430
|
+
)
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
render(<Example />)
|
|
435
|
+
```
|
package/src/Options/index.tsx
CHANGED
|
@@ -134,7 +134,7 @@ class Options extends Component<OptionsProps> {
|
|
|
134
134
|
return this.renderSubList(child)
|
|
135
135
|
}
|
|
136
136
|
if (matchComponentTypes(child, ['Item', 'Separator'])) {
|
|
137
|
-
return safeCloneElement(child, { as: this.childAs })
|
|
137
|
+
return safeCloneElement(child, { as: this.childAs || child.props.as })
|
|
138
138
|
}
|
|
139
139
|
return undefined
|
|
140
140
|
})
|
|
@@ -161,7 +161,13 @@ class Options extends Component<OptionsProps> {
|
|
|
161
161
|
margin="none"
|
|
162
162
|
padding="none"
|
|
163
163
|
background="primary"
|
|
164
|
-
aria-labelledby={
|
|
164
|
+
aria-labelledby={
|
|
165
|
+
renderLabel
|
|
166
|
+
? this._labelId
|
|
167
|
+
: this.props['aria-labelledby']
|
|
168
|
+
? this.props['aria-labelledby']
|
|
169
|
+
: undefined
|
|
170
|
+
}
|
|
165
171
|
>
|
|
166
172
|
{this.renderChildren()}
|
|
167
173
|
</View>
|
package/src/Options/theme.ts
CHANGED
|
@@ -25,14 +25,6 @@
|
|
|
25
25
|
import type { Theme } from '@instructure/ui-themes'
|
|
26
26
|
import type { OptionsTheme } from '@instructure/shared-types'
|
|
27
27
|
|
|
28
|
-
const optionsThemeKeys: (keyof OptionsTheme)[] = [
|
|
29
|
-
'labelFontWeight',
|
|
30
|
-
'background',
|
|
31
|
-
'labelColor',
|
|
32
|
-
'labelPadding',
|
|
33
|
-
'nestedLabelPadding'
|
|
34
|
-
]
|
|
35
|
-
|
|
36
28
|
/**
|
|
37
29
|
* Generates the theme object for the component from the theme and provided additional information
|
|
38
30
|
* @param {Object} theme The actual theme object.
|
|
@@ -41,7 +33,6 @@ const optionsThemeKeys: (keyof OptionsTheme)[] = [
|
|
|
41
33
|
const generateComponentTheme = (theme: Theme): OptionsTheme => {
|
|
42
34
|
const { colors, typography, spacing } = theme
|
|
43
35
|
|
|
44
|
-
// TODO: if updated, update optionsThemeKeys array too
|
|
45
36
|
const componentVariables: OptionsTheme = {
|
|
46
37
|
labelFontWeight: typography?.fontWeightBold,
|
|
47
38
|
|
|
@@ -57,5 +48,5 @@ const generateComponentTheme = (theme: Theme): OptionsTheme => {
|
|
|
57
48
|
}
|
|
58
49
|
}
|
|
59
50
|
|
|
60
|
-
export { generateComponentTheme as optionsThemeGenerator
|
|
51
|
+
export { generateComponentTheme as optionsThemeGenerator }
|
|
61
52
|
export default generateComponentTheme
|
package/src/index.ts
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
export { Options } from './Options'
|
|
26
26
|
|
|
27
|
-
export { optionsThemeGenerator
|
|
27
|
+
export { optionsThemeGenerator } from './Options/theme'
|
|
28
28
|
export { optionsItemThemeGenerator } from './Options/Item/theme'
|
|
29
29
|
export { optionsSeparatorThemeGenerator } from './Options/Separator/theme'
|
|
30
30
|
|