Refactor chip component hierarchy: AvatarChip → AvatarOrIcon (#18313)

## Summary

Cleans up the chip component hierarchy in `twenty-ui`:

- **Fix twenty-ui Storybook** — The `wyw-in-js` Vite plugin crashed on
`/@react-refresh` virtual module. Fixed by setting `enforce: 'pre'` so
it runs before the React refresh plugin injects virtual imports.
- **Rename `AvatarChip` → `AvatarOrIcon`** — The old name was
misleading. This component is not a chip — it's a polymorphic renderer
that displays either an `Avatar` (image/initials) or an `Icon` (plain or
with colored background). It's typically slotted into `Chip`/`LinkChip`
as `leftComponent`.
- **Move `rightComponentDivider` to `Chip`/`LinkChip`** — The vertical
separator between chip content and a right action (e.g. a close button)
is a chip layout concern, not an avatar concern. Added
`rightComponentDivider` boolean prop to `Chip` and `LinkChip`.
- **Remove `MultipleAvatarChip`** — Zero consumers in the codebase. The
command menu implements its own overlapping avatar layout.
- **Migrate raw icon usages** — `CalendarEventDetails` and `FileIcon`
(small size) now use `AvatarOrIcon` for consistent Chip icon rendering.
- **Enhance stories** — Full `CatalogDecorator` coverage for `Chip` and
`LinkChip` showing all variants, sizes, accents, and states.

## Component hierarchy

```
AvatarOrIcon (twenty-ui)
  ├── No Icon → renders Avatar (image or initials)
  ├── Icon + background → renders icon in colored square
  └── Icon only → renders plain icon
  Used as leftComponent/rightComponent in Chip or standalone

Chip (twenty-ui)
  ├── leftComponent (typically AvatarOrIcon)
  ├── label (with overflow tooltip)
  ├── rightComponentDivider (optional vertical separator)
  └── rightComponent (e.g. close icon via AvatarOrIcon)

LinkChip (twenty-ui)
  └── Wraps Chip inside a react-router <Link>

RecordChip (twenty-front)
  └── Composes Chip/LinkChip + AvatarOrIcon with record data
```

## `Chip` API additions

| Prop | Type | Description |
|------|------|-------------|
| `rightComponentDivider` | `boolean` | Renders a vertical separator
before `rightComponent` |

## Stories

<img width="1032" height="576" alt="image"
src="https://github.com/user-attachments/assets/fe7c7666-9b16-4545-b87e-1b53e22d462d"
/>
This commit is contained in:
Charles Bochet
2026-03-02 15:48:49 +01:00
committed by GitHub
parent 37bcb35391
commit 9c4b0f526c
21 changed files with 413 additions and 205 deletions
@@ -22,7 +22,7 @@ import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomState
import { useState } from 'react';
import { getImageAbsoluteURI, isDefined } from 'twenty-shared/utils';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import { AvatarChip, Chip } from 'twenty-ui/components';
import { AvatarOrIcon, Chip } from 'twenty-ui/components';
import {
H2Title,
IconEyeShare,
@@ -151,7 +151,7 @@ export const SettingsAdminWorkspaceContent = ({
label={activeWorkspace?.name ?? ''}
emptyLabel={t`Untitled`}
leftComponent={
<AvatarChip
<AvatarOrIcon
avatarUrl={
getImageAbsoluteURI({
imageUrl: isNonEmptyString(activeWorkspace?.logo)