@kaizen/components 1.42.5 → 1.42.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaizen/components",
3
- "version": "1.42.5",
3
+ "version": "1.42.6",
4
4
  "description": "Kaizen component library",
5
5
  "author": "Geoffrey Chong <geoff.chong@cultureamp.com>",
6
6
  "homepage": "https://cultureamp.design",
@@ -1,4 +1,5 @@
1
1
  import { Canvas, Controls , Meta } from "@storybook/blocks"
2
+ import { InlineNotification } from "~components/Notification"
2
3
  import { ResourceLinks, KAIOInstallation } from "~storybook/components"
3
4
  import * as TagStories from "./Tag.stories"
4
5
 
@@ -13,6 +14,12 @@ import * as TagStories from "./Tag.stories"
13
14
  className="!mb-8"
14
15
  />
15
16
 
17
+
18
+ <InlineNotification type="cautionary" persistent>
19
+ {`This version of the Tag will soon be deprecated and will be removed in the next major release.
20
+ Import Tag from "@kaizen/components/future" for the latest version and veiw our migration guide in the Future folder` }
21
+ </InlineNotification>
22
+
16
23
  <KAIOInstallation exportNames="Tag" />
17
24
 
18
25
  ## Overview
@@ -59,7 +66,7 @@ An Avatar can be added in two ways, either by importing the `<Avatar />` compone
59
66
  <Canvas of={TagStories.ProfileWithAvatarProps} />
60
67
 
61
68
  ### Dismissable
62
- <Canvas of={TagStories.Dismissable} />
69
+ <Canvas of={TagStories.Dismissible} />
63
70
 
64
71
  ### TruncateWidth
65
72
  A pixel width which sets a limit for when the text starts to truncate.
@@ -137,7 +137,7 @@ export const ProfileWithAvatarProps: Story = {
137
137
  },
138
138
  }
139
139
 
