Skip to content

Commit

Permalink
Tag: Add small size (#1497)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltaranto authored May 23, 2024
1 parent 37b0687 commit c5edd65
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 46 deletions.
20 changes: 20 additions & 0 deletions .changeset/six-laws-burn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'braid-design-system': minor
---

---
new:
- Tag
---

**Tag:** Add `small` size

Introduce a new `small` size for `Tag` component.
This size sits alongside the existing `standard` size, which is the default.

**EXAMPLE USAGE:**
```jsx
<Tag size="small">
Tag
</Tag>
```
69 changes: 58 additions & 11 deletions packages/braid-design-system/src/lib/components/Tag/Tag.docs.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import React from 'react';
import type { ComponentDocs } from 'site/types';
import { Card, Inline, Tag, Strong, Text, TextLinkButton } from '../';
import {
Card,
Inline,
Tag,
Strong,
Text,
TextLinkButton,
Stack,
IconLanguage,
IconTag,
} from '../';
import source from '@braid-design-system/source.macro';
import { IconLanguage, IconPromote } from '../icons';

const docs: ComponentDocs = {
category: 'Content',
Expand All @@ -19,24 +28,41 @@ const docs: ComponentDocs = {
alternatives: [{ name: 'Badge', description: 'For static labels.' }],
additional: [
{
label: 'Inserting an icon',
label: 'Sizes',
background: 'surface',
description: (
<>
<Text>
For decoration or help distinguishing between tags, an{' '}
<Strong>icon</Strong> can be provided. This will be placed to the
left of the text.
You can customise the size of the tag via the <Strong>size</Strong>{' '}
prop, which accepts either <Strong>standard</Strong> or{' '}
<Strong>small</Strong>.
</Text>
</>
),
Example: () =>
source(
<Inline space="small">
<Tag icon={<IconPromote />}>One</Tag>
<Tag icon={<IconPromote />}>Two</Tag>
<Tag icon={<IconPromote />}>Three</Tag>
</Inline>,
<Stack space="large">
<Stack space="small">
<Text size="xsmall" tone="secondary">
STANDARD
</Text>
<Inline space="small" alignY="center">
<Tag>One</Tag>
<Tag>Two</Tag>
<Tag>Three</Tag>
</Inline>
</Stack>
<Stack space="small">
<Text size="xsmall" tone="secondary">
SMALL
</Text>
<Inline space="xsmall" alignY="center">
<Tag size="small">One</Tag>
<Tag size="small">Two</Tag>
<Tag size="small">Three</Tag>
</Inline>
</Stack>
</Stack>,
),
},
{
Expand Down Expand Up @@ -103,6 +129,27 @@ const docs: ComponentDocs = {
</Inline>,
),
},
{
label: 'Inserting an icon',
background: 'surface',
description: (
<>
<Text>
For decoration or help distinguishing between tags, an{' '}
<Strong>icon</Strong> can be provided. This will be placed to the
left of the text.
</Text>
</>
),
Example: () =>
source(
<Inline space="small">
<Tag icon={<IconTag />}>One</Tag>
<Tag icon={<IconTag />}>Two</Tag>
<Tag icon={<IconTag />}>Three</Tag>
</Inline>,
),
},
],
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export const galleryItems: ComponentExample[] = [
background: 'surface',
Example: () => source(<Tag>Tag</Tag>),
},
{
label: 'Small',
background: 'surface',
Example: () => source(<Tag size="small">Tag</Tag>),
},
{
label: 'With an icon',
background: 'surface',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import { useFallbackId } from '../../playroom/utils';
import { type TagProps, Tag as BraidTag } from './Tag';
import { type TagProps, Tag as BraidTag, tagSizes } from './Tag';

export const Tag = ({ icon, id, ...restProps }: TagProps) => {
export const Tag = ({ icon, id, size, ...restProps }: TagProps) => {
const fallbackId = useFallbackId();
return (
<BraidTag
id={id ?? fallbackId}
icon={typeof icon !== 'boolean' ? icon : undefined}
size={size && tagSizes.includes(size) ? size : undefined}
{...restProps}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
import React from 'react';
import type { ComponentScreenshot } from 'site/types';
import { Tag, Inline, IconHelp } from '../';
import { Tag, Inline, IconTag, Stack } from '../';
import { debugTouchableAttrForDataProp } from '../private/touchable/debugTouchable';

export const screenshots: ComponentScreenshot = {
screenshotWidths: [320],
examples: [
{
label: 'Standard Tag',
background: 'surface',
Example: () => <Tag>Tag</Tag>,
Example: ({ handler }) => (
<Inline space="small">
<Tag>Tag</Tag>
<Tag icon={<IconTag />}>Tag</Tag>
<Tag icon={<IconTag />} onClear={handler} clearLabel="Clear">
Tag
</Tag>
</Inline>
),
},
{
label: 'Clearable Tag',
label: 'Small Tag',
background: 'surface',
Example: ({ handler }) => (
<Tag onClear={handler} clearLabel="Clear tag">
Tag
</Tag>
<Inline space="xsmall">
<Tag size="small">Tag</Tag>
<Tag size="small" icon={<IconTag />}>
Tag
</Tag>
<Tag
size="small"
icon={<IconTag />}
onClear={handler}
clearLabel="Clear"
>
Tag
</Tag>
</Inline>
),
},
{
Expand All @@ -33,27 +53,35 @@ export const screenshots: ComponentScreenshot = {
),
},
{
label: 'Test: Standard and clearable tags should be equal height',
label: 'Virtual touch target',
background: 'surface',
Example: ({ handler }) => (
<Inline space="small">
<Tag>Tag</Tag>
<Tag onClear={handler} clearLabel="Clear tag">
Tag
</Tag>
</Inline>
),
},
{
label: 'With an icon',
background: 'surface',
Example: ({ handler }) => (
<Inline space="small">
<Tag icon={<IconHelp />}>Tag</Tag>
<Tag icon={<IconHelp />} onClear={handler} clearLabel="Clear tag">
Tag
</Tag>
</Inline>
<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
</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
</Tag>
</Inline>
</Stack>
),
},
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import type { Snippets } from '../private/Snippets';
import { Inline, Tag } from '../../playroom/components';
import { IconTag, Inline, Tag } from '../../playroom/components';
import source from '@braid-design-system/source.macro';

export const snippets: Snippets = [
Expand All @@ -14,6 +14,16 @@ export const snippets: Snippets = [
</Inline>,
),
},
{
name: 'Small',
code: source(
<Inline space="xsmall">
<Tag size="small">Tag</Tag>
<Tag size="small">Tag</Tag>
<Tag size="small">Tag</Tag>
</Inline>,
),
},
{
name: 'Clearable',
code: source(
Expand All @@ -30,4 +40,14 @@ export const snippets: Snippets = [
</Inline>,
),
},
{
name: 'With icon',
code: source(
<Inline space="small">
<Tag icon={<IconTag />}>Tag</Tag>
<Tag icon={<IconTag />}>Tag</Tag>
<Tag icon={<IconTag />}>Tag</Tag>
</Inline>,
),
},
];
28 changes: 21 additions & 7 deletions packages/braid-design-system/src/lib/components/Tag/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@ import buildDataAttributes, {
type DataAttributeMap,
} from '../private/buildDataAttributes';
import type { AllOrNone } from '../private/AllOrNone';
import type { Space } from '../../css/atoms/atoms';
import * as styles from './Tag.css';

export const tagSizes = ['small', 'standard'] as const;

export type TagProps = {
children: string;
size?: (typeof tagSizes)[number];
data?: DataAttributeMap;
id?: string;
icon?: TextProps['icon'];
} & AllOrNone<{ onClear: () => void; clearLabel: string }>;

const paddingXForSize: Record<NonNullable<TagProps['size']>, Space> = {
small: 'xsmall',
standard: 'small',
};

export const Tag = ({
onClear,
clearLabel = 'Clear',
size = 'standard',
data,
id,
icon,
Expand Down Expand Up @@ -47,27 +57,31 @@ export const Tag = ({
minWidth={0}
alignItems="center"
background="neutralLight"
paddingY={onClear ? undefined : 'xxsmall'}
paddingLeft={icon ? 'xsmall' : 'small'}
paddingRight={onClear ? undefined : 'small'}
paddingY="xxsmall"
paddingX={paddingXForSize[size]}
paddingRight={onClear ? 'xsmall' : paddingXForSize[size]}
borderRadius="full"
>
<Box minWidth={0} title={children}>
<Text baseline={false} maxLines={1} icon={icon}>
{children}
<Text size={size} baseline={false} maxLines={1}>
{icon} {children}
</Text>
</Box>
{onClear ? (
<Box flexShrink={0} display="flex" className={styles.clearGutter}>
<Box
flexShrink={0}
marginLeft="xxsmall"
className={styles.clearGutter}
>
<ButtonIcon
// @ts-expect-error With no id, ButtonIcon will fallback from Tooltip to title internally.
// ID will no longer be required when React 18 has sufficient adoption and we can safely `useId()`
id={id ? `${id}-clear` : undefined}
icon={<IconClear />}
label={clearLabel}
tone="secondary"
size="small"
variant="transparent"
bleed={false}
onClick={onClear}
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7574,6 +7574,9 @@ exports[`Tag 1`] = `
icon?: ReactElement<UseIconProps, string | JSXElementConstructor<any>>
id?: string
onClear?: () => void
size?:
| "small"
| "standard"
},
}
`;
Expand Down

0 comments on commit c5edd65

Please sign in to comment.