@instructure/ui-buttons 8.13.1-snapshot.9 → 8.14.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/es/BaseButton/index.js +64 -43
  3. package/es/BaseButton/props.js +2 -88
  4. package/es/BaseButton/theme.js +1 -1
  5. package/es/Button/index.js +2 -2
  6. package/es/Button/props.js +3 -65
  7. package/es/CloseButton/index.js +23 -18
  8. package/es/CloseButton/props.js +2 -60
  9. package/es/CondensedButton/index.js +2 -2
  10. package/es/CondensedButton/props.js +3 -48
  11. package/es/IconButton/index.js +2 -2
  12. package/es/IconButton/props.js +3 -68
  13. package/es/ToggleButton/index.js +4 -5
  14. package/es/ToggleButton/props.js +1 -58
  15. package/lib/BaseButton/index.js +67 -43
  16. package/lib/BaseButton/props.js +2 -88
  17. package/lib/BaseButton/theme.js +1 -1
  18. package/lib/Button/index.js +2 -2
  19. package/lib/Button/props.js +3 -65
  20. package/lib/CloseButton/index.js +23 -18
  21. package/lib/CloseButton/props.js +2 -60
  22. package/lib/CondensedButton/index.js +2 -2
  23. package/lib/CondensedButton/props.js +3 -48
  24. package/lib/IconButton/index.js +2 -2
  25. package/lib/IconButton/props.js +3 -68
  26. package/lib/ToggleButton/index.js +4 -5
  27. package/lib/ToggleButton/props.js +1 -58
  28. package/package.json +21 -22
  29. package/src/BaseButton/index.tsx +35 -27
  30. package/src/BaseButton/props.ts +103 -72
  31. package/src/BaseButton/theme.ts +1 -6
  32. package/src/Button/index.tsx +4 -8
  33. package/src/Button/props.ts +74 -48
  34. package/src/CloseButton/index.tsx +4 -6
  35. package/src/CloseButton/props.ts +67 -41
  36. package/src/CondensedButton/index.tsx +3 -7
  37. package/src/CondensedButton/props.ts +56 -34
  38. package/src/IconButton/index.tsx +3 -7
  39. package/src/IconButton/props.ts +77 -50
  40. package/src/ToggleButton/index.tsx +8 -15
  41. package/src/ToggleButton/props.ts +65 -39
  42. package/tsconfig.build.json +25 -2
  43. package/tsconfig.build.tsbuildinfo +1 -0
  44. package/types/BaseButton/BaseButtonLocator.d.ts +57 -56
  45. package/types/BaseButton/BaseButtonLocator.d.ts.map +1 -1
  46. package/types/BaseButton/index.d.ts +16 -15
  47. package/types/BaseButton/index.d.ts.map +1 -1
  48. package/types/BaseButton/props.d.ts +76 -5
  49. package/types/BaseButton/props.d.ts.map +1 -1
  50. package/types/BaseButton/theme.d.ts.map +1 -1
  51. package/types/Button/ButtonLocator.d.ts +57 -56
  52. package/types/Button/ButtonLocator.d.ts.map +1 -1
  53. package/types/Button/index.d.ts +10 -7
  54. package/types/Button/index.d.ts.map +1 -1
  55. package/types/Button/locator.d.ts +52 -52
  56. package/types/Button/props.d.ts +57 -3
  57. package/types/Button/props.d.ts.map +1 -1
  58. package/types/CloseButton/CloseButtonLocator.d.ts +52 -52
  59. package/types/CloseButton/index.d.ts +4 -3
  60. package/types/CloseButton/index.d.ts.map +1 -1
  61. package/types/CloseButton/props.d.ts +55 -5
  62. package/types/CloseButton/props.d.ts.map +1 -1
  63. package/types/CondensedButton/CondensedButtonLocator.d.ts +57 -56
  64. package/types/CondensedButton/CondensedButtonLocator.d.ts.map +1 -1
  65. package/types/CondensedButton/index.d.ts +9 -6
  66. package/types/CondensedButton/index.d.ts.map +1 -1
  67. package/types/CondensedButton/props.d.ts +44 -3
  68. package/types/CondensedButton/props.d.ts.map +1 -1
  69. package/types/IconButton/IconButtonLocator.d.ts +57 -56
  70. package/types/IconButton/IconButtonLocator.d.ts.map +1 -1
  71. package/types/IconButton/index.d.ts +11 -8
  72. package/types/IconButton/index.d.ts.map +1 -1
  73. package/types/IconButton/props.d.ts +60 -4
  74. package/types/IconButton/props.d.ts.map +1 -1
  75. package/types/ToggleButton/ToggleButtonLocator.d.ts +57 -56
  76. package/types/ToggleButton/ToggleButtonLocator.d.ts.map +1 -1
  77. package/types/ToggleButton/index.d.ts +12 -13
  78. package/types/ToggleButton/index.d.ts.map +1 -1
  79. package/types/ToggleButton/props.d.ts +52 -4
  80. package/types/ToggleButton/props.d.ts.map +1 -1
  81. package/LICENSE.md +0 -27
