@spark-web/button 1.0.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 +21 -0
- package/README.md +217 -0
- package/dist/declarations/src/Button.d.ts +22 -0
- package/dist/declarations/src/ButtonLink.d.ts +9 -0
- package/dist/declarations/src/index.d.ts +4 -0
- package/dist/declarations/src/resolveButtonChildren.d.ts +8 -0
- package/dist/declarations/src/types.d.ts +31 -0
- package/dist/declarations/src/useButtonStyles.d.ts +10 -0
- package/dist/declarations/src/utils.d.ts +32 -0
- package/dist/spark-web-button.cjs.d.ts +1 -0
- package/dist/spark-web-button.cjs.dev.js +405 -0
- package/dist/spark-web-button.cjs.js +7 -0
- package/dist/spark-web-button.cjs.prod.js +405 -0
- package/dist/spark-web-button.esm.js +381 -0
- package/package.json +25 -0
- package/src/Button.stories.tsx +34 -0
- package/src/Button.test.tsx +34 -0
- package/src/Button.tsx +110 -0
- package/src/ButtonLink.tsx +56 -0
- package/src/index.ts +7 -0
- package/src/resolveButtonChildren.tsx +57 -0
- package/src/types.ts +42 -0
- package/src/useButtonStyles.ts +96 -0
- package/src/utils.ts +170 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @spark-web/button
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#27](https://github.com/brighte-labs/spark-web/pull/27)
|
|
8
|
+
[`4c8e398`](https://github.com/brighte-labs/spark-web/commit/4c8e3988f8a59d3dab60a6b67b1128b6ff2a5f2c)
|
|
9
|
+
Thanks [@JedWatson](https://github.com/JedWatson)! - Initial Version
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
[[`4c8e398`](https://github.com/brighte-labs/spark-web/commit/4c8e3988f8a59d3dab60a6b67b1128b6ff2a5f2c)]:
|
|
15
|
+
- @spark-web/a11y@1.0.0
|
|
16
|
+
- @spark-web/box@1.0.0
|
|
17
|
+
- @spark-web/icon@1.0.0
|
|
18
|
+
- @spark-web/link@1.0.0
|
|
19
|
+
- @spark-web/text@1.0.0
|
|
20
|
+
- @spark-web/theme@1.0.0
|
|
21
|
+
- @spark-web/utils@1.0.0
|
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Button
|
|
3
|
+
storybookPath: forms-buttons-button--default
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Buttons are clickable elements that are used to trigger actions. They
|
|
7
|
+
communicate calls to action to the user and allow users to interact with pages
|
|
8
|
+
in a variety of ways. Button labels express what action will occur when the user
|
|
9
|
+
interacts with it.
|
|
10
|
+
|
|
11
|
+
## Tone
|
|
12
|
+
|
|
13
|
+
Button tones can be broken up into two types; decorative and semantic.
|
|
14
|
+
|
|
15
|
+
For destructive actions like “delete” you should use the semantic `tone` of
|
|
16
|
+
`critical`.
|
|
17
|
+
|
|
18
|
+
For buttons that have no semantic action type (more common on marketing pages)
|
|
19
|
+
use one of our decorative `tones`.
|
|
20
|
+
|
|
21
|
+
Defaults to `primary`.
|
|
22
|
+
|
|
23
|
+
```jsx live
|
|
24
|
+
<Stack gap="large">
|
|
25
|
+
<Text weight="strong">Decorative tones</Text>
|
|
26
|
+
<Inline gap="small">
|
|
27
|
+
<Button tone="primary">Primary</Button>
|
|
28
|
+
<Button tone="secondary">Secondary</Button>
|
|
29
|
+
</Inline>
|
|
30
|
+
<Divider />
|
|
31
|
+
<Text weight="strong">Semantic tones</Text>
|
|
32
|
+
<Inline gap="small">
|
|
33
|
+
<Button tone="neutral">Neutral</Button>
|
|
34
|
+
<Button tone="positive">Positive</Button>
|
|
35
|
+
<Button tone="critical">Critical</Button>
|
|
36
|
+
</Inline>
|
|
37
|
+
</Stack>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Prominence
|
|
41
|
+
|
|
42
|
+
The appearance of the button can be customised with the prominence prop. Valid
|
|
43
|
+
options are: `low` and `high`.
|
|
44
|
+
|
|
45
|
+
Defaults to `high`.
|
|
46
|
+
|
|
47
|
+
```jsx live
|
|
48
|
+
<Stack gap="large">
|
|
49
|
+
<Text weight="strong">High prominence</Text>
|
|
50
|
+
<Inline gap="small">
|
|
51
|
+
<Button prominence="high" tone="primary">
|
|
52
|
+
<LightBulbIcon />
|
|
53
|
+
Primary
|
|
54
|
+
</Button>
|
|
55
|
+
<Button prominence="high" tone="secondary">
|
|
56
|
+
<LightBulbIcon />
|
|
57
|
+
Secondary
|
|
58
|
+
</Button>
|
|
59
|
+
<Button prominence="high" tone="neutral">
|
|
60
|
+
<LightBulbIcon />
|
|
61
|
+
Neutral
|
|
62
|
+
</Button>
|
|
63
|
+
<Button prominence="high" tone="positive">
|
|
64
|
+
<LightBulbIcon />
|
|
65
|
+
Positive
|
|
66
|
+
</Button>
|
|
67
|
+
<Button prominence="high" tone="critical">
|
|
68
|
+
<LightBulbIcon />
|
|
69
|
+
Critical
|
|
70
|
+
</Button>
|
|
71
|
+
</Inline>
|
|
72
|
+
<Divider />
|
|
73
|
+
<Text weight="strong">Low prominence</Text>
|
|
74
|
+
<Inline gap="small">
|
|
75
|
+
<Button prominence="low" tone="primary">
|
|
76
|
+
<LightBulbIcon />
|
|
77
|
+
Primary
|
|
78
|
+
</Button>
|
|
79
|
+
<Button prominence="low" tone="secondary">
|
|
80
|
+
<LightBulbIcon />
|
|
81
|
+
Secondary
|
|
82
|
+
</Button>
|
|
83
|
+
<Button prominence="low" tone="neutral">
|
|
84
|
+
<LightBulbIcon />
|
|
85
|
+
Neutral
|
|
86
|
+
</Button>
|
|
87
|
+
<Button prominence="low" tone="positive">
|
|
88
|
+
<LightBulbIcon />
|
|
89
|
+
Positive
|
|
90
|
+
</Button>
|
|
91
|
+
<Button prominence="low" tone="critical">
|
|
92
|
+
<LightBulbIcon />
|
|
93
|
+
Critical
|
|
94
|
+
</Button>
|
|
95
|
+
<Button prominence="low" tone="caution">
|
|
96
|
+
<LightBulbIcon />
|
|
97
|
+
Critical
|
|
98
|
+
</Button>
|
|
99
|
+
<Button prominence="low" tone="info">
|
|
100
|
+
<LightBulbIcon />
|
|
101
|
+
Informative
|
|
102
|
+
</Button>
|
|
103
|
+
</Inline>
|
|
104
|
+
<Divider />
|
|
105
|
+
<Text weight="strong">None prominence</Text>
|
|
106
|
+
<Inline gap="small">
|
|
107
|
+
<Button prominence="none" tone="primary">
|
|
108
|
+
<LightBulbIcon />
|
|
109
|
+
Primary
|
|
110
|
+
</Button>
|
|
111
|
+
<Button prominence="none" tone="secondary">
|
|
112
|
+
<LightBulbIcon />
|
|
113
|
+
Secondary
|
|
114
|
+
</Button>
|
|
115
|
+
<Button prominence="none" tone="neutral">
|
|
116
|
+
<LightBulbIcon />
|
|
117
|
+
Neutral
|
|
118
|
+
</Button>
|
|
119
|
+
<Button prominence="none" tone="positive">
|
|
120
|
+
<LightBulbIcon />
|
|
121
|
+
Positive
|
|
122
|
+
</Button>
|
|
123
|
+
<Button prominence="none" tone="critical">
|
|
124
|
+
<LightBulbIcon />
|
|
125
|
+
Critical
|
|
126
|
+
</Button>
|
|
127
|
+
<Button prominence="none" tone="caution">
|
|
128
|
+
<LightBulbIcon />
|
|
129
|
+
Critical
|
|
130
|
+
</Button>
|
|
131
|
+
<Button prominence="none" tone="info">
|
|
132
|
+
<LightBulbIcon />
|
|
133
|
+
Informative
|
|
134
|
+
</Button>
|
|
135
|
+
</Inline>
|
|
136
|
+
</Stack>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Size
|
|
140
|
+
|
|
141
|
+
Button's are available in two size: `medium` and `large`.
|
|
142
|
+
|
|
143
|
+
Defaults to `medium`.
|
|
144
|
+
|
|
145
|
+
```jsx live
|
|
146
|
+
<Inline gap="small">
|
|
147
|
+
<Button size="medium">Medium</Button>
|
|
148
|
+
<Button size="large">Large</Button>
|
|
149
|
+
</Inline>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Icons
|
|
153
|
+
|
|
154
|
+
Icons can be placed next to labels to both clarify an action and call attention
|
|
155
|
+
to a button.
|
|
156
|
+
|
|
157
|
+
```jsx live
|
|
158
|
+
<Inline gap="small">
|
|
159
|
+
<Button>
|
|
160
|
+
<DownloadIcon />
|
|
161
|
+
Download
|
|
162
|
+
</Button>
|
|
163
|
+
<Button tone="critical">
|
|
164
|
+
<TrashIcon />
|
|
165
|
+
Delete
|
|
166
|
+
</Button>
|
|
167
|
+
</Inline>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Icon only
|
|
171
|
+
|
|
172
|
+
When using buttons that contain only an icon, you must provide a `label` for
|
|
173
|
+
users of assistive technology.
|
|
174
|
+
|
|
175
|
+
```jsx live
|
|
176
|
+
<Inline gap="small">
|
|
177
|
+
<Button label="Download PDF">
|
|
178
|
+
<DownloadIcon />
|
|
179
|
+
</Button>
|
|
180
|
+
<Button tone="critical" label="Delete item">
|
|
181
|
+
<TrashIcon />
|
|
182
|
+
</Button>
|
|
183
|
+
<Button tone="neutral" label="Dismiss">
|
|
184
|
+
<XIcon size="xxsmall" />
|
|
185
|
+
</Button>
|
|
186
|
+
</Inline>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## ButtonLink
|
|
190
|
+
|
|
191
|
+
The appearance of a button, with the semantics of a link — shares `Button` API,
|
|
192
|
+
with the exception of `href` vs `onClick` props.
|
|
193
|
+
|
|
194
|
+
```jsx live
|
|
195
|
+
<Text>
|
|
196
|
+
<ButtonLink href="#">Visually a link, with button semantics</ButtonLink>
|
|
197
|
+
</Text>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Props
|
|
201
|
+
|
|
202
|
+
| Prop | Type | Default | Description |
|
|
203
|
+
| ----------------- | ---------------------------------------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
204
|
+
| aria-controls? | string | | Identifies the element (or elements) whose contents or presence are controlled by the current element. Only applicable for `Button`. |
|
|
205
|
+
| aria-describedby? | string | | Identifies the element (or elements) that describes the object. Only applicable for `Button`. |
|
|
206
|
+
| aria-expanded? | string | | Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. Only applicable for `Button`. |
|
|
207
|
+
| children | string \| React.ReactElement<IconProps\> | | Children element to be rendered inside the button. |
|
|
208
|
+
| data? | Object | | Allows setting of data attributes on the button. |
|
|
209
|
+
| disabled? | boolean | | When true, prevents `onClick` from firing. Only applicable for `Button`. |
|
|
210
|
+
| href | string | | Specifies the url the button should redirect to upon being clicked. Only applicable for `ButtonLink`. |
|
|
211
|
+
| id? | string | | Unique identifier for the button. |
|
|
212
|
+
| label? | string | | Implicit label for buttons only required for icon-only buttons for accessibility reasons. |
|
|
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`. |
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { CommonButtonProps, NativeButtonProps } from './types';
|
|
3
|
+
export declare type ButtonProps = CommonButtonProps & {
|
|
4
|
+
'aria-controls'?: NativeButtonProps['aria-controls'];
|
|
5
|
+
'aria-describedby'?: NativeButtonProps['aria-describedby'];
|
|
6
|
+
'aria-expanded'?: NativeButtonProps['aria-expanded'];
|
|
7
|
+
onClick?: NativeButtonProps['onClick'];
|
|
8
|
+
size?: CommonButtonProps['size'];
|
|
9
|
+
type?: 'button' | 'submit' | 'reset';
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Buttons are used to initialize an action, their label should express what
|
|
14
|
+
* action will occur when the user interacts with it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
17
|
+
/**
|
|
18
|
+
* Prevent click events when the component is "disabled".
|
|
19
|
+
* Note: we don't want to actually disable a button element for several reasons.
|
|
20
|
+
* One being because that would prohibit the use of tooltips.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getPreventableClickHandler(onClick: NativeButtonProps['onClick'], disabled: boolean): (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { LinkComponentProps } from '@spark-web/link';
|
|
3
|
+
import type { CommonButtonProps } from './types';
|
|
4
|
+
export declare type ButtonLinkProps = LinkComponentProps & CommonButtonProps;
|
|
5
|
+
/** The appearance of a `Button`, with the semantics of a link. */
|
|
6
|
+
export declare const ButtonLink: <Comp extends import("react").ElementType<any> = "a">(props: {
|
|
7
|
+
as?: Comp | undefined;
|
|
8
|
+
ref?: import("react").Ref<Comp extends "symbol" | "clipPath" | "filter" | "mask" | "marker" | "text" | "circle" | "svg" | "animate" | "animateMotion" | "animateTransform" | "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" | "textPath" | "tspan" | "use" | "view" | keyof HTMLElementTagNameMap | "set" ? (HTMLElementTagNameMap & Pick<SVGElementTagNameMap, "symbol" | "clipPath" | "filter" | "mask" | "marker" | "text" | "circle" | "svg" | "animate" | "animateMotion" | "animateTransform" | "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" | "textPath" | "tspan" | "use" | "view" | "set">)[Comp] : Comp extends new (...args: any) => any ? InstanceType<Comp> : undefined> | undefined;
|
|
9
|
+
} & Omit<import("react").PropsWithoutRef<import("react").ComponentProps<Comp>>, "as"> & ButtonLinkProps) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ButtonChildrenProps, ButtonProminence, ButtonSize, ButtonTone } from './types';
|
|
2
|
+
declare type ResolveButtonChildren = ButtonChildrenProps & {
|
|
3
|
+
prominence: ButtonProminence;
|
|
4
|
+
size: ButtonSize;
|
|
5
|
+
tone: ButtonTone;
|
|
6
|
+
};
|
|
7
|
+
export declare const resolveButtonChildren: ({ children, prominence, size, tone, }: ResolveButtonChildren) => JSX.Element[];
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { BackgroundTone } from '@spark-web/a11y';
|
|
2
|
+
import type { IconProps } from '@spark-web/icon';
|
|
3
|
+
import type { DataAttributeMap } from '@spark-web/utils/internal';
|
|
4
|
+
import type { ButtonHTMLAttributes, ReactElement } from 'react';
|
|
5
|
+
import type { mapTokens } from './utils';
|
|
6
|
+
export declare type ButtonSize = keyof typeof mapTokens[keyof typeof mapTokens];
|
|
7
|
+
export declare type ButtonProminence = 'high' | 'low' | 'none';
|
|
8
|
+
export declare type ButtonTone = BackgroundTone;
|
|
9
|
+
declare type ChildrenWithText = {
|
|
10
|
+
label?: never;
|
|
11
|
+
children: string | [ReactElement<IconProps>, string] | [string, ReactElement<IconProps>];
|
|
12
|
+
};
|
|
13
|
+
declare type IconOnly = {
|
|
14
|
+
label: string;
|
|
15
|
+
children: ReactElement<IconProps>;
|
|
16
|
+
};
|
|
17
|
+
export declare type ButtonChildrenProps = ChildrenWithText | IconOnly;
|
|
18
|
+
export declare type NativeButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;
|
|
19
|
+
export declare type CommonButtonProps = {
|
|
20
|
+
data?: DataAttributeMap;
|
|
21
|
+
id?: string;
|
|
22
|
+
} & ButtonChildrenProps & ButtonStyleProps;
|
|
23
|
+
export declare type ButtonStyleProps = {
|
|
24
|
+
/** Sets the visual prominence of the button. */
|
|
25
|
+
prominence?: ButtonProminence;
|
|
26
|
+
/** Sets the size of the button. */
|
|
27
|
+
size?: ButtonSize;
|
|
28
|
+
/** Sets the tone of the button. */
|
|
29
|
+
tone?: ButtonTone;
|
|
30
|
+
};
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BoxProps } from '@spark-web/box';
|
|
2
|
+
import type { ButtonProminence, ButtonSize, ButtonTone } from './types';
|
|
3
|
+
declare type UseButtonStylesProps = {
|
|
4
|
+
iconOnly: boolean;
|
|
5
|
+
prominence: ButtonProminence;
|
|
6
|
+
size: ButtonSize;
|
|
7
|
+
tone: ButtonTone;
|
|
8
|
+
};
|
|
9
|
+
export declare function useButtonStyles({ iconOnly, prominence, size, tone, }: UseButtonStylesProps): Partial<BoxProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BoxProps } from '@spark-web/box';
|
|
2
|
+
import type { ForegroundTone } from '@spark-web/text';
|
|
3
|
+
import type { BrighteTheme } from '@spark-web/theme';
|
|
4
|
+
import type { ButtonProminence, ButtonTone } from './types';
|
|
5
|
+
declare type ButtonStyles = {
|
|
6
|
+
background: BoxProps['background'];
|
|
7
|
+
border?: BoxProps['border'];
|
|
8
|
+
borderWidth?: BoxProps['borderWidth'];
|
|
9
|
+
textTone?: ForegroundTone;
|
|
10
|
+
backgroundHover: keyof BrighteTheme['backgroundInteractions'];
|
|
11
|
+
borderHover?: keyof BrighteTheme['border']['color'];
|
|
12
|
+
textToneHover?: keyof BrighteTheme['color']['foreground'];
|
|
13
|
+
backgroundActive: keyof BrighteTheme['backgroundInteractions'];
|
|
14
|
+
borderActive?: keyof BrighteTheme['border']['color'];
|
|
15
|
+
textToneActive?: keyof BrighteTheme['color']['foreground'];
|
|
16
|
+
};
|
|
17
|
+
export declare const variants: Record<ButtonProminence, Record<ButtonTone, ButtonStyles | undefined>>;
|
|
18
|
+
export declare const mapTokens: {
|
|
19
|
+
readonly fontSize: {
|
|
20
|
+
readonly medium: "small";
|
|
21
|
+
readonly large: "standard";
|
|
22
|
+
};
|
|
23
|
+
readonly size: {
|
|
24
|
+
readonly medium: "medium";
|
|
25
|
+
readonly large: "large";
|
|
26
|
+
};
|
|
27
|
+
readonly spacing: {
|
|
28
|
+
readonly medium: "medium";
|
|
29
|
+
readonly large: "xlarge";
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./declarations/src/index";
|