Skip to content

Account – Workspaces

  • Path: /account/workspaces
  • Parent: README.md

View and manage workspaces within the organization (create, browse, configure).

  • Org Admin, Workspace Admin
  • Permissions: workspace.list, workspace.create, workspace.manage (TBD)

Reference: Permissions model

Client-side mock only. No API integration exists yet. All data is held in React state seeded with the values below.

Group: { id: "default", name: "Default group" }

Workspace: (default display name is “My Workspace”; user can rename via Edit workspace)

{
id: "ws-1",
name: "My Workspace",
defaultKbId: "kb-default-1",
defaultAgentId: "agent-default-1",
groupId: "default",
description: "This first workspace. A default knowledge base is already connected and must be configured for AI to work.",
numberOfKnowledgeBases: 1,
numberOfUsers: 1,
connectedApps: [],
appsActivated: false
}

Dialogs that include a Cancel button in the footer must not show a close (×) button in the top-right of the header. The user dismisses via Cancel or the primary action only. This avoids duplicate ways to close and keeps the pattern consistent.

Workspace and related account dialogs use a shared width scale:

  • Small (sm): max-w-[400px] — compact confirms and small single-purpose dialogs.
  • Medium (md): max-w-[480px] — standard edit dialogs; default choice.
  • Large (lg): max-w-[640px] — large multi-step or dense form dialogs.

Standard workspace edit dialogs use the md width inside a rounded-[16px] bg-card shadow-xl flex flex-col overflow-hidden container:

