Files
twenty/packages/twenty-ui/vite.config.individual.ts
T
Charles Bochet 9c4b0f526c 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"
/>
2026-03-02 15:48:49 +01:00

75 lines
1.8 KiB
TypeScript

import react from '@vitejs/plugin-react-swc';
import wyw from '@wyw-in-js/vite';
import * as path from 'path';
import { defineConfig } from 'vite';
import svgr from 'vite-plugin-svgr';
import tsconfigPaths from 'vite-tsconfig-paths';
import packageJson from './package.json';
const depNames = Object.keys(packageJson.dependencies || {});
const isExternal = (id: string): boolean =>
depNames.some((dep) => id === dep || id.startsWith(dep + '/'));
export default defineConfig(() => {
return {
resolve: {
alias: {
'@ui/': path.resolve(__dirname, 'src') + '/',
'@assets/': path.resolve(__dirname, 'src/assets') + '/',
},
},
css: {
modules: {
localsConvention: 'camelCaseOnly',
},
},
root: __dirname,
cacheDir: '../../node_modules/.vite/packages/twenty-ui-individual',
assetsInclude: ['src/**/*.svg'],
plugins: [
react(),
tsconfigPaths({
root: __dirname,
projects: ['tsconfig.json'],
}),
svgr(),
{
...wyw({
babelOptions: {
presets: ['@babel/preset-typescript', '@babel/preset-react'],
},
}),
enforce: 'pre',
},
],
build: {
cssCodeSplit: false,
minify: 'esbuild',
sourcemap: true,
outDir: './dist/individual',
emptyOutDir: true,
commonjsOptions: {
transformMixedEsModules: true,
interopDefault: true,
defaultIsModuleExports: true,
requireReturnsDefault: 'auto',
},
lib: {
entry: 'src/individual-entry.ts',
formats: ['es'],
},
rollupOptions: {
external: isExternal,
output: {
preserveModules: true,
preserveModulesRoot: 'src',
entryFileNames: '[name].js',
},
},
},
logLevel: 'warn',
};
});