From 0cf53140451d4fb603e0d986ceb242fbcd5cac24 Mon Sep 17 00:00:00 2001 From: Emir Karabeg Date: Tue, 9 Jun 2026 18:38:18 -0700 Subject: [PATCH 1/3] improvement(emcn): consolidate chip chrome, enforce ChipModalField, paint real chrome in loading fallbacks - Move chip chrome single-source to chip/chip-chrome.ts (surface, typography, and new content tokens); delete chip-input/chip-field-chrome.ts - Rework Chip variants: implicit default replaces ghost, filled reserved for chip fields/triggers and removed from Chip's public API; add ChipChevron - Migrate every labeled modal body field to ChipModalField across knowledge, settings, tables, files, deploy, sidebar, and ee modals - Replace skeleton loading.tsx files with ResourceChromeFallback that paints the page's real header, actions, search/filter/sort chips, and column headers - Rename resource-options-bar to resource-options; simplify resource.tsx and resource-header - Delete legacy Breadcrumb, Callout, and FormField components - Add shared connector-config-fields (knowledge) and ee InfoNote; add useTagUsageQuery; make useInlineRename save async with isSaving - Update AGENTS.md/CLAUDE.md and emcn/styling rules (with .cursor/.agents mirrors) --- .agents/skills/emcn-design-review/SKILL.md | 338 ++---------- .claude/commands/emcn-design-review.md | 5 +- .claude/rules/emcn-components.md | 9 +- .claude/rules/sim-styling.md | 4 +- .cursor/commands/emcn-design-review.md | 19 +- .cursor/rules/emcn-components.mdc | 9 +- .cursor/rules/sim-styling.mdc | 4 +- AGENTS.md | 167 +----- CLAUDE.md | 4 +- apps/sim/app/(auth)/login/login-form.tsx | 7 +- .../landing-preview-tables.tsx | 2 +- .../components/request-integration-modal.tsx | 7 +- apps/sim/app/playground/page.tsx | 12 - .../connect-oauth-modal.tsx | 2 +- .../components/chip-field.ts | 5 +- .../components/unsaved-changes-modal.tsx | 2 +- .../[workspaceId]/components/index.ts | 19 +- .../inline-rename-input.tsx | 57 +- .../message-actions/message-actions.tsx | 4 +- .../resource-chrome-fallback/index.ts | 2 + .../resource-chrome-fallback.tsx | 92 ++++ .../components/resource-header/index.ts | 3 +- .../resource-header/resource-header.tsx | 215 ++++---- .../components/resource-options-bar/index.ts | 8 - .../components/resource-options/index.ts | 9 + .../resource-options.tsx} | 144 ++---- .../components/resource/resource.tsx | 309 ++++------- .../delete-confirm-modal.tsx | 2 +- .../components/file-viewer/docx-preview.tsx | 13 +- .../components/file-viewer/file-viewer.tsx | 24 +- .../components/file-viewer/pdf-viewer.tsx | 26 +- .../components/file-viewer/pptx-preview.tsx | 31 +- .../components/file-viewer/preview-panel.tsx | 21 +- .../components/file-viewer/preview-shared.tsx | 49 +- .../components/file-viewer/text-editor.tsx | 18 +- .../components/file-viewer/xlsx-preview.tsx | 33 +- .../workspace/[workspaceId]/files/files.tsx | 185 +++---- .../workspace/[workspaceId]/files/loading.tsx | 86 ++- .../workspace/[workspaceId]/files/page.tsx | 9 +- .../suggested-actions/suggested-actions.tsx | 2 +- .../connect-service-account-modal.tsx | 8 +- .../showcase-with-explore.tsx | 1 - .../connected-credential-detail.tsx | 2 +- .../delete-chunk-modal/delete-chunk-modal.tsx | 2 +- .../document-tags-modal.tsx | 9 +- .../knowledge/[id]/[documentId]/document.tsx | 94 ++-- .../knowledge/[id]/[documentId]/loading.tsx | 96 ++-- .../[workspaceId]/knowledge/[id]/base.tsx | 151 +++--- .../add-connector-modal.tsx | 236 +++------ .../add-documents-modal.tsx | 186 +++---- .../base-tags-modal/base-tags-modal.tsx | 137 +++-- .../connector-config-fields.tsx | 157 ++++++ .../connector-config-fields/index.ts | 1 + .../connectors-section/connectors-section.tsx | 20 +- .../edit-connector-modal.tsx | 131 +---- .../rename-document-modal.tsx | 2 +- .../[workspaceId]/knowledge/[id]/loading.tsx | 102 ++-- .../create-base-modal/create-base-modal.tsx | 489 ++++++++---------- .../delete-knowledge-base-modal.tsx | 2 +- .../edit-knowledge-base-modal.tsx | 2 +- .../[workspaceId]/knowledge/knowledge.tsx | 52 +- .../[workspaceId]/knowledge/loading.tsx | 85 +-- .../logs/components/dashboard/dashboard.tsx | 93 +--- .../notifications/notifications.tsx | 388 ++++++-------- .../workspace/[workspaceId]/logs/loading.tsx | 98 ++-- .../app/workspace/[workspaceId]/logs/logs.tsx | 71 ++- .../create-schedule-modal/schedule-modal.tsx | 396 +++++++------- .../[workspaceId]/scheduled-tasks/loading.tsx | 82 +-- .../scheduled-tasks/scheduled-tasks.tsx | 58 ++- .../settings/components/api-keys/api-keys.tsx | 1 - .../create-api-key-modal.tsx | 2 +- .../settings/components/billing/billing.tsx | 1 - .../settings/components/byok/byok.tsx | 3 +- .../settings/components/copilot/copilot.tsx | 2 - .../credential-sets/credential-sets.tsx | 6 +- .../components/custom-tools/custom-tools.tsx | 2 +- .../settings/components/general/general.tsx | 1 - .../inbox-enable-toggle.tsx | 11 +- .../inbox-settings-tab/inbox-settings-tab.tsx | 33 +- .../mcp/components/form-field/form-field.tsx | 21 - .../mcp/components/form-field/index.ts | 1 - .../components/mcp/components/index.ts | 1 - .../mcp-server-form-modal.tsx | 105 ++-- .../settings/components/mcp/mcp.tsx | 2 +- .../recently-deleted/recently-deleted.tsx | 5 +- .../secrets-manager/secrets-manager.tsx | 1 - .../no-organization-view.tsx | 7 +- .../organization-member-lists.tsx | 6 +- .../remove-member-dialog.tsx | 2 +- .../transfer-ownership-dialog.tsx | 2 +- .../components/teammates/teammates.tsx | 2 +- .../create-workflow-mcp-server-modal.tsx | 3 +- .../workflow-mcp-servers.tsx | 10 +- .../components/skill-import/skill-import.tsx | 1 - .../components/skill-modal/skill-modal.tsx | 2 +- .../workspace/[workspaceId]/skills/skills.tsx | 2 +- .../new-column-dropdown.tsx | 18 +- .../components/row-modal/row-modal.tsx | 218 +++----- .../components/table-grid/constants.ts | 3 - .../components/table-grid/table-grid.tsx | 263 ++++------ .../table-grid/table-primitives.tsx | 43 +- .../tables/[tableId]/loading.tsx | 66 +-- .../[workspaceId]/tables/[tableId]/table.tsx | 44 +- .../import-csv-dialog/import-csv-dialog.tsx | 119 ++--- .../[workspaceId]/tables/loading.tsx | 78 ++- .../workspace/[workspaceId]/tables/tables.tsx | 101 ++-- .../[workspaceId]/upgrade/upgrade.tsx | 3 +- .../deploy-modal/components/chat/chat.tsx | 1 - .../general/components/api-info-modal.tsx | 4 +- .../components/version-description-modal.tsx | 53 +- .../components/general/general.tsx | 4 +- .../components/deploy-modal/deploy-modal.tsx | 14 +- .../grouped-checkbox-list.tsx | 95 ++-- .../custom-tool-modal/custom-tool-modal.tsx | 9 +- .../w/[workflowId]/components/panel/panel.tsx | 7 +- .../components/help-modal/help-modal.tsx | 176 +++---- .../settings-sidebar/settings-sidebar.tsx | 2 +- .../components/delete-modal/delete-modal.tsx | 7 +- .../create-workspace-modal.tsx | 2 +- .../components/invite-modal/invite-modal.tsx | 4 +- .../workspace-header/workspace-header.tsx | 7 +- .../emcn/components/breadcrumb/breadcrumb.tsx | 52 -- .../emcn/components/callout/callout.tsx | 60 --- .../chip-date-picker/chip-date-picker.tsx | 8 +- .../chip-input/chip-field-chrome.ts | 8 - .../emcn/components/chip-input/chip-input.tsx | 2 +- .../emcn/components/chip-modal/chip-modal.tsx | 16 + .../components/chip-select/chip-select.tsx | 9 +- .../components/chip-switch/chip-switch.tsx | 2 +- .../chip-textarea/chip-textarea.tsx | 2 +- .../emcn/components/chip/chip-chevron.tsx | 34 ++ .../emcn/components/chip/chip-chrome.ts | 50 ++ .../components/emcn/components/chip/chip.tsx | 63 ++- .../dropdown-menu/dropdown-menu.tsx | 2 +- .../emcn/components/form-field/form-field.tsx | 28 - apps/sim/components/emcn/components/index.ts | 48 +- .../emcn/components/toast/toast.tsx | 1 - apps/sim/components/emcn/index.ts | 1 - .../components/access-control.tsx | 19 +- apps/sim/ee/components/info-note.tsx | 22 + .../components/data-drains-settings.tsx | 23 +- .../components/data-retention-settings.tsx | 5 +- apps/sim/ee/sso/components/sso-settings.tsx | 125 +++-- apps/sim/hooks/queries/kb/knowledge.ts | 32 ++ apps/sim/hooks/use-inline-rename.ts | 48 +- 145 files changed, 3134 insertions(+), 4210 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-chrome-fallback/index.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-chrome-fallback/resource-chrome-fallback.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-options-bar/index.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-options/index.ts rename apps/sim/app/workspace/[workspaceId]/components/resource/components/{resource-options-bar/resource-options-bar.tsx => resource-options/resource-options.tsx} (67%) create mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-config-fields/connector-config-fields.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/connector-config-fields/index.ts delete mode 100644 apps/sim/app/workspace/[workspaceId]/settings/components/mcp/components/form-field/form-field.tsx delete mode 100644 apps/sim/app/workspace/[workspaceId]/settings/components/mcp/components/form-field/index.ts delete mode 100644 apps/sim/components/emcn/components/breadcrumb/breadcrumb.tsx delete mode 100644 apps/sim/components/emcn/components/callout/callout.tsx delete mode 100644 apps/sim/components/emcn/components/chip-input/chip-field-chrome.ts create mode 100644 apps/sim/components/emcn/components/chip/chip-chevron.tsx create mode 100644 apps/sim/components/emcn/components/chip/chip-chrome.ts delete mode 100644 apps/sim/components/emcn/components/form-field/form-field.tsx create mode 100644 apps/sim/ee/components/info-note.tsx diff --git a/.agents/skills/emcn-design-review/SKILL.md b/.agents/skills/emcn-design-review/SKILL.md index 04e39da1f8e..b53d3e19582 100644 --- a/.agents/skills/emcn-design-review/SKILL.md +++ b/.agents/skills/emcn-design-review/SKILL.md @@ -13,12 +13,12 @@ User arguments: $ARGUMENTS ## Context -This codebase uses **emcn**, a custom component library built on Radix UI primitives with CVA (class-variance-authority) variants and CSS variable design tokens. All UI must use emcn components and tokens — never raw HTML elements or hardcoded colors. +This codebase uses **emcn**, a custom component library built on Radix UI primitives with CVA variants and CSS variable design tokens. All UI must use emcn components and tokens. ## Steps -1. Read the emcn barrel export at `apps/sim/components/emcn/components/index.ts` to know what's available -2. Read `apps/sim/app/_styles/globals.css` for the full set of CSS variable tokens +1. Read the emcn public barrel at `apps/sim/components/emcn/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `apps/sim/components/emcn/icons/index.ts` +2. Read `apps/sim/app/_styles/globals.css` for CSS variable tokens 3. Analyze the specified scope against every rule below 4. If fix=true, apply the fixes. If fix=false, propose the fixes without applying. @@ -26,313 +26,59 @@ This codebase uses **emcn**, a custom component library built on Radix UI primit ## Imports -- Import components from `@/components/emcn`, never from subpaths -- Import icons from `@/components/emcn/icons` or `lucide-react` -- Import `cn` from `@/lib/core/utils/cn` for conditional class merging -- Import app-specific wrappers (Select, VerifiedBadge) from `@/components/ui` +- Import from `@/components/emcn` barrel, never subpaths +- Icons from `@/components/emcn/icons` or `lucide-react` +- Use `cn` from `@/lib/core/utils/cn` for conditional classes -```tsx -// Good -import { Button, Modal, Badge } from '@/components/emcn' -// Bad -import { Button } from '@/components/emcn/components/button/button' -``` +## Design Tokens ---- - -## Design Tokens (CSS Variables) - -Never use raw color values. Always use CSS variable tokens via Tailwind arbitrary values: `text-[var(--text-primary)]`, not `text-gray-500` or `#333`. The CSS variable pattern is canonical (1,700+ uses) — do not use Tailwind semantic classes like `text-muted-foreground`. - -### Text hierarchy -| Token | Use | -|-------|-----| -| `text-[var(--text-primary)]` | Main content text | -| `text-[var(--text-secondary)]` | Secondary/supporting text | -| `text-[var(--text-tertiary)]` | Tertiary text | -| `text-[var(--text-muted)]` | Disabled, placeholder text | -| `text-[var(--text-icon)]` | Icon tinting | -| `text-[var(--text-inverse)]` | Text on dark backgrounds | -| `text-[var(--text-error)]` | Error/warning messages | - -### Surfaces (elevation) -| Token | Use | -|-------|-----| -| `bg-[var(--bg)]` | Page background | -| `bg-[var(--surface-2)]` through `bg-[var(--surface-7)]` | Increasing elevation | -| `bg-[var(--surface-hover)]` | Hover state backgrounds | -| `bg-[var(--surface-active)]` | Active/selected backgrounds | - -### Borders -| Token | Use | -|-------|-----| -| `border-[var(--border)]` | Default borders | -| `border-[var(--border-1)]` | Stronger borders (inputs, cards) | -| `border-[var(--border-muted)]` | Subtle dividers | - -### Status -| Token | Use | -|-------|-----| -| `--success` | Success states | -| `--error` | Error states | -| `--caution` | Warning states | - -### Brand -| Token | Use | -|-------|-----| -| `--brand-secondary` | Brand color | -| `--brand-accent` | Accent/CTA color | - -### Shadows -Use shadow tokens, never raw box-shadow values: -- `shadow-subtle`, `shadow-medium`, `shadow-overlay` -- `shadow-kbd`, `shadow-card` - -### Z-Index -Use z-index tokens for layering: -- `z-[var(--z-dropdown)]` (100), `z-[var(--z-modal)]` (200), `z-[var(--z-popover)]` (300), `z-[var(--z-tooltip)]` (400), `z-[var(--z-toast)]` (500) - ---- - -## Component Usage Rules - -### Buttons -Available variants: `default`, `primary`, `destructive`, `ghost`, `outline`, `active`, `secondary`, `tertiary`, `subtle`, `ghost-secondary`, `3d` - -| Action type | Variant | Frequency | -|-------------|---------|-----------| -| Toolbar, icon-only, utility actions | `ghost` | Most common (28%) | -| Primary action (create, save, submit) | `primary` | Very common (24%) | -| Cancel, close, secondary action | `default` | Common | -| Delete, remove, destructive action | `destructive` | Targeted use only | -| Active/selected state | `active` | Targeted use only | -| Toggle, mode switch | `outline` | Moderate | - -Sizes: `sm` (compact, 32% of buttons) or `md` (default, used when no size specified). Never create custom button styles — use an existing variant. - -Buttons without an explicit variant prop get `default` styling. This is acceptable for cancel/secondary actions. - -### Modals (Dialogs) -Use `Modal` + subcomponents. Never build custom dialog overlays. - -```tsx - - - Title - Content - - - - - - -``` - -Modal sizes by frequency: `sm` (440px, most common — confirmations and simple dialogs), `md` (500px, forms), `lg` (600px, content-heavy), `xl` (800px, rare), `full` (1200px, rare). - -Footer buttons: Cancel on left (`variant="default"`), primary action on right. This pattern is followed 100% across the codebase. - -### Delete/Remove Confirmations -Always use Modal with `size="sm"`. The established pattern: +Use CSS variable pattern (`text-[var(--text-primary)]`), never Tailwind semantics (`text-muted-foreground`) or hardcoded colors (`text-gray-500`, `#333`). -```tsx - - - Delete {itemType} - -

