{"id":47617773,"url":"https://github.com/tangle-network/sandbox-ui","last_synced_at":"2026-04-08T06:01:18.644Z","repository":{"id":345382030,"uuid":"1185679482","full_name":"tangle-network/sandbox-ui","owner":"tangle-network","description":"React component library for AI agent interfaces — chat, terminal, file browser, tool calls, dashboards","archived":false,"fork":false,"pushed_at":"2026-04-02T05:33:39.000Z","size":749,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-02T05:36:30.139Z","etag":null,"topics":["ai-agents","components","radix-ui","react","sandbox","tailwindcss","tangle","typescript","ui"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tangle-network.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-18T20:48:25.000Z","updated_at":"2026-04-01T22:15:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tangle-network/sandbox-ui","commit_stats":null,"previous_names":["tangle-network/sandbox-ui"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/tangle-network/sandbox-ui","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fsandbox-ui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fsandbox-ui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fsandbox-ui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fsandbox-ui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tangle-network","download_url":"https://codeload.github.com/tangle-network/sandbox-ui/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fsandbox-ui/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31542384,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"online","status_checked_at":"2026-04-08T02:00:06.127Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","components","radix-ui","react","sandbox","tailwindcss","tangle","typescript","ui"],"created_at":"2026-04-01T21:43:40.094Z","updated_at":"2026-04-08T06:01:18.638Z","avatar_url":"https://github.com/tangle-network.png","language":"TypeScript","readme":"![Tangle Network Banner](https://raw.githubusercontent.com/tangle-network/tangle/refs/heads/main/assets/Tangle%20%20Banner.png)\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@tangle-network/sandbox-ui\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@tangle-network/sandbox-ui?color=8E59FF\u0026label=npm\" alt=\"npm\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/tangle-network/sandbox-ui/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/@tangle-network/sandbox-ui?color=6888F9\" alt=\"license\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/tangle-network/sandbox-ui\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/tangle-network/sandbox-ui?style=flat\u0026color=8E59FF\" alt=\"stars\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# @tangle-network/sandbox-ui\n\nReact component library for [Tangle Sandbox](https://sandbox.tangle.tools) — a shadcn-style primitive layer plus higher-order sandbox surfaces for agent chat, files, runtime state, artifacts, and dashboard views.\n\n## Install\n\n```bash\nnpm install @tangle-network/sandbox-ui\n```\n\n**Peer dependencies:** `react` and `react-dom` (18 or 19). Optional peers for specific subpaths — see [package.json](./package.json).\n\n## Usage\n\n```tsx\nimport {\n  SandboxWorkbench,\n  type FileNode,\n  type SessionMessage,\n  type SessionPart,\n} from \"@tangle-network/sandbox-ui\";\n```\n\nImport styles in your app root:\n\n```tsx\nimport \"@tangle-network/sandbox-ui/styles\";\n```\n\nIf you are building on the sandbox SDK directly, use `useSdkSession` to turn raw SDK/session-gateway events into the `messages + partMap` model that `ChatContainer` and `SandboxWorkbench` expect:\n\n```tsx\nimport {\n  SandboxWorkbench,\n} from \"@tangle-network/sandbox-ui\";\nimport { useSdkSession } from \"@tangle-network/sandbox-ui/sdk-hooks\";\n\nfunction App() {\n  const {\n    messages,\n    partMap,\n    isStreaming,\n    appendUserMessage,\n    beginAssistantMessage,\n    applySdkEvent,\n    completeAssistantMessage,\n    failAssistantMessage,\n  } = useSdkSession();\n\n  async function runTurn(text: string) {\n    appendUserMessage({ content: text });\n    const assistantMessageId = beginAssistantMessage();\n\n    try {\n      for await (const event of sdk.streamPrompt(text)) {\n        applySdkEvent(event, { messageId: assistantMessageId });\n      }\n      completeAssistantMessage({ messageId: assistantMessageId });\n    } catch (error) {\n      failAssistantMessage(\n        error instanceof Error ? error.message : \"Agent run failed\",\n        { messageId: assistantMessageId },\n      );\n    }\n  }\n\n  return (\n    \u003cSandboxWorkbench\n      session={{\n        messages,\n        partMap,\n        isStreaming,\n        onSend: runTurn,\n      }}\n    /\u003e\n  );\n}\n```\n\nCompose sandbox applications around `SandboxWorkbench` when you want the library’s default operating model:\n\n```tsx\nconst root: FileNode = {\n  name: \"agent\",\n  path: \"/home/agent\",\n  type: \"directory\",\n  children: [],\n};\n\nconst messages: SessionMessage[] = [];\nconst partMap: Record\u003cstring, SessionPart[]\u003e = {};\n\n\u003cSandboxWorkbench\n  title=\"Tax filing workspace\"\n  directory={{\n    root,\n    visibility: {\n      hiddenPathPrefixes: [\"/home/agent/tax_toolkit\"],\n    },\n  }}\n  session={{\n    messages,\n    partMap,\n    isStreaming: false,\n    presentation: \"timeline\",\n    onSend: console.log,\n  }}\n  runtime={{\n    title: \"Runtime\",\n  }}\n/\u003e;\n```\n\n`FileTreeVisibilityOptions` is a UI-layer policy only. Sensitive paths still need to be hidden and denied by the app/backend layer.\n\n## Theming And Retheming\n\nThere is a built-in Tangle default theme, but consumers can restyle the library in three layers:\n\n1. Pick a built-in surface theme\n2. Override semantic tokens\n3. Wrap higher-level components when you want a different product composition\n\n### 1. Pick a Built-in Theme\n\n`WorkspaceLayout` and `SandboxWorkbench` support:\n\n- `theme=\"vault\"` — light theme with solid surfaces\n- No theme prop — default dark theme\n\nThey also support `density=\"comfortable\"` and `density=\"compact\"`.\n\n```tsx\n\u003cSandboxWorkbench\n  layout={{\n    theme: \"vault\",\n    density: \"comfortable\",\n  }}\n  session={{ ... }}\n/\u003e\n```\n\nIf you are not using `SandboxWorkbench`, you can set the same attributes yourself:\n\n```tsx\n\u003cdiv data-sandbox-ui data-sandbox-theme=\"vault\" data-density=\"compact\"\u003e\n  \u003cYourSandboxApp /\u003e\n\u003c/div\u003e\n```\n\n### 2. Override Semantic Tokens\n\nThe shared visual contract lives in [src/styles/tokens.css](./src/styles/tokens.css). The important tokens are:\n\n- surfaces: `--bg-root`, `--bg-card`, `--bg-elevated`, `--bg-section`, `--bg-input`\n- text: `--text-primary`, `--text-secondary`, `--text-muted`\n- brand: `--brand-cool`, `--brand-glow`, `--brand-purple`\n- accent surfaces: `--accent-gradient-strong`, `--accent-surface-soft`, `--accent-surface-strong`, `--accent-text`\n- borders: `--border-subtle`, `--border-default`, `--border-accent`\n- radii/shadows: `--radius-*`, `--shadow-card`, `--shadow-dropdown`, `--shadow-accent`\n\nApp-level overrides can be scoped to a wrapper:\n\n```css\n.tax-theme {\n  --brand-cool: hsl(187 75% 54%);\n  --brand-glow: hsl(164 74% 56%);\n  --bg-root: hsl(222 18% 9%);\n  --bg-card: hsl(223 20% 12%);\n  --border-accent: hsl(187 75% 48% / 0.35);\n  --font-sans: \"Satoshi\", ui-sans-serif, system-ui, sans-serif;\n}\n```\n\n```tsx\n\u003cdiv className=\"tax-theme\"\u003e\n  \u003cSandboxWorkbench ... /\u003e\n\u003c/div\u003e\n```\n\n### 3. Know When To Wrap Instead Of Override\n\nToken overrides are the right tool when you want:\n\n- a different brand color system\n- different typography\n- tighter or roomier density\n- a more consumer-facing or operator-facing tone\n\nWrap or compose on lower-level exports when you want:\n\n- a different page shell\n- different header chrome\n- a different artifact tab model\n- app-specific empty states and actions\n\nThe higher-order dashboard/billing surfaces are now accent-token driven rather than hardcoded to the default Tangle look. The main seams are:\n\n- `DashboardLayout.className`, `sidebarClassName`, `contentClassName`\n- `BillingDashboard.className`, `cardClassName`\n- `PricingCards.className`, `cardClassName`\n- `UsageChart.className`\n- `StandalonePricingPage.className`\n\nFor that, compose directly from:\n\n- `/workspace`\n- `/chat`\n- `/run`\n- `/files`\n\n### Current Reality\n\nRetheming is absolutely supported, but the documentation was thinner than it should be. The token layer is strong; the higher-level surfaces are themeable, but more opinionated. For a radically different product look, prefer keeping the token contract and wrapping the higher-level workbench/chat surfaces rather than fighting every internal class.\n\n## Docs\n\n| Guide | Description |\n|-------|-------------|\n| [Sidebar](./docs/sidebar.md) | Composable Rail + Panel sidebar system (architecture, components, full API) |\n\n## Subpath Exports\n\n| Subpath | Description |\n|---------|-------------|\n| `/primitives` | Button, Card, Dialog, Badge, Input, Select, Table, Tabs, Toast, etc. |\n| `/chat` | ChatContainer, ChatInput, ChatMessage, AgentTimeline, ThinkingIndicator |\n| `/run` | ToolCallFeed, RunGroup, InlineToolItem, ExpandedToolDetail |\n| `/workspace` | SandboxWorkbench, WorkspaceLayout, DirectoryPane, RuntimePane, StatusBar |\n| `/openui` | OpenUIArtifactRenderer and schema types for structured artifact rendering |\n| `/files` | FileTree, FilePreview, FileTabs, FileArtifactPane |\n| `/dashboard` | [Sidebar](./docs/sidebar.md), DashboardLayout, BillingDashboard, UsageChart, ProfileSelector |\n| `/editor` | TipTap collaborative editor (requires optional peers) |\n| `/terminal` | xterm.js terminal view (requires optional peers) |\n| `/markdown` | Markdown renderer with GFM, code blocks, copy button |\n| `/auth` | AuthHeader, GitHubLoginButton, UserMenu |\n| `/pages` | Pre-built billing, pricing, profiles pages |\n| `/hooks` | useSSEStream, useAuth, usePtySession, useRunGroups, etc. |\n| `/sdk-hooks` | Lightweight session/stream hooks without the React Query CRUD hook bundle |\n| `/stores` | Session and chat nanostores |\n| `/types` | TypeScript types for messages, parts, runs, sessions |\n| `/utils` | cn, formatDuration, timeAgo, tool display helpers |\n| `/styles` | Compiled CSS bundle |\n\n## Stack\n\n- [Radix UI](https://www.radix-ui.com/) primitives\n- [Tailwind CSS](https://tailwindcss.com/) v4\n- [Lucide](https://lucide.dev/) icons\n- [CVA](https://cva.style/) for variant management\n- Shared semantic tokens for default dark and `vault` light sandbox themes\n- ESM-only, tree-shakeable, fully typed\n\n## License\n\nApache-2.0\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangle-network%2Fsandbox-ui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftangle-network%2Fsandbox-ui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangle-network%2Fsandbox-ui/lists"}