Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chips-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@workflowbuilder/ui': minor
---

Add the `Chip` component — a compact tag in the DS 2.0 solid and outline treatments, four sizes (`s`–`xl`), optional prefix icon and close affordance.
5 changes: 5 additions & 0 deletions .changeset/conditions-tag-chip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@workflowbuilder/sdk': patch
---

The dynamic-conditions counter tag is rendered with the UI `Chip` component. Same neutral surface colors; the tag gets the DS 2.0 chip metrics — 10px label (was 12px) in a 20px-tall pill with slightly tighter padding.
1 change: 1 addition & 0 deletions apps/docs/scripts/ui-components.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const COMPONENTS = [
dir: 'button',
},
{ slug: 'checkbox', name: 'Checkbox', propsType: 'CheckboxProps', dir: 'checkbox' },
{ slug: 'chips', name: 'Chip', propsType: 'ChipProps', dir: 'chips' },
{ slug: 'collapsible', name: 'Collapsible', propsType: 'CollapsibleProps', dir: 'collapsible' },
{ slug: 'date-picker', name: 'DatePicker', propsType: 'DatePickerProps', dir: 'date-picker' },
{ slug: 'icon-switch', name: 'IconSwitch', propsType: 'IconSwitchProps', dir: 'switch/icon-switch' },
Expand Down
17 changes: 17 additions & 0 deletions apps/docs/src/components/ui-examples/chips.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Tag } from '@phosphor-icons/react';
import { Chip } from '@workflowbuilder/ui';

import { ComponentPreview } from './component-preview';

export function ChipsExample() {
return (
<ComponentPreview>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
<Chip label="tag label" />
<Chip label="tag label" variant="outline" />
<Chip label="with icon" size="l" prefixIcon={<Tag />} />
<Chip label="removable" size="l" variant="outline" onClose={() => {}} />
</div>
</ComponentPreview>
);
}
33 changes: 33 additions & 0 deletions apps/docs/src/content/docs/ui-library/ui-components/chips.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: Chip
description: Compact tag for labeling and filtering, in solid and outline treatments.
---

import CssVariablesTable from '../../../../components/api/css-variables-table.astro';
import PropsTable from '../../../../components/api/props-table.astro';
import { ChipsExample } from '../../../../components/ui-examples/chips';

A `Chip` is a compact tag in one of two treatments: `solid` on the neutral
chip surface, or `outline` with the brand border and accent. Four sizes
(`s`, `m`, `l`, `xl`), an optional prefix icon, and an optional close
affordance.

<ChipsExample client:visible />

## Usage

```tsx
import { Chip } from '@workflowbuilder/ui';

function Example() {
return <Chip label="tag label" variant="outline" size="l" onClose={() => remove()} />;
}
```

## Props

<PropsTable slug="chips" />

## CSS variables

<CssVariablesTable slug="chips" />
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
--wb-conditions-form-border-color: var(--ax-ui-stroke-primary-default); /* missing token */
--wb-conditions-form-border-radius: 0.75rem; /* missing token */
--wb-conditions-form-header-color: var(--ax-public-form-label-color);

--wb-conditions-form-tag-bg-color: var(--ax-chips-neutral-bg);
}

.container {
Expand All @@ -27,12 +25,5 @@
}

