@spark-web/button 1.1.2 → 1.3.1

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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  title: Button
3
3
  storybookPath: forms-buttons-button--default
4
+ isExperimentalPackage: true
4
5
  ---
5
6
 
6
7
  Buttons are clickable elements that are used to trigger actions. They
@@ -196,25 +197,17 @@ with the exception of `href` vs `onClick` props.
196
197
  </Text>
197
198
  ```
198
199
 
199
- ## Props
200
-
201
- | Prop | Type | Default | Description |
202
- | ----------------- | ---------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
203
- | aria-controls? | string | | Identifies the element (or elements) whose contents or presence are controlled by the current element. Only applicable for `Button`. |
204
- | aria-describedby? | string | | Identifies the element (or elements) that describes the object. Only applicable for `Button`. |
205
- | aria-expanded? | string | | Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. Only applicable for `Button`. |
206
- | children | string \| React.ReactElement\<IconProps> | | Children element to be rendered inside the button. |
207
- | data? | [DataAttributeMap][data-attribute-map] | | Allows setting of data attributes on the button. |
208
- | disabled? | boolean | | When true, prevents `onClick` from firing. Only applicable for `Button`. |
209
- | href | string | | Specifies the url the button should redirect to upon being clicked. Only applicable for `ButtonLink`. |
210
- | id? | string | | Unique identifier for the button. |
211
- | label? | string | | Implicit label for buttons only required for icon-only buttons for accessibility reasons. |
212
- | loading? | boolean | | When true, the button will display a loading spinner. |
213
- | onClick? | Function | | Function to be fired following a click event of the button. Only applicable for `Button`. |
214
- | prominence? | 'high' \| 'low' | 'high' | Sets the visual prominence of the button. |
215
- | size? | 'medium' \| 'large' | 'medium' | Sets the size of the button. |
216
- | tone? | 'primary' \| 'secondary' \| 'neutral' \| 'positive' \| 'caution' \| 'critical' \| 'info' | 'primary' | Sets the tone of the button. |
217
- | type? | 'button' \| 'submit' \| 'reset' | 'button' | Sets the button type. Only applicable for `Button`. |
218
-
219
- [data-attribute-map]:
220
- https://github.com/brighte-labs/spark-web/blob/e7f6f4285b4cfd876312cc89fbdd094039aa239a/packages/utils/src/internal/buildDataAttributes.ts#L1
200
+ ## BaseButton
201
+
202
+ Unstyled button primitive that:
203
+
204
+ - Forwards the button ref
205
+ - Provides a default type of `button` (so it doesn't accidently submit forms if
206
+ left off)
207
+ - Prevents `onClick` from firing when disabled without disabling the button
208
+ - Forces focus of the underlying button when clicked (to address a bug in
209
+ Safari)
210
+
211
+ ## Button Props
212
+
213
+ <PropsTable displayName="Button" />
@@ -0,0 +1,10 @@
1
+ import type { BoxProps } from '@spark-web/box';
2
+ import type { MouseEvent as ReactMouseEvent } from 'react';
3
+ import type { NativeButtonProps } from './types';
4
+ export declare type BaseButtonProps = NativeButtonProps & Partial<BoxProps>;
5
+ export declare const BaseButton: import("react").ForwardRefExoticComponent<NativeButtonProps & Partial<BoxProps> & import("react").RefAttributes<HTMLButtonElement>>;
6
+ /**
7
+ * handle "disabled" behaviour w/o disabling buttons
8
+ * @see https://axesslab.com/disabled-buttons-suck/
9
+ */
10
+ export declare function getPreventableClickHandler(onClick: BaseButtonProps['onClick'], disabled: boolean): (event: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => void;
@@ -1,4 +1,4 @@
1
- import type { MouseEvent as ReactMouseEvent } from 'react';
1
+ /// <reference types="react" />
2
2
  import type { CommonButtonProps, NativeButtonProps } from './types';
3
3
  export declare type ButtonProps = CommonButtonProps & {
4
4
  /**
@@ -26,9 +26,3 @@ export declare type ButtonProps = CommonButtonProps & {
26
26
  * action will occur when the user interacts with it.
27
27
  */
28
28
  export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
29
- /**
30
- * Prevent click events when the component is "disabled".
31
- * Note: we don't want to actually disable a button element for several reasons.
32
- * One being because that would prohibit the use of tooltips.
33
- */
34
- export declare function getPreventableClickHandler(onClick: NativeButtonProps['onClick'], disabled: boolean): (event: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => void;
@@ -5,5 +5,5 @@ export declare type ButtonLinkProps = LinkComponentProps & CommonButtonProps;
5
5
  /** The appearance of a `Button`, with the semantics of a link. */
6
6
  export declare const ButtonLink: <Comp extends import("react").ElementType<any> = "a">(props: {
7
7
  as?: Comp | undefined;
8
- ref?: import("react").Ref<Comp extends "symbol" | "clipPath" | "filter" | "mask" | "marker" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | keyof HTMLElementTagNameMap | "set" ? (HTMLElementTagNameMap & Pick<SVGElementTagNameMap, "symbol" | "clipPath" | "filter" | "mask" | "marker" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | "set">)[Comp] : Comp extends new (...args: any) => any ? InstanceType<Comp> : undefined> | undefined;
8
+ ref?: import("react").Ref<Comp extends "symbol" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "clipPath" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "filter" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | "set" | keyof HTMLElementTagNameMap ? (HTMLElementTagNameMap & Pick<SVGElementTagNameMap, "symbol" | "svg" | "animate" | "animateMotion" | "animateTransform" | "circle" | "clipPath" | "defs" | "desc" | "ellipse" | "feBlend" | "feColorMatrix" | "feComponentTransfer" | "feComposite" | "feConvolveMatrix" | "feDiffuseLighting" | "feDisplacementMap" | "feDistantLight" | "feDropShadow" | "feFlood" | "feFuncA" | "feFuncB" | "feFuncG" | "feFuncR" | "feGaussianBlur" | "feImage" | "feMerge" | "feMergeNode" | "feMorphology" | "feOffset" | "fePointLight" | "feSpecularLighting" | "feSpotLight" | "feTile" | "feTurbulence" | "filter" | "foreignObject" | "g" | "image" | "line" | "linearGradient" | "marker" | "mask" | "metadata" | "mpath" | "path" | "pattern" | "polygon" | "polyline" | "radialGradient" | "rect" | "stop" | "switch" | "text" | "textPath" | "tspan" | "use" | "view" | "set">)[Comp] : Comp extends new (...args: any) => any ? InstanceType<Comp> : undefined> | undefined;
9
9
  } & Omit<import("react").PropsWithoutRef<import("react").ComponentProps<Comp>>, "as"> & ButtonLinkProps) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
@@ -1,4 +1,6 @@
1
+ export { BaseButton } from './BaseButton';
1
2
  export { Button } from './Button';
2
3
  export { ButtonLink } from './ButtonLink';
4
+ export type { BaseButtonProps } from './BaseButton';
3
5
  export type { ButtonProps } from './Button';
4
6
  export type { ButtonLinkProps } from './ButtonLink';
@@ -5,10 +5,10 @@ import type { ButtonHTMLAttributes, ReactElement } from 'react';
5
5
  import type { mapTokens } from './utils';
6
6
  export declare type ButtonSize = keyof typeof mapTokens[keyof typeof mapTokens];
7
7
  export declare type ButtonProminence = 'high' | 'low' | 'none';
8
- export declare type ButtonTone = BackgroundTone;
8
+ export declare type ButtonTone = Exclude<BackgroundTone, 'disabled'>;
9
9
  declare type ChildrenWithText = {
10
10
  label?: never;
11
- children: string | [ReactElement<IconProps>, string] | [string, ReactElement<IconProps>];
11
+ children: string | number | [ReactElement<IconProps>, string | number] | [string | number, ReactElement<IconProps>];
12
12
  };
13
13
  declare type IconOnly = {
14
14
  /**
@@ -2,19 +2,30 @@ import type { BoxProps } from '@spark-web/box';
2
2
  import type { ForegroundTone } from '@spark-web/text';
3
3
  import type { BrighteTheme } from '@spark-web/theme';
4
4
  import type { ButtonProminence, ButtonTone } from './types';
5
- declare type ButtonStyles = {
5
+ declare type BaseButtonStyles = {
6
6
  background: BoxProps['background'];
7
7
  border?: BoxProps['border'];
8
8
  borderWidth?: BoxProps['borderWidth'];
9
9
  textTone?: ForegroundTone;
10
+ };
11
+ declare type HoverButtonStyles = {
10
12
  backgroundHover: keyof BrighteTheme['backgroundInteractions'];
11
13
  borderHover?: keyof BrighteTheme['border']['color'];
12
14
  textToneHover?: keyof BrighteTheme['color']['foreground'];
15
+ };
16
+ declare type ActiveButtonStyles = {
13
17
  backgroundActive: keyof BrighteTheme['backgroundInteractions'];
14
18
  borderActive?: keyof BrighteTheme['border']['color'];
15
19
  textToneActive?: keyof BrighteTheme['color']['foreground'];
16
20
  };
17
- export declare const variants: Record<ButtonProminence, Record<ButtonTone, ButtonStyles | undefined>>;
21
+ declare type DisabledButtonStyles = {
22
+ backgroundDisabled: keyof BrighteTheme['color']['background'];
23
+ borderDisabled?: keyof BrighteTheme['border']['color'];
24
+ textToneDisabled: keyof BrighteTheme['color']['foreground'];
25
+ };
26
+ declare type ButtonStyles = BaseButtonStyles & HoverButtonStyles & ActiveButtonStyles & DisabledButtonStyles;
27
+ declare type Variants = Record<ButtonProminence, Record<ButtonTone, ButtonStyles | undefined>>;
28
+ export declare const variants: Variants;
18
29
  export declare const mapTokens: {
19
30
  readonly fontSize: {
20
31
  readonly medium: "small";
@@ -4,51 +4,124 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
6
6
  var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
7
- var a11y = require('@spark-web/a11y');
8
7
  var box = require('@spark-web/box');
9
- var spinner = require('@spark-web/spinner');
10
- var internal = require('@spark-web/utils/internal');
8
+ var utils = require('@spark-web/utils');
11
9
  var react = require('react');
12
- var text = require('@spark-web/text');
13
10
  var jsxRuntime = require('react/jsx-runtime');
11
+ var a11y = require('@spark-web/a11y');
12
+ var spinner = require('@spark-web/spinner');
13
+ var text = require('@spark-web/text');
14
14
  var css = require('@emotion/css');
15
15
  var theme = require('@spark-web/theme');
16
16
  var link = require('@spark-web/link');
17
+ var internal = require('@spark-web/utils/internal');
17
18
  var ts = require('@spark-web/utils/ts');
18
19
 
20
+ var _excluded$2 = ["onClick", "disabled", "type"];
21
+ var BaseButton = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
22
+ var onClickProp = _ref.onClick,
23
+ _ref$disabled = _ref.disabled,
24
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
25
+ _ref$type = _ref.type,
26
+ type = _ref$type === void 0 ? 'button' : _ref$type,
27
+ consumerProps = _objectWithoutProperties(_ref, _excluded$2);
28
+
29
+ var internalRef = react.useRef(null);
30
+ var composedRef = utils.useComposedRefs(internalRef, forwardedRef);
31
+ /**
32
+ * In Safari buttons are not focused automatically by the browser once
33
+ * pressed, the default behaviour is to focus the nearest focusable ancestor.
34
+ * To fix this we need to manually focus the button element after the user
35
+ * presses the element.
36
+ */
37
+
38
+ var onClick = react.useCallback(function (event) {
39
+ var _internalRef$current;
40
+
41
+ (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.focus();
42
+ var preventableClickHandler = getPreventableClickHandler(onClickProp, disabled);
43
+ preventableClickHandler(event);
44
+ }, [disabled, onClickProp]);
45
+ return /*#__PURE__*/jsxRuntime.jsx(box.Box, _objectSpread(_objectSpread({}, consumerProps), {}, {
46
+ as: "button",
47
+ ref: composedRef,
48
+ "aria-disabled": disabled,
49
+ onClick: onClick,
50
+ type: type
51
+ }));
52
+ });
53
+ BaseButton.displayName = 'BaseButton';
54
+ /**
55
+ * handle "disabled" behaviour w/o disabling buttons
56
+ * @see https://axesslab.com/disabled-buttons-suck/
57
+ */
58
+
59
+ function getPreventableClickHandler(onClick, disabled) {
60
+ return function handleClick(event) {
61
+ if (disabled) {
62
+ event.preventDefault();
63
+ } else {
64
+ onClick === null || onClick === void 0 ? void 0 : onClick(event);
65
+ }
66
+ };
67
+ }
68
+
69
+ var highDisabledStyles = {
70
+ backgroundDisabled: 'disabled',
71
+ borderDisabled: 'fieldDisabled',
72
+ textToneDisabled: 'neutralInverted'
73
+ };
74
+ var highDisabledAltStyles = {
75
+ backgroundDisabled: 'neutral',
76
+ borderDisabled: 'standard',
77
+ textToneDisabled: 'placeholder'
78
+ };
79
+ var lowDisabledStyles = {
80
+ backgroundDisabled: 'inputDisabled',
81
+ textToneDisabled: 'disabled'
82
+ };
83
+ var lowDisabledAltStyles = {
84
+ backgroundDisabled: 'inputDisabled',
85
+ borderDisabled: 'fieldDisabled',
86
+ textToneDisabled: 'disabled'
87
+ };
88
+ var noneDisabledStyles = {
89
+ backgroundDisabled: 'neutral',
90
+ textToneDisabled: 'disabled'
91
+ };
19
92
  var variants = {
20
93
  high: {
21
- primary: {
94
+ primary: _objectSpread({
22
95
  background: 'primary',
23
96
  backgroundHover: 'primaryHover',
24
97
  backgroundActive: 'primaryActive'
25
- },
26
- secondary: {
98
+ }, highDisabledStyles),
99
+ secondary: _objectSpread({
27
100
  background: 'secondary',
28
101
  backgroundHover: 'secondaryHover',
29
102
  backgroundActive: 'secondaryActive'
30
- },
31
- neutral: {
103
+ }, highDisabledStyles),
104
+ neutral: _objectSpread({
32
105
  background: 'neutral',
33
106
  border: 'field',
34
107
  backgroundHover: 'neutralHover',
35
108
  backgroundActive: 'neutralActive'
36
- },
37
- positive: {
109
+ }, highDisabledAltStyles),
110
+ positive: _objectSpread({
38
111
  background: 'positive',
39
112
  backgroundHover: 'positiveHover',
40
113
  backgroundActive: 'positiveActive'
41
- },
42
- critical: {
114
+ }, highDisabledStyles),
115
+ critical: _objectSpread({
43
116
  background: 'critical',
44
117
  backgroundHover: 'criticalHover',
45
118
  backgroundActive: 'criticalActive'
46
- },
119
+ }, highDisabledStyles),
47
120
  caution: undefined,
48
121
  info: undefined
49
122
  },
50
123
  low: {
51
- primary: {
124
+ primary: _objectSpread({
52
125
  background: 'surface',
53
126
  border: 'primary',
54
127
  borderWidth: 'large',
@@ -59,8 +132,8 @@ var variants = {
59
132
  backgroundActive: 'none',
60
133
  borderActive: 'primaryActive',
61
134
  textToneActive: 'primaryActive'
62
- },
63
- secondary: {
135
+ }, lowDisabledAltStyles),
136
+ secondary: _objectSpread({
64
137
  background: 'surface',
65
138
  border: 'secondary',
66
139
  borderWidth: 'large',
@@ -71,76 +144,76 @@ var variants = {
71
144
  backgroundActive: 'none',
72
145
  borderActive: 'secondaryActive',
73
146
  textToneActive: 'secondaryActive'
74
- },
75
- neutral: {
147
+ }, lowDisabledAltStyles),
148
+ neutral: _objectSpread({
76
149
  background: 'neutralLow',
77
150
  backgroundHover: 'neutralLowHover',
78
151
  backgroundActive: 'neutralLowActive'
79
- },
80
- positive: {
152
+ }, lowDisabledStyles),
153
+ positive: _objectSpread({
81
154
  background: 'positiveLow',
82
155
  backgroundHover: 'positiveLowHover',
83
156
  backgroundActive: 'positiveLowActive'
84
- },
85
- caution: {
157
+ }, lowDisabledStyles),
158
+ caution: _objectSpread({
86
159
  background: 'cautionLow',
87
160
  backgroundHover: 'cautionLowHover',
88
161
  backgroundActive: 'cautionLowActive'
89
- },
90
- critical: {
162
+ }, lowDisabledStyles),
163
+ critical: _objectSpread({
91
164
  background: 'criticalLow',
92
165
  backgroundHover: 'criticalLowHover',
93
166
  backgroundActive: 'criticalLowActive'
94
- },
95
- info: {
167
+ }, lowDisabledStyles),
168
+ info: _objectSpread({
96
169
  background: 'infoLow',
97
170
  backgroundHover: 'infoLowHover',
98
171
  backgroundActive: 'infoLowActive'
99
- }
172
+ }, lowDisabledStyles)
100
173
  },
101
174
  none: {
102
- primary: {
175
+ primary: _objectSpread({
103
176
  background: 'surface',
104
177
  textTone: 'primaryActive',
105
178
  backgroundHover: 'primaryLowHover',
106
179
  backgroundActive: 'primaryLowActive'
107
- },
108
- secondary: {
180
+ }, noneDisabledStyles),
181
+ secondary: _objectSpread({
109
182
  background: 'surface',
110
183
  textTone: 'secondaryActive',
111
184
  backgroundHover: 'secondaryLowHover',
112
185
  backgroundActive: 'secondaryLowActive'
113
- },
114
- neutral: {
186
+ }, noneDisabledStyles),
187
+ neutral: _objectSpread({
115
188
  background: 'surface',
116
189
  textTone: 'neutral',
117
190
  backgroundHover: 'neutralLowHover',
118
191
  backgroundActive: 'neutralLowActive'
119
- },
120
- positive: {
192
+ }, noneDisabledStyles),
193
+ positive: _objectSpread({
121
194
  background: 'surface',
122
195
  textTone: 'positive',
123
196
  backgroundHover: 'positiveLowHover',
124
197
  backgroundActive: 'positiveLowActive'
125
- },
126
- caution: {
198
+ }, noneDisabledStyles),
199
+ caution: _objectSpread({
127
200
  background: 'surface',
128
201
  textTone: 'caution',
129
202
  backgroundHover: 'cautionLowHover',
130
203
  backgroundActive: 'cautionLowActive'
131
- },
132
- critical: {
204
+ }, noneDisabledStyles),
205
+ critical: _objectSpread({
133
206
  background: 'surface',
134
207
  textTone: 'critical',
135
208
  backgroundHover: 'criticalLowHover',
136
209
  backgroundActive: 'criticalLowActive'
137
- },
138
- info: {
210
+ }, noneDisabledStyles),
211
+ info: _objectSpread({
139
212
  background: 'surface',
140
213
  textTone: 'info',
141
214
  backgroundHover: 'infoLowHover',
142
215
  backgroundActive: 'infoLowActive'
143
- }
216
+ }, noneDisabledStyles)
144
217
  }
145
218
  };
146
219
  var mapTokens = {
@@ -166,7 +239,7 @@ var resolveButtonChildren = function resolveButtonChildren(_ref) {
166
239
  tone = _ref.tone;
167
240
  var variant = variants[prominence][tone];
168
241
  return react.Children.map(children, function (child) {
169
- if (typeof child === 'string') {
242
+ if (typeof child === 'string' || typeof child === 'number') {
170
243
  return /*#__PURE__*/jsxRuntime.jsx(HiddenWhenLoading, {
171
244
  isLoading: isLoading,
172
245
  children: /*#__PURE__*/jsxRuntime.jsx(text.Text, {
@@ -222,9 +295,12 @@ function useButtonStyles(_ref) {
222
295
  var focusRingStyles = a11y.useFocusRing({
223
296
  tone: tone
224
297
  });
298
+ var disabledFocusRingStyles = a11y.useFocusRing({
299
+ tone: 'disabled'
300
+ });
225
301
  var variant = variants[prominence][tone];
226
302
  var isLarge = size === 'large';
227
- var transitionColours = {
303
+ var transitionColors = {
228
304
  transitionProperty: 'color, background-color, border-color, text-decoration-color',
229
305
  transitionTimingFunction: 'cubic-bezier(0.02, 1.505, 0.745, 1.235)',
230
306
  transitionDuration: "".concat(theme$1.animation.standard.duration, "ms")
@@ -244,27 +320,39 @@ function useButtonStyles(_ref) {
244
320
  position: 'relative',
245
321
  width: iconOnly ? mapTokens.size[size] : undefined,
246
322
  // interactions styles
247
- className: css.css(_objectSpread(_objectSpread({}, transitionColours), {}, {
248
- '&:hover': {
249
- borderColor: variant !== null && variant !== void 0 && variant.borderHover ? theme$1.border.color[variant.borderHover] : undefined,
250
- backgroundColor: variant !== null && variant !== void 0 && variant.backgroundHover ? theme$1.backgroundInteractions[variant.backgroundHover] : undefined,
251
- // Style button text when hovering
252
- '> *': _objectSpread(_objectSpread({}, transitionColours), {}, {
253
- color: variant !== null && variant !== void 0 && variant.textToneHover ? theme$1.color.foreground[variant.textToneHover] : undefined,
254
- stroke: variant !== null && variant !== void 0 && variant.textToneHover ? theme$1.color.foreground[variant.textToneHover] : undefined
255
- })
323
+ className: css.css(_objectSpread(_objectSpread({}, transitionColors), {}, {
324
+ '&:not([aria-disabled=true])': {
325
+ ':hover': {
326
+ borderColor: variant !== null && variant !== void 0 && variant.borderHover ? theme$1.border.color[variant.borderHover] : undefined,
327
+ backgroundColor: variant !== null && variant !== void 0 && variant.backgroundHover ? theme$1.backgroundInteractions[variant.backgroundHover] : undefined,
328
+ // Style button text when hovering
329
+ '> *': _objectSpread(_objectSpread({}, transitionColors), {}, {
330
+ color: variant !== null && variant !== void 0 && variant.textToneHover ? theme$1.color.foreground[variant.textToneHover] : undefined,
331
+ stroke: variant !== null && variant !== void 0 && variant.textToneHover ? theme$1.color.foreground[variant.textToneHover] : undefined
332
+ })
333
+ },
334
+ ':active': {
335
+ borderColor: variant !== null && variant !== void 0 && variant.borderActive ? theme$1.border.color[variant.borderActive] : undefined,
336
+ backgroundColor: variant !== null && variant !== void 0 && variant.backgroundActive ? theme$1.backgroundInteractions[variant === null || variant === void 0 ? void 0 : variant.backgroundActive] : undefined,
337
+ transform: 'scale(0.98)',
338
+ // Style button text when it's active
339
+ '> *': _objectSpread(_objectSpread({}, transitionColors), {}, {
340
+ color: variant !== null && variant !== void 0 && variant.textToneActive ? theme$1.color.foreground[variant.textToneActive] : undefined,
341
+ stroke: variant !== null && variant !== void 0 && variant.textToneActive ? theme$1.color.foreground[variant.textToneActive] : undefined
342
+ })
343
+ },
344
+ ':focus': focusRingStyles
256
345
  },
257
- '&:active': {
258
- borderColor: variant !== null && variant !== void 0 && variant.borderActive ? theme$1.border.color[variant.borderActive] : undefined,
259
- backgroundColor: variant !== null && variant !== void 0 && variant.backgroundActive ? theme$1.backgroundInteractions[variant === null || variant === void 0 ? void 0 : variant.backgroundActive] : undefined,
260
- transform: 'scale(0.98)',
261
- // Style button text when it's active
262
- '> *': _objectSpread(_objectSpread({}, transitionColours), {}, {
263
- color: variant !== null && variant !== void 0 && variant.textToneActive ? theme$1.color.foreground[variant.textToneActive] : undefined,
264
- stroke: variant !== null && variant !== void 0 && variant.textToneActive ? theme$1.color.foreground[variant.textToneActive] : undefined
265
- })
266
- },
267
- ':focus': focusRingStyles
346
+ '&[aria-disabled=true]': {
347
+ backgroundColor: variant !== null && variant !== void 0 && variant.backgroundDisabled ? theme$1.color.background[variant === null || variant === void 0 ? void 0 : variant.backgroundDisabled] : undefined,
348
+ borderColor: variant !== null && variant !== void 0 && variant.borderDisabled ? theme$1.border.color[variant.borderDisabled] : undefined,
349
+ cursor: 'default',
350
+ '*': {
351
+ color: variant !== null && variant !== void 0 && variant.textToneDisabled ? theme$1.color.foreground[variant.textToneDisabled] : undefined,
352
+ stroke: variant !== null && variant !== void 0 && variant.textToneDisabled ? theme$1.color.foreground[variant.textToneDisabled] : undefined
353
+ },
354
+ ':focus': disabledFocusRingStyles
355
+ }
268
356
  }))
269
357
  };
270
358
  return buttonStyleProps;
@@ -276,13 +364,12 @@ var _excluded$1 = ["aria-controls", "aria-describedby", "aria-expanded", "data",
276
364
  * Buttons are used to initialize an action, their label should express what
277
365
  * action will occur when the user interacts with it.
278
366
  */
279
- var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
367
+ var Button = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
280
368
  var ariaControls = _ref['aria-controls'],
281
369
  ariaDescribedBy = _ref['aria-describedby'],
282
370
  ariaExpanded = _ref['aria-expanded'],
283
371
  data = _ref.data,
284
- _ref$disabled = _ref.disabled,
285
- disabled = _ref$disabled === void 0 ? false : _ref$disabled,
372
+ disabled = _ref.disabled,
286
373
  id = _ref.id,
287
374
  _ref$loading = _ref.loading,
288
375
  loading = _ref$loading === void 0 ? false : _ref$loading,
@@ -293,8 +380,7 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
293
380
  size = _ref$size === void 0 ? 'medium' : _ref$size,
294
381
  _ref$tone = _ref.tone,
295
382
  tone = _ref$tone === void 0 ? 'primary' : _ref$tone,
296
- _ref$type = _ref.type,
297
- type = _ref$type === void 0 ? 'button' : _ref$type,
383
+ type = _ref.type,
298
384
  props = _objectWithoutProperties(_ref, _excluded$1);
299
385
 
300
386
  var iconOnly = Boolean(props.label);
@@ -307,24 +393,17 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
307
393
  var isDisabled = disabled || loading;
308
394
  var isLoading = loading && !disabled;
309
395
  var variant = variants[prominence][tone];
310
- /**
311
- * handle "disabled" behaviour w/o disabling buttons
312
- * @see https://axesslab.com/disabled-buttons-suck/
313
- */
314
-
315
- var handleClick = getPreventableClickHandler(onClick, isDisabled);
316
- return /*#__PURE__*/jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread(_objectSpread({
396
+ return /*#__PURE__*/jsxRuntime.jsxs(BaseButton, _objectSpread(_objectSpread({}, buttonStyleProps), {}, {
317
397
  "aria-controls": ariaControls,
318
398
  "aria-describedby": ariaDescribedBy,
319
- "aria-disabled": isDisabled,
320
399
  "aria-expanded": ariaExpanded,
321
400
  "aria-label": props.label,
322
- as: "button",
401
+ data: data,
402
+ disabled: isDisabled,
323
403
  id: id,
324
- onClick: handleClick,
325
- ref: ref,
326
- type: type
327
- }, buttonStyleProps), data ? internal.buildDataAttributes(data) : undefined), {}, {
404
+ onClick: onClick,
405
+ ref: forwardedRef,
406
+ type: type,
328
407
  children: [resolveButtonChildren(_objectSpread(_objectSpread({}, props), {}, {
329
408
  isLoading: isLoading,
330
409
  prominence: prominence,
@@ -336,21 +415,6 @@ var Button = /*#__PURE__*/react.forwardRef(function (_ref, ref) {
336
415
  }));
337
416
  });
338
417
  Button.displayName = 'Button';
339
- /**
340
- * Prevent click events when the component is "disabled".
341
- * Note: we don't want to actually disable a button element for several reasons.
342
- * One being because that would prohibit the use of tooltips.
343
- */
344
-
345
- function getPreventableClickHandler(onClick, disabled) {
346
- return function handleClick(event) {
347
- if (disabled) {
348
- event.preventDefault();
349
- } else {
350
- onClick === null || onClick === void 0 ? void 0 : onClick(event);
351
- }
352
- };
353
- }
354
418
 
355
419
  function Loading(_ref2) {
356
420
  var tone = _ref2.tone;
@@ -413,5 +477,6 @@ var ButtonLink = ts.forwardRefWithAs(function (_ref, ref) {
413
477
  }));
414
478
  });
415
479
 
480
+ exports.BaseButton = BaseButton;
416
481
  exports.Button = Button;
417
482
  exports.ButtonLink = ButtonLink;