Skip to content

Commit

Permalink
Tag: Introduce “addable” support (#1521)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltaranto authored Jun 27, 2024
1 parent c5cd1b5 commit 3e51af6
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 126 deletions.
18 changes: 18 additions & 0 deletions .changeset/sharp-bears-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
'braid-design-system': minor
---

---
updated:
- Tag
---

**Tag:** Introduce "addable" support

Tag actions have been extended to now support being “added”.
A `Tag` will include a small add icon button when both an `onAdd` handler and `addLabel` prop are provided.

**EXAMPLE USAGE:**
```jsx
<Tag onAdd={() => {...}} addLabel="Add Tag" />
```
147 changes: 87 additions & 60 deletions packages/braid-design-system/src/lib/components/Tag/Tag.docs.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from 'react';
import type { ComponentDocs } from 'site/types';
import {
Card,
Inline,
Tag,
Strong,
Text,
TextLinkButton,
TextLink,
Stack,
IconLanguage,
IconTag,
Expand All @@ -17,13 +16,11 @@ const docs: ComponentDocs = {
category: 'Content',
Example: () =>
source(
<Card rounded>
<Inline space="small">
<Tag>One</Tag>
<Tag>Two</Tag>
<Tag>Three</Tag>
</Inline>
</Card>,
<Inline space="small">
<Tag>One</Tag>
<Tag>Two</Tag>
<Tag>Three</Tag>
</Inline>,
),
alternatives: [{ name: 'Badge', description: 'For static labels.' }],
additional: [
Expand Down Expand Up @@ -66,68 +63,98 @@ const docs: ComponentDocs = {
),
},
{
label: 'Clearable',
label: 'Actionable tags',
description: (
<>
<Text>
Tags can be made clearable, by providing an <Strong>onClear</Strong>{' '}
handler and a <Strong>clearLabel</Strong> to describe what clicking
it will do.
Tags can be made actionable to support either being “cleared” or
“added”.
</Text>

<Text>
By providing an <Strong>onClear</Strong> handler and a{' '}
<Strong>clearLabel</Strong>, a{' '}
<TextLink href="/components/ButtonIcon">ButtonIcon</TextLink>{' '}
component with a clear icon will be added to the right of the tag
label.
</Text>

<Text>
Alternatively, providing an <Strong>onAdd</Strong> handler and an{' '}
<Strong>addLabel</Strong> will insert a{' '}
<TextLink href="/components/ButtonIcon">ButtonIcon</TextLink>{' '}
component with an add icon to the right of the tag label.
</Text>

<Text tone="promote" id="translations">
<IconLanguage title="Translation hint" titleId="translations" /> The{' '}
<Strong>aria-label</Strong> for the clear button can be customised
by providing the <Strong>clearLabel</Strong> prop.
<Strong>aria-label</Strong> for the button can be customised by
providing the relevant <Strong>clearLabel</Strong> or{' '}
<Strong>addLabel</Strong> prop.
</Text>
</>
),
background: 'surface',
Example: ({ getState, setState, toggleState }) =>
source(
<Inline space="small" alignY="center">
{!getState('clearOne') ? (
<Tag
onClear={() => toggleState('clearOne')}
clearLabel={'Clear "One"'}
id="clear-1"
>
One
</Tag>
) : null}
{!getState('clearTwo') ? (
<Tag
onClear={() => toggleState('clearTwo')}
clearLabel={'Clear "Two"'}
id="clear-2"
>
Two
</Tag>
) : null}
{!getState('clearThree') ? (
<Tag
onClear={() => toggleState('clearThree')}
clearLabel={'Clear "Three"'}
id="clear-3"
>
Three
</Tag>
) : null}
<Text tone="secondary">
<TextLinkButton
weight="weak"
hitArea="large"
onClick={() => {
setState('clearOne', false);
setState('clearTwo', false);
setState('clearThree', false);
}}
>
Reset
</TextLinkButton>
</Text>
</Inline>,
),
Example: ({ setDefaultState, getState, setState }) => {
const { code, value } = source(
<>
{setDefaultState('selected', ['One', 'Two', 'Three'])}

<Stack space="large">
<Stack space="small">
<Text size="xsmall" tone="secondary">
ADDABLE
</Text>
<Inline space="small" alignY="center">
{['One', 'Two', 'Three', 'Four', 'Five']
.filter((tag) => !getState('selected').includes(tag))
.map((tag) => (
<Tag
key={tag}
onAdd={() =>
setState('selected', [...getState('selected'), tag])
}
addLabel={`Add "${tag}"`}
id={`add-${tag}`}
>
{tag}
</Tag>
))}
</Inline>
</Stack>
<Stack space="small">
<Text size="xsmall" tone="secondary">
CLEARABLE
</Text>
<Inline space="small" alignY="center">
{getState('selected').map((selectedTag: string) => (
<Tag
key={selectedTag}
onClear={() => {
setState(
'selected',
getState('selected').filter(
(tag: string) => tag !== selectedTag,
),
);
}}
clearLabel={`Clear "${selectedTag}"`}
id={`clear-${selectedTag}`}
>
{selectedTag}
</Tag>
))}
</Inline>
</Stack>
</Stack>
</>,
);

return {
code: code.replaceAll(': string', ''),
value,
};
},
},
{
label: 'Inserting an icon',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import type { GalleryComponent } from 'site/types';
import { Tag, Inline, Text, TextLinkButton, IconTag } from '../';
import { Tag, Inline, IconTag } from '../';
import source from '@braid-design-system/source.macro';

export const galleryItems: GalleryComponent = {
Expand All @@ -21,40 +21,17 @@ export const galleryItems: GalleryComponent = {
Example: () => source(<Tag icon={<IconTag />}>Tag</Tag>),
},
{
label: 'Clearable',
label: 'Actionable',
background: 'surface',
Example: ({ getState, setState }) =>
Example: () =>
source(
<Inline space="small" alignY="center">
<Tag>One</Tag>
{!getState('clearTwo') ? (
<Tag
onClear={() => setState('clearTwo', true)}
clearLabel={'Clear "Two"'}
>
Two
</Tag>
) : null}
{!getState('clearThree') ? (
<Tag
onClear={() => setState('clearThree', true)}
clearLabel={'Clear "Three"'}
>
Three
</Tag>
) : null}
<Text tone="secondary">
<TextLinkButton
weight="weak"
hitArea="large"
onClick={() => {
setState('clearTwo', false);
setState('clearThree', false);
}}
>
Reset
</TextLinkButton>
</Text>
<Tag addLabel="Add" onAdd={() => {}}>
Addable
</Tag>
<Tag clearLabel="Clear" onClear={() => {}}>
Clearable
</Tag>
</Inline>,
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Tag, Inline, IconTag, Stack } from '../';
import { debugTouchableAttrForDataProp } from '../private/touchable/debugTouchable';

export const screenshots: ComponentScreenshot = {
screenshotWidths: [320],
screenshotWidths: [768],
examples: [
{
label: 'Standard Tag',
Expand All @@ -16,6 +16,9 @@ export const screenshots: ComponentScreenshot = {
<Tag icon={<IconTag />} onClear={handler} clearLabel="Clear">
Tag
</Tag>
<Tag icon={<IconTag />} onAdd={handler} addLabel="Add">
Tag
</Tag>
</Inline>
),
},
Expand All @@ -36,20 +39,46 @@ export const screenshots: ComponentScreenshot = {
>
Tag
</Tag>
<Tag size="small" icon={<IconTag />} onAdd={handler} addLabel="Add">
Tag
</Tag>
</Inline>
),
},
{
label: 'Truncated Tag',
background: 'surface',
Example: ({ handler }) => (
<Tag onClear={handler} clearLabel="Clear tag">
The quick brown fox jumps over the lazy dog. The quick brown fox jumps
over the lazy dog. The quick brown fox jumps over the lazy dog. The
quick brown fox jumps over the lazy dog. The quick brown fox jumps
over the lazy dog. The quick brown fox jumps over the lazy dog. The
quick brown fox jumps over the lazy dog.
</Tag>
<Stack space="small">
<Tag>
The quick brown fox jumps over the lazy dog. The quick brown fox
jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog. The quick brown
fox jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog.
</Tag>
<Tag icon={<IconTag />}>
The quick brown fox jumps over the lazy dog. The quick brown fox
jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog. The quick brown
fox jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog.
</Tag>
<Tag onClear={handler} clearLabel="Clear tag">
The quick brown fox jumps over the lazy dog. The quick brown fox
jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog. The quick brown
fox jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog.
</Tag>
<Tag icon={<IconTag />} onClear={handler} clearLabel="Clear tag">
The quick brown fox jumps over the lazy dog. The quick brown fox
jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog. The quick brown
fox jumps over the lazy dog. The quick brown fox jumps over the lazy
dog. The quick brown fox jumps over the lazy dog.
</Tag>
</Stack>
),
},
{
Expand All @@ -58,26 +87,19 @@ export const screenshots: ComponentScreenshot = {
Example: ({ handler }) => (
<Stack space="large">
<Inline space="xsmall" data={{ [debugTouchableAttrForDataProp]: '' }}>
<Tag size="small">Tag</Tag>
<Tag size="small" onClear={handler} clearLabel="Clear">
Tag
</Tag>
<Tag
size="small"
icon={<IconTag />}
onClear={handler}
clearLabel="Clear"
>
<Tag size="small" onAdd={handler} addLabel="Add">
Tag
</Tag>
</Inline>

<Inline space="small" data={{ [debugTouchableAttrForDataProp]: '' }}>
<Tag>Tag</Tag>
<Tag onClear={handler} clearLabel="Clear">
Tag
</Tag>
<Tag icon={<IconTag />} onClear={handler} clearLabel="Clear">
<Tag onAdd={handler} addLabel="Add">
Tag
</Tag>
</Inline>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ export const snippets: Snippets = [
</Inline>,
),
},
{
name: 'Addable',
code: source(
<Inline space="small">
<Tag onAdd={() => {}} addLabel="Add">
Tag
</Tag>
<Tag onAdd={() => {}} addLabel="Add">
Tag
</Tag>
<Tag onAdd={() => {}} addLabel="Add">
Tag
</Tag>
</Inline>,
),
},
{
name: 'With icon',
code: source(
Expand Down
Loading

0 comments on commit 3e51af6

Please sign in to comment.