.tag {
composes: ax-public-p10 from global;

display: inline-block;
margin-top: 0.25rem;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
background-color: var(--wb-conditions-form-tag-bg-color);
margin-right: auto;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NavButton } from '@workflowbuilder/ui';
import { Chip, NavButton } from '@workflowbuilder/ui';
import clsx from 'clsx';
import { useCallback, useRef } from 'react';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -49,7 +49,7 @@ function DynamicConditionsControl(props: DynamicConditionsControlProps) {
</NavButton>
</div>
<Dependencies conditions={data} onClick={openEditorModal} disabled={isDisabled} />
<span className={styles['tag']}>{t('totalNumber', { count: data.length })}</span>
<Chip size="l" className={styles['tag']} label={t('totalNumber', { count: data.length })} />
</div>
);
}
Expand Down
69 changes: 69 additions & 0 deletions packages/ui/src/components/chips/chips.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
@layer ui.component {
.chip {
display: inline-flex;
align-items: center;
gap: var(--wb-space-50);
border-radius: var(--wb-radius-50);
white-space: nowrap;
}

.solid {
background-color: var(--wb-components-chips-solid);
color: var(--wb-components-chips-solid-text);
}

.outline {
background-color: var(--wb-components-chips-inset-outline);
background-image: linear-gradient(
var(--wb-components-chips-overlay-outline),
var(--wb-components-chips-overlay-outline)
);
box-shadow: 0 0 0 var(--wb-size-12) var(--wb-components-chips-inset-outline);
color: var(--wb-components-chips-inset-outline);
}

.s {
height: 0.875rem;
padding-inline: var(--wb-space-50);
}

.m {
height: 1rem;
padding-inline: var(--wb-space-50);
}

.l {
height: 1.25rem;
padding-inline: var(--wb-space-75);
}

.xl {
height: 1.375rem;
padding-inline: var(--wb-space-75);
}

.icon,
.close {
display: inline-flex;
align-items: center;
}

.icon svg,
.close svg {
width: 0.625rem;
height: 0.625rem;
}

.close {
padding: 0;
border: none;
background: none;
color: inherit;
cursor: pointer;

&:focus-visible {
box-shadow: 0 0 0 2px var(--ax-focus-ring-element);
outline: none;
}
}
}
51 changes: 51 additions & 0 deletions packages/ui/src/components/chips/chips.tsx

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file is named chips/chips.tsx. It probably should be chip/chip.tsx to match the rest of the application.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { X } from '@phosphor-icons/react';
import clsx from 'clsx';
import { HTMLAttributes, ReactNode, forwardRef } from 'react';

import styles from './chips.module.css';

export type ChipProps = {
label: string;
/**
* @default 'solid'
*/
variant?: ChipVariant;
/**
* @default 'm'
*/
size?: ChipSize;
prefixIcon?: ReactNode;
/**
* When set, a close affordance is rendered and invokes this callback.
*/
onClose?: () => void;
/**
* Accessible name of the close affordance.
* @default `Remove ${label}`
*/
closeLabel?: string;
} & HTMLAttributes<HTMLSpanElement>;

export type ChipVariant = 'solid' | 'outline';
export type ChipSize = 's' | 'm' | 'l' | 'xl';

export const Chip = forwardRef<HTMLSpanElement, ChipProps>(
({ label, variant = 'solid', size = 'm', prefixIcon, onClose, closeLabel, className, ...rest }, ref) => {
return (
<span ref={ref} {...rest} className={clsx(styles['chip'], styles[variant], styles[size], className)}>
{prefixIcon && <span className={styles['icon']}>{prefixIcon}</span>}
<span className="wb-text-label-s">{label}</span>
Comment thread
librowski marked this conversation as resolved.
{onClose && (
<button
type="button"
className={styles['close']}
aria-label={closeLabel ?? `Remove ${label}`}
onClick={onClose}
>
<X />
</button>
)}
</span>
);
},
);
1 change: 1 addition & 0 deletions packages/ui/src/components/chips/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './chips';
1 change: 1 addition & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './components/accordion';
export * from './components/avatar';
export * from './components/button';
export * from './components/checkbox';
export * from './components/chips';
export * from './components/collapsible';
export * from './components/date-picker';
export * from './components/edge';
Expand Down
18 changes: 18 additions & 0 deletions packages/ui/src/styles/_provisional.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,23 @@
--wb-font-size-300: 1.5rem;
--wb-font-size-350: 1.75rem;
--wb-font-size-400: 2rem;

--wb-radius-50: 0.25rem;
--wb-space-50: 0.25rem;
--wb-space-75: 0.375rem;
--wb-size-12: 0.0625rem;
--wb-components-chips-inset-outline: var(--ax-colors-acc1-500);
}

html[data-theme='light'] {
--wb-components-chips-solid: var(--ax-colors-gray-300);
--wb-components-chips-solid-text: var(--ax-colors-gray-800);
--wb-components-chips-overlay-outline: color-mix(in srgb, var(--ax-colors-gray-100) 85%, transparent);
}

html[data-theme='dark'] {
--wb-components-chips-solid: var(--ax-colors-gray-650);
--wb-components-chips-solid-text: var(--ax-colors-gray-100);
--wb-components-chips-overlay-outline: color-mix(in srgb, var(--ax-colors-gray-900) 75%, transparent);
}
}
1 change: 1 addition & 0 deletions packages/ui/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const componentEntries = [
'avatar',
'button',
'checkbox',
'chips',
'collapsible',
'date-picker',
'edge',
Expand Down
Loading