From 24e497d4fb60173d89855ba6aa351ed11d87e579 Mon Sep 17 00:00:00 2001 From: JakePitman Date: Tue, 24 Oct 2023 15:01:47 +1300 Subject: [PATCH] Kds 1780 tag dismiss button (#4131) * Add RemoveableTag component * Make ClearIcon regular sized, with comment * Add mdx file * Make Playground add/remove tags * Lint fixes * Replace ClearIcon with ClearButton * Add changeset * Add RemoveButton * Add hover state and adjust focus ring * Remove reversed support * Add hover colors * Add purple color to close icon * Use color tokens * Lint fixes * Move to subcomponents folder * TMP: Rename subcomponents * Rename subcomponents to lowercase * Type colors * Define RemoveButtonBaseProps * Remove unnecessary types * Use restProps instead of icon prop * Spread removeButtonProps * Fix RemoveableTag src code path * Fix path * Make uppercase * Remove ability to add/remove tags * Replace StoryObj with Story * Change section to * Add hover styles on focus-visible as well * Add RemoveTagIcon * Export RemoveableTag from index * Remove design guidelines * Rename to American spelling * Fix Title path * Restructure Tag folder * Lint fixes * Use larger frame for remove icon * Add icon mapping to Playground * Clean up code preview Co-authored-by: Geoffrey Chong * Remove unnecessary back ticks * Fix typo Co-authored-by: Geoffrey Chong * Remove nesting * Add stickersheet with pseudo states * Add rtl stickersheet * Fix rtl padding issue * Update changeset description * Lint fixes * Move restProps after color * Comment out colors * Remove nesting * Fix color issue * Add focus state, and remove icon support * Lint fix * Add focus styles * Lint fix * Remove color and icon from api docs --------- Co-authored-by: Geoffrey Chong --- .changeset/hungry-frogs-end.md | 5 + .../Tag/RemovableTag/RemovableTag.module.scss | 8 ++ .../Tag/RemovableTag/RemovableTag.tsx | 36 ++++++ .../Tag/RemovableTag/_docs/RemovableTag.mdx | 57 +++++++++ .../RemovableTag.stickersheet.stories.tsx | 93 ++++++++++++++ .../_docs/RemovableTag.stories.tsx | 115 ++++++++++++++++++ .../src/__future__/Tag/RemovableTag/index.ts | 1 + .../subcomponents/RemoveButton.module.scss | 102 ++++++++++++++++ .../subcomponents/RemoveButton.tsx | 44 +++++++ .../subcomponents/RemoveTagIcon.tsx | 20 +++ .../__future__/Tag/{ => Tag}/Tag.module.scss | 0 .../src/__future__/Tag/{ => Tag}/Tag.tsx | 6 +- .../__future__/Tag/{ => Tag}/_docs/Tag.mdx | 0 .../_docs/Tag.stickersheet.stories.tsx | 0 .../Tag/{ => Tag}/_docs/Tag.stories.tsx | 0 .../src/__future__/Tag/Tag/index.ts | 1 + .../src/__future__/Tag/{ => Tag}/types.ts | 0 .../components/src/__future__/Tag/index.ts | 1 + 18 files changed, 488 insertions(+), 1 deletion(-) create mode 100644 .changeset/hungry-frogs-end.md create mode 100644 packages/components/src/__future__/Tag/RemovableTag/RemovableTag.module.scss create mode 100644 packages/components/src/__future__/Tag/RemovableTag/RemovableTag.tsx create mode 100644 packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.mdx create mode 100644 packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stickersheet.stories.tsx create mode 100644 packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stories.tsx create mode 100644 packages/components/src/__future__/Tag/RemovableTag/index.ts create mode 100644 packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.module.scss create mode 100644 packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.tsx create mode 100644 packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveTagIcon.tsx rename packages/components/src/__future__/Tag/{ => Tag}/Tag.module.scss (100%) rename packages/components/src/__future__/Tag/{ => Tag}/Tag.tsx (83%) rename packages/components/src/__future__/Tag/{ => Tag}/_docs/Tag.mdx (100%) rename packages/components/src/__future__/Tag/{ => Tag}/_docs/Tag.stickersheet.stories.tsx (100%) rename packages/components/src/__future__/Tag/{ => Tag}/_docs/Tag.stories.tsx (100%) create mode 100644 packages/components/src/__future__/Tag/Tag/index.ts rename packages/components/src/__future__/Tag/{ => Tag}/types.ts (100%) diff --git a/.changeset/hungry-frogs-end.md b/.changeset/hungry-frogs-end.md new file mode 100644 index 00000000000..a2cbfde4741 --- /dev/null +++ b/.changeset/hungry-frogs-end.md @@ -0,0 +1,5 @@ +--- +"@kaizen/components": minor +--- + +Add Future RemovableTag and RemovableButton components diff --git a/packages/components/src/__future__/Tag/RemovableTag/RemovableTag.module.scss b/packages/components/src/__future__/Tag/RemovableTag/RemovableTag.module.scss new file mode 100644 index 00000000000..3464b01a0a1 --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/RemovableTag.module.scss @@ -0,0 +1,8 @@ +@import "~@kaizen/design-tokens/sass/spacing"; + +.removableTag { + padding: $spacing-4 $spacing-4 $spacing-4 $spacing-8; + padding-block: $spacing-4; + padding-inline-start: $spacing-8; + padding-inline-end: $spacing-4; +} diff --git a/packages/components/src/__future__/Tag/RemovableTag/RemovableTag.tsx b/packages/components/src/__future__/Tag/RemovableTag/RemovableTag.tsx new file mode 100644 index 00000000000..8667db49104 --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/RemovableTag.tsx @@ -0,0 +1,36 @@ +import React from "react" +import classNames from "classnames" +import { Tag, TagProps } from "../Tag" +import { + RemoveButton, + RemoveButtonBaseProps, +} from "./subcomponents/RemoveButton" +import styles from "./RemovableTag.module.scss" + +export type RemovableTagProps = { + removeButtonProps: RemoveButtonBaseProps +} & Omit + +export const RemovableTag = ({ + children, + classNameOverride, + // Note: We've commented out color support for now, but may introduce it back in later + // if a good use case comes along. + // color = "gray", + removeButtonProps, + ...restProps +}: RemovableTagProps): JSX.Element => ( + + {children} + + +) + +RemovableTag.displayName = "RemovableTag" diff --git a/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.mdx b/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.mdx new file mode 100644 index 00000000000..883b14503fb --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.mdx @@ -0,0 +1,57 @@ +import { Canvas, Controls, Meta } from "@storybook/blocks" +import { ResourceLinks, KaioNotification, Installation } from "~storybook/components" +import * as RemovableTagStories from "./RemovableTag.stories" + + + +# RemovableTag + + + + + + + +## Overview + +Similar to the Tag component, but with a remove icon, that recieves a callback from props. +The consumer should manage the state regarding whether or not the icon should be rendered, +and pass a callback to remove the RemovableTag component via the `removeButtonProps` prop. + +## API + + + + +### `children` + +Takes a `ReactNode`. This should be the text that is displayed inside the Tag. + + + +### `classNameOverride` + +Allows classnames to be attached to the outermost element of Tag. + + + +### Controlling the remove button + +RemovableTag tags have a `removeButtonProps` prop that can be used to control the behaviour of the remove button. + +#### `aria-label` + +An aria label that is attached to the remove button. This is necessary for assistive technology, such as screen-readers. +The string passed here will be read out by screen-readers when the remove button is focused. + +#### `onClick` + +A callback that gets invoked when clicking the remove button. +For example, if the removal of a tag is controlled by a function, that function can +be passed as a callback via this prop, and executed when clicking the remove button. + diff --git a/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stickersheet.stories.tsx b/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stickersheet.stories.tsx new file mode 100644 index 00000000000..8d025b1192a --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stickersheet.stories.tsx @@ -0,0 +1,93 @@ +import React from "react" +import { Meta } from "@storybook/react" +import { + StickerSheet, + StickerSheetStory, +} from "~storybook/components/StickerSheet" +import { RemovableTag } from "../index" + +export default { + title: "Components/Tag/Future/RemovableTag", + parameters: { + chromatic: { disable: false }, + controls: { disable: true }, + }, +} satisfies Meta + +const StickerSheetTemplate: StickerSheetStory = { + render: () => ( + <> + + + + + alert("clicked"), + }} + > + My tag + + alert("clicked"), + }} + > + My tag + + alert("clicked"), + }} + > + My tag + + alert("clicked"), + }} + > + My tag + + + + + + ), + parameters: { + pseudo: { + hover: [ + '[data-sb-pseudo-styles="hover"]', + '[data-sb-pseudo-styles="hover"] > button', + ], + focus: [ + '[data-sb-pseudo-styles="focus"]', + '[data-sb-pseudo-styles="focus"] > button', + ], + focusVisible: [ + '[data-sb-pseudo-styles="focus-visible"]', + '[data-sb-pseudo-styles="focus-visible"] > button', + ], + }, + }, +} + +export const StickerSheetDefault: StickerSheetStory = { + ...StickerSheetTemplate, + name: "Sticker Sheet (Default)", +} + +export const StickerSheetRTL: StickerSheetStory = { + ...StickerSheetTemplate, + name: "Sticker Sheet (RTL)", + parameters: { ...StickerSheetTemplate.parameters, textDirection: "rtl" }, +} diff --git a/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stories.tsx b/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stories.tsx new file mode 100644 index 00000000000..f745a0a66bd --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/_docs/RemovableTag.stories.tsx @@ -0,0 +1,115 @@ +import { Meta, StoryObj } from "@storybook/react" +// import { AcademyIcon, ActionOffIcon, AddIcon, TagIcon } from "~components/Icon" +// import { TagColorKeys } from "../../Tag/types" +import { RemovableTag } from "../RemovableTag" + +const meta = { + title: "Components/Tag/Future/RemovableTag", + component: RemovableTag, + args: { + children: "My tag", + removeButtonProps: { + onClick: () => alert("Clicked"), + ariaLabel: "Remove tag icon", + }, + }, +} satisfies Meta + +export default meta + +type Story = StoryObj + +export const Playground: Story = { + // This can be added when we add Icon support + // argTypes: { + // icon: { + // options: ["AcademyIcon", "ActionOffIcon", "AddIcon", "TagIcon"], + // control: { type: "radio" }, + // mapping: { + // AcademyIcon: , + // ActionOffIcon: , + // AddIcon: , + // TagIcon: , + // }, + // }, + // }, + parameters: { + docs: { + canvas: { + sourceState: "shown", + }, + }, + }, +} + +export const Children: Story = { + args: { children: "This text is the children" }, +} + +// Colors and Icons may be added in at a later time. +// +// export const Color: Story = { +// render: () => ( +// <> +// {TagColorKeys.map(color => ( +// } +// key={color} +// removeButtonProps={{ +// ariaLabel: "close", +// onClick: () => alert("Clicked"), +// }} +// > +// {color} +// +// ))} +// +// ), +// parameters: { +// docs: { +// source: { type: "dynamic" }, +// }, +// }, +// } +// export const Icon: Story = { +// render: () => ( +// <> +// } +// removeButtonProps={{ +// ariaLabel: "close", +// onClick: () => alert("Clicked"), +// }} +// > +// AcademyIcon +// +// } +// removeButtonProps={{ +// ariaLabel: "close", +// onClick: () => alert("Clicked"), +// }} +// > +// ActionOffIcon +// +// } +// removeButtonProps={{ +// ariaLabel: "close", +// onClick: () => alert("Clicked"), +// }} +// > +// AddIcon +// +// +// ), +// } + +export const ClassNameOverride: Story = { + args: { + classNameOverride: "border-red-500 border-solid border-", + }, +} diff --git a/packages/components/src/__future__/Tag/RemovableTag/index.ts b/packages/components/src/__future__/Tag/RemovableTag/index.ts new file mode 100644 index 00000000000..9f383da9b42 --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/index.ts @@ -0,0 +1 @@ +export * from "./RemovableTag" diff --git a/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.module.scss b/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.module.scss new file mode 100644 index 00000000000..a8aef72f6c8 --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.module.scss @@ -0,0 +1,102 @@ +@import "~@kaizen/design-tokens/sass/border"; +@import "~@kaizen/design-tokens/sass/color"; +@import "../../../../../styles/button-reset"; + +.removeButton { + @include button-reset; + + position: relative; + display: inline-flex; + border-radius: 50%; + + &:focus, + &:focus-visible { + outline: none; + + &::after { + $focus-ring-offset: -3px; + + border-color: $color-blue-500; + content: ""; + position: absolute; + background: transparent; + border-width: $border-focus-ring-border-width; + border-style: $border-focus-ring-border-style; + border-radius: 50%; + inset: $focus-ring-offset; + } + } + + &::before { + position: absolute; + content: ""; + inset: -5px; + border-radius: 50%; + } + + color: rgba($color-purple-800-rgb, 0.7); + + &:hover, + &:focus, + &:focus-visible { + background-color: rgba($color-gray-600-rgb, 0.2); + cursor: pointer; + color: $color-purple-800; + } +} + +// .gray { +// &:hover, +// &:focus, +// &:focus-visible { +// background-color: rgba($color-gray-600-rgb, 0.2); +// } +// } + +// .blue { +// &:hover, +// &:focus, +// &:focus-visible { +// background-color: rgba($color-blue-500-rgb, 0.3); +// } +// } + +// .green { +// &:hover, +// &:focus, +// &:focus-visible { +// background-color: rgba($color-green-500-rgb, 0.3); +// } +// } + +// .yellow { +// &:hover, +// &:focus, +// &:focus-visible { +// background-color: rgba($color-yellow-500-rgb, 0.5); +// } +// } + +// .orange { +// &:hover, +// &:focus, +// &:focus-visible { +// background-color: rgba($color-orange-500-rgb, 0.3); +// } +// } + +// .red { +// &:hover, +// &:focus, +// &:focus-visible { +// background-color: rgba($color-red-500-rgb, 0.3); +// } +// } + +// .purple { +// &:hover, +// &:focus, +// &:focus-visible { +// background-color: rgba($color-purple-500-rgb, 0.3); +// } +// } diff --git a/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.tsx b/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.tsx new file mode 100644 index 00000000000..cb1bcc5ad32 --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveButton.tsx @@ -0,0 +1,44 @@ +import React, { ButtonHTMLAttributes } from "react" +import classnames from "classnames" +import { OverrideClassName } from "~types/OverrideClassName" +import { RemoveTagIcon } from "./RemoveTagIcon" +import styles from "./RemoveButton.module.scss" + +// type RemoveButtonColor = +// | "gray" +// | "blue" +// | "green" +// | "yellow" +// | "orange" +// | "red" +// | "purple" + +export type RemoveButtonBaseProps = { + // color?: RemoveButtonColor + ariaLabel: string + onClick: () => void +} +export type RemoveButtonProps = OverrideClassName< + Omit, "children" | "color"> & + RemoveButtonBaseProps +> + +export const RemoveButton = ({ + classNameOverride, + // color = "gray", + ariaLabel, + onClick, + ...restProps +}: RemoveButtonProps): JSX.Element => ( + +) + +RemoveButton.displayName = "RemoveButton" diff --git a/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveTagIcon.tsx b/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveTagIcon.tsx new file mode 100644 index 00000000000..e84fed67e02 --- /dev/null +++ b/packages/components/src/__future__/Tag/RemovableTag/subcomponents/RemoveTagIcon.tsx @@ -0,0 +1,20 @@ +import React from "react" +import { SVG, IconProps } from "~components/Icon/subcomponents/SVG" + +export const RemoveTagIcon = (props: IconProps): JSX.Element => { + const svgContent = ( + <> + + + ) + return ( + + {svgContent} + + ) +} diff --git a/packages/components/src/__future__/Tag/Tag.module.scss b/packages/components/src/__future__/Tag/Tag/Tag.module.scss similarity index 100% rename from packages/components/src/__future__/Tag/Tag.module.scss rename to packages/components/src/__future__/Tag/Tag/Tag.module.scss diff --git a/packages/components/src/__future__/Tag/Tag.tsx b/packages/components/src/__future__/Tag/Tag/Tag.tsx similarity index 83% rename from packages/components/src/__future__/Tag/Tag.tsx rename to packages/components/src/__future__/Tag/Tag/Tag.tsx index 4f6c0e8abf4..94d3d9ec8b0 100644 --- a/packages/components/src/__future__/Tag/Tag.tsx +++ b/packages/components/src/__future__/Tag/Tag/Tag.tsx @@ -15,8 +15,12 @@ export const Tag = ({ classNameOverride, icon, color = "gray", + ...restProps }: TagProps): JSX.Element => ( - + {icon && {icon}} {children} diff --git a/packages/components/src/__future__/Tag/_docs/Tag.mdx b/packages/components/src/__future__/Tag/Tag/_docs/Tag.mdx similarity index 100% rename from packages/components/src/__future__/Tag/_docs/Tag.mdx rename to packages/components/src/__future__/Tag/Tag/_docs/Tag.mdx diff --git a/packages/components/src/__future__/Tag/_docs/Tag.stickersheet.stories.tsx b/packages/components/src/__future__/Tag/Tag/_docs/Tag.stickersheet.stories.tsx similarity index 100% rename from packages/components/src/__future__/Tag/_docs/Tag.stickersheet.stories.tsx rename to packages/components/src/__future__/Tag/Tag/_docs/Tag.stickersheet.stories.tsx diff --git a/packages/components/src/__future__/Tag/_docs/Tag.stories.tsx b/packages/components/src/__future__/Tag/Tag/_docs/Tag.stories.tsx similarity index 100% rename from packages/components/src/__future__/Tag/_docs/Tag.stories.tsx rename to packages/components/src/__future__/Tag/Tag/_docs/Tag.stories.tsx diff --git a/packages/components/src/__future__/Tag/Tag/index.ts b/packages/components/src/__future__/Tag/Tag/index.ts new file mode 100644 index 00000000000..52f17bddcfd --- /dev/null +++ b/packages/components/src/__future__/Tag/Tag/index.ts @@ -0,0 +1 @@ +export * from "./Tag" diff --git a/packages/components/src/__future__/Tag/types.ts b/packages/components/src/__future__/Tag/Tag/types.ts similarity index 100% rename from packages/components/src/__future__/Tag/types.ts rename to packages/components/src/__future__/Tag/Tag/types.ts diff --git a/packages/components/src/__future__/Tag/index.ts b/packages/components/src/__future__/Tag/index.ts index 52f17bddcfd..2c70ebd29d8 100644 --- a/packages/components/src/__future__/Tag/index.ts +++ b/packages/components/src/__future__/Tag/index.ts @@ -1 +1,2 @@ +export * from "./RemovableTag" export * from "./Tag"