Chip
Chips help people enter information, make selections, filter content, or trigger actions.
Chip — overview and usage
Chips are small interactive components that represent an action, a choice or a compact input. They follow Material 3 principles and come in four main usage types:
- Assist (triggers a quick action, close to a button)
- Filter (on/off or multi-selection)
- Input (represents a value entered by the user, e.g. a tag)
- Suggestion (offers contextual options)
This page explains how to use Chip in Udixio, with practical examples. The component code may evolve, but the concepts and best practices remain valid.
Installation and import
React:
import { Chip } from '@udixio/ui-react';Angular:
import { Chip } from '@udixio/ui-angular';Svelte:
import { Chip } from '@udixio/ui-svelte';Minimal example
The label is passed with label in all adapters. React also accepts a string via children; Svelte accepts a children snippet, while Angular uses the label input.
import { Chip } from '@udixio/ui-react';
export default function ChipBasicReact() {
return <Chip label="Option" />;
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
@Component({
selector: 'docs-chip-basic-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<udx-chip label="Option" />`,
})
export class ChipBasicAngular {}<script lang="ts">
import { Chip } from '@udixio/ui-svelte';
</script>
<Chip label="Option" />Usage types
Assist chip (quick action)
An assist chip triggers an immediate action: open a view, copy some text, apply a temporary filter, etc.
import { Chip } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
export default function ChipAssistReact() {
return (
<Chip
label="Nouveau"
icon={iAdd}
onClick={() => console.info('Nouvelle action')}
/>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
@Component({
selector: 'docs-chip-assist-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<udx-chip label="Nouveau" [icon]="addIcon" (click)="createAction()" />
`,
})
export class ChipAssistAngular {
protected readonly addIcon = iAdd;
protected createAction(): void {
console.info('Nouvelle action');
}
}<script lang="ts">
import { iAdd } from '@udixio/icons-rounded-400/add';
import { Chip } from '@udixio/ui-svelte';
</script>
<Chip label="Nouveau" icon={iAdd} onclick={() => console.info('Nouvelle action')} />Filter chip (selection)
Make a chip selectable with selected and onSelectedChange in React, selected and selectedChange in Angular, or bind:selected in Svelte. For self-contained state, initialize it with defaultSelected.
import { useState } from 'react';
import { Chip } from '@udixio/ui-react';
export default function ChipStatesReact() {
const [selected, setSelected] = useState(false);
return (
<Chip label="Photos" selected={selected} onSelectedChange={setSelected} />
);
}import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
@Component({
selector: 'docs-chip-states-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<udx-chip
label="Photos"
[selected]="selected()"
(selectedChange)="selected.set($event)"
/>`,
})
export class ChipStatesAngular {
protected readonly selected = signal(false);
}<script lang="ts">
import { Chip } from '@udixio/ui-svelte';
let selected = $state(false);
</script>
<Chip label="Photos" bind:selected />Suggestion chip (proposal)
Present contextual suggestions (quick replies, search filters). Keep labels short (ideally ≤ 20 characters). Use outlined on a neutral background and elevated when extra visual separation is needed.
import { Chip } from '@udixio/ui-react';
export default function ChipSuggestionsReact() {
return (
<div className="flex flex-wrap gap-2">
<Chip label="Near me" />
<Chip label="Open now" variant="elevated" />
<Chip label="4★ and up" />
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
@Component({
selector: 'docs-chip-suggestions-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap gap-2">
<udx-chip label="Near me" />
<udx-chip label="Open now" variant="elevated" />
<udx-chip label="4★ and up" />
</div>
`,
})
export class ChipSuggestionsAngular {}<script lang="ts">
import { Chip } from '@udixio/ui-svelte';
</script>
<div class="flex flex-wrap gap-2">
<Chip label="Near me" />
<Chip label="Open now" variant="elevated" />
<Chip label="4★ and up" />
</div>Input chip (entered value)
Represents user input (e.g. tags). Adding and removing is handled by your application logic.
import { useState } from 'react';
import { Chip } from '@udixio/ui-react';
export default function ChipInputReact() {
const [tags, setTags] = useState(['React', 'TypeScript', 'Angular']);
return (
<div className="flex flex-wrap gap-2">
{tags.map((tag) => (
<Chip
key={tag}
label={tag}
onRemove={() =>
setTags((current) => current.filter((item) => item !== tag))
}
/>
))}
</div>
);
}import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
@Component({
selector: 'docs-chip-input-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap gap-2">
@for (tag of tags(); track tag) {
<udx-chip [label]="tag" removable (remove)="removeTag(tag)" />
}
</div>
`,
})
export class ChipInputAngular {
protected readonly tags = signal(['React', 'TypeScript', 'Angular']);
protected removeTag(tag: string): void {
this.tags.update((current) => current.filter((item) => item !== tag));
}
}<script lang="ts">
import { Chip } from '@udixio/ui-svelte';
let tags = $state(['Svelte', 'TypeScript', 'Angular']);
</script>
<div class="flex flex-wrap gap-2">
{#each tags as tag (tag)}
<Chip label={tag} onRemove={() => (tags = tags.filter((item) => item !== tag))} />
{/each}
</div>Icon
You can display an icon from the Udixio catalog inside the chip. The Angular adapter does not require Font Awesome.
import { Chip } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
export default function ChipIconReact() {
return <Chip label="Ajouter" icon={iAdd} />;
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
@Component({
selector: 'docs-chip-icon-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<udx-chip label="Ajouter" [icon]="addIcon" />`,
})
export class ChipIconAngular {
protected readonly addIcon = iAdd;
}<script lang="ts">
import { iAdd } from '@udixio/icons-rounded-400/add';
import { Chip } from '@udixio/ui-svelte';
</script>
<Chip label="Ajouter" icon={iAdd} />Link or action
When href is provided, the component can behave as a link. Otherwise it acts as an interactive control (click/toggle).
import { Chip } from '@udixio/ui-react';
export default function ChipActionsReact() {
return (
<div className="flex flex-wrap gap-3">
<Chip label="Action" onClick={() => console.info('Action')} />
<Chip label="Documentation" href="/components/chip" />
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
@Component({
selector: 'docs-chip-actions-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap gap-3">
<udx-chip label="Action" (click)="runAction()" />
<udx-chip label="Documentation" href="/components/chip" />
</div>
`,
})
export class ChipActionsAngular {
protected runAction(): void {
console.info('Action');
}
}<script lang="ts">
import { Chip } from '@udixio/ui-svelte';
</script>
<div class="flex flex-wrap gap-3">
<Chip label="Action" onclick={() => console.info('Action')} />
<Chip label="Documentation" href="/components/chip" />
</div>States and accessibility
disabledmakes the chip inactive.- Selectable chips expose
aria-pressedautomatically. - Keep a touch target of at least 48 dp and sufficient contrast for the theme.
import { Chip } from '@udixio/ui-react';
export default function ChipDisabledReact() {
return (
<div className="flex flex-wrap gap-3">
<Chip label="Indisponible" disabled />
<Chip label="Lien indisponible" href="/components/chip" disabled />
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
@Component({
selector: 'docs-chip-disabled-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex flex-wrap gap-3">
<udx-chip label="Indisponible" disabled />
<udx-chip label="Lien indisponible" href="/components/chip" disabled />
</div>
`,
})
export class ChipDisabledAngular {}<script lang="ts">
import { Chip } from '@udixio/ui-svelte';
</script>
<div class="flex flex-wrap gap-3">
<Chip label="Indisponible" disabled />
<Chip label="Lien indisponible" href="/components/chip" disabled />
</div>Chips (list)
The Chips container component does not support a children mode. It only renders a list from items and notifies changes via onItemsChange in React, itemsChange in Angular, or onItemsChange/bind:items in Svelte.
The detailed contracts remain available separately in the Chip and Chips API references.
A stable application id is recommended, especially when items get reordered. Without an id, Chips keeps an internal identifier tied to the object in React and uses its position in Angular.
import { useState } from 'react';
import { Chips, type ChipItem } from '@udixio/ui-react';
export default function ChipsListReact() {
const [items, setItems] = useState<ChipItem[]>([{ id: 'photos', label: 'Photos', selected: true }, { id: 'videos', label: 'Videos', removable: true }]);
return <Chips label="Media filters" items={items} onItemsChange={setItems} />;
}import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { Chips } from '@udixio/ui-angular';
@Component({ selector: 'docs-chips-list-angular', standalone: true, imports: [Chips], changeDetection: ChangeDetectionStrategy.OnPush, template: `<udx-chips label="Media filters" [items]="items()" (itemsChange)="items.set($event)" />` })
export class ChipsListAngular { protected readonly items = signal([{ id: 'photos', label: 'Photos', selected: true }, { id: 'videos', label: 'Videos', removable: true }]); }<script lang="ts">
import { Chips } from '@udixio/ui-svelte';
let items = $state([
{ id: 'photos', label: 'Photos', selected: true },
{ id: 'videos', label: 'Videos', removable: true },
]);
</script>
<Chips label="Media filters" bind:items />selected turns an item into a controlled filter. removable adds the remove action at the end of the chip. An item that declares neither capability stays a compact action. Use scrollable when horizontal scrolling is preferable to wrapping.
Editing (variant=“input”)
- Double-click (or F2/Enter when the chip has focus and is not selectable) puts a chip into editing directly.
- Editing is inline via
contenteditable(no separate input field). Press Enter to commit, Escape to cancel, or blur to commit. - Committing an empty label on a removable chip removes the chip.
- The existing shortcuts remain: Enter/Space for selection, Backspace/Delete for
onRemovewhen the chip is selected and not being edited.
import { useState } from 'react';
import { Chip } from '@udixio/ui-react';
export default function ChipEditingReact() {
const [label, setLabel] = useState('Double-cliquez pour modifier');
return <Chip label={label} editable onEditCommit={setLabel} />;
}import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { Chip } from '@udixio/ui-angular';
@Component({
selector: 'docs-chip-editing-angular',
standalone: true,
imports: [Chip],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<udx-chip [label]="label()" editable (editCommit)="label.set($event)" />
`,
})
export class ChipEditingAngular {
protected readonly label = signal('Double-cliquez pour modifier');
}<script lang="ts">
import { Chip } from '@udixio/ui-svelte';
let label = $state('Double-cliquez pour modifier');
</script>
<Chip label={label} editable onEditCommit={(next) => (label = next)} />In React, holding focus for one second also starts editing. This deferred trigger does not exist in Angular; double-click, F2 and Enter remain common to both adapters.
With Chips variant="input", React additionally lets you click an empty area of the container to create a chip. Angular does not offer this creation shortcut yet: add the item in your application logic before editing it.