Skip to content

Commit

Permalink
Kds 1780 tag dismiss button (#4131)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* Remove unnecessary back ticks

* Fix typo

Co-authored-by: Geoffrey Chong <[email protected]>

* 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 <[email protected]>
  • Loading branch information
JakePitman and gyfchong authored Oct 24, 2023
1 parent f44539f commit 24e497d
Show file tree
Hide file tree
Showing 18 changed files with 488 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/hungry-frogs-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kaizen/components": minor
---

Add Future RemovableTag and RemovableButton components
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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<TagProps, "color" | "icon">

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 => (
<Tag
classNameOverride={classNames(classNameOverride, styles.removableTag)}
// color={color}
{...restProps}
>
{children}
<RemoveButton
// color={color}
{...removeButtonProps}
/>
</Tag>
)

RemovableTag.displayName = "RemovableTag"
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Canvas, Controls, Meta } from "@storybook/blocks"
import { ResourceLinks, KaioNotification, Installation } from "~storybook/components"
import * as RemovableTagStories from "./RemovableTag.stories"

<Meta of={RemovableTagStories} />

# RemovableTag

<ResourceLinks
sourceCode="https://github.com/cultureamp/kaizen-design-system/tree/main/packages/components/src/__future__/Tag/RemovableTag.tsx"
/>

<KaioNotification />

<Installation
installCommand="yarn add @kaizen/components"
importStatement="import { RemovableTag } from `@kaizen/components/future`"
/>

## 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

<Canvas of={RemovableTagStories.Playground} />
<Controls of={RemovableTagStories.Playground} />

### `children`

Takes a `ReactNode`. This should be the text that is displayed inside the Tag.

<Canvas of={RemovableTagStories.Children} />

### `classNameOverride`

Allows classnames to be attached to the outermost element of Tag.

<Canvas of={RemovableTagStories.ClassNameOverride} />

### 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.

Original file line number Diff line number Diff line change
@@ -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: () => (
<>
<StickerSheet heading="Button Group">
<StickerSheet.Header
headings={["Default", "Hover", "Focus", "Focus visible"]}
/>
<StickerSheet.Body>
<StickerSheet.Row>
<RemovableTag
removeButtonProps={{
ariaLabel: "Remove tag",
onClick: () => alert("clicked"),
}}
>
My tag
</RemovableTag>
<RemovableTag
data-sb-pseudo-styles="hover"
removeButtonProps={{
ariaLabel: "Remove tag",
onClick: () => alert("clicked"),
}}
>
My tag
</RemovableTag>
<RemovableTag
data-sb-pseudo-styles="focus"
removeButtonProps={{
ariaLabel: "Remove tag",
onClick: () => alert("clicked"),
}}
>
My tag
</RemovableTag>
<RemovableTag
data-sb-pseudo-styles="focus-visible"
removeButtonProps={{
ariaLabel: "Remove tag",
onClick: () => alert("clicked"),
}}
>
My tag
</RemovableTag>
</StickerSheet.Row>
</StickerSheet.Body>
</StickerSheet>
</>
),
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" },
}
Original file line number Diff line number Diff line change
@@ -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<typeof RemovableTag>

export default meta

type Story = StoryObj<typeof meta>

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: <AcademyIcon role="presentation" />,
// ActionOffIcon: <ActionOffIcon role="presentation" />,
// AddIcon: <AddIcon role="presentation" />,
// TagIcon: <TagIcon role="presentation" />,
// },
// },
// },
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 => (
// <RemovableTag
// color={color}
// icon={<TagIcon role="presentation" />}
// key={color}
// removeButtonProps={{
// ariaLabel: "close",
// onClick: () => alert("Clicked"),
// }}
// >
// {color}
// </RemovableTag>
// ))}
// </>
// ),
// parameters: {
// docs: {
// source: { type: "dynamic" },
// },
// },
// }
// export const Icon: Story = {
// render: () => (
// <>
// <RemovableTag
// icon={<AcademyIcon role="presentation" />}
// removeButtonProps={{
// ariaLabel: "close",
// onClick: () => alert("Clicked"),
// }}
// >
// AcademyIcon
// </RemovableTag>
// <RemovableTag
/// / color="yellow"
// icon={<ActionOffIcon role="presentation" />}
// removeButtonProps={{
// ariaLabel: "close",
// onClick: () => alert("Clicked"),
// }}
// >
// ActionOffIcon
// </RemovableTag>
// <RemovableTag
/// / color="green"
// icon={<AddIcon role="presentation" />}
// removeButtonProps={{
// ariaLabel: "close",
// onClick: () => alert("Clicked"),
// }}
// >
// AddIcon
// </RemovableTag>
// </>
// ),
// }

export const ClassNameOverride: Story = {
args: {
classNameOverride: "border-red-500 border-solid border-",
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./RemovableTag"
Loading

0 comments on commit 24e497d

Please sign in to comment.