From 0dc6272da57d184724cd93ba7de8f0778a9d618f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Tue, 30 Jun 2026 11:17:48 +0200 Subject: [PATCH] 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. --- .../src/constants/template/package.json | 1 + .../src/front-components/main-page.tsx | 6 +- ...PersonResendEmailStats.front-component.tsx | 8 +- .../html-viewer/components/HtmlPreview.tsx | 14 +- .../components/RecordHtmlViewer.tsx | 14 +- ...ailBroadcastHtmlViewer.front-component.tsx | 8 +- .../components/ResendSyncStatus.tsx | 8 +- .../send-message-form.front-component.tsx | 8 +- .../references/concepts/how-apps-work.md | 6 +- .../develop-app/front-components.md | 11 +- .../scripts/validators/cross-doc-contracts.js | 8 +- .../extend/apps/layout/front-components.mdx | 72 ++- .../build-source-examples.ts | 27 +- .../twenty-ui-example.front-component.tsx | 13 +- packages/twenty-sdk/package.json | 8 - .../manifest-extract-config-from-file.ts | 24 +- packages/twenty-sdk/src/ui/index.ts | 513 ------------------ packages/twenty-sdk/vite.config.browser.ts | 14 +- 18 files changed, 163 insertions(+), 600 deletions(-) delete mode 100644 packages/twenty-sdk/src/ui/index.ts diff --git a/packages/create-twenty-app/src/constants/template/package.json b/packages/create-twenty-app/src/constants/template/package.json index c9ba7fd636..9d4ae15919 100644 --- a/packages/create-twenty-app/src/constants/template/package.json +++ b/packages/create-twenty-app/src/constants/template/package.json @@ -28,6 +28,7 @@ "react-dom": "^19.0.0", "twenty-client-sdk": "TO-BE-GENERATED", "twenty-sdk": "TO-BE-GENERATED", + "twenty-ui": "1.0.0-alpha.1", "typescript": "^5.9.3", "vite-tsconfig-paths": "^4.2.1", "vitest": "^4.0.0" diff --git a/packages/create-twenty-app/src/constants/template/src/front-components/main-page.tsx b/packages/create-twenty-app/src/constants/template/src/front-components/main-page.tsx index 98de444270..07370138f7 100644 --- a/packages/create-twenty-app/src/constants/template/src/front-components/main-page.tsx +++ b/packages/create-twenty-app/src/constants/template/src/front-components/main-page.tsx @@ -1,12 +1,12 @@ import { defineFrontComponent } from 'twenty-sdk/define'; +import { useState } from 'react'; +import { Avatar } from 'twenty-ui/data-display'; import { - Avatar, IconBox, IconHierarchy, IconLayout, IconSettingsAutomation, -} from 'twenty-sdk/ui'; -import { useState } from 'react'; +} from 'twenty-ui/icon'; import { APP_DISPLAY_NAME, diff --git a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/email-stats/front-components/PersonResendEmailStats.front-component.tsx b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/email-stats/front-components/PersonResendEmailStats.front-component.tsx index 55da62b7aa..42eebf5207 100644 --- a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/email-stats/front-components/PersonResendEmailStats.front-component.tsx +++ b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/email-stats/front-components/PersonResendEmailStats.front-component.tsx @@ -17,10 +17,10 @@ import { } from '@modules/resend/email-stats/constants/email-status-groups'; import { usePersonResendEmailStats } from '@modules/resend/email-stats/hooks/usePersonResendEmailStats'; -// Workaround: 'twenty-sdk/ui' currently fails typecheck because it re-exports -// from the unresolvable 'twenty-ui-deprecated'. Inline only the theme tokens -// this component uses, keeping the same runtime CSS-variable values. Revert to -// `import { themeCssVariables } from 'twenty-sdk/ui'` once the SDK export is fixed. +// Theme tokens are inlined as their CSS-variable values because the SDK mocks +// the UI package during manifest extraction, which would leave an imported +// `themeCssVariables` undefined at module level. The values mirror +// `twenty-ui/theme-constants`. const THEME_COLORS: ReadonlyArray = [ 'red', 'ruby', diff --git a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/HtmlPreview.tsx b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/HtmlPreview.tsx index 3ed90c5f87..305d047137 100644 --- a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/HtmlPreview.tsx +++ b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/HtmlPreview.tsx @@ -5,10 +5,10 @@ type HtmlPreviewProps = { html: string | null | undefined; }; -// Workaround: 'twenty-sdk/ui' currently fails typecheck because it re-exports -// from the unresolvable 'twenty-ui-deprecated'. Inline only the theme tokens -// this component uses, keeping the same runtime CSS-variable values. Revert to -// `import { themeCssVariables } from 'twenty-sdk/ui'` once the SDK export is fixed. +// Theme tokens are inlined as their CSS-variable values because the SDK mocks +// the UI package during manifest extraction, which would leave an imported +// `themeCssVariables` undefined at module level. The values mirror +// `twenty-ui/theme-constants`. const themeCssVariables = { spacing: { '4': 'var(--t-spacing-4)', @@ -28,9 +28,9 @@ const themeCssVariables = { }, }; -// Styles are computed lazily inside the component body because the SDK -// mocks `twenty-sdk/ui` at manifest-build time, which leaves -// `themeCssVariables` undefined during static module evaluation. +// Styles are computed lazily inside the component body because the SDK mocks +// the UI package at manifest-build time, which leaves `themeCssVariables` +// undefined during static module evaluation. const getStyles = (): Record => ({ emptyState: { display: 'flex', diff --git a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/RecordHtmlViewer.tsx b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/RecordHtmlViewer.tsx index aa8e10e467..b208f57763 100644 --- a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/RecordHtmlViewer.tsx +++ b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/components/RecordHtmlViewer.tsx @@ -9,10 +9,10 @@ type RecordHtmlViewerProps = { loadingText: string; }; -// Workaround: 'twenty-sdk/ui' currently fails typecheck because it re-exports -// from the unresolvable 'twenty-ui-deprecated'. Inline only the theme tokens -// this component uses, keeping the same runtime CSS-variable values. Revert to -// `import { themeCssVariables } from 'twenty-sdk/ui'` once the SDK export is fixed. +// Theme tokens are inlined as their CSS-variable values because the SDK mocks +// the UI package during manifest extraction, which would leave an imported +// `themeCssVariables` undefined at module level. The values mirror +// `twenty-ui/theme-constants`. const themeCssVariables = { spacing: { '4': 'var(--t-spacing-4)', @@ -39,9 +39,9 @@ const themeCssVariables = { }, }; -// Styles are computed lazily inside the component body because the SDK -// mocks `twenty-sdk/ui` at manifest-build time, which leaves -// `themeCssVariables` undefined during static module evaluation. +// Styles are computed lazily inside the component body because the SDK mocks +// the UI package at manifest-build time, which leaves `themeCssVariables` +// undefined during static module evaluation. const getStyles = (): Record => { const stateContainer: React.CSSProperties = { padding: themeCssVariables.spacing[4], diff --git a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/front-components/EmailBroadcastHtmlViewer.front-component.tsx b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/front-components/EmailBroadcastHtmlViewer.front-component.tsx index 27b7767712..54473a7fc8 100644 --- a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/front-components/EmailBroadcastHtmlViewer.front-component.tsx +++ b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/html-viewer/front-components/EmailBroadcastHtmlViewer.front-component.tsx @@ -6,10 +6,10 @@ import { EMAIL_BROADCAST_HTML_VIEWER_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from import { HtmlPreview } from '@modules/resend/html-viewer/components/HtmlPreview'; import { useRelatedBroadcastHtml } from '@modules/resend/html-viewer/hooks/useRelatedBroadcastHtml'; -// Workaround: 'twenty-sdk/ui' currently fails typecheck because it re-exports -// from the unresolvable 'twenty-ui-deprecated'. Inline only the theme tokens -// this component uses, keeping the same runtime CSS-variable values. Revert to -// `import { themeCssVariables } from 'twenty-sdk/ui'` once the SDK export is fixed. +// Theme tokens are inlined as their CSS-variable values because the SDK mocks +// the UI package during manifest extraction, which would leave an imported +// `themeCssVariables` undefined at module level. The values mirror +// `twenty-ui/theme-constants`. const themeCssVariables = { spacing: { '4': 'var(--t-spacing-4)', diff --git a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/manual-sync/components/ResendSyncStatus.tsx b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/manual-sync/components/ResendSyncStatus.tsx index c88f486126..e70f4f1208 100644 --- a/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/manual-sync/components/ResendSyncStatus.tsx +++ b/packages/twenty-apps/internal/twenty-for-twenty/src/modules/resend/manual-sync/components/ResendSyncStatus.tsx @@ -13,10 +13,10 @@ import { extractConnection } from '@modules/resend/shared/utils/typed-client'; import { RESEND_SYNC_CURSOR_STEPS } from '@modules/resend/sync/cursor/constants/resend-sync-cursor-steps'; import type { SyncCursorStep } from '@modules/resend/sync/cursor/types/sync-cursor-step'; -// Workaround: 'twenty-sdk/ui' currently fails typecheck because it re-exports -// from the unresolvable 'twenty-ui-deprecated'. Inline only the theme tokens -// this component uses, keeping the same runtime CSS-variable values. Revert to -// `import { themeCssVariables } from 'twenty-sdk/ui'` once the SDK export is fixed. +// Theme tokens are inlined as their CSS-variable values because the SDK mocks +// the UI package during manifest extraction, which would leave an imported +// `themeCssVariables` undefined at module level. The values mirror +// `twenty-ui/theme-constants`. const themeCssVariables = { spacing: { '1': 'var(--t-spacing-1)', diff --git a/packages/twenty-apps/public/twenty-slack/src/components/send-message-form.front-component.tsx b/packages/twenty-apps/public/twenty-slack/src/components/send-message-form.front-component.tsx index 5025cf9ac6..3356a2834e 100644 --- a/packages/twenty-apps/public/twenty-slack/src/components/send-message-form.front-component.tsx +++ b/packages/twenty-apps/public/twenty-slack/src/components/send-message-form.front-component.tsx @@ -4,10 +4,10 @@ import { closeSidePanel, enqueueSnackbar, unmountFrontComponent } from 'twenty-s import { SEND_MESSAGE_FORM_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from 'src/constants/universal-identifiers'; -// Workaround: 'twenty-sdk/ui' currently fails typecheck because it re-exports -// from the unresolvable 'twenty-ui-deprecated'. Inline only the theme tokens -// this component uses, keeping the same runtime CSS-variable values. Revert to -// `import { themeCssVariables } from 'twenty-sdk/ui'` once the SDK export is fixed. +// Theme tokens are inlined as their CSS-variable values because the SDK mocks +// the UI package during manifest extraction, which would leave an imported +// `themeCssVariables` undefined at module level. The values mirror +// `twenty-ui/theme-constants`. const themeCssVariables = { spacing: { '1': 'var(--t-spacing-1)', diff --git a/packages/twenty-codex-plugin/references/concepts/how-apps-work.md b/packages/twenty-codex-plugin/references/concepts/how-apps-work.md index f7197c5dfc..0390597509 100644 --- a/packages/twenty-codex-plugin/references/concepts/how-apps-work.md +++ b/packages/twenty-codex-plugin/references/concepts/how-apps-work.md @@ -14,14 +14,14 @@ A Twenty app depends on two SDK packages: | Package | Purpose | Used in | | --- | --- | --- | -| `twenty-sdk` | Define app entities and access front component runtime APIs | Entity definitions (`twenty-sdk/define`), front component hooks and host APIs (`twenty-sdk/front-component`), Twenty UI components (`twenty-sdk/ui`) | +| `twenty-sdk` | Define app entities and access front component runtime APIs | Entity definitions (`twenty-sdk/define`), front component hooks and host APIs (`twenty-sdk/front-component`) | | `twenty-client-sdk` | Access workspace data from front components | Core object queries (`twenty-client-sdk/core`), metadata queries (`twenty-client-sdk/metadata`) | `twenty-sdk/define` provides the registration functions: `defineApplication`, `defineObject`, `defineField`, `defineView`, `definePageLayout`, `defineFrontComponent`, `defineNavigationMenuItem`, `defineLogicFunction`, `defineRole`, and others. Every app entity is declared through one of these functions. `twenty-sdk/front-component` provides runtime APIs available inside front components: `navigate`, `enqueueSnackbar`, `openSidePanelPage`, `useSelectedRecordIds`, `getApplicationVariable`, and others. -`twenty-sdk/ui` re-exports Twenty UI components (`Button`, `Chip`, `Tag`, `Status`, `H2Title`, `ThemeProvider`, icons, `themeCssVariables`). Always import from `twenty-sdk/ui`, not from `twenty-ui` directly, so build aliases and runtime packaging stay aligned. +Twenty UI components (`Button`, `Chip`, `Tag`, `Status`, `H2Title`, `ThemeProvider`, icons, `themeCssVariables`) live in the `twenty-ui` package. Install `twenty-ui@1.0.0-alpha.1` from npm and import from its subpaths (`twenty-ui/input`, `twenty-ui/data-display`, `twenty-ui/icon`, `twenty-ui/typography`, `twenty-ui/theme-constants`, and others). `twenty-client-sdk/core` provides `CoreApiClient` for querying and mutating workspace records (companies, people, custom objects). `twenty-client-sdk/metadata` provides access to workspace metadata (object definitions, field definitions). @@ -75,7 +75,7 @@ Front components do not run as a separate frontend application. The Twenty works This means: - Front components cannot access `document` or `window` globals directly. - They cannot use React portals or third-party libraries that manipulate the DOM outside their tree. -- They import UI primitives from `twenty-sdk/ui`, not from `twenty-ui` or external component libraries. +- They import UI primitives from `twenty-ui` (installed from npm), not from external component libraries. - They fetch workspace data through `twenty-client-sdk/core`, not through direct API calls. ## App File Structure diff --git a/packages/twenty-codex-plugin/references/develop-app/front-components.md b/packages/twenty-codex-plugin/references/develop-app/front-components.md index b558f8807a..30caaf9e97 100644 --- a/packages/twenty-codex-plugin/references/develop-app/front-components.md +++ b/packages/twenty-codex-plugin/references/develop-app/front-components.md @@ -33,16 +33,15 @@ Keep imports narrow: - Use `twenty-sdk/front-component` for front component hooks and host APIs. - Use `twenty-client-sdk/core` or `twenty-client-sdk/metadata` for data access. -- Use `twenty-sdk/ui` for Twenty UI components, icons, and theme tokens before adding external UI libraries. -- Do not import from `twenty-ui` directly. Use the SDK re-export so build aliases and runtime packaging stay aligned. +- Install `twenty-ui@1.0.0-alpha.1` from npm and import Twenty UI components, icons, and theme tokens from its subpaths (`twenty-ui/input`, `twenty-ui/data-display`, `twenty-ui/icon`, `twenty-ui/typography`, `twenty-ui/theme-constants`, and others) before adding external UI libraries. -The front component renderer provides a Twenty `ThemeProvider` around the remote root. For isolated examples or local story-style verification, wrapping the component in `ThemeProvider` from `twenty-sdk/ui` is also acceptable. +The front component renderer provides a Twenty `ThemeProvider` around the remote root. For isolated examples or local story-style verification, wrapping the component in `ThemeProvider` from `twenty-ui/theme-constants` is also acceptable. -The canonical Twenty UI front component example is `packages/twenty-front-component-renderer/src/__stories__/example-sources/twenty-ui-example.front-component.tsx`. It imports `Button`, `Chip`, `H2Title`, `Status`, `Tag`, and `ThemeProvider` from `twenty-sdk/ui`. +The canonical Twenty UI front component example is `packages/twenty-front-component-renderer/src/__stories__/showcase/twenty-ui-example.front-component.tsx`. It imports `Button` from `twenty-ui/input`; `Chip`, `Status`, and `Tag` from `twenty-ui/data-display`; `H2Title` from `twenty-ui/typography`; and `ThemeProvider` from `twenty-ui/theme-constants`. -When using `themeCssVariables`, compute styles inside the component body or a function called by the component. The SDK mocks `twenty-sdk/ui` during manifest extraction, so module-level constants that dereference `themeCssVariables` can fail before the component renders. +Read theme tokens with the `useTheme()` hook from `twenty-ui/theme-constants` inside the component body. The same tokens are also exported as the `themeCssVariables` constant, but the SDK mocks `twenty-ui` during manifest extraction, so a module-level constant that dereferences `themeCssVariables` can fail before the component renders — prefer `useTheme()`. -Prefer Twenty UI icons from `twenty-sdk/ui` when one exists. Use inline SVG only for app-specific marks or icons that are not available through the SDK export. +Prefer Twenty UI icons from `twenty-ui/icon` when one exists. Use inline SVG only for app-specific marks or icons that are not available from `twenty-ui/icon`. ## Record Context And Data diff --git a/packages/twenty-codex-plugin/scripts/validators/cross-doc-contracts.js b/packages/twenty-codex-plugin/scripts/validators/cross-doc-contracts.js index 9a83a3c69f..44d8df6db3 100644 --- a/packages/twenty-codex-plugin/scripts/validators/cross-doc-contracts.js +++ b/packages/twenty-codex-plugin/scripts/validators/cross-doc-contracts.js @@ -82,12 +82,12 @@ const assertFrontComponentGuidance = (fail) => { 'defineFrontComponent', 'Use `twenty-sdk/front-component`', 'Use `twenty-client-sdk/core` or `twenty-client-sdk/metadata`', - 'Use `twenty-sdk/ui` for Twenty UI components', - 'Do not import from `twenty-ui` directly', + 'twenty-ui@1.0.0-alpha.1', + 'import Twenty UI components, icons, and theme tokens from its subpaths', 'ThemeProvider', - 'example-sources/twenty-ui-example.front-component.tsx', + 'showcase/twenty-ui-example.front-component.tsx', 'themeCssVariables', - 'mocks `twenty-sdk/ui` during manifest extraction', + 'mocks `twenty-ui` during manifest extraction', 'A clean typecheck and sync is not runtime verification', 'without a `FrontComponent error`', 'hard refresh', diff --git a/packages/twenty-docs/developers/extend/apps/layout/front-components.mdx b/packages/twenty-docs/developers/extend/apps/layout/front-components.mdx index 37124078b9..a267f835c1 100644 --- a/packages/twenty-docs/developers/extend/apps/layout/front-components.mdx +++ b/packages/twenty-docs/developers/extend/apps/layout/front-components.mdx @@ -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 ( +
+ Themed card +
+ ); +}; +``` + +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'`. diff --git a/packages/twenty-front-component-renderer/scripts/front-component-stories/build-source-examples.ts b/packages/twenty-front-component-renderer/scripts/front-component-stories/build-source-examples.ts index 553cca6504..6ecc9b5692 100644 --- a/packages/twenty-front-component-renderer/scripts/front-component-stories/build-source-examples.ts +++ b/packages/twenty-front-component-renderer/scripts/front-component-stories/build-source-examples.ts @@ -61,12 +61,37 @@ const twentySharedAliases = Object.fromEntries( ]), ); +const TWENTY_UI_SUBMODULES = [ + 'accessibility', + 'data-display', + 'feedback', + 'icon', + 'input', + 'json-visualizer', + 'layout', + 'navigation', + 'surfaces', + 'theme-constants', + 'typography', + 'utilities', +]; + +const twentyUiAliases = { + 'twenty-ui': twentyUiIndividualIndex, + ...Object.fromEntries( + TWENTY_UI_SUBMODULES.map((submodule) => [ + `twenty-ui/${submodule}`, + twentyUiIndividualIndex, + ]), + ), +}; + const storyAlias = { react: path.join(rootNodeModules, 'react'), 'react-dom': path.join(rootNodeModules, 'react-dom'), 'twenty-sdk/define': sdkDefineIndex, 'twenty-sdk/front-component': sdkFrontComponentIndex, - 'twenty-sdk/ui': twentyUiIndividualIndex, + ...twentyUiAliases, ...twentySharedAliases, }; diff --git a/packages/twenty-front-component-renderer/src/__stories__/showcase/twenty-ui-example.front-component.tsx b/packages/twenty-front-component-renderer/src/__stories__/showcase/twenty-ui-example.front-component.tsx index 06b796fe97..74a6f95568 100644 --- a/packages/twenty-front-component-renderer/src/__stories__/showcase/twenty-ui-example.front-component.tsx +++ b/packages/twenty-front-component-renderer/src/__stories__/showcase/twenty-ui-example.front-component.tsx @@ -1,14 +1,9 @@ import { defineFrontComponent } from 'twenty-sdk/define'; import { useState } from 'react'; -import { - Button, - Chip, - ChipVariant, - H2Title, - Status, - Tag, - ThemeProvider, -} from 'twenty-sdk/ui'; +import { Chip, ChipVariant, Status, Tag } from 'twenty-ui/data-display'; +import { Button } from 'twenty-ui/input'; +import { ThemeProvider } from 'twenty-ui/theme-constants'; +import { H2Title } from 'twenty-ui/typography'; const CARD_STYLE = { padding: 24, diff --git a/packages/twenty-sdk/package.json b/packages/twenty-sdk/package.json index 0a87dba23f..e7a3690adf 100644 --- a/packages/twenty-sdk/package.json +++ b/packages/twenty-sdk/package.json @@ -48,11 +48,6 @@ "import": "./dist/utils/index.mjs", "require": "./dist/utils/index.cjs" }, - "./ui": { - "types": "./dist/ui/index.d.ts", - "import": "./dist/ui/index.mjs", - "require": "./dist/ui/index.cjs" - }, "./cli": { "types": "./dist/cli/operations/index.d.ts", "import": "./dist/operations.mjs", @@ -135,9 +130,6 @@ "cli": [ "dist/cli/operations/index.d.ts" ], - "ui": [ - "dist/ui/index.d.ts" - ], "front-component-renderer": [ "dist/front-component-renderer/index.d.ts" ], diff --git a/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-extract-config-from-file.ts b/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-extract-config-from-file.ts index 04e935f0c9..26477ec354 100644 --- a/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-extract-config-from-file.ts +++ b/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-extract-config-from-file.ts @@ -16,22 +16,30 @@ type CompiledModuleWrapper = ( ) => void; const MANIFEST_MOCK_MODULES = [ - 'twenty-sdk/ui', + 'twenty-ui', 'twenty-client-sdk/core', 'twenty-client-sdk/metadata', ]; +const escapeRegExp = (value: string): string => + value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const manifestMockPlugin: esbuild.Plugin = { name: 'manifest-mock', setup: (build) => { - const filter = new RegExp( - `^(${MANIFEST_MOCK_MODULES.map((module) => module.replace('/', '\\/')).join('|')})$`, - ); + const escapedModules = MANIFEST_MOCK_MODULES.map(escapeRegExp); + const filter = new RegExp(`^(${escapedModules.join('|')})(/.*)?$`); - build.onResolve({ filter }, ({ path: modulePath }) => ({ - path: modulePath, - namespace: 'manifest-mock', - })); + build.onResolve({ filter }, ({ path: modulePath }) => { + if (modulePath.endsWith('.css')) { + return null; + } + + return { + path: modulePath, + namespace: 'manifest-mock', + }; + }); build.onLoad({ filter: /.*/, namespace: 'manifest-mock' }, () => ({ contents: 'module.exports = new Proxy({}, { get: () => () => {} });', diff --git a/packages/twenty-sdk/src/ui/index.ts b/packages/twenty-sdk/src/ui/index.ts deleted file mode 100644 index 76972f12b3..0000000000 --- a/packages/twenty-sdk/src/ui/index.ts +++ /dev/null @@ -1,513 +0,0 @@ -export * from 'twenty-ui/accessibility'; -export * from 'twenty-ui/data-display'; - -// Selective re-export from twenty-ui's component domains: -// IconsProvider, useIcons, and iconsState are excluded to avoid bundling -// the AllIcons module (~5000 Tabler icons) which adds ~4MB to the SDK dist. -export { - Banner, - Callout, - Info, - SidePanelInformationBanner, -} from 'twenty-ui/feedback'; -export { - Icon, - Icon123, - IconAddressBook, - IconAlertCircle, - IconAlertTriangle, - IconAlignBoxLeftTop, - IconAlignCenter, - IconAlignLeft, - IconAlignRight, - IconApi, - IconAppWindow, - IconApps, - IconArchive, - IconArchiveOff, - IconArrowBackUp, - IconArrowDown, - IconArrowLeft, - IconArrowMerge, - IconArrowRight, - IconArrowUp, - IconArrowUpRight, - IconArrowsDiagonal, - IconArrowsSort, - IconArrowsSplit2, - IconArrowsVertical, - IconAt, - IconAxisX, - IconAxisY, - IconBadge2k, - IconBaselineDensitySmall, - IconBell, - IconBlockquote, - IconBold, - IconBolt, - IconBook2, - IconBookmark, - IconBookmarkPlus, - IconBox, - IconBoxMultiple, - IconBrackets, - IconBracketsAngle, - IconBracketsContain, - IconBrain, - IconBrandAnthropic, - IconBrandDaysCounter, - IconBrandGemini, - IconBrandGithub, - IconBrandGoogle, - IconBrandGraphql, - IconBrandGroq, - IconBrandLinkedin, - IconBrandMistral, - IconBrandOpenai, - IconBrandX, - IconBrandXai, - IconBriefcase, - IconBroadcast, - IconBrowserMaximize, - IconBuildingSkyscraper, - IconCalendar, - IconCalendarDue, - IconCalendarEvent, - IconCalendarMonth, - IconCalendarRepeat, - IconCalendarTime, - IconCalendarWeek, - IconCalendarX, - IconCancel, - IconCaretLeft, - IconCaretRight, - IconChartBar, - IconChartBarHorizontal, - IconChartBarPopular, - IconChartCandle, - IconChartDots3, - IconChartLine, - IconChartPie, - IconCheck, - IconCheckbox, - IconChevronDown, - IconChevronLeft, - IconChevronRight, - IconChevronRightPipe, - IconChevronUp, - IconChevronsRight, - IconCircle, - IconCircleDashed, - IconCircleDot, - IconCircleOff, - IconCirclePlus, - IconCircleX, - IconClick, - IconClock, - IconClockHour8, - IconClockPlay, - IconClockShare, - IconCode, - IconCodeCircle, - IconCoins, - IconColorSwatch, - IconColumnInsertRight, - IconColumns, - IconCommand, - IconComment, - IconCopy, - IconCopyPlus, - IconCpu, - IconCreativeCommonsSa, - IconCreditCard, - IconCsv, - IconCube, - IconCurrencyAfghani, - IconCurrencyBahraini, - IconCurrencyBaht, - IconCurrencyDinar, - IconCurrencyDirham, - IconCurrencyDollar, - IconCurrencyDollarAustralian, - IconCurrencyDollarBrunei, - IconCurrencyDollarCanadian, - IconCurrencyDollarGuyanese, - IconCurrencyDollarSingapore, - IconCurrencyDong, - IconCurrencyDram, - IconCurrencyEuro, - IconCurrencyFlorin, - IconCurrencyForint, - IconCurrencyFrank, - IconCurrencyGuarani, - IconCurrencyHryvnia, - IconCurrencyIranianRial, - IconCurrencyKip, - IconCurrencyKroneCzech, - IconCurrencyKroneDanish, - IconCurrencyKroneSwedish, - IconCurrencyLari, - IconCurrencyLeu, - IconCurrencyLira, - IconCurrencyLyd, - IconCurrencyManat, - IconCurrencyNaira, - IconCurrencyPaanga, - IconCurrencyPeso, - IconCurrencyPound, - IconCurrencyQuetzal, - IconCurrencyReal, - IconCurrencyRenminbi, - IconCurrencyRiyal, - IconCurrencyRubel, - IconCurrencyRufiyaa, - IconCurrencyRupee, - IconCurrencyRupeeNepalese, - IconCurrencyShekel, - IconCurrencySom, - IconCurrencyTaka, - IconCurrencyTenge, - IconCurrencyTugrik, - IconCurrencyWon, - IconCurrencyYen, - IconCurrencyYuan, - IconCurrencyZloty, - IconDatabase, - IconDatabaseExport, - IconDecimal, - IconDeviceFloppy, - IconDoorEnter, - IconDotsVertical, - IconDownload, - IconEdit, - IconEditCircle, - IconEraser, - IconExclamationCircle, - IconExternalLink, - IconEye, - IconEyeOff, - IconEyeShare, - IconFile, - IconFileCheck, - IconFileExport, - IconFileImport, - IconFileInfo, - IconFilePencil, - IconFileText, - IconFileUpload, - IconFileZip, - IconFilter, - IconFilterCog, - IconFilterOff, - IconFilterPlus, - IconFilterX, - IconFilters, - IconFlag, - IconFlask, - IconFocusCentered, - IconFolder, - IconFolderOpen, - IconFolderPlus, - IconFolderRoot, - IconFolderSymlink, - IconForbid, - IconFrame, - IconFunction, - IconGauge, - IconGitBranchDeleted, - IconGitCommit, - IconGizmo, - IconGmail, - IconGoogle, - IconGoogleCalendar, - IconGripVertical, - IconH1, - IconH2, - IconH3, - IconH4, - IconH5, - IconH6, - IconHandClick, - IconHandMove, - IconHeadphones, - IconHeart, - IconHeartOff, - IconHeartRateMonitor, - IconHelp, - IconHelpCircle, - IconHierarchy, - IconHierarchy2, - IconHistory, - IconHistoryToggle, - IconHome, - IconHourglassHigh, - IconHours24, - IconHttpGet, - IconHttpPost, - IconId, - IconInbox, - IconInfoCircle, - IconItalic, - IconJetpack, - IconJson, - IconKey, - IconLanguage, - IconLayersLinked, - IconLayout, - IconLayoutDashboard, - IconLayoutGrid, - IconLayoutKanban, - IconLayoutList, - IconLayoutNavbar, - IconLayoutSidebarLeftCollapse, - IconLayoutSidebarRight, - IconLayoutSidebarRightCollapse, - IconLayoutSidebarRightExpand, - IconLetterK, - IconLibraryPlus, - IconLifebuoy, - IconLink, - IconLinkOff, - IconLinkPlus, - IconList, - IconListCheck, - IconListDetails, - IconListNumbers, - IconListSearch, - IconLoader, - IconLock, - IconLockCustom, - IconLockOpen, - IconLogin2, - IconLogout, - IconMail, - IconMailCog, - IconMailX, - IconMap, - IconMathMax, - IconMathMin, - IconMathXy, - IconMaximize, - IconMessage, - IconMessageCirclePlus, - IconMicrosoft, - IconMicrosoftCalendar, - IconMicrosoftOutlook, - IconMinus, - IconModelClaude, - IconMoneybag, - IconMoodSmile, - IconMoon, - IconMouse2, - IconNewSection, - IconNorthStar, - IconNoteOff, - IconNotes, - IconNumber, - IconNumber123, - IconNumber9, - IconNumbers, - IconPaint, - IconPaperclip, - IconPassword, - IconPencil, - IconPencilOff, - IconPercentage, - IconPhone, - IconPhoto, - IconPhotoUp, - IconPilcrow, - IconPinned, - IconPinnedOff, - IconPlayerPause, - IconPlayerPlay, - IconPlayerStop, - IconPlaylistAdd, - IconPlaystationSquare, - IconPlug, - IconPlus, - IconPoint, - IconPower, - IconPresentation, - IconPrinter, - IconProgressCheck, - IconProviderOpenai, - IconPuzzle, - IconPuzzle2, - IconQuestionMark, - IconRadiusBottomLeft, - IconRadiusBottomRight, - IconRadiusTopLeft, - IconRadiusTopRight, - IconRefresh, - IconRefreshAlert, - IconRefreshDot, - IconRelationManyToMany, - IconRelationManyToOne, - IconRelationOneToMany, - IconRelationOneToOne, - IconReload, - IconReorder, - IconRepeat, - IconRestore, - IconRobot, - IconRocket, - IconRotate, - IconRotate2, - IconRowInsertBottom, - IconRowInsertTop, - IconSearch, - IconSend, - IconServer, - IconServer2, - IconSettings, - IconSettings2, - IconSettingsAutomation, - IconSettingsBolt, - IconShare, - IconShield, - IconSitemap, - IconSlash, - IconSortAZ, - IconSortAscending, - IconSortAscendingLetters, - IconSortAscendingNumbers, - IconSortDescending, - IconSortDescendingLetters, - IconSortDescendingNumbers, - IconSortZA, - IconSparkles, - IconSpy, - IconSql, - IconSquare, - IconSquareKey, - IconSquareNumber1, - IconSquareNumber2, - IconSquareNumber3, - IconSquareNumber4, - IconSquareNumber5, - IconSquareNumber6, - IconSquareNumber7, - IconSquareNumber8, - IconSquareNumber9, - IconSquarePlus, - IconSquareRoundedCheck, - IconSquareRoundedX, - IconStack2, - IconStatusChange, - IconStepInto, - IconStrikethrough, - IconSum, - IconSun, - IconSunMoon, - IconSwitchHorizontal, - IconTable, - IconTag, - IconTags, - IconTarget, - IconTargetArrow, - IconTerminal, - IconTestPipe, - IconTextCaption, - IconTextSize, - IconTextWrap, - IconTimeDuration30, - IconTimeDuration60, - IconTimelineEvent, - IconTool, - IconTransform, - IconTrash, - IconTrashOff, - IconTrashX, - IconTrashXOff, - IconTrendingDown, - IconTrendingUp, - IconTwentyStar, - IconTwentyStarFilled, - IconTypography, - IconUnderline, - IconUnlink, - IconUpload, - IconUser, - IconUserCircle, - IconUserCog, - IconUserPin, - IconUserPlus, - IconUsers, - IconVariable, - IconVariablePlus, - IconVersions, - IconVersionsOff, - IconVideo, - IconWand, - IconWebhook, - IconWorld, - IconX, - IllustrationIconArray, - IllustrationIconCalendarEvent, - IllustrationIconCalendarTime, - IllustrationIconCurrency, - IllustrationIconFile, - IllustrationIconJson, - IllustrationIconLink, - IllustrationIconMail, - IllustrationIconManyToMany, - IllustrationIconMap, - IllustrationIconNumbers, - IllustrationIconOneToMany, - IllustrationIconOneToOne, - IllustrationIconPhone, - IllustrationIconSetting, - IllustrationIconStar, - IllustrationIconTag, - IllustrationIconTags, - IllustrationIconText, - IllustrationIconToggle, - IllustrationIconUid, - IllustrationIconUser, - IllustrationIconWrapper, - ThinkingOrbitLoaderIcon, -} from 'twenty-ui/icon'; -export { HorizontalSeparator } from 'twenty-ui/layout'; -export { - AppTooltip, - OverflowingTextWithTooltip, - TooltipDelay, - TooltipPosition, -} from 'twenty-ui/surfaces'; -export { - H1Title, - H1TitleFontColor, - H2Title, - H3Title, - Label, - SeparatorLineText, - StyledText, - StyledTextContent, - StyledTextWrapper, -} from 'twenty-ui/typography'; -export type { - BannerColor, - BannerVariant, - CalloutProps, - CalloutVariant, - InfoAccent, - InfoProps, - SidePanelInformationBannerProps, -} from 'twenty-ui/feedback'; -export type { - IconComponent, - IconComponentProps, - IconProps, - TablerIconsProps, -} from 'twenty-ui/icon'; -export type { AppTooltipProps } from 'twenty-ui/surfaces'; -export type { LabelVariant } from 'twenty-ui/typography'; - -export * from 'twenty-ui/feedback'; -export * from 'twenty-ui/input'; -export * from 'twenty-ui/json-visualizer'; -export * from 'twenty-ui/layout'; -export * from 'twenty-ui/navigation'; -export * from 'twenty-ui/theme-constants'; -export * from 'twenty-ui/utilities'; diff --git a/packages/twenty-sdk/vite.config.browser.ts b/packages/twenty-sdk/vite.config.browser.ts index 274aedd2da..066fe27fec 100644 --- a/packages/twenty-sdk/vite.config.browser.ts +++ b/packages/twenty-sdk/vite.config.browser.ts @@ -18,7 +18,7 @@ export default defineConfig(() => { emptyOutDir: false, outDir: 'dist', lib: { - entry: ['src/ui/index.ts', 'src/front-component-renderer/index.ts'], + entry: ['src/front-component-renderer/index.ts'], name: 'twenty-sdk', }, rollupOptions: { @@ -42,12 +42,6 @@ export default defineConfig(() => { { format: 'es', entryFileNames: (chunk) => { - if ( - chunk.name === 'index' && - chunk.facadeModuleId?.includes('ui/index.ts') - ) { - return 'ui/index.mjs'; - } if ( chunk.facadeModuleId?.includes( 'front-component-renderer/index.ts', @@ -63,12 +57,6 @@ export default defineConfig(() => { esModule: true, exports: 'named', entryFileNames: (chunk) => { - if ( - chunk.name === 'index' && - chunk.facadeModuleId?.includes('ui/index.ts') - ) { - return 'ui/index.cjs'; - } if ( chunk.facadeModuleId?.includes( 'front-component-renderer/index.ts',