Description of consequences

-

Warning about irreversibility

-
- - - - -
-
-``` +**Text**: `--text-primary`, `--text-secondary`, `--text-tertiary`, `--text-muted`, `--text-body` (canonical value text), `--text-icon`, `--text-placeholder`, `--text-subtle`, `--text-inverse`, `--text-error` +**Surfaces**: `--bg`, `--surface-1` through `--surface-7`, `--surface-hover`, `--surface-active` +**Borders**: `--border`, `--border-1`, `--border-muted` +**Brand/accent**: `--brand-secondary`, `--brand-accent` +**Z-Index**: `--z-dropdown` (100), `--z-modal` (200), `--z-popover` (300), `--z-tooltip` (400), `--z-toast` (500) +**Shadows**: `shadow-subtle`, `shadow-medium`, `shadow-overlay`, `shadow-card` +**Badges**: `--badge-*` semantic families (success/error/gray/blue/purple/orange/amber/teal/cyan/pink, each with `-bg`/`-text`) -Rules: -- Title: "Delete {ItemType}" or "Remove {ItemType}" (use "Remove" for membership/association changes) -- Include consequence description -- Use `text-[var(--text-error)]` for warning text when the action is irreversible -- `variant="destructive"` for the action button (100% compliance) -- `variant="default"` for cancel (100% compliance) -- Cancel left, destructive right (100% compliance) -- For high-risk deletes (workspaces), require typing the name to confirm -- Include recovery info if soft-delete: "You can restore it from Recently Deleted in Settings" +## Buttons -### Toast Notifications -Use the imperative `toast` API from `@/components/emcn`. Never build custom notification UI. +Intent-to-variant mapping (read the actual `buttonVariants` in `apps/sim/components/emcn/components/button/button.tsx` for the full variant set — it exposes more than listed here): -```tsx -import { toast } from '@/components/emcn' +| Action | Variant | +|--------|---------| +| Toolbar, icon-only | `ghost` | +| Create, save, submit | `primary` | +| Cancel, close | `default` | +| Delete, remove | `destructive` | +| Selected state | `active` | +| Toggle | `outline` | -toast.success('Item saved') -toast.error('Something went wrong') -toast.success('Deleted', { action: { label: 'Undo', onClick: handleUndo } }) -``` +## Delete/Remove Confirmations -Variants: `default`, `success`, `error`. Auto-dismiss after 5s. Supports optional action buttons with callbacks. +`ChipModal` `size='sm'`, title "Delete/Remove {ItemType}", destructive confirm button, plain Cancel (follow the chip footer layout in `.claude/rules/emcn-components.md`). Use `text-[var(--text-error)]` for irreversible warnings. -### Badges -Use semantic color variants for status: +## Toast -| Status | Variant | Usage | -|--------|---------|-------| -| Error, failed, disconnected | `red` | Most common (15 uses) | -| Metadata, roles, auth types, scopes | `gray-secondary` | Very common (12 uses) | -| Type annotations (TS types, field types) | `type` | Very common (12 uses) | -| Success, active, enabled, running | `green` | Common (7 uses) | -| Neutral, default, unknown | `gray` | Common (6 uses) | -| Outline, parameters, public | `outline` | Moderate (6 uses) | -| Warning, processing | `amber` | Moderate (5 uses) | -| Paused, warning | `orange` | Occasional | -| Info, queued | `blue` | Occasional | -| Data types (arrays) | `purple` | Occasional | -| Generic with border | `default` | Occasional | +`toast.success()`, `toast.error()`, `toast()` from `@/components/emcn`. Never custom notification UI. -Use `dot` prop for status indicators (19 instances in codebase). `icon` prop is available but rarely used. +## Badges -### Tooltips -Use `Tooltip` from emcn with namespace pattern: +`red`=error/failed, `gray-secondary`=metadata/roles, `type`=type annotations, `green`=success/active, `gray`=neutral, `amber`=processing, `orange`=paused, `blue`=info. Use `dot` prop for status indicators. -```tsx - - - - - Helpful text - -``` +## Icons -Use tooltips for icon-only buttons and truncated text. Don't tooltip self-explanatory elements. - -### Popovers -Use for filters, option menus, and nested navigation: - -```tsx - - - - - - Section Title - - Item Label - - - - -``` - -### Dropdown Menus -Use for context menus and action menus: - -```tsx - - - - - - Edit - - - Delete - - - -``` - -Destructive items go last, after a separator, in error color. - -### Forms -Use `FormField` wrapper for labeled inputs: - -```tsx - - setName(e.target.value)} /> - -``` - -Rules: -- Use `Input` from emcn, never raw `` (exception: hidden file inputs) -- Use `Textarea` from emcn, never raw `