@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.
@@ -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;
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var styles = {
4
+ "linkButton": "LinkButton-module_linkButton__1kdGO"
5
+ };
6
+ module.exports = styles;
@@ -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 };
@@ -0,0 +1,4 @@
1
+ var styles = {
2
+ "linkButton": "LinkButton-module_linkButton__1kdGO"
3
+ };
4
+ export { styles as default };
@@ -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
@@ -308,6 +308,11 @@
308
308
  visibility: hidden;
309
309
  }
310
310
 
311
+ .LinkButton-module_linkButton__1kdGO {
312
+ /* Reset */
313
+ text-decoration: inherit;
314
+ }
315
+
311
316
  .PendingContent-module_pendingContent__c4IFS {
312
317
  display: inline-flex;
313
318
  align-items: center;
@@ -1,2 +1,3 @@
1
1
  export * from "./Menu/v3";
2
2
  export * from "./Button/v3";
3
+ export * from "./LinkButton/v3";
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-20241121010628",
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/design-tokens": "10.8.4",
122
- "@kaizen/package-bundler": "2.0.1"
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",
@@ -49,6 +49,7 @@ export const LinkButton = forwardRef(
49
49
  isFullWidth && buttonStyles.fullWidth,
50
50
  className
51
51
  )}
52
+ isDisabled={isDisabled}
52
53
  {...otherProps}
53
54
  >
54
55
  {racStateProps => {
@@ -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 { Badge } from "~components/Badge"
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
+ }
@@ -1,2 +1,3 @@
1
1
  export * from "./Menu/v3"
2
2
  export * from "./Button/v3"
3
+ export * from "./LinkButton/v3"