Remove twenty-ui reexport from the SDK and use twenty-ui directly (#22326)

## What & why

Removes the `twenty-sdk/ui` reexport. Apps now use Twenty UI by
installing
[`twenty-ui@1.0.0-alpha.1`](https://www.npmjs.com/package/twenty-ui/v/1.0.0-alpha.1)
from npm and importing its subpaths directly. The reexport re-exported
types that didn't resolve, forcing typecheck workarounds.

## Changes

- **twenty-sdk**: delete `src/ui/index.ts`, drop the `./ui` export,
remove it from the browser vite build, and rewire the CLI manifest-mock
to `twenty-ui` (`.css` falls through to the empty-CSS loader).
`twenty-ui` stays a devDependency for the CLI fixture tests.
- **Renderer + create-twenty-app template**: import from `twenty-ui`
subpaths; the template pins `twenty-ui@1.0.0-alpha.1`.
- **Docs**: new "Using Twenty UI components" section (install + subpath
imports + `useTheme()` for theme tokens), codex references, and the
cross-doc-contract validator.

The `twenty-for-twenty` / `twenty-slack` example apps are intentionally
left on `twenty-sdk/ui`: they consume the published SDK (which still
ships `./ui`), and `twenty-ui@1.0.0-alpha.1` requires react 19 + a
`monaco-editor` peer the react-18 apps can't satisfy. They migrate once
the SDK is republished.
This commit is contained in:
Raphaël Bosi
2026-06-30 11:17:48 +02:00
committed by GitHub
parent b0d7516951
commit 0dc6272da5
18 changed files with 163 additions and 600 deletions
@@ -523,15 +523,43 @@ See the [public assets section](/developers/extend/apps/config/public-assets) fo
Front components support multiple styling approaches. You can use:
- **Inline styles** — `style={{ color: 'red' }}`
- **Twenty UI components** — import from `twenty-sdk/ui` (Button, Tag, Status, Chip, Avatar, and more)
- **Twenty UI components** — Twenty's own component library; see [Using Twenty UI components](#using-twenty-ui-components) below
- **Emotion** — CSS-in-JS with `@emotion/react`
- **Styled-components** — `styled.div` patterns
- **Tailwind CSS** — utility classes
- **Any CSS-in-JS library** compatible with React
## Using Twenty UI components
Twenty ships its component library as the [`twenty-ui`](https://www.npmjs.com/package/twenty-ui/v/1.0.0-alpha.1) package. Front components can use it for buttons, tags, status pills, chips, avatars, icons, typography, and theme tokens that automatically match the workspace's light and dark theme.
### Installation
Add the package to your app, pinned to the version your Twenty instance ships:
```bash
yarn add twenty-ui@1.0.0-alpha.1
```
`twenty-ui` is bundled into your front component at build time, so it only needs to be a dependency of your app — there is nothing to configure at runtime.
### Importing components
Import from the matching subpath rather than the package root, so only the components you use end up in your bundle:
| Subpath | What it exports |
| --- | --- |
| `twenty-ui/input` | `Button` and form inputs |
| `twenty-ui/data-display` | `Tag`, `Status`, `Chip`, `Avatar`, and more |
| `twenty-ui/feedback` | `Callout`, `Banner`, `Info`, and more |
| `twenty-ui/typography` | `H1Title`, `H2Title`, `H3Title`, `Label`, and more |
| `twenty-ui/icon` | `Icon*` components (e.g. `IconCheck`) |
| `twenty-ui/theme-constants` | `ThemeProvider`, `themeCssVariables` |
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
import { Status, Tag } from 'twenty-ui/data-display';
import { Button } from 'twenty-ui/input';
const StyledWidget = () => {
return (
@@ -549,3 +577,43 @@ export default defineFrontComponent({
component: StyledWidget,
});
```
### Icons
Import individual icons from `twenty-ui/icon`:
```tsx
import { IconBox, IconCheck } from 'twenty-ui/icon';
```
Each named icon is tree-shaken, so importing a handful adds little to your bundle. Avoid `IconsProvider`, `useIcons`, and `iconsState` — they pull in the full Tabler icon set (several MB).
### Theming and theme tokens
Twenty UI components automatically match the workspace's light and dark theme — the renderer applies the active color scheme on the host, and the components resolve their colors against it.
To use the same design tokens in your own inline styles, call the `useTheme()` hook. It returns Twenty's theme tokens (spacing, colors, radii, fonts) wired to the active theme, with no `ThemeProvider` setup needed in your component:
```tsx
import { useTheme } from 'twenty-ui/theme-constants';
const Card = () => {
const theme = useTheme();
return (
<div
style={{
padding: theme.spacing[4],
background: theme.background.secondary,
color: theme.font.color.primary,
}}
>
Themed card
</div>
);
};
```
Because `useTheme()` is a hook, you read tokens inside the component body, so the values always reflect the live theme. The same token map is also exported as the `themeCssVariables` constant, but prefer `useTheme()` in front components — a module-level constant that dereferences `themeCssVariables` can be undefined while the app manifest is extracted.
To branch on the active scheme explicitly, read it with `useColorScheme()` from `twenty-sdk/front-component`, which returns `'light'` or `'dark'`.