@kaizen/components 0.0.0-canary-link-button-wip-canary-20241121010628 → 0.0.0-canary-link-button-wip-canary-20241121043208
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/dist/cjs/__actions__/LinkButton/v3/LinkButton.cjs +56 -0
- package/dist/cjs/__actions__/LinkButton/v3/LinkButton.module.css.cjs +6 -0
- package/dist/cjs/actionsV3.cjs +2 -0
- package/dist/esm/__actions__/LinkButton/v3/LinkButton.mjs +47 -0
- package/dist/esm/__actions__/LinkButton/v3/LinkButton.module.css.mjs +4 -0
- package/dist/esm/actionsV3.mjs +1 -0
- package/dist/styles.css +5 -0
- package/dist/types/__actions__/v3.d.ts +1 -0
- package/package.json +3 -3
- package/src/__actions__/LinkButton/v3/LinkButton.tsx +1 -0
- package/src/__actions__/LinkButton/v3/_docs/LinkButton--api-specification.mdx +10 -0
- package/src/__actions__/LinkButton/v3/_docs/LinkButton.doc.stories.tsx +16 -15
- package/src/__actions__/LinkButton/v3/_docs/LinkButton.stickersheet.stories.tsx +176 -0
- package/src/__actions__/v3.ts +1 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib = require('tslib');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var reactAriaComponents = require('react-aria-components');
|
|
6
|
+
var buttonStyles = require('~components/__actions__/Button/v3/Button.module.css');
|
|
7
|
+
require('classnames');
|
|
8
|
+
require('../../../Loading/LoadingGraphic/LoadingGraphic.cjs');
|
|
9
|
+
require('../../../Loading/LoadingHeading/LoadingHeading.cjs');
|
|
10
|
+
require('../../../Loading/LoadingInput/LoadingInput.cjs');
|
|
11
|
+
require('../../../Loading/LoadingParagraph/LoadingParagraph.cjs');
|
|
12
|
+
require('../../../Loading/LoadingSpinner/LoadingSpinner.cjs');
|
|
13
|
+
require('../../../VisuallyHidden/VisuallyHidden.cjs');
|
|
14
|
+
var ButtonContent = require('../../Button/v3/subcomponents/ButtonContent/ButtonContent.cjs');
|
|
15
|
+
var mergeClassNames = require('../../../utils/mergeClassNames.cjs');
|
|
16
|
+
var LinkButton_module = require('./LinkButton.module.css.cjs');
|
|
17
|
+
var ReversedColors = require('../../../__utilities__/ReversedColors/v3/ReversedColors.cjs');
|
|
18
|
+
function _interopDefault(e) {
|
|
19
|
+
return e && e.__esModule ? e : {
|
|
20
|
+
default: e
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
24
|
+
var buttonStyles__default = /*#__PURE__*/_interopDefault(buttonStyles);
|
|
25
|
+
var LinkButton = React.forwardRef(function (_a, ref) {
|
|
26
|
+
var children = _a.children,
|
|
27
|
+
_b = _a.variant,
|
|
28
|
+
variant = _b === void 0 ? "primary" : _b,
|
|
29
|
+
_c = _a.size,
|
|
30
|
+
size = _c === void 0 ? "medium" : _c,
|
|
31
|
+
icon = _a.icon,
|
|
32
|
+
_d = _a.iconPosition,
|
|
33
|
+
iconPosition = _d === void 0 ? "start" : _d,
|
|
34
|
+
_e = _a.hasHiddenLabel,
|
|
35
|
+
hasHiddenLabel = _e === void 0 ? false : _e,
|
|
36
|
+
_f = _a.isFullWidth,
|
|
37
|
+
isFullWidth = _f === void 0 ? false : _f,
|
|
38
|
+
isDisabled = _a.isDisabled,
|
|
39
|
+
className = _a.className,
|
|
40
|
+
otherProps = tslib.__rest(_a, ["children", "variant", "size", "icon", "iconPosition", "hasHiddenLabel", "isFullWidth", "isDisabled", "className"]);
|
|
41
|
+
var isReversed = ReversedColors.useReversedColors();
|
|
42
|
+
return React__default.default.createElement(reactAriaComponents.Link, tslib.__assign({
|
|
43
|
+
ref: ref,
|
|
44
|
+
className: mergeClassNames.mergeClassNames(LinkButton_module.linkButton, buttonStyles__default.default.button, buttonStyles__default.default[size], hasHiddenLabel && buttonStyles__default.default["".concat(size, "IconButton")], isDisabled && buttonStyles__default.default.isDisabled, isReversed ? buttonStyles__default.default["".concat(variant, "Reversed")] : buttonStyles__default.default[variant], isFullWidth && buttonStyles__default.default.fullWidth, className),
|
|
45
|
+
isDisabled: isDisabled
|
|
46
|
+
}, otherProps), function (racStateProps) {
|
|
47
|
+
var childIsFunction = typeof children === "function";
|
|
48
|
+
return React__default.default.createElement(ButtonContent.ButtonContent, {
|
|
49
|
+
size: size,
|
|
50
|
+
icon: icon,
|
|
51
|
+
iconPosition: iconPosition,
|
|
52
|
+
hasHiddenLabel: hasHiddenLabel
|
|
53
|
+
}, childIsFunction ? children(racStateProps) : children);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
exports.LinkButton = LinkButton;
|
package/dist/cjs/actionsV3.cjs
CHANGED
|
@@ -4,7 +4,9 @@ var Menu = require('./__actions__/Menu/v3/Menu.cjs');
|
|
|
4
4
|
var MenuItem = require('./__actions__/Menu/v3/MenuItem.cjs');
|
|
5
5
|
var MenuTrigger = require('./__actions__/Menu/v3/MenuTrigger.cjs');
|
|
6
6
|
var Button = require('./__actions__/Button/v3/Button.cjs');
|
|
7
|
+
var LinkButton = require('./__actions__/LinkButton/v3/LinkButton.cjs');
|
|
7
8
|
exports.Menu = Menu.Menu;
|
|
8
9
|
exports.MenuItem = MenuItem.MenuItem;
|
|
9
10
|
exports.MenuTrigger = MenuTrigger.MenuTrigger;
|
|
10
11
|
exports.Button = Button.Button;
|
|
12
|
+
exports.LinkButton = LinkButton.LinkButton;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { __rest, __assign } from 'tslib';
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import { Link } from 'react-aria-components';
|
|
4
|
+
import buttonStyles from '~components/__actions__/Button/v3/Button.module.css';
|
|
5
|
+
import 'classnames';
|
|
6
|
+
import '../../../Loading/LoadingGraphic/LoadingGraphic.mjs';
|
|
7
|
+
import '../../../Loading/LoadingHeading/LoadingHeading.mjs';
|
|
8
|
+
import '../../../Loading/LoadingInput/LoadingInput.mjs';
|
|
9
|
+
import '../../../Loading/LoadingParagraph/LoadingParagraph.mjs';
|
|
10
|
+
import '../../../Loading/LoadingSpinner/LoadingSpinner.mjs';
|
|
11
|
+
import '../../../VisuallyHidden/VisuallyHidden.mjs';
|
|
12
|
+
import { ButtonContent } from '../../Button/v3/subcomponents/ButtonContent/ButtonContent.mjs';
|
|
13
|
+
import { mergeClassNames } from '../../../utils/mergeClassNames.mjs';
|
|
14
|
+
import styles from './LinkButton.module.css.mjs';
|
|
15
|
+
import { useReversedColors } from '../../../__utilities__/ReversedColors/v3/ReversedColors.mjs';
|
|
16
|
+
var LinkButton = /*#__PURE__*/forwardRef(function (_a, ref) {
|
|
17
|
+
var children = _a.children,
|
|
18
|
+
_b = _a.variant,
|
|
19
|
+
variant = _b === void 0 ? "primary" : _b,
|
|
20
|
+
_c = _a.size,
|
|
21
|
+
size = _c === void 0 ? "medium" : _c,
|
|
22
|
+
icon = _a.icon,
|
|
23
|
+
_d = _a.iconPosition,
|
|
24
|
+
iconPosition = _d === void 0 ? "start" : _d,
|
|
25
|
+
_e = _a.hasHiddenLabel,
|
|
26
|
+
hasHiddenLabel = _e === void 0 ? false : _e,
|
|
27
|
+
_f = _a.isFullWidth,
|
|
28
|
+
isFullWidth = _f === void 0 ? false : _f,
|
|
29
|
+
isDisabled = _a.isDisabled,
|
|
30
|
+
className = _a.className,
|
|
31
|
+
otherProps = __rest(_a, ["children", "variant", "size", "icon", "iconPosition", "hasHiddenLabel", "isFullWidth", "isDisabled", "className"]);
|
|
32
|
+
var isReversed = useReversedColors();
|
|
33
|
+
return /*#__PURE__*/React.createElement(Link, __assign({
|
|
34
|
+
ref: ref,
|
|
35
|
+
className: mergeClassNames(styles.linkButton, buttonStyles.button, buttonStyles[size], hasHiddenLabel && buttonStyles["".concat(size, "IconButton")], isDisabled && buttonStyles.isDisabled, isReversed ? buttonStyles["".concat(variant, "Reversed")] : buttonStyles[variant], isFullWidth && buttonStyles.fullWidth, className),
|
|
36
|
+
isDisabled: isDisabled
|
|
37
|
+
}, otherProps), function (racStateProps) {
|
|
38
|
+
var childIsFunction = typeof children === "function";
|
|
39
|
+
return /*#__PURE__*/React.createElement(ButtonContent, {
|
|
40
|
+
size: size,
|
|
41
|
+
icon: icon,
|
|
42
|
+
iconPosition: iconPosition,
|
|
43
|
+
hasHiddenLabel: hasHiddenLabel
|
|
44
|
+
}, childIsFunction ? children(racStateProps) : children);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
export { LinkButton };
|
package/dist/esm/actionsV3.mjs
CHANGED
|
@@ -2,3 +2,4 @@ export { Menu } from './__actions__/Menu/v3/Menu.mjs';
|
|
|
2
2
|
export { MenuItem } from './__actions__/Menu/v3/MenuItem.mjs';
|
|
3
3
|
export { MenuTrigger } from './__actions__/Menu/v3/MenuTrigger.mjs';
|
|
4
4
|
export { Button } from './__actions__/Button/v3/Button.mjs';
|
|
5
|
+
export { LinkButton } from './__actions__/LinkButton/v3/LinkButton.mjs';
|
package/dist/styles.css
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaizen/components",
|
|
3
|
-
"version": "0.0.0-canary-link-button-wip-canary-
|
|
3
|
+
"version": "0.0.0-canary-link-button-wip-canary-20241121043208",
|
|
4
4
|
"description": "Kaizen component library",
|
|
5
5
|
"author": "Geoffrey Chong <geoff.chong@cultureamp.com>",
|
|
6
6
|
"homepage": "https://cultureamp.design",
|
|
@@ -118,8 +118,8 @@
|
|
|
118
118
|
"svgo": "^3.3.2",
|
|
119
119
|
"tslib": "^2.8.0",
|
|
120
120
|
"tsx": "^4.19.2",
|
|
121
|
-
"@kaizen/
|
|
122
|
-
"@kaizen/
|
|
121
|
+
"@kaizen/package-bundler": "2.0.1",
|
|
122
|
+
"@kaizen/design-tokens": "10.8.4"
|
|
123
123
|
},
|
|
124
124
|
"devDependenciesComments": {
|
|
125
125
|
"sass": "Prevent deprecation warnings introduced in 1.80 as we plan to move away from sass",
|
|
@@ -103,6 +103,16 @@ function ReactRouterApp() {
|
|
|
103
103
|
|
|
104
104
|
Additional notes can be found in the React Aria's documentation on the using the `RouterProvider` with [React Router](https://react-spectrum.adobe.com/react-aria/routing.html#react-router).
|
|
105
105
|
|
|
106
|
+
### Target `_blank` and opening in a new tab
|
|
107
|
+
|
|
108
|
+
The general recommendation is to limit the number of links that open in a new tab or window on a page. While there are valid scenarios that help avoid loss of data and or progress on a page, opening a new tab or window can be disorienting for users, especially those who have difficulty perceiving visual content.
|
|
109
|
+
|
|
110
|
+
In order to provide advance warning to all users, it is recommended that `LinkButton`'s that use `target="_blank"` be accompanied by a visual indicator and audible warning, as in the example below.
|
|
111
|
+
|
|
112
|
+
<Canvas of={exampleStories.LinkButtonOpensInNewTab} />
|
|
113
|
+
|
|
114
|
+
You can get more context on this recommendation via the [W3C page on the G200 success criteria](https://www.w3.org/TR/WCAG20-TECHS/G200.html).
|
|
115
|
+
|
|
106
116
|
### Variants
|
|
107
117
|
|
|
108
118
|
`LinkButton` supports the following variants: `primary`, `secondary` and `tertiary`. If the `variant` prop is not specified, the default will be `primary`.
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from "react"
|
|
2
|
-
// import { action } from "@storybook/addon-actions"
|
|
3
2
|
import { Meta, StoryObj } from "@storybook/react"
|
|
4
|
-
import {
|
|
3
|
+
import { VisuallyHidden } from "~components/VisuallyHidden"
|
|
5
4
|
import { Icon } from "~components/__future__"
|
|
6
5
|
import { ReversedColors } from "~components/__utilities__/v3"
|
|
7
6
|
import { LinkButton } from "../index"
|
|
@@ -22,6 +21,21 @@ type Story = StoryObj<typeof meta>
|
|
|
22
21
|
|
|
23
22
|
export const Playground: Story = {}
|
|
24
23
|
|
|
24
|
+
export const LinkButtonOpensInNewTab: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
children: (
|
|
27
|
+
<>
|
|
28
|
+
Label
|
|
29
|
+
<VisuallyHidden> opens a new tab</VisuallyHidden>
|
|
30
|
+
</>
|
|
31
|
+
),
|
|
32
|
+
href: "https://www.google.com",
|
|
33
|
+
target: "_blank",
|
|
34
|
+
icon: <Icon isPresentational name="open_in_new" shouldMirrorInRTL />,
|
|
35
|
+
iconPosition: "end",
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
export const LinkButtonVariants: Story = {
|
|
26
40
|
render: args => (
|
|
27
41
|
<>
|
|
@@ -116,16 +130,3 @@ export const LinkButtonFullWidth: Story = {
|
|
|
116
130
|
isFullWidth: true,
|
|
117
131
|
},
|
|
118
132
|
}
|
|
119
|
-
|
|
120
|
-
export const LinkButtonWithBadge: Story = {
|
|
121
|
-
args: {
|
|
122
|
-
children: (
|
|
123
|
-
<>
|
|
124
|
-
Label
|
|
125
|
-
<Badge classNameOverride="ms-8" size="small">
|
|
126
|
-
3
|
|
127
|
-
</Badge>
|
|
128
|
-
</>
|
|
129
|
-
),
|
|
130
|
-
},
|
|
131
|
-
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import React from "react"
|
|
2
|
+
import { Meta } from "@storybook/react"
|
|
3
|
+
import { within } from "@storybook/test"
|
|
4
|
+
import { Icon } from "~components/__future__/Icon"
|
|
5
|
+
import {
|
|
6
|
+
StickerSheet,
|
|
7
|
+
StickerSheetStory,
|
|
8
|
+
} from "~storybook/components/StickerSheet"
|
|
9
|
+
import { LinkButton, LinkButtonProps } from "../index"
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
title: "Actions/LinkButton/LinkButton (v3)",
|
|
13
|
+
parameters: {
|
|
14
|
+
chromatic: { disable: false },
|
|
15
|
+
controls: { disable: true },
|
|
16
|
+
},
|
|
17
|
+
} satisfies Meta
|
|
18
|
+
|
|
19
|
+
const variants = ["primary", "secondary", "tertiary"] satisfies Array<
|
|
20
|
+
LinkButtonProps["variant"]
|
|
21
|
+
>
|
|
22
|
+
const sizes = ["small", "medium", "large"] satisfies Array<
|
|
23
|
+
LinkButtonProps["size"]
|
|
24
|
+
>
|
|
25
|
+
|
|
26
|
+
const RowTemplate = ({
|
|
27
|
+
isReversed = false,
|
|
28
|
+
}: {
|
|
29
|
+
isReversed?: boolean
|
|
30
|
+
}): JSX.Element => (
|
|
31
|
+
<>
|
|
32
|
+
{variants.map(variant =>
|
|
33
|
+
sizes.map(size => (
|
|
34
|
+
<StickerSheet.Row
|
|
35
|
+
key={size + variant}
|
|
36
|
+
isReversed={isReversed}
|
|
37
|
+
rowTitle={`${variant} (${size})`}
|
|
38
|
+
>
|
|
39
|
+
<LinkButton variant={variant} size={size}>
|
|
40
|
+
Label
|
|
41
|
+
</LinkButton>
|
|
42
|
+
<LinkButton
|
|
43
|
+
icon={<Icon name="add" isPresentational />}
|
|
44
|
+
variant={variant}
|
|
45
|
+
size={size}
|
|
46
|
+
>
|
|
47
|
+
Label
|
|
48
|
+
</LinkButton>
|
|
49
|
+
<LinkButton
|
|
50
|
+
icon={
|
|
51
|
+
<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />
|
|
52
|
+
}
|
|
53
|
+
iconPosition="end"
|
|
54
|
+
variant={variant}
|
|
55
|
+
size={size}
|
|
56
|
+
>
|
|
57
|
+
Label
|
|
58
|
+
</LinkButton>
|
|
59
|
+
<LinkButton
|
|
60
|
+
icon={<Icon name="delete" isPresentational />}
|
|
61
|
+
variant={variant}
|
|
62
|
+
hasHiddenLabel
|
|
63
|
+
size={size}
|
|
64
|
+
>
|
|
65
|
+
Label
|
|
66
|
+
</LinkButton>
|
|
67
|
+
<LinkButton
|
|
68
|
+
icon={
|
|
69
|
+
<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />
|
|
70
|
+
}
|
|
71
|
+
iconPosition="end"
|
|
72
|
+
variant={variant}
|
|
73
|
+
size={size}
|
|
74
|
+
isDisabled
|
|
75
|
+
>
|
|
76
|
+
Label
|
|
77
|
+
</LinkButton>
|
|
78
|
+
</StickerSheet.Row>
|
|
79
|
+
))
|
|
80
|
+
)}
|
|
81
|
+
</>
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
const StickerSheetTemplate: StickerSheetStory = {
|
|
85
|
+
render: ({ isReversed }) => (
|
|
86
|
+
<>
|
|
87
|
+
<StickerSheet heading="Button" isReversed={isReversed}>
|
|
88
|
+
<StickerSheet.Header
|
|
89
|
+
headings={[
|
|
90
|
+
"Base",
|
|
91
|
+
"Icon start",
|
|
92
|
+
"Icon end",
|
|
93
|
+
"hasHiddenLabel",
|
|
94
|
+
"isDisabled",
|
|
95
|
+
]}
|
|
96
|
+
headingsWidth="10rem"
|
|
97
|
+
hasVerticalHeadings
|
|
98
|
+
verticalHeadingsWidth="12rem"
|
|
99
|
+
/>
|
|
100
|
+
<StickerSheet.Body>
|
|
101
|
+
<RowTemplate isReversed={isReversed} />
|
|
102
|
+
</StickerSheet.Body>
|
|
103
|
+
</StickerSheet>
|
|
104
|
+
<StickerSheet heading="Pseudo states" isReversed={isReversed}>
|
|
105
|
+
<StickerSheet.Header
|
|
106
|
+
headings={["isHovered", "isFocusVisible", "isPressed"]}
|
|
107
|
+
headingsWidth="10rem"
|
|
108
|
+
hasVerticalHeadings
|
|
109
|
+
verticalHeadingsWidth="12rem"
|
|
110
|
+
/>
|
|
111
|
+
<StickerSheet.Body>
|
|
112
|
+
{variants.map(variant => (
|
|
113
|
+
<StickerSheet.Row
|
|
114
|
+
key={variant}
|
|
115
|
+
isReversed={isReversed}
|
|
116
|
+
rowTitle={variant}
|
|
117
|
+
>
|
|
118
|
+
<LinkButton data-testid="testid__button-hover" variant={variant}>
|
|
119
|
+
Label
|
|
120
|
+
</LinkButton>
|
|
121
|
+
<LinkButton data-testid="testid__button-focus" variant={variant}>
|
|
122
|
+
Label
|
|
123
|
+
</LinkButton>
|
|
124
|
+
<LinkButton
|
|
125
|
+
data-testid="testid__button-pressed"
|
|
126
|
+
variant={variant}
|
|
127
|
+
>
|
|
128
|
+
Label
|
|
129
|
+
</LinkButton>
|
|
130
|
+
</StickerSheet.Row>
|
|
131
|
+
))}
|
|
132
|
+
</StickerSheet.Body>
|
|
133
|
+
</StickerSheet>
|
|
134
|
+
</>
|
|
135
|
+
),
|
|
136
|
+
play: ({ canvasElement }) => {
|
|
137
|
+
const canvas = within(canvasElement)
|
|
138
|
+
const focusButtons = canvas.getAllByTestId("testid__button-focus")
|
|
139
|
+
const hoverButtons = canvas.getAllByTestId("testid__button-hover")
|
|
140
|
+
const pressedButton = canvas.getAllByTestId("testid__button-pressed")
|
|
141
|
+
|
|
142
|
+
focusButtons.forEach(button => {
|
|
143
|
+
button.setAttribute("data-focus-visible", "true")
|
|
144
|
+
})
|
|
145
|
+
hoverButtons.forEach(button => {
|
|
146
|
+
button.setAttribute("data-hovered", "true")
|
|
147
|
+
})
|
|
148
|
+
pressedButton.forEach(button => {
|
|
149
|
+
button.setAttribute("data-pressed", "true")
|
|
150
|
+
})
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export const StickerSheetDefault: StickerSheetStory = {
|
|
155
|
+
...StickerSheetTemplate,
|
|
156
|
+
name: "Sticker Sheet (Default)",
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const StickerSheetRTL: StickerSheetStory = {
|
|
160
|
+
...StickerSheetTemplate,
|
|
161
|
+
name: "Sticker Sheet (RTL)",
|
|
162
|
+
parameters: {
|
|
163
|
+
textDirection: "rtl",
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export const StickerSheetReversed: StickerSheetStory = {
|
|
168
|
+
...StickerSheetTemplate,
|
|
169
|
+
name: "Sticker Sheet (Reversed)",
|
|
170
|
+
parameters: {
|
|
171
|
+
reverseColors: true,
|
|
172
|
+
},
|
|
173
|
+
args: {
|
|
174
|
+
isReversed: true,
|
|
175
|
+
},
|
|
176
|
+
}
|
package/src/__actions__/v3.ts
CHANGED