@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 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,4 @@
1
+ export { Button } from './Button';
2
+ export { ButtonLink } from './ButtonLink';
3
+ export type { ButtonProps } from './Button';
4
+ export type { ButtonLinkProps } from './ButtonLink';
@@ -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";