@edux-design/buttons 0.2.0 → 0.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/CHANGELOG.md +16 -0
- package/README.md +4 -0
- package/dist/index.d.mts +136 -5
- package/dist/index.d.ts +136 -5
- package/dist/index.js +296 -34
- package/dist/index.mjs +295 -33
- package/docs/button-group.md +25 -0
- package/docs/toolbar.md +146 -0
- package/package.json +8 -17
- package/dist/chevron-EVM4GL6D.svg +0 -4
- package/dist/chunk-M47FNL4P.mjs +0 -10
- package/dist/elements/Button.js +0 -39
- package/dist/elements/Button.mjs +0 -6
- package/src/demo/Button.stories.jsx +0 -103
- package/src/demo/ButtonCompatibility.stories.jsx +0 -115
- package/src/demo/ButtonCounter.stories.jsx +0 -101
- package/src/demo/ButtonGroup.stories.jsx +0 -67
- package/src/elements/Button.a11y.test.jsx +0 -60
- package/src/elements/Button.jsx +0 -127
- package/src/elements/Button.test.jsx +0 -120
- package/src/elements/ButtonCounter.jsx +0 -356
- package/src/elements/ButtonCounter.test.jsx +0 -121
- package/src/elements/ButtonGroup.jsx +0 -404
- package/src/elements/ButtonGroup.test.jsx +0 -130
- package/src/elements/ButtonGroupItem.jsx +0 -8
- package/src/elements/IconButton.jsx +0 -115
- package/src/elements/IconButton.test.jsx +0 -62
- package/src/elements/MenuButton.jsx +0 -68
- package/src/elements/MenuButton.test.jsx +0 -40
- package/src/elements/testA11y.js +0 -14
- package/src/index.js +0 -6
- package/src/util/MenuButtonContext.jsx +0 -3
- package/tsconfig.json +0 -12
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none"
|
|
2
|
-
xmlns="http://www.w3.org/2000/svg">
|
|
3
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5858 12L9.29289 7.70711C8.90237 7.31658 8.90237 6.68342 9.29289 6.29289C9.68342 5.90237 10.3166 5.90237 10.7071 6.29289L15.7071 11.2929C16.0976 11.6834 16.0976 12.3166 15.7071 12.7071L10.7071 17.7071C10.3166 18.0976 9.68342 18.0976 9.29289 17.7071C8.90237 17.3166 8.90237 16.6834 9.29289 16.2929L13.5858 12Z" fill="currentColor"/>
|
|
4
|
-
</svg>
|
package/dist/chunk-M47FNL4P.mjs
DELETED
package/dist/elements/Button.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
-
|
|
29
|
-
// src/elements/Button.jsx
|
|
30
|
-
var Button_exports = {};
|
|
31
|
-
__export(Button_exports, {
|
|
32
|
-
default: () => Button_default
|
|
33
|
-
});
|
|
34
|
-
module.exports = __toCommonJS(Button_exports);
|
|
35
|
-
var import_react = __toESM(require("react"));
|
|
36
|
-
function Button() {
|
|
37
|
-
return /* @__PURE__ */ import_react.default.createElement("div", { className: "border-2 border-primary-700" }, "Button");
|
|
38
|
-
}
|
|
39
|
-
var Button_default = Button;
|
package/dist/elements/Button.mjs
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Button, IconButton } from "./../index";
|
|
3
|
-
import { Close, External, Warning } from "@edux-design/icons";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
title: "Components/Button",
|
|
7
|
-
component: Button,
|
|
8
|
-
argTypes: {
|
|
9
|
-
size: {
|
|
10
|
-
control: { type: "select" },
|
|
11
|
-
options: ["small", "medium", "large"],
|
|
12
|
-
},
|
|
13
|
-
isSecondary: { control: "boolean" },
|
|
14
|
-
isDanger: { control: "boolean" },
|
|
15
|
-
isBare: { control: "boolean" },
|
|
16
|
-
isStretched: { control: "boolean" },
|
|
17
|
-
disabled: { control: "boolean" },
|
|
18
|
-
startIcon: { control: false },
|
|
19
|
-
endIcon: { control: false },
|
|
20
|
-
children: { control: "text" },
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// Base template
|
|
25
|
-
const Template = (args) => <Button {...args} />;
|
|
26
|
-
|
|
27
|
-
// Default story
|
|
28
|
-
export const Primary = Template.bind({});
|
|
29
|
-
Primary.args = {
|
|
30
|
-
children: "Primary Button",
|
|
31
|
-
size: "medium",
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Variants
|
|
35
|
-
export const Secondary = Template.bind({});
|
|
36
|
-
Secondary.args = {
|
|
37
|
-
children: "Secondary Button",
|
|
38
|
-
isSecondary: true,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const Danger = Template.bind({});
|
|
42
|
-
Danger.args = {
|
|
43
|
-
children: "Delete",
|
|
44
|
-
isDanger: true,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const Bare = Template.bind({});
|
|
48
|
-
Bare.args = {
|
|
49
|
-
children: "Bare Button",
|
|
50
|
-
isBare: true,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const DangerBare = Template.bind({});
|
|
54
|
-
DangerBare.args = {
|
|
55
|
-
children: "Log out",
|
|
56
|
-
isBare: true,
|
|
57
|
-
isDanger: true,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export const Disabled = Template.bind({});
|
|
61
|
-
Disabled.args = {
|
|
62
|
-
children: "Disabled",
|
|
63
|
-
disabled: true,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// Sizes
|
|
67
|
-
export const Small = Template.bind({});
|
|
68
|
-
Small.args = {
|
|
69
|
-
children: "Small",
|
|
70
|
-
size: "small",
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export const Large = Template.bind({});
|
|
74
|
-
Large.args = {
|
|
75
|
-
children: "Large",
|
|
76
|
-
size: "large",
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// Stretched (full width)
|
|
80
|
-
export const Stretched = Template.bind({});
|
|
81
|
-
Stretched.args = {
|
|
82
|
-
children: "Full Width",
|
|
83
|
-
isStretched: true,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export const Default = () => (
|
|
87
|
-
<div className="flex gap-4 items-center">
|
|
88
|
-
<IconButton icon={<Close />} aria-label="Close" isBare />
|
|
89
|
-
<IconButton icon={<Close />} isSecondary aria-label="Close" />
|
|
90
|
-
<IconButton icon={<Close />} isDanger aria-label="Delete" />
|
|
91
|
-
<IconButton icon={<Close />} disabled aria-label="Disabled" />
|
|
92
|
-
</div>
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
export const WithIcons = () => (
|
|
96
|
-
<div className="flex gap-4 items-center">
|
|
97
|
-
<Button startIcon={<Warning />}>Start icon</Button>
|
|
98
|
-
<Button endIcon={<External />}>End icon</Button>
|
|
99
|
-
<Button isDanger isBare endIcon={<External />}>
|
|
100
|
-
Log out
|
|
101
|
-
</Button>
|
|
102
|
-
</div>
|
|
103
|
-
);
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import {
|
|
3
|
-
Button,
|
|
4
|
-
ButtonCounter,
|
|
5
|
-
ButtonGroup,
|
|
6
|
-
ButtonGroupItem,
|
|
7
|
-
IconButton,
|
|
8
|
-
MenuButton,
|
|
9
|
-
} from "./../index";
|
|
10
|
-
|
|
11
|
-
const sizes = ["small", "medium", "large"];
|
|
12
|
-
const variants = [
|
|
13
|
-
{ label: "Primary", props: {} },
|
|
14
|
-
{ label: "Secondary", props: { isSecondary: true } },
|
|
15
|
-
{ label: "Bare", props: { isBare: true } },
|
|
16
|
-
{ label: "Danger", props: { isDanger: true } },
|
|
17
|
-
{ label: "Danger bare", props: { isDanger: true, isBare: true } },
|
|
18
|
-
{ label: "Disabled", props: { disabled: true } },
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
function GroupExample() {
|
|
22
|
-
const [value, setValue] = useState("one");
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<ButtonGroup value={value} onChange={setValue}>
|
|
26
|
-
<ButtonGroupItem value="one">One</ButtonGroupItem>
|
|
27
|
-
<ButtonGroupItem value="two">Two</ButtonGroupItem>
|
|
28
|
-
<ButtonGroupItem value="three">Three</ButtonGroupItem>
|
|
29
|
-
</ButtonGroup>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function ControlMatrix() {
|
|
34
|
-
return (
|
|
35
|
-
<div className="space-y-24">
|
|
36
|
-
<section className="space-y-12">
|
|
37
|
-
<h3 className="text-lg font-semibold text-fg-emphasis">
|
|
38
|
-
Button variants
|
|
39
|
-
</h3>
|
|
40
|
-
<div className="grid gap-12">
|
|
41
|
-
{variants.map(({ label, props }) => (
|
|
42
|
-
<div key={label} className="flex flex-wrap items-center gap-12">
|
|
43
|
-
{sizes.map((size) => (
|
|
44
|
-
<Button key={size} size={size} {...props}>
|
|
45
|
-
{label} {size}
|
|
46
|
-
</Button>
|
|
47
|
-
))}
|
|
48
|
-
</div>
|
|
49
|
-
))}
|
|
50
|
-
</div>
|
|
51
|
-
</section>
|
|
52
|
-
|
|
53
|
-
<section className="space-y-12">
|
|
54
|
-
<h3 className="text-lg font-semibold text-fg-emphasis">
|
|
55
|
-
Related controls
|
|
56
|
-
</h3>
|
|
57
|
-
<div className="flex flex-wrap items-center gap-12">
|
|
58
|
-
{sizes.map((size) => (
|
|
59
|
-
<IconButton
|
|
60
|
-
key={size}
|
|
61
|
-
size={size}
|
|
62
|
-
icon={<span aria-hidden="true">×</span>}
|
|
63
|
-
aria-label={`Close ${size}`}
|
|
64
|
-
/>
|
|
65
|
-
))}
|
|
66
|
-
<MenuButton size="small" aria-expanded="false">
|
|
67
|
-
Small menu
|
|
68
|
-
</MenuButton>
|
|
69
|
-
<MenuButton size="medium" aria-expanded="false">
|
|
70
|
-
Medium menu
|
|
71
|
-
</MenuButton>
|
|
72
|
-
</div>
|
|
73
|
-
<div className="flex flex-wrap items-center gap-12">
|
|
74
|
-
{sizes.map((size) => (
|
|
75
|
-
<ButtonCounter
|
|
76
|
-
key={size}
|
|
77
|
-
size={size}
|
|
78
|
-
defaultValue={2}
|
|
79
|
-
aria-label={`${size} quantity`}
|
|
80
|
-
/>
|
|
81
|
-
))}
|
|
82
|
-
</div>
|
|
83
|
-
<GroupExample />
|
|
84
|
-
</section>
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const themeCases = [
|
|
90
|
-
{ label: "Light · Blue", className: "theme--light brand--blue" },
|
|
91
|
-
{ label: "Light · Teal", className: "theme--light brand--teal" },
|
|
92
|
-
{ label: "Dark · Blue", className: "theme--dark brand--blue" },
|
|
93
|
-
{ label: "Dark · Teal", className: "theme--dark brand--teal" },
|
|
94
|
-
];
|
|
95
|
-
|
|
96
|
-
export default {
|
|
97
|
-
title: "Components/Button/Compatibility",
|
|
98
|
-
parameters: {
|
|
99
|
-
layout: "fullscreen",
|
|
100
|
-
chromatic: { disableSnapshot: false },
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
export const CompatibilityMatrix = {
|
|
105
|
-
render: () => (
|
|
106
|
-
<div className="grid grid-cols-1 2xl:grid-cols-2">
|
|
107
|
-
{themeCases.map(({ label, className }) => (
|
|
108
|
-
<div key={label} className={`${className} bg-bg-base p-24`}>
|
|
109
|
-
<h2 className="mb-16 text-xl font-bold text-fg-emphasis">{label}</h2>
|
|
110
|
-
<ControlMatrix />
|
|
111
|
-
</div>
|
|
112
|
-
))}
|
|
113
|
-
</div>
|
|
114
|
-
),
|
|
115
|
-
};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { ButtonCounter } from "./../index";
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
title: "Components/Button",
|
|
6
|
-
component: ButtonCounter,
|
|
7
|
-
argTypes: {
|
|
8
|
-
size: {
|
|
9
|
-
control: { type: "select" },
|
|
10
|
-
options: ["small", "medium", "large"],
|
|
11
|
-
},
|
|
12
|
-
isSecondary: { control: "boolean" },
|
|
13
|
-
isDanger: { control: "boolean" },
|
|
14
|
-
isBare: { control: "boolean" },
|
|
15
|
-
isStretched: { control: "boolean" },
|
|
16
|
-
disabled: { control: "boolean" },
|
|
17
|
-
isEditable: { control: "boolean" },
|
|
18
|
-
inputProps: { control: false },
|
|
19
|
-
defaultValue: { control: "number" },
|
|
20
|
-
min: { control: "number" },
|
|
21
|
-
max: { control: "number" },
|
|
22
|
-
step: { control: "number" },
|
|
23
|
-
value: { control: false },
|
|
24
|
-
onChange: { control: false },
|
|
25
|
-
decrementIcon: { control: false },
|
|
26
|
-
incrementIcon: { control: false },
|
|
27
|
-
decrementButtonProps: { control: false },
|
|
28
|
-
incrementButtonProps: { control: false },
|
|
29
|
-
children: { control: false },
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const Template = (args) => <ButtonCounter {...args} />;
|
|
34
|
-
|
|
35
|
-
export const PrimaryCounter = Template.bind({});
|
|
36
|
-
PrimaryCounter.args = {
|
|
37
|
-
defaultValue: 1,
|
|
38
|
-
size: "medium",
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const EditableCounter = Template.bind({});
|
|
42
|
-
EditableCounter.args = {
|
|
43
|
-
defaultValue: 1,
|
|
44
|
-
isEditable: true,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const SecondaryCounter = Template.bind({});
|
|
48
|
-
SecondaryCounter.args = {
|
|
49
|
-
defaultValue: 1,
|
|
50
|
-
isSecondary: true,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const DangerCounter = Template.bind({});
|
|
54
|
-
DangerCounter.args = {
|
|
55
|
-
defaultValue: 1,
|
|
56
|
-
isDanger: true,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export const BareCounter = Template.bind({});
|
|
60
|
-
BareCounter.args = {
|
|
61
|
-
defaultValue: 1,
|
|
62
|
-
isBare: true,
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const DangerBareCounter = Template.bind({});
|
|
66
|
-
DangerBareCounter.args = {
|
|
67
|
-
defaultValue: 1,
|
|
68
|
-
isBare: true,
|
|
69
|
-
isDanger: true,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export const DisabledCounter = Template.bind({});
|
|
73
|
-
DisabledCounter.args = {
|
|
74
|
-
defaultValue: 1,
|
|
75
|
-
disabled: true,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const SmallCounter = Template.bind({});
|
|
79
|
-
SmallCounter.args = {
|
|
80
|
-
defaultValue: 1,
|
|
81
|
-
size: "small",
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export const LargeCounter = Template.bind({});
|
|
85
|
-
LargeCounter.args = {
|
|
86
|
-
defaultValue: 1,
|
|
87
|
-
size: "large",
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const StretchedCounter = Template.bind({});
|
|
91
|
-
StretchedCounter.args = {
|
|
92
|
-
defaultValue: 1,
|
|
93
|
-
isStretched: true,
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export const WithBoundsCounter = Template.bind({});
|
|
97
|
-
WithBoundsCounter.args = {
|
|
98
|
-
defaultValue: 2,
|
|
99
|
-
min: 0,
|
|
100
|
-
max: 3,
|
|
101
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { ButtonGroup, ButtonGroupItem } from "./../index";
|
|
3
|
-
import { Warning } from "@edux-design/icons";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
title: "Components/ButtonGroup",
|
|
7
|
-
component: ButtonGroup,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: "centered",
|
|
10
|
-
},
|
|
11
|
-
argTypes: {
|
|
12
|
-
size: {
|
|
13
|
-
control: { type: "select" },
|
|
14
|
-
options: ["small", "medium", "large"],
|
|
15
|
-
},
|
|
16
|
-
isStretched: { control: "boolean" },
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const Template = (args) => {
|
|
21
|
-
const [value, setValue] = useState(args.value ?? args.defaultValue ?? "one");
|
|
22
|
-
return (
|
|
23
|
-
<ButtonGroup
|
|
24
|
-
{...args}
|
|
25
|
-
value={value}
|
|
26
|
-
onChange={(nextValue) => {
|
|
27
|
-
setValue(nextValue);
|
|
28
|
-
args.onChange?.(nextValue);
|
|
29
|
-
}}
|
|
30
|
-
>
|
|
31
|
-
<ButtonGroupItem value="one">Label (11)</ButtonGroupItem>
|
|
32
|
-
<ButtonGroupItem value="two">Label (11)</ButtonGroupItem>
|
|
33
|
-
<ButtonGroupItem
|
|
34
|
-
value="alert"
|
|
35
|
-
endIcon={<Warning className="h-4 w-4 text-warning-600" />}
|
|
36
|
-
>
|
|
37
|
-
Label
|
|
38
|
-
</ButtonGroupItem>
|
|
39
|
-
</ButtonGroup>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const Playground = Template.bind({});
|
|
44
|
-
Playground.args = { defaultValue: "one" };
|
|
45
|
-
|
|
46
|
-
export const WithIconCounts = () => {
|
|
47
|
-
const [value, setValue] = useState("inbox");
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<div className="w-[360px]">
|
|
51
|
-
<ButtonGroup
|
|
52
|
-
isStretched
|
|
53
|
-
value={value}
|
|
54
|
-
onChange={(next) => setValue(next)}
|
|
55
|
-
>
|
|
56
|
-
<ButtonGroupItem value="inbox">Inbox (11)</ButtonGroupItem>
|
|
57
|
-
<ButtonGroupItem value="drafts">Drafts (11)</ButtonGroupItem>
|
|
58
|
-
<ButtonGroupItem
|
|
59
|
-
value="alerts"
|
|
60
|
-
endAdornment={<Warning className="h-3.5 w-3.5 text-warning-600" />}
|
|
61
|
-
>
|
|
62
|
-
Alerts
|
|
63
|
-
</ButtonGroupItem>
|
|
64
|
-
</ButtonGroup>
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
};
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import { Button } from "./Button";
|
|
4
|
-
import { IconButton } from "./IconButton";
|
|
5
|
-
import { MenuButton } from "./MenuButton";
|
|
6
|
-
import { ButtonGroup } from "./ButtonGroup";
|
|
7
|
-
import { ButtonGroupItem } from "./ButtonGroupItem";
|
|
8
|
-
import { ButtonCounter } from "./ButtonCounter";
|
|
9
|
-
import { expectNoAxeViolations } from "./testA11y";
|
|
10
|
-
|
|
11
|
-
describe("buttons accessibility", () => {
|
|
12
|
-
it("Button has no detectable accessibility violations", async () => {
|
|
13
|
-
const { container } = render(
|
|
14
|
-
<Button startIcon={<span aria-hidden="true">+</span>}>Save</Button>,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
await expectNoAxeViolations(container);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("IconButton has no detectable accessibility violations when named", async () => {
|
|
21
|
-
const { container } = render(
|
|
22
|
-
<IconButton
|
|
23
|
-
icon={<span aria-hidden="true">X</span>}
|
|
24
|
-
aria-label="Close dialog"
|
|
25
|
-
/>,
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
await expectNoAxeViolations(container);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("MenuButton has no detectable accessibility violations", async () => {
|
|
32
|
-
const { container } = render(
|
|
33
|
-
<MenuButton aria-expanded={false}>Options</MenuButton>,
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
await expectNoAxeViolations(container);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("ButtonGroup has no detectable accessibility violations", async () => {
|
|
40
|
-
const { container } = render(
|
|
41
|
-
<ButtonGroup defaultValue="first">
|
|
42
|
-
<ButtonGroupItem value="first">First</ButtonGroupItem>
|
|
43
|
-
<ButtonGroupItem value="second">Second</ButtonGroupItem>
|
|
44
|
-
<ButtonGroupItem value="third" disabled>
|
|
45
|
-
Third
|
|
46
|
-
</ButtonGroupItem>
|
|
47
|
-
</ButtonGroup>,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
await expectNoAxeViolations(container);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("ButtonCounter has no detectable accessibility violations", async () => {
|
|
54
|
-
const { container } = render(
|
|
55
|
-
<ButtonCounter defaultValue={2} aria-label="Quantity" />,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
await expectNoAxeViolations(container);
|
|
59
|
-
});
|
|
60
|
-
});
|
package/src/elements/Button.jsx
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import React, { forwardRef } from "react";
|
|
2
|
-
import { cx } from "@edux-design/utils";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Props for the Button component.
|
|
6
|
-
*
|
|
7
|
-
* Extends all native HTML `<button>` attributes, while adding
|
|
8
|
-
* design-system variants and state controls.
|
|
9
|
-
*
|
|
10
|
-
* @typedef {React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
11
|
-
* children?: React.ReactNode,
|
|
12
|
-
* startIcon?: React.ReactNode,
|
|
13
|
-
* endIcon?: React.ReactNode,
|
|
14
|
-
* size?: "small"|"medium"|"large",
|
|
15
|
-
* isSecondary?: boolean,
|
|
16
|
-
* isDanger?: boolean,
|
|
17
|
-
* isBare?: boolean,
|
|
18
|
-
* isStretched?: boolean,
|
|
19
|
-
* disabled?: boolean,
|
|
20
|
-
* className?: string
|
|
21
|
-
* }} ButtonProps
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Button component.
|
|
26
|
-
*
|
|
27
|
-
* Provides design-system styled button with support for
|
|
28
|
-
* multiple visual variants, sizing, and states.
|
|
29
|
-
*
|
|
30
|
-
* @component
|
|
31
|
-
* @type {React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>}
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* ```jsx
|
|
35
|
-
* <Button size="small">Save</Button>
|
|
36
|
-
* <Button isSecondary>Cancel</Button>
|
|
37
|
-
* <Button isDanger disabled>Delete</Button>
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export const Button = forwardRef(
|
|
41
|
-
(
|
|
42
|
-
{
|
|
43
|
-
children,
|
|
44
|
-
startIcon,
|
|
45
|
-
endIcon,
|
|
46
|
-
size = "medium",
|
|
47
|
-
isSecondary,
|
|
48
|
-
isDanger,
|
|
49
|
-
isBare,
|
|
50
|
-
isStretched,
|
|
51
|
-
disabled,
|
|
52
|
-
className,
|
|
53
|
-
...props
|
|
54
|
-
},
|
|
55
|
-
ref
|
|
56
|
-
) => {
|
|
57
|
-
let variant = "primary";
|
|
58
|
-
if (disabled) {
|
|
59
|
-
variant = "disabled";
|
|
60
|
-
} else if (isDanger && isBare) {
|
|
61
|
-
variant = "dangerBare";
|
|
62
|
-
} else if (isDanger) {
|
|
63
|
-
variant = "danger";
|
|
64
|
-
} else if (isSecondary) {
|
|
65
|
-
variant = "secondary";
|
|
66
|
-
} else if (isBare) {
|
|
67
|
-
variant = "bare";
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// handle conflicting props - the last bool wins
|
|
71
|
-
if (process.env.NODE_ENV !== "production") {
|
|
72
|
-
const count = [isSecondary, isDanger, isBare].filter(Boolean).length;
|
|
73
|
-
const hasAllowedCombo = isDanger && isBare && count === 2;
|
|
74
|
-
if (count > 1 && !hasAllowedCombo) {
|
|
75
|
-
console.warn(
|
|
76
|
-
"[Button]: Multiple variant props passed. Using the highest priority only."
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const defaults =
|
|
82
|
-
"flex justify-center items-center gap-8 focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out cursor-pointer";
|
|
83
|
-
|
|
84
|
-
const fonts =
|
|
85
|
-
"text-bold tracking-normal hover:underline hover:underline-offset-(--underline-offset-btn) active:underline active:underline-offset-(--underline-offset-btn)";
|
|
86
|
-
|
|
87
|
-
const sizes = {
|
|
88
|
-
small: "h-control-sm py-8 px-16 rounded-lg text-sm",
|
|
89
|
-
medium: "h-control-md py-8 px-16 rounded-lg text-base",
|
|
90
|
-
large: "h-control-lg py-8 px-16 rounded-lg text-lg",
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const width = isStretched ? "w-full" : "w-fit-content";
|
|
94
|
-
|
|
95
|
-
const variants = {
|
|
96
|
-
primary:
|
|
97
|
-
"border-2 border-border-primary-emphasis bg-bg-primary-base text-white hover:bg-border-focus hover:text-fg-focus hover:border-border-emphasis hover:shadow-md active:bg-border-focus active:bg-bg-focus-overlay active:text-fg-focus",
|
|
98
|
-
secondary:
|
|
99
|
-
"border-2 border-border-primary-base bg-bg-base text-fg-primary-emphasis hover:shadow-md hover:bg-bg-primary-subtle active:bg-bg-primary-subtle-90",
|
|
100
|
-
bare: "bg-bg-base text-fg-primary-emphasis hover:bg-bg-minimal active:bg-bg-minimal-5",
|
|
101
|
-
dangerBare:
|
|
102
|
-
"bg-bg-base text-fg-danger-emphasis hover:bg-bg-danger-subtle active:bg-bg-danger-subtle",
|
|
103
|
-
danger:
|
|
104
|
-
"bg-bg-danger-base border-2 border-border-danger-emphasis text-white hover:bg-bg-danger-base-5 active:bg-bg-danger-base-10",
|
|
105
|
-
disabled:
|
|
106
|
-
"border-2 border-border-subtle bg-bg-inactive text-fg-inactive hover:no-underline",
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const STYLES = cx(defaults, sizes[size], width, fonts, variants[variant]);
|
|
110
|
-
|
|
111
|
-
return (
|
|
112
|
-
<button
|
|
113
|
-
role="button"
|
|
114
|
-
type="button"
|
|
115
|
-
aria-disabled={disabled}
|
|
116
|
-
disabled={disabled}
|
|
117
|
-
className={STYLES}
|
|
118
|
-
ref={ref}
|
|
119
|
-
{...props}
|
|
120
|
-
>
|
|
121
|
-
{startIcon}
|
|
122
|
-
{children ? <span>{children}</span> : null}
|
|
123
|
-
{endIcon}
|
|
124
|
-
</button>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
);
|