140
- export const Dismissable: Story = {
140
+ export const Dismissible: Story = {
141
141
  args: {
142
142
  dismissible: true,
143
143
  onDismiss: () => alert("Dismissed"),
@@ -550,6 +550,25 @@ $tab-container-height-medium-and-small-collapsed: 0;
550
550
  text-decoration: underline;
551
551
  }
552
552
 
553
+ &:focus {
554
+ outline: none;
555
+
556
+ &::after {
557
+ $focus-ring-offset: calc(
558
+ (-2 * #{$border-focus-ring-border-width}) - #{$border-focus-ring-border-width}
559
+ );
560
+
561
+ content: "";
562
+ position: absolute;
563
+ background: transparent;
564
+ border-color: $color-blue-200;
565
+ border-radius: 50%;
566
+ border-width: $border-focus-ring-border-width;
567
+ border-style: $border-focus-ring-border-style;
568
+ inset: $focus-ring-offset;
569
+ }
570
+ }
571
+
553
572
  @media only screen and (max-width: $breadcrumb-breakpoint-width) {
554
573
  position: relative;
555
574
 
@@ -2,6 +2,7 @@ import React from "react"
2
2
  import { Meta, StoryObj } from "@storybook/react"
3
3
  import { assetUrl } from "@kaizen/hosted-assets"
4
4
  import { AddIcon, StarOnIcon } from "~components/Icon"
5
+ import { StickerSheet } from "~storybook/components/StickerSheet"
5
6
  import { NavigationTab, TitleBlockZen } from "../index"
6
7
 
7
8
  const SECONDARY_ACTIONS = [
@@ -97,76 +98,38 @@ export const Playground: Story = {
97
98
  },
98
99
  }
99
100
 
100
- // export const WithBadge: Story = {
101
- // render: args => {
102
- // const [badgeCount, setBadgeCount] = React.useState(1)
103
- // return (
104
- // <TitleBlockZen
105
- // {...args}
106
- // primaryAction={{
107
- // label: "Click Me",
108
- // icon: <ArrowForwardIcon role="presentation" />,
109
- // iconPosition: "end",
110
- // href: "#",
111
- // onClick: () => setBadgeCount(b => b + 1),
112
- // badge: {
113
- // text: String(badgeCount),
114
- // animateChange: true,
115
- // },
116
- // }}
117
- // defaultAction={{
118
- // label: "Default link",
119
- // onClick: () => setBadgeCount(b => b + 1),
120
- // href: "#",
121
- // }}
122
- // />
123
- // )
124
- // },
125
- // }
126
-
127
- // export const WithAvatarProps: Story = {
128
- // args: {
129
- // avatar: {
130
- // avatarSrc: assetUrl("site/empty-state.png"),
131
- // fullName: "Blanca Wheeler",
132
- // },
133
- // },
134
- // }
135
-
136
- // export const WithDefaultTag: Story = {
137
- // args: {
138
- // surveyStatus: { text: "Due July 8, 2030", status: "default" },
139
- // },
140
- // }
141
-
142
- // export const WithMenuButton: Story = {
143
- // args: {
144
- // primaryAction: {
145
- // label: "Menu button",
146
- // menuItems: [
147
- // {
148
- // action: "#",
149
- // label: "Item 1",
150
- // },
151
- // {
152
- // action: () => alert("Item 2 clicked"),
153
- // label: "Item 2",
154
- // },
155
- // {
156
- // action: "#",
157
- // label: "Item 3",
158
- // },
159
- // ],
160
- // },
161
- // },
162
- // }
163
-
164
- // export const Subtitle: Story = {
165
- // args: {
166
- // subtitle: (
167
- // <Text variant="body">
168
- // This is a <a href="/">link</a>
169
- // </Text>
170
- // ),
171
- // },
172
- // }
101
+ export const StickerSheetDefault: Story = {
102
+ parameters: {
103
+ docs: {
104
+ canvas: {
105
+ sourceState: "shown",
106
+ },
107
+ },
108
+ pseudo: {
109
+ hover: [
110
+ '#tab-hover-example [class^="TitleBlockZen-TitleBlockZen-module__navigationTabsList"] li:nth-child(2) a',
111
+ '#Breadcrumbs-hover-example [class^="TitleBlockZen-TitleBlockZen-module__breadcrumb"]',
112
+ ],
113
+ focus: [
114
+ '#tab-focus-example [class^="TitleBlockZen-TitleBlockZen-module__navigationTabsList"] li:nth-child(2) a',
115
+ '#Breadcrumbs-focus-example [class^="TitleBlockZen-TitleBlockZen-module__breadcrumb"]',
116
+ ],
117
+ },
118
+ },
119
+ render: args => (
120
+ <StickerSheet>
121
+ <StickerSheet.Row rowTitle="Tab hover">
122
+ <TitleBlockZen {...args} id="tab-hover-example" />
123
+ </StickerSheet.Row>
124
+ <StickerSheet.Row rowTitle="Tab focus">
125
+ <TitleBlockZen {...args} id="tab-focus-example" />
126
+ </StickerSheet.Row>
127
+ <StickerSheet.Row rowTitle="Breadcrumbs hover">
128
+ <TitleBlockZen {...args} id="Breadcrumbs-hover-example" />
129
+ </StickerSheet.Row>
130
+ <StickerSheet.Row rowTitle="Breadcrumbs focus">
131
+ <TitleBlockZen {...args} id="Breadcrumbs-focus-example" />
132
+ </StickerSheet.Row>
133
+ </StickerSheet>
134
+ ),
135
+ }
@@ -59,13 +59,16 @@
59
59
  margin: 0;
60
60
  }
61
61
 
62
- &.active {
62
+ $active-tab-marker-height: 5px;
63
+
64
+ &.active,
65
+ &:focus {
63
66
  color: $color-white;
64
67
 
65
68
  &::before {
66
69
  content: "";
67
70
  display: block;
68
- height: 5px;
71
+ height: $active-tab-marker-height;
69
72
  position: absolute;
70
73
  top: 0;
71
74
  left: 0;
@@ -82,6 +85,34 @@
82
85
  }
83
86
  }
84
87
  }
88
+
89
+ &:focus {
90
+ outline: none;
91
+
92
+ &::before {
93
+ background-color: $color-blue-200;
94
+ }
95
+
96
+ &::after {
97
+ $focus-ring-offset: calc((-1 * #{$border-focus-ring-border-width}));
98
+
99
+ content: "";
100
+ position: absolute;
101
+ background: transparent;
102
+ border-color: $color-blue-200;
103
+ border-radius: 0 0 $border-focus-ring-border-radius
104
+ $border-focus-ring-border-radius;
105
+ border-width: $border-focus-ring-border-width;
106
+ border-style: $border-focus-ring-border-style;
107
+ inset: 0 $focus-ring-offset $active-tab-marker-height $focus-ring-offset;
108
+
109
+ @include title-block-medium-and-small {
110
+ border-radius: $border-focus-ring-border-radius
111
+ $border-focus-ring-border-radius 0 0;
112
+ inset: $active-tab-marker-height $focus-ring-offset 0 $focus-ring-offset;
113
+ }
114
+ }
115
+ }
85
116
  }
86
117
 
87
118
  .linkAnchor.lightBackground {
@@ -0,0 +1,172 @@
1
+ import { Canvas, Meta } from "@storybook/blocks"
2
+ import * as LegacyTagStories from "../../../../Tag/_docs/Tag.stories"
3
+ import * as TagMigrationStories from "./Tag-migration-guide.stories"
4
+
5
+ <Meta of={TagMigrationStories} />
6
+
7
+ # Future Tag migration guide
8
+
9
+ A brief guide on how and why to migrate from Kaizen's current `Tag` to the `future` release.
10
+
11
+ ## Why the change?
12
+
13
+ Tag was rebuilt to allow for greater composability as the number of cases for a distinct Tags could not be solved through the use of `variant` without impacting the developer experience for existing users. The flexibility of `Tag` content as `children` also addresses several accessibility issues that the original could not solve intuitively.
14
+
15
+ ## Component and API changes at a glance
16
+
17
+ There were a number key changes between current and future `Tag` to achieve the flexibility we were aiming to provide, we've listed these below but also go into further detail in the [migration examples](/docs/components-tag-future-migration-guide--migrationguide#migration-examples).
18
+
19
+ - `variant` prop has been removed
20
+ - This has been superseded by a combination of the `color` and `icon` prop
21
+ - `inline` prop and the default `margin` on all Tags has been removed.
22
+ - This can be directly controlled through `classNameOverride` or a `flex-gap` on the container.
23
+ - `size` has been removed and all tags are the same size.
24
+ - `truncationWidth` has been removed as child content.
25
+ - `dismissible` prop has been removed.
26
+ - A `DismissibleTag` component is now available in its place.
27
+ - `Avatar` and all child content must now be composed by the consumer.
28
+ - This offers a greater degree of flexibility to ensure that the right accessible context can be provided to the end user.
29
+
30
+
31
+ ## Migration examples
32
+
33
+ The following are example of migrating from previously available props to the composable solution.
34
+
35
+ ### Status
36
+
37
+ With the `variant` prop there are four values associated with statuses: `statusLive`, `statusDraft`, `statusClosed`, `statusAction`.
38
+
39
+ For the most part these can all be replaced with the use of the `color` prop, with exception to the `live` status.
40
+
41
+ #### Before
42
+
43
+ <Canvas of={LegacyTagStories.Status} />
44
+
45
+
46
+ #### After
47
+
48
+ <Canvas of={TagMigrationStories.StatusMigration} sourceState="shown"/>
49
+
50
+ While the `LiveIcon` is exported from `@kaizen/components` the current `Tag` uses an animated implementation, which is not exported directly from Kaizen. As an interim solution, you can use the following Story's code snippet to create a `LiveIconComponent`. This can then be passed into the future `Tag` as `Children`.
51
+
52
+ <Canvas of={TagMigrationStories.LiveIconComponentStory} sourceState="hidden"/>
53
+
54
+ ### Validation
55
+
56
+ Following the same pattern as status, `validationPositive`, `validationInformative`, `validationNegative`, `validationCautionary` can all be replace with the `color` and `icon` prop.
57
+
58
+ Note: because the icons convey meaning, they should have an accessible label that provides context to the `Tag`. A contextual `aria-label` and role of `img` addresses one of the [accessibility issues](https://github.com/cultureamp/kaizen-discourse/issues/102) with the current `Tag`.
59
+
60
+ #### Before
61
+
62
+ <Canvas of={LegacyTagStories.Validation} />
63
+
64
+ #### After
65
+
66
+ <Canvas of={TagMigrationStories.ValidationMigration} sourceState="shown"/>
67
+
68
+
69
+ Note: When using the `icon` prop, the icon's color will be determined by the `color` value that has been set. This is to ensure that an accessible contrast ratio is achieved.
70
+
71
+ Any Icons added as a child of future `Tag` will need to set their own colors and ensure the right contrast ratio is achieved.
72
+
73
+ ### Sentiment
74
+
75
+ While migration of any `Tag` using, `sentimentPositive`, `sentimentNeutral` or `sentimentNegative` is relatively straight forward using the `color` prop, `sentimentNone` does not align to any Kaizen's [semantic colors](https://cultureamp.atlassian.net/wiki/spaces/DesignSystem/pages/3064857902/Color).
76
+
77
+ #### Before
78
+
79
+ <Canvas of={LegacyTagStories.Sentiments} />
80
+
81
+ #### After
82
+
83
+ <Canvas of={TagMigrationStories.SentimentsMigration} sourceState="shown"/>
84
+
85
+ If required, you could use `classNameOverride` to implement the same UI. It is important that any override of the default styles still meets minimum contrast ratios to ensure the component is accessible.
86
+
87
+ <Canvas of={TagMigrationStories.SentimentNone} />
88
+
89
+ This is also a good time to stop and check if this change is necessary. If there is an opportunity remove older styles that are no longer available, this can help to reduce inconsistencies across the platform. As always, check in with your designer to see if any new option can be used in its place.
90
+
91
+
92
+ ### Dismissible
93
+
94
+ The `dismissible` prop is no longer available in the future `Tag` component. We have split the dismissible functionality into the [RemovableTag](/docs/components-tag-future-removabletag--docs).
95
+
96
+ This increases the hit box for the dismiss button and makes the `ariaLabel` in the `removeButtonProps` a required prop. This offers a more accessible experience for user and address one of the standing [accessibility issues](https://github.com/cultureamp/kaizen-discourse/issues/101) with the legacy `Tag`.
97
+
98
+ #### Before
99
+
100
+ <Canvas of={LegacyTagStories.Dismissible} />
101
+
102
+ #### After
103
+
104
+ <Canvas of={TagMigrationStories.DismissibleMigration} sourceState="shown"/>
105
+
106
+ Remember that when handling dismiss (or any destructive action), a user's focus should not be lost on the page.
107
+
108
+
109
+ ### Avatars
110
+
111
+ Avatars are no longer provided directly to the `Tag` as a prop. Instead they will be passed in as children.
112
+
113
+ #### Before
114
+
115
+ <Canvas of={LegacyTagStories.ProfileWithAvatarProps} />
116
+
117
+ #### After
118
+
119
+ <Canvas of={TagMigrationStories.AvatarMigration} sourceState="shown"/>
120
+
121
+
122
+ Note: The use of `ps-4` (or `padding-inline-start`) in the `classNameOverride` is to override the default spacing at start of the `Tag`. This will ensure the Avatar can contour the border radius of the `Tag`.
123
+
124
+ #### Dismissible Avatars
125
+
126
+ Following a similar pattern to the above, you can use the `RemovableTag` with an `Avatar` and plain text as its `children` to achieve a dismissible version.
127
+
128
+ <Canvas of={TagMigrationStories.AvatarRemovableMigration} />
129
+
130
+ ### Inline
131
+
132
+ Originally the `Tag` was built with the assumption that it would always required spacing at the end. This necessitated the need for the `inline` prop to remove the margin from end when it was not required.
133
+
134
+ In future `Tag` this has been removed so consumers can now control spacing with CSS properties like `gap` or `margin-inline`.
135
+
136
+ #### Before
137
+
138
+ <Canvas of={LegacyTagStories.Inline} />
139
+
140
+ #### After
141
+
142
+ <Canvas of={TagMigrationStories.InlineMigration} sourceState="shown"/>
143
+
144
+ To simplify this example we have avoided DOM elements such as `ul` and `li`. In production, lists should be used if you are rendering a group of `Tag`s.
145
+
146
+
147
+ ### truncationWidth
148
+
149
+ While the current Tag controls truncation via the `truncationWidth` prop, which set a `max-width` of inner text via inline styles, we have chosen not to adopt this in the future `Tag` as it presents a risk of violating accessibility standards. While truncation can still be achieved in future `Tag` via Tailwind or DOM manipulation, it is important to call out out this as a accessibility concern.
150
+
151
+ #### Before
152
+
153
+ <Canvas of={LegacyTagStories.Truncate} />
154
+
155
+ Where truncation often fails WCAG's success criteria is in [1.4.4](https://www.w3.org/WAI/WCAG21/Techniques/failures/F69) or [1.3.1](https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html). The crux of the issue is that removing content with an ellipsis may lead to a loss of context for visual users. While `aria` labels can support those that use assistive technologies, they are not enough to resolve this issue for sighted users.
156
+
157
+ The recommendation from WCAG is that any truncated content comes with the functionality to visually revealing its full content. This can be accessible either via focus or some form of activation - like an `onClick` to reveal. Based on this, our recommendation is to avoid truncation unless necessary.
158
+
159
+ ### Size
160
+
161
+ The two sizes for tag have been remove in favour of a default size in between `medium` and `small`. The `small` specifically was removed due to the reduced hit radius for the dismissible button and poor compatibility with avatars and icon.
162
+
163
+ `classNameOverride` can be leveraged to add padding and modify properties but should be done with caution to reduce inconsistencies in the platform and reduce the risk of accessibility violations.
164
+
165
+
166
+ #### Before
167
+
168
+ <Canvas of={LegacyTagStories.Sizes} />
169
+
170
+ #### After
171
+
172
+ <Canvas of={TagMigrationStories.SizesMigration} sourceState="shown"/>