@@ -23,9 +23,10 @@
23
23
  */
24
24
 
25
25
  /** @jsx jsx */
26
- import { Component } from 'react'
26
+ import React, { Component } from 'react'
27
27
  import keycode from 'keycode'
28
28
 
29
+ import { warn } from '@instructure/console'
29
30
  import { testable } from '@instructure/ui-testable'
30
31
  import {
31
32
  getElementType,
@@ -36,6 +37,7 @@ import {
36
37
  import { isActiveElement } from '@instructure/ui-dom-utils'
37
38
  import { hasVisibleChildren } from '@instructure/ui-a11y-utils'
38
39
  import { View } from '@instructure/ui-view'
40
+ import type { ViewProps } from '@instructure/ui-view'
39
41
 
40
42
  import { withStyle, jsx } from '@instructure/emotion'
41
43
 
@@ -49,6 +51,7 @@ import type { BaseButtonProps, BaseButtonStyleProps } from './props'
49
51
  ---
50
52
  category: components/utilities
51
53
  ---
54
+ @tsProps
52
55
  **/
53
56
 
54
57
  @withStyle(generateStyles, generateComponentTheme)
@@ -59,13 +62,11 @@ class BaseButton extends Component<BaseButtonProps> {
59
62
  static propTypes = propTypes
60
63
  static allowedProps = allowedProps
61
64
  static defaultProps = {
62
- children: null,
63
65
  type: 'button',
64
66
  size: 'medium',
65
- // @ts-expect-error ts-migrate(6133) FIXME: 'el' is declared but its value is never read.
66
- elementRef: (el) => {},
67
67
  as: 'button',
68
68
  // Leave interaction default undefined so that `disabled` and `readOnly` can also be supplied
69
+ interaction: undefined,
69
70
  color: 'secondary',
70
71
  shape: 'rectangle',
71
72
  display: 'inline-block',
@@ -74,23 +75,19 @@ class BaseButton extends Component<BaseButtonProps> {
74
75
  withBorder: true,
75
76
  isCondensed: false,
76
77
  margin: '0',
77
- cursor: 'pointer',
78
- // @ts-expect-error ts-migrate(6133) FIXME: 'event' is declared but its value is never read.
79
- onKeyDown: (event) => {}
78
+ cursor: 'pointer'
80
79
  } as const
81
80
 
82
81
  ref: Element | null = null
83
82
 
84
83
  componentDidMount() {
85
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
86
- this.props.makeStyles(this.makeStylesVariables)
84
+ this.props.makeStyles?.(this.makeStylesVariables)
87
85
  }
88
86
 
89
- // @ts-expect-error ts-migrate(6133) FIXME: 'prevProps' is declared but its value is never rea... Remove this comment to see the full error message
90
- componentDidUpdate(prevProps, prevState, snapshot) {
91
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
92
- this.props.makeStyles(this.makeStylesVariables)
87
+ componentDidUpdate() {
88
+ this.props.makeStyles?.(this.makeStylesVariables)
93
89
  }
90
+
94
91
  get _rootElement() {
95
92
  console.warn(
96
93
  '_rootElement property is deprecated and will be removed in v9, please use ref instead'
@@ -131,6 +128,20 @@ class BaseButton extends Component<BaseButtonProps> {
131
128
  return this.interaction === 'enabled'
132
129
  }
133
130
 
131
+ // TODO: delete once the type of tabIndex is changed to number only
132
+ get tabIndex() {
133
+ const { tabIndex } = this.props
134
+
135
+ if (typeof tabIndex === 'string') {
136
+ warn(
137
+ false,
138
+ 'The `string` value for `tabIndex` is deprecated. Only `number` type will be accepted from V9.0.0.'
139
+ )
140
+ return parseInt(tabIndex)
141
+ }
142
+ return tabIndex
143
+ }
144
+
134
145
  get focusColor() {
135
146
  const { color, focusColor, withBackground } = this.props
136
147
 
@@ -147,8 +158,7 @@ class BaseButton extends Component<BaseButtonProps> {
147
158
  return 'info'
148
159
  }
149
160
 
150
- // @ts-expect-error ts-migrate(2532) FIXME: Object is possibly 'undefined'.
151
- return color.includes('inverse') ? 'inverse' : 'info'
161
+ return color!.includes('inverse') ? 'inverse' : 'info'
152
162
  }
153
163
 
154
164
  get focused() {
@@ -156,8 +166,7 @@ class BaseButton extends Component<BaseButtonProps> {
156
166
  }
157
167
 
158
168
  focus() {
159
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
160
- this.ref && this.ref.focus()
169
+ this.ref && (this.ref as HTMLElement).focus()
161
170
  }
162
171
 
163
172
  handleElementRef = (el: Element | null) => {
@@ -170,8 +179,7 @@ class BaseButton extends Component<BaseButtonProps> {
170
179
  }
171
180
  }
172
181
 
173
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
174
- handleClick = (event) => {
182
+ handleClick = (event: React.MouseEvent<ViewProps>) => {
175
183
  const { onClick } = this.props
176
184
  const { interaction } = this
177
185
 
@@ -186,13 +194,13 @@ class BaseButton extends Component<BaseButtonProps> {
186
194
  }
187
195
  }
188
196
 
189
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'event' implicitly has an 'any' type.
190
- handleKeyDown = (event) => {
197
+ handleKeyDown = (event: React.KeyboardEvent<ViewProps>) => {
191
198
  const { onClick, onKeyDown, href } = this.props
192
199
  const { interaction } = this
193
200
 
194
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
195
- onKeyDown(event)
201
+ if (typeof onKeyDown === 'function') {
202
+ onKeyDown(event)
203
+ }
196
204
 
197
205
  // behave like a button when space key is pressed
198
206
  const { space, enter } = keycode.codes
@@ -209,8 +217,7 @@ class BaseButton extends Component<BaseButtonProps> {
209
217
  }
210
218
 
211
219
  if (href) {
212
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
213
- this.ref && this.ref.click()
220
+ this.ref && (this.ref as HTMLElement).click()
214
221
  }
215
222
  }
216
223
  }
@@ -274,6 +281,8 @@ class BaseButton extends Component<BaseButtonProps> {
274
281
 
275
282
  const { isDisabled, isEnabled, isReadOnly } = this
276
283
 
284
+ const tabIndexNumber = this.tabIndex
285
+
277
286
  return (
278
287
  <View
279
288
  {...passthroughProps(props)}
@@ -294,8 +303,7 @@ class BaseButton extends Component<BaseButtonProps> {
294
303
  onClick={this.handleClick}
295
304
  onKeyDown={this.handleKeyDown}
296
305
  role={onClick && as !== 'button' ? 'button' : undefined}
297
- //@ts-expect-error fix this later to be number
298
- tabIndex={onClick && as ? tabIndex || '0' : tabIndex}
306
+ tabIndex={onClick && as ? tabIndexNumber || 0 : tabIndexNumber}
299
307
  disabled={isDisabled || isReadOnly}
300
308
  css={isEnabled ? styles?.baseButton : null}
301
309
  >
@@ -34,34 +34,130 @@ import type {
34
34
  ComponentStyle
35
35
  } from '@instructure/emotion'
36
36
  import type {
37
+ ToProp,
37
38
  AsElementType,
38
39
  BaseButtonTheme,
39
40
  OtherHTMLAttributes,
40
41
  PropValidators
41
42
  } from '@instructure/shared-types'
42
43
  import type { Cursor } from '@instructure/ui-prop-types'
44
+ import type { ViewProps } from '@instructure/ui-view'
43
45
 
44
46
  type BaseButtonOwnProps = {
47
+ /**
48
+ * Specifies the `Button` children.
49
+ */
45
50
  children?: React.ReactNode
51
+
52
+ /**
53
+ * Specifies the type of the `Button`'s underlying html element.
54
+ */
46
55
  type?: 'button' | 'submit' | 'reset'
56
+
57
+ /**
58
+ * The size of the `Button`
59
+ */
47
60
  size?: 'small' | 'medium' | 'large'
61
+
62
+ /**
63
+ * Provides a reference to the `Button`'s underlying html element.
64
+ */
48
65
  elementRef?: (element: Element | null) => void
66
+
67
+ /**
68
+ * The element to render as the component root, `Button` by default.
69
+ */
49
70
  as?: AsElementType
71
+
72
+ /**
73
+ * Specifies if interaction with the `Button` is enabled, disabled, or readonly.
74
+ */
50
75
  interaction?: InteractionType
76
+
77
+ /**
78
+ * Specifies the color for the `Button`.
79
+ */
51
80
  color?: 'primary' | 'primary-inverse' | 'secondary' | 'success' | 'danger'
81
+
82
+ /**
83
+ * Override the `Button`'s default focus outline color.
84
+ */
52
85
  focusColor?: 'info' | 'inverse'
86
+
87
+ /**
88
+ * The `Button` display property. When set to `inline-block`, the `Button` displays inline with other elements.
89
+ * When set to block, the `Button` expands to fill the width of the container.
90
+ */
53
91
  display?: 'inline-block' | 'block'
92
+
93
+ /**
94
+ * Sets the alignment of the `Button` children and/or icon.
95
+ */
54
96
  textAlign?: 'start' | 'center'
97
+
98
+ /**
99
+ * Specifies if the `Button` shape should be a circle or rectangle.
100
+ */
55
101
  shape?: 'rectangle' | 'circle'
102
+
103
+ /**
104
+ * Specifies if the `Button` should render with a solid background. When false, the background is transparent.
105
+ */
56
106
  withBackground?: boolean
107
+
108
+ /**
109
+ * Specifies if the `Button` should render with a border.
110
+ */
57
111
  withBorder?: boolean
112
+
113
+ /**
114
+ * Designates if the `Button` should render without padding. This option should only be set when `withBorder` and
115
+ * `withBackground` are also set to false.
116
+ */
58
117
  isCondensed?: boolean
118
+
119
+ /**
120
+ * Valid values are `0`, `none`, `auto`, `xxx-small`, `xx-small`, `x-small`,
121
+ * `small`, `medium`, `large`, `x-large`, `xx-large`. Apply these values via
122
+ * familiar CSS-like shorthand. For example: `margin="small auto large"`.
123
+ */
59
124
  margin?: Spacing
125
+
126
+ /**
127
+ * Specify a mouse cursor to use when hovering over the button.
128
+ * The `pointer` cursor is used by default.
129
+ */
60
130
  cursor?: Cursor
131
+
132
+ /**
133
+ * Specifies an href attribute for the `Button`'s underlying html element.
134
+ */
61
135
  href?: string
62
- onClick?: (...args: any[]) => any
63
- onKeyDown?: (...args: any[]) => any
64
- renderIcon?: React.ReactNode | ((...args: any[]) => any)
136
+
137
+ /**
138
+ * Callback fired when the `Button` is clicked.
139
+ */
140
+ onClick?: (
141
+ event: React.KeyboardEvent<ViewProps> | React.MouseEvent<ViewProps>
142
+ ) => void
143
+
144
+ /**
145
+ * Callback fired when the `Button` receives a keydown event.
146
+ */
147
+ onKeyDown?: (event: React.KeyboardEvent<ViewProps>) => void
148
+
149
+ /**
150
+ * An icon, or function that returns an icon.
151
+ */
152
+ renderIcon?: React.ReactNode | (() => React.ReactNode)
153
+
154
+ // Deprecated `string` tabIndex type
155
+ // TODO: remove string type in v9
156
+ /**
157
+ * Specifies the tabindex of the `Button`.
158
+ *
159
+ * (`string` type is __deprecated__, use `number`)
160
+ */
65
161
  tabIndex?: number | string
66
162
  }
67
163
 
@@ -76,7 +172,8 @@ type AllowedPropKeys = Readonly<Array<PropKeys>>
76
172
 
77
173
  type BaseButtonProps = BaseButtonOwnProps &
78
174
  WithStyleProps<BaseButtonTheme, BaseButtonStyle> &
79
- OtherHTMLAttributes<BaseButtonOwnProps>
175
+ OtherHTMLAttributes<BaseButtonOwnProps> &
176
+ ToProp
80
177
 
81
178
  type BaseButtonStyle = ComponentStyle<
82
179
  | 'baseButton'
@@ -90,33 +187,12 @@ type BaseButtonStyle = ComponentStyle<
90
187
  >
91
188
 
92
189
  const propTypes: PropValidators<PropKeys> = {
93
- /**
94
- * Specifies the `Button` children.
95
- */
96
190
  children: PropTypes.node,
97
- /**
98
- * Specifies the type of the `Button`'s underlying html element.
99
- */
100
191
  type: PropTypes.oneOf(['button', 'submit', 'reset']),
101
- /**
102
- * The size of the `Button`
103
- */
104
192
  size: PropTypes.oneOf(['small', 'medium', 'large']),
105
- /**
106
- * Provides a reference to the `Button`'s underlying html element.
107
- */
108
193
  elementRef: PropTypes.func,
109
- /**
110
- * The element to render as the component root, `Button` by default.
111
- */
112
194
  as: PropTypes.elementType,
113
- /**
114
- * Specifies if interaction with the `Button` is enabled, disabled, or readonly.
115
- */
116
195
  interaction: PropTypes.oneOf(['enabled', 'disabled', 'readonly']),
117
- /**
118
- * Specifies the color for the `Button`.
119
- */
120
196
  color: PropTypes.oneOf([
121
197
  'primary',
122
198
  'primary-inverse',
@@ -124,66 +200,21 @@ const propTypes: PropValidators<PropKeys> = {
124
200
  'success',
125
201
  'danger'
126
202
  ]),
127
- /**
128
- * Override the `Button`'s default focus outline color.
129
- */
130
203
  focusColor: PropTypes.oneOf(['info', 'inverse']),
131
- /**
132
- * The `Button` display property. When set to `inline-block`, the `Button` displays inline with other elements.
133
- * When set to block, the `Button` expands to fill the width of the container.
134
- */
135
204
  display: PropTypes.oneOf(['inline-block', 'block']),
136
- /**
137
- * Sets the alignment of the `Button` children and/or icon.
138
- */
139
205
  textAlign: PropTypes.oneOf(['start', 'center']),
140
- /**
141
- * Specifies if the `Button` shape should be a circle or rectangle.
142
- */
143
206
  shape: PropTypes.oneOf(['rectangle', 'circle']),
144
- /**
145
- * Specifies if the `Button` should render with a solid background. When false, the background is transparent.
146
- */
147
207
  withBackground: PropTypes.bool,
148
- /**
149
- * Specifies if the `Button` should render with a border.
150
- */
151
208
  withBorder: PropTypes.bool,
152
- /**
153
- * Designates if the `Button` should render without padding. This option should only be set when `withBorder` and
154
- * `withBackground` are also set to false.
155
- */
156
209
  isCondensed: PropTypes.bool,
157
- /**
158
- * Valid values are `0`, `none`, `auto`, `xxx-small`, `xx-small`, `x-small`,
159
- * `small`, `medium`, `large`, `x-large`, `xx-large`. Apply these values via
160
- * familiar CSS-like shorthand. For example: `margin="small auto large"`.
161
- */
162
210
  margin: ThemeablePropTypes.spacing,
163
- /**
164
- * Specify a mouse cursor to use when hovering over the button.
165
- * The `pointer` cursor is used by default.
166
- */
167
211
  cursor: PropTypes.string,
168
- /**
169
- * Specifies an href attribute for the `Button`'s underlying html element.
170
- */
171
212
  href: PropTypes.string,
172
- /**
173
- * Callback fired when the `Button` is clicked.
174
- */
175
213
  onClick: PropTypes.func,
176
- /**
177
- * Callback fired when the `Button` receives a keydown event.
178
- */
179
214
  onKeyDown: PropTypes.func,
180
- /**
181
- * An icon, or function that returns an icon.
182
- */
183
215
  renderIcon: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
184
- /**
185
- * Specifies the tabindex of the `Button`.
186
- */
216
+ // Deprecated `string` tabIndex type
217
+ // TODO: remove string type in v9
187
218
  tabIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
188
219
  }
189
220
 
@@ -75,12 +75,7 @@ const generateButtonThemeVars = <Variant extends Variants>({
75
75
  [`${style}Background`]: backgroundColor,
76
76
  [`${style}HoverBackground`]: darken(backgroundColor, 10),
77
77
  [`${style}ActiveBackground`]: darken(backgroundColor, 10),
78
- [`${style}ActiveBoxShadow`]: `${activeShadow} ${darken(
79
- borderColor,
80
- 20,
81
- // @ts-expect-error ts-migrate(2554) FIXME: Expected 2 arguments, but got 3.
82
- 0.45
83
- )}`,
78
+ [`${style}ActiveBoxShadow`]: `${activeShadow} ${darken(borderColor, 20)}`,
84
79
 
85
80
  [`${style}GhostColor`]: ghostTextColor,
86
81
  [`${style}GhostBorderColor`]: ghostBorderColor,
@@ -39,6 +39,7 @@ import type { ButtonProps } from './props'
39
39
  ---
40
40
  category: components
41
41
  ---
42
+ @tsProps
42
43
  **/
43
44
  // needed for listing the available theme variables on docs page
44
45
  @withStyle(null, generateComponentTheme)
@@ -49,13 +50,11 @@ class Button extends Component<ButtonProps> {
49
50
  static propTypes = propTypes
50
51
  static allowedProps = allowedProps
51
52
  static defaultProps = {
52
- children: null,
53
53
  type: 'button',
54
54
  size: 'medium',
55
- // @ts-expect-error ts-migrate(6133) FIXME: 'el' is declared but its value is never read.
56
- elementRef: (el) => {},
57
55
  as: 'button',
58
56
  // Leave interaction default undefined so that `disabled` and `readOnly` can also be supplied
57
+ interaction: undefined,
59
58
  color: 'secondary',
60
59
  display: 'inline-block',
61
60
  textAlign: 'center',
@@ -64,17 +63,15 @@ class Button extends Component<ButtonProps> {
64
63
  cursor: 'pointer'
65
64
  }
66
65
 
67
- _buttonComponent = null
66
+ _buttonComponent: BaseButton | null = null
68
67
 
69
68
  ref: Element | null = null
70
69
 
71
70
  get focused() {
72
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
73
71
  return this._buttonComponent && this._buttonComponent.focused
74
72
  }
75
73
 
76
74
  focus() {
77
- // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'.
78
75
  this._buttonComponent && this._buttonComponent.focus()
79
76
  }
80
77
 
@@ -88,8 +85,7 @@ class Button extends Component<ButtonProps> {
88
85
  }
89
86
  }
90
87
 
91
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'component' implicitly has an 'any' type... Remove this comment to see the full error message
92
- handleButtonRef = (component) => {
88
+ handleButtonRef = (component: BaseButton | null) => {
93
89
  this._buttonComponent = component
94
90
  }
95
91
 
@@ -29,110 +29,135 @@ import { ThemeablePropTypes } from '@instructure/emotion'
29
29
 
30
30
  import type { Spacing, WithStyleProps } from '@instructure/emotion'
31
31
  import type {
32
+ ToProp,
32
33
  AsElementType,
33
34
  PropValidators,
34
35
  BaseButtonTheme,
35
36
  OtherHTMLAttributes
36
37
  } from '@instructure/shared-types'
37
38
  import type { Cursor } from '@instructure/ui-prop-types'
39
+ import type { ViewProps } from '@instructure/ui-view'
38
40
 
39
41
  type ButtonOwnProps = {
40
- children?: React.ReactNode
41
- type?: 'button' | 'submit' | 'reset'
42
- size?: 'small' | 'medium' | 'large'
43
- elementRef?: (element: Element | null) => void
44
- as?: AsElementType
45
- interaction?: 'enabled' | 'disabled' | 'readonly'
46
- color?: 'primary' | 'primary-inverse' | 'secondary' | 'success' | 'danger'
47
- focusColor?: 'info' | 'inverse'
48
- display?: 'inline-block' | 'block'
49
- textAlign?: 'start' | 'center'
50
- withBackground?: boolean
51
- margin?: Spacing
52
- cursor?: Cursor
53
- href?: string
54
- renderIcon?: React.ReactNode | ((...args: any[]) => any)
55
- }
56
-
57
- type PropKeys = keyof ButtonOwnProps
58
-
59
- type AllowedPropKeys = Readonly<Array<PropKeys>>
60
-
61
- type ButtonProps = ButtonOwnProps &
62
- WithStyleProps<BaseButtonTheme, null> &
63
- OtherHTMLAttributes<ButtonOwnProps>
64
-
65
- const propTypes: PropValidators<PropKeys> = {
66
42
  /**
67
43
  * Specifies the `Button` children.
68
44
  */
69
- children: PropTypes.node,
45
+ children?: React.ReactNode
46
+
70
47
  /**
71
48
  * Specifies the type of the `Button`'s underlying html element.
72
49
  */
73
- type: PropTypes.oneOf(['button', 'submit', 'reset']),
50
+ type?: 'button' | 'submit' | 'reset'
51
+
74
52
  /**
75
53
  * The size of the `Button`
76
54
  */
77
- size: PropTypes.oneOf(['small', 'medium', 'large']),
55
+ size?: 'small' | 'medium' | 'large'
56
+
78
57
  /**
79
58
  * Provides a reference to the `Button`'s underlying html element.
80
59
  */
81
- elementRef: PropTypes.func,
60
+ elementRef?: (element: Element | null) => void
61
+
82
62
  /**
83
63
  * The element to render as the component root, `Button` by default.
84
64
  */
85
- as: PropTypes.elementType,
65
+ as?: AsElementType
66
+
86
67
  /**
87
68
  * Specifies if interaction with the `Button` is enabled, disabled, or readonly.
88
69
  */
89
- interaction: PropTypes.oneOf(['enabled', 'disabled', 'readonly']),
70
+ interaction?: 'enabled' | 'disabled' | 'readonly'
71
+
90
72
  /**
91
73
  * Specifies the color for the `Button`.
92
74
  */
93
- color: PropTypes.oneOf([
94
- 'primary',
95
- 'primary-inverse',
96
- 'secondary',
97
- 'success',
98
- 'danger'
99
- ]),
75
+ color?: 'primary' | 'primary-inverse' | 'secondary' | 'success' | 'danger'
76
+
100
77
  /**
101
78
  * Override the `Button`'s default focus outline color.
102
79
  */
103
- focusColor: PropTypes.oneOf(['info', 'inverse']),
80
+ focusColor?: 'info' | 'inverse'
81
+
104
82
  /**
105
83
  * The `Button` display property. When set to `inline-block`, the `Button` displays inline with other elements.
106
84
  * When set to block, the `Button` expands to fill the width of the container.
107
85
  */
108
- display: PropTypes.oneOf(['inline-block', 'block']),
86
+ display?: 'inline-block' | 'block'
87
+
109
88
  /**
110
89
  * Sets the alignment of the `Button` children and/or icon.
111
90
  */
112
- textAlign: PropTypes.oneOf(['start', 'center']),
91
+ textAlign?: 'start' | 'center'
92
+
113
93
  /**
114
94
  * Specifies if the `Button` should render with a solid background. When false, the background is transparent.
115
95
  */
116
- withBackground: PropTypes.bool,
96
+ withBackground?: boolean
97
+
117
98
  /**
118
99
  * Valid values are `0`, `none`, `auto`, `xxx-small`, `xx-small`, `x-small`,
119
100
  * `small`, `medium`, `large`, `x-large`, `xx-large`. Apply these values via
120
101
  * familiar CSS-like shorthand. For example: `margin="small auto large"`.
121
102
  */
122
- margin: ThemeablePropTypes.spacing,
103
+ margin?: Spacing
104
+
123
105
  /**
124
106
  * Specify a mouse cursor to use when hovering over the button.
125
107
  * The `pointer` cursor is used by default.
126
108
  */
127
- cursor: PropTypes.string,
109
+ cursor?: Cursor
110
+
128
111
  /**
129
112
  * Specifies an href attribute for the `Button`'s underlying html element.
130
113
  */
131
- href: PropTypes.string,
114
+ href?: string
115
+
132
116
  /**
133
117
  * An icon, or function that returns an icon.
134
118
  */
135
- renderIcon: PropTypes.oneOfType([PropTypes.node, PropTypes.func])
119
+ renderIcon?: React.ReactNode | (() => React.ReactNode)
120
+
121
+ /**
122
+ * Callback fired when the `Button` is clicked.
123
+ */
124
+ onClick?: (
125
+ event: React.KeyboardEvent<ViewProps> | React.MouseEvent<ViewProps>
126
+ ) => void
127
+ }
128
+
129
+ type PropKeys = keyof ButtonOwnProps
130
+
131
+ type AllowedPropKeys = Readonly<Array<PropKeys>>
132
+
133
+ type ButtonProps = ButtonOwnProps &
134
+ WithStyleProps<BaseButtonTheme, null> &
135
+ OtherHTMLAttributes<ButtonOwnProps> &
136
+ ToProp
137
+
138
+ const propTypes: PropValidators<PropKeys> = {
139
+ children: PropTypes.node,
140
+ type: PropTypes.oneOf(['button', 'submit', 'reset']),
141
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
142
+ elementRef: PropTypes.func,
143
+ as: PropTypes.elementType,
144
+ interaction: PropTypes.oneOf(['enabled', 'disabled', 'readonly']),
145
+ color: PropTypes.oneOf([
146
+ 'primary',
147
+ 'primary-inverse',
148
+ 'secondary',
149
+ 'success',
150
+ 'danger'
151
+ ]),
152
+ focusColor: PropTypes.oneOf(['info', 'inverse']),
153
+ display: PropTypes.oneOf(['inline-block', 'block']),
154
+ textAlign: PropTypes.oneOf(['start', 'center']),
155
+ withBackground: PropTypes.bool,
156
+ margin: ThemeablePropTypes.spacing,
157
+ cursor: PropTypes.string,
158
+ href: PropTypes.string,
159
+ renderIcon: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
160
+ onClick: PropTypes.func
136
161
  }
137
162
 
138
163
  const allowedProps: AllowedPropKeys = [
@@ -150,7 +175,8 @@ const allowedProps: AllowedPropKeys = [
150
175
  'size',
151
176
  'textAlign',
152
177
  'type',
153
- 'withBackground'
178
+ 'withBackground',
179
+ 'onClick'
154
180
  ]
155
181
 
156
182
  export type { ButtonProps }