RegionTailwind classesNotes
Headerpx-6 py-4 border-b border-[#ebebeb]Title text-[16px] font-semibold. No × when Cancel is in footer.
Bodyflex flex-col gap-4 px-6 py-5Form fields or confirmation content.
Footerpx-6 py-4 border-t border-[#ebebeb]Action buttons.

Divider rule: Use border-[#ebebeb] (not border-border) for dialog header/footer dividers. The border-border token resolves to the same value but using the literal prevents invisible dividers if the token is overridden by a surface-specific dark mode rule.

Control radius rule: Inside dialog bodies, standard form controls and card-like utility rows should use rounded-md for a consistent, professional visual rhythm. Avoid mixing 8px, 10px, and larger radii within the same form unless a component has a strong, intentional reason to differ.

Overlay: fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4.

Simple confirmation dialogs (Delete workspace, Delete group, Add group) may omit the header/footer dividers and use a single padded surface when they contain only a title, short body text, and two action buttons.

The page follows the standard account shell layout:

  • Merged top section (border-b #ebebeb, px-6 py-5):
    • Title “Workspaces” + count badge with cards_star icon. This top badge always shows the total number of workspaces in the account, regardless of active filters.
    • Below the title row, in the same surface with no internal divider:
      • Left: shared “All workspaces” workspace-filter combobox (cards_star icon) plus the “All groups” filter button (stacks icon).
      • Right: view switcher pill + “Add workspace” primary button.
  • Content area (p-6): card grid or table depending on active view.

Two view modes are supported and persisted to localStorage under the key "workspaces-view". Default is "card".

ModeIconBehaviour
Cardgrid_viewAuto-fit grid (minmax(320px, 1fr)). Cards grouped by group (no toggle in MVP).
TabledehazeFull-width table with pagination. Columns: Name, Description, Group, KBs, Agents, Users, Channels.

The view switcher has exactly two buttons in order: Card first, Table second. User preference is persisted to localStorage key "workspaces-view".

  • Each card: workspace avatar in a fixed-size box — when an image is set it must fill the box (no letterboxing/pillarboxing; e.g. w/h: 100% + object-cover + matching radius); when no image is set, show the photo_camera placeholder icon centered in the same box — plus name, description, Details section (KB count + user count), Apps chips.
  • “All groups” control is a multi-select combobox (see Toolbar behaviours). Which groups are visible is controlled by the selection. When the selection is empty, all groups are shown; when one or more groups are selected, only those groups appear as section headings with their workspaces. There is no toggle to hide group headings in MVP.
  • Visible groups: When the filter selection is empty, all groups are shown (including groups with zero workspaces). When one or more groups are selected, only those groups appear. A group with no workspaces appears as a section with only the group header and no cards below it (empty state). Historical design reference: Figma – empty group in card view.
  • Group header: Each group section uses the reusable GroupBadge component: shadcn Badge (solid, secondary variant) with group name; on hover, a three-dots button appears. Menu: Rename (inline edit), Add group, Delete. Delete is disabled when the group is the default group or when it is the only remaining group. Same component is used on the workspace open page for the group topper. Rename must not accept a name that duplicates another group (case-insensitive); show inline error and do not apply the rename.
    • Add group: Opens the Add group dialog. User enters a name; Add creates the group (when unique) and closes the dialog. Cancel closes without creating.
    • Delete (when enabled): If the group has no workspaces, it is deleted immediately with no confirmation. If the group has one or more workspaces, a confirmation dialog opens: Delete moves all workspaces in that group to the default group and removes the group; Cancel closes without changes.
  • Workspace card click: Clicking the card (avatar, name, description, details, or apps area) navigates to the open workspace page at /account/workspaces/[workspaceId]. The three-dot menu and drag-and-drop must not trigger navigation. See Workspace open.
  • Workspace card overflow menu: Each card has a three-dot “more” button in the header. Clicking it opens a menu: Edit, Duplicate, Delete (with divider before Delete). Edit opens the Edit workspace dialog. Duplicate creates a copy of the workspace with name "{original name} (Copy)" and the same group. Delete is disabled when the account has only one workspace; otherwise it opens the Delete workspace confirmation dialog. The platform must always retain at least one workspace.
  • Drag and drop (card view only): When group headings are visible, workspace cards can be dragged and dropped between groups. The user drags a card from one group section and drops it onto another group’s area (e.g. the group header or the group’s card list). On drop, the workspace’s groupId is updated to the target group and the card appears in that group. No dialog or confirmation is required for the move. Dragging is not available when group headings are hidden (flat grid). Table view does not support drag-and-drop for moving between groups; the user can change group via the Edit workspace dialog.

Historical design reference: Figma – Table view with multiple workspaces.

  • Group visibility follows the same filter as card view. When the group filter selection is empty, all groups are visible. When one or more groups are selected, only those groups are visible in table view as well. The table is ordered by group (in the same order as in the group list), but it does not render a separate group header/divider row. The Group column displays the group name on each row, so a dedicated group header row is redundant. Groups with zero workspaces still appear: they show a single empty-state row (e.g. “No workspaces in this group”) with the group name shown in the Group column for that row.
  • Header columns: Name | Description | Group | KBs | Agents | Users | Channels (total number). Header text: 14px, medium weight, #333. Row padding 16px; 1px row separators; white row background.
  • Sortable headers: The headers that have meaningful ordering should use the same inline button pattern as other account tables, with swap_vert when inactive and arrow_upward / arrow_downward when active. Sortable columns for MVP: Name, Group, KBs, Agents, Users, and Channels. Description remains static text.
  • Table section header: Above the table grid, show title “Workspaces” plus a live count with the cards_star icon, and a view_column control button. This section count reflects the currently visible filtered table dataset.
  • Column visibility control: view_column opens a popover with per-column pill toggles (Switch size="sm"). The first column (Name) is always visible and its toggle is disabled. Other columns can be shown/hidden.
  • Data cells: 14px text. Description and long text use ellipsis. KBs, Agents, Users, and Channels are numeric values with compact icons.
  • Row click behavior: Clicking a workspace row (name, description, group, and metric cells) navigates to /account/workspaces/[workspaceId], matching workspace-card behavior.
  • Row hover: #fafafa background.
  • Pagination footer: Left: total count text (e.g. “4 workspaces”). Right: “Rows per page” label + dropdown (10 / 25 / 50 / 100, default 25); then “Page N of M” (e.g. “Page 1 of 1”); then four navigation buttons: first page (keyboard_double_arrow_left), previous (keyboard_arrow_left), next (keyboard_arrow_right), last page (keyboard_double_arrow_right). Buttons use border #ccc, rounded 8px; disabled state for first/prev when on page 1 and for next/last when on last page.

All workspaces filter (multi-select combobox)

Section titled “All workspaces filter (multi-select combobox)”

The All workspaces control uses the shared account workspace-filter combobox. It is a checkbox-based multi-select trigger with a leading cards_star icon and the label “All workspaces” when nothing is selected.

Behaviour (selection logic):

  1. Default (nothing selected): By default no workspaces are checked. Empty selection means show all workspaces.
  2. Specific workspace(s) selected: When one or more workspaces are checked, only those workspaces remain visible in the current page view.
  3. Select all / Deselect: The dropdown includes the same Select all / Deselect affordance as other multi-select account filters.
  4. Trigger label: One selected workspace shows its name; multiple selections collapse to a count label (for example 3 workspaces).
  5. Group dependency: Clearing the workspace selection also clears any active group selection so the page returns to the full unfiltered state.

All groups and group filter (multi-select combobox)

Section titled “All groups and group filter (multi-select combobox)”

Historical design reference: Figma – Group filter dropdown sheet.

The All groups control is a multi-select combobox (trigger shows “All groups” with stacks icon; click opens a dropdown). On the Workspaces page the control is always enabled. The selection applies in both card view and table view. When no groups are selected (empty selection), all groups are shown.

Dropdown panel layout (when combobox is open):

  • Container: Panel ~240px wide, white background, border #e5e5e5, rounded 12px, shadow. Positioned below the “All groups” trigger; click outside or Escape closes it.
  • Search: Top section with a single text input, placeholder “Search…”. Used to filter the list of groups inside the panel (so the user can find a group by name). Does not filter workspaces on the page.
  • Header row: Label “Groups” (left, 12px, muted color) and a link on the right: “Select all” or “Deselect”. See Behaviour below.
  • Group list: Scrollable list of all groups. Each row: group name (14px, #333) + checkbox (16px). Checkboxes use the shadcn neutral theme: dark fill when checked, light border when unchecked. List has internal scroll when there are many groups.

Behaviour (selection logic):

  1. Default (nothing selected): By default no checkboxes are selected. An empty selection means show all groups — all groups and their workspaces are visible. This is the initial state.
  2. Specific group(s) selected: When the user checks one or more groups, only those groups (and their workspaces) are shown. Unchecking all returns to “show all” (empty selection).
  3. Select all: The link “Select all” checks every group checkbox at once (show all groups by selection). It is a UX shortcut so the user can then deselect the groups they don’t want, leaving only the ones they do.
  4. Deselect: When all groups are currently checked, the link changes to “Deselect”. Clicking it clears the selection (unchecks all), which again means show all groups.
  5. Visibility: Empty selection → show all groups. Non-empty selection → show only workspaces in selected groups. In card view, only the visible groups appear as section headings; in table view, only those groups are visible. Empty selected groups still show a single “No workspaces in this group” row with the group name shown in the Group column.
  6. Workspace dependency: Clearing the workspace selection also clears any active group selection. On the Workspaces page, the group filter remains enabled so users can still narrow by group while showing all workspaces.
  7. Persistence: Selection can be kept in component state for the session; no need to persist to localStorage unless product specifies.
  8. Table view: The same combobox and filter selection apply.

Workspace group names must be unique among workspace groups only (org-wide, case-insensitive). They are not linked to KB group names — the same name (e.g. “Default group”) may be used for a workspace group and for a KB group. When adding or renaming a workspace group, the UI must reject a name that already exists at the workspace level and show an inline error (e.g. “A group with this name already exists”). Add group dialog and GroupBadge rename both enforce this. See Workspace and KB groups for the two-level schema.

Triggered by Add group in the group header overflow menu. Modal overlay, same pattern as other dialogs. Per the dialog convention, no close (×) in the header when the footer has Cancel.

  • Title: “Add group”.
  • Field: Label “Name”, single-line input, placeholder “e.g. Group name”. Auto-focus when the dialog opens so the user can type immediately. Validation: If the trimmed name (case-insensitive) matches an existing group name, do not submit; show inline error “A group with this name already exists” below the input and keep the dialog open.
  • Footer: Cancel (ghost/bordered) closes without creating. Add (primary, black) creates a new group with the entered name (trimmed) only when the name is non-empty and unique; then closes the dialog. Add is disabled while the name is empty.

Triggered by Delete in the group header overflow menu when the group is not the default and not the only group, and only when the group has at least one workspace (empty groups are deleted immediately without this dialog). Modal overlay. Per the dialog convention, no close (×) in the header when the footer has Cancel.

  • Title: “Delete group”.
  • Body: Warning text: “Deleting this group will move all its workspaces to the default group. This action cannot be undone.”
  • Footer: Cancel (ghost/bordered) closes without changes. Delete (destructive, red) moves all workspaces in that group to the default group, removes the group, and closes the dialog.

Triggered by the “Add workspace” primary button. Modal overlay (fixed inset-0 z-50 bg-black/50).

FieldRequiredDefault
ImageNo— (shows photo_camera upload area; uses URL.createObjectURL for preview)
NameYes
DescriptionNo
GroupYesFirst group in list (Default group)

Group field: Use the design system Select (custom dropdown with trigger + chevron + option list). Do not use a native HTML <select>; the control should follow the current app’s design-system Select pattern: trigger shows selected group name, right-aligned chevron-down icon, click opens list of groups. The list must include an “Add new” option. When the user selects “Add new”, an input field appears below the dropdown for entering the new group name (placeholder e.g. “e.g. Group name”). The new group is not created at that moment; the dialog holds a pending group name. When the user clicks Add (workspace), the workspace is created and the new group is created at the same time (via the parent’s onAddGroup callback); the workspace is assigned to the new group. The primary “Add” (workspace) button is disabled until a valid group is selected (i.e. while “Add new” is selected and the new group name has not been entered, or the name is empty). The list page’s group filter selection is not modified when the user adds a workspace (including when they create a new group in the dialog).

Historical design reference: Figma – Add workspace dialog.

  • Cancel: secondary/ghost button, closes dialog and discards changes.
  • Add: single primary button (use the design system Button component). Saves and closes. No split button and no dropdown; “Add and edit” is out of scope for this dialog in the current design.

Add is disabled while the name field is empty.

When the user clicks Add, the platform must:

  1. Create the new workspace in local state with defaults (see below).

  2. Automatically create a blank knowledge base and connect it to that workspace. The new KB has a generated id (e.g. kb-{workspaceId}-default or a unique id), workspaceId set to the new workspace’s id, a default name (e.g. “My Knowledge Base” or “Untitled knowledge base”), and status: "incomplete". Add this KB to the app’s knowledge-base list (e.g. seed or context that holds KBs for the account).

  3. Automatically create a default agent for that workspace, assigned to the auto-created default KB. The workspace stores that agent’s id as defaultAgentId.

  4. Set the new workspace’s numberOfKnowledgeBases to 1 (because the auto-created KB is linked to it).

New workspace defaults:

numberOfKnowledgeBases: 1 // one auto-created blank KB
numberOfUsers: 1
connectedApps: []
appsActivated: false

Reference: Default workspace and KB — every workspace must have at least one KB and one agent; new workspaces get both automatically.

Historical design reference: Figma – Edit workspace dialog.

Triggered by Edit in the workspace card (or table row) overflow menu. Same modal pattern as Add.

Pre-filled with the selected workspace: Image, Name, Description, Group. User can change any of these.

  • Image: When an image is present (existing or newly selected), show a Remove/Clear control that resets the workspace back to no image (upload placeholder) without closing the dialog.

Group: Use the same design system Select (custom dropdown with trigger + chevron + list), not a native <select>. Options: all existing groups plus “Add new”. When the user selects “Add new”, an input field appears below the dropdown for entering the new group name (placeholder e.g. “e.g. Group name”). The new group is not created until the user clicks Apply; the dialog holds a pending group name. On Apply, the workspace is updated and the new group is created (via the parent’s onAddGroup callback); the workspace is assigned to the new group. The list page’s group filter selection is not modified when the user edits a workspace or adds a new group from this dialog.

  • Delete (left, destructive, red): Does not delete immediately. Closes the Edit dialog and opens the Delete workspace warning modal (same as the standalone Delete flow). Historical design reference: Figma – Delete workspace warning modal. The user must confirm in that modal to complete deletion. Shown only when the account has more than one workspace; otherwise disabled (platform must retain at least one workspace).
  • Cancel: closes dialog, discards changes.
  • Apply (primary, right): saves changes to local state and closes the dialog.

Triggered by Delete in the workspace card (or table row) overflow menu — or by Delete in the Edit workspace dialog (which closes the Edit dialog and opens this warning modal). Only when the account has more than one workspace; if only one workspace exists, the Delete menu item and the Edit-dialog Delete button are disabled.

  • Title: “Delete workspace”. Per the dialog convention, no close (×) in the header when the footer has Cancel.
  • Warning icon and “Warning!” heading.
  • Body text: explains that deleting the workspace will permanently delete all knowledge bases it contains, remove user access, and stop all AI products; recommends moving knowledge bases to another workspace first if the user wants to keep them.
  • Cancel: closes dialog, no change.
  • Delete (destructive, red): removes the workspace from local state and closes the dialog.
ConditionChip appearance
appsActivated: falseSingle red chip: error icon + “Not activated” in #ef4444
appsActivated: true, connectedApps not emptyGreen chip per app: check icon + app label in #22c55e
appsActivated: true, connectedApps empty”No apps connected” label

In table view: “No apps activated” text when appsActivated is false; comma-separated app labels otherwise.

  • "comment-responder" → “Comment Responder”
  • "chatti-live" → “Chatti Live”

(Defined in src/types/workspaces.ts as WORKSPACE_APP_LABEL.)

  • No workspaces: centered empty state with icon, title “No workspaces found”, and supportive body copy. When filters are active, use a search-style empty state with a Clear filters action; otherwise use the default workspaces icon and onboarding-oriented copy.

Workspace creation and membership gating — deferred to API integration phase.

  • GET /workspaces
  • POST /workspaces
  • Multi-brand governance (naming, ownership, policies)
  • User belongs to zero workspaces (org exists but no workspace membership).
  • Workspace creation fails validation (naming/policy constraints are TBD).
  • Audit workspace creation and settings changes

Reference: Security and compliance

  • workspace.created
  • workspace.switched

Reference: Analytics events