Skip to content

dashboard: mobile adaptation + restore web terminal + env-aware API URL#840

Merged
DorianZheng merged 46 commits into
boxlite-ai:mainfrom
law-chain-hot:codex/pr829-uiux-mobile
Jun 24, 2026
Merged

dashboard: mobile adaptation + restore web terminal + env-aware API URL#840
DorianZheng merged 46 commits into
boxlite-ai:mainfrom
law-chain-hot:codex/pr829-uiux-mobile

Conversation

@law-chain-hot

Copy link
Copy Markdown
Contributor

Continues the dashboard restyle from #829. Frontend-only (apps/dashboard/*), 0 Rust / backend files.

This session's work (tip commit 0e55a9b7)

  • Mobile / responsive: Boxes list (card list <md), Create Box dialog, Sidebar, Box detail; desktop L/R padding unified to 40px.
  • Web terminal restored: in-page terminal panel (responsive) + /terminal fullscreen route are back. SSH entry points stay hidden — SSH and the web Terminal are separate features and had been wrongly removed together.
  • Box detail: narrower spec column, tighter grouping, image hover tooltip; lifecycle section dropped (unsupported).
  • Boxes list: stat cards drop CPU-hours + decorative index labels, add a stopped-count card; mock /box/paginated now honors ?states=.
  • Env-aware Quickstart API URL: lib/environment.ts resolves env by hostname (not config.environment — dev stage reports "production") and pins the public REST API URL per env. Temporary frontend shim with a fallback; long-term should be a /api/config field.
  • Rename user-facing Sandboxes → Boxes.

⚠️ Base note

Targeting main while #829 (feat/dashboard-floating-restyle) is still open means this PR bundles #829's restyle commits too (62 commits via merge-base). For a clean 5-commit incremental, retarget the base to feat/dashboard-floating-restyle.

Verification

  • dashboard build ✓ · lint 0 errors / 40 warnings (baseline) · vitest (dashboard-features + environment) pass
  • Manually verified at 320 / 768 / 1440 + the fullscreen terminal route via Playwright; no horizontal overflow; SSH absent everywhere.

… env

Local dashboard dev calls a same-origin /api path; Vite proxies it to the selected backend, so the browser never makes a cross-origin (CORS-gated) request and no backend has to allow-list localhost. Replaces the prior VITE_BASE_API_URL=dev direct-call approach, which the browser blocked with CORS.

- start-dashboard.mjs: API_TARGETS map (local/dev + prod placeholder), --api=<url> for any env, --yes-prod guard for prod
- vite.config.mts: /api proxy target read from DASHBOARD_API_PROXY_TARGET
- package.json: start:prod (replaces throwaway start:dev-proxy)
- apps/CLAUDE.md: fix 'from repository root' -> apps/, document the proxy model
…n onboarding

- BoxTable: remove the Region column from the desktop table and the Region
  entry from the compact mobile meta. The box table no longer surfaces region.
- Remove the now-unused getRegionName plumbing from the box-table path
  (Boxes page, BoxTable, useBoxTable, columns, types) and the stale 'region'
  entry from persisted column visibility. useRegions/getRegionName stay in
  place for the other consumers (Runners, Org Settings, Box details).
- onboarding-code-examples: use the fully-qualified image reference
  ghcr.io/boxlite-ai/boxlite-agent-base:20260605-p0-r3 across all four SDK
  snippets (JS/TS, Python, Go, Rust) instead of the short 'boxlite/base'.
- BoxTable: drop the stale min-w-[1360px] (sized for removed columns) to
  min-w-[1120px] so the table fills the viewport without horizontal scroll,
  and tighten row vertical padding (py-2 -> py-1, scoped to this table) so
  rows are ~41px instead of ~46px.
- use-mobile: lower COMPACT_BREAKPOINT 1200 -> 1024 so the dashboard keeps
  the full table (not the compact card layout) down to 1024px.
Adopt exe.dev's calm/minimal/progressive-disclosure feel on the box list.

List minimalism + progressive disclosure:
- Default visible columns reduced to Name + Last Event + actions. Box ID,
  State, Resources, and Created At are hidden by default and toggleable via
  the View menu (TanStack columnVisibility + localStorage, bumped to a V2 key
  so the old forced 'id:true' default does not stick).
- Status now leads the Name cell as a compact status dot (BoxState gains an
  iconOnly mode with a tooltip) instead of a dedicated State column.

Centered-narrow layout:
- New PageLayout 'content' size (~1040px); Boxes list switches off 'full'
  (1440px) onto it, so the list centers with side whitespace instead of
  filling the viewport. Table min-width lowered 1120 -> 680 for the trimmed row.

Visual calm (global tokens):
- Root font-size 15px -> 14px; --border lightened to a hairline; Card drops
  shadow-sm to rely on the border. Warm-cream brand palette kept.

Verified in Chrome against the dev API: list centers, shows Name+dot / Last
Event / actions, View menu toggles the four hidden columns back on.
…ass 2)

Restructure the box detail page to exe.dev's calm, centered, progressive layout
(approach B: observability moves into the column, not a full-bleed split).

- BoxDetails: drop the full-bleed resizable Group/Panel split and the
  desktop/mobile duality. Detail now flows in one centered max-w-[1040px]
  scrolling column: metadata grid -> content tabs. Removes isDesktop /
  react-resizable-panels / ScrollArea usage.
- BoxHeader: compress the two-line header (name over Box ID) into a single
  row (name + copy + inline mono Box ID + copy).
- SDK 'Connect with the SDK' nudge demoted from a full-width banner owning the
  top to a compact inline card inside the column.
- BoxInfoPanel: reflow the vertical sidebar sections into a 2-column metadata
  grid and surface fields that were in the Box model but never rendered —
  Image (full ghcr ref) and Region (getRegionName(target)), plus Labels.
- BoxContentTabs: drop the now-redundant Overview tab (metadata is always shown
  above) and give the tab shell a bounded height (60vh) so the terminal and
  observability tabs render correctly inside the scrolling column.
- Remove the now-dead InfoSection/InfoRow exports.

Verified in Chrome: detail centers in ~1040px, header is one line, metadata
grid shows Image + Region, terminal tab renders bounded.
Both the global top nav and the box-detail header spanned wider than the new
centered ~1040px content column, so they didn't line up with it.

- Sidebar (global top nav): constrain inner content max-w 1440 -> 1040 so the
  logo/tabs/search align with the page content column.
- BoxHeader: center its content in a max-w-[1040px] inner wrapper (full-width
  border-b kept as the divider) so back/name align left and actions align right
  with the content below.

Verified in Chrome: nav, box header, and detail content share one centered
1040px column on both the list and detail pages.
…inent

- Org switcher/display moves out of the top nav into the right-side profile
  dropdown as an Organization section (org name -> settings, Copy organization
  ID). The 'Copy Organization ID' command-palette entry is preserved (re-
  registered in Sidebar). Removes the now-unused OrganizationPicker component.
- Make the primary state action prominent: Start / Stop / Recover use the
  filled default button variant instead of muted outline, in both the box-table
  row (desktop + mobile) and the detail header, so the main action stands out
  from the secondary (terminal / SSH / overflow) buttons.

Verified in Chrome: nav no longer shows the org pill; profile menu shows the
Organization section; Start/Stop render as filled buttons in list and detail.
…ge row

- BoxInfoPanel: remove the Auto-stop and Auto-delete metadata rows. The
  auto-stop/auto-delete feature is not supported (pipeline removed), so the
  dashboard should not surface it. (Note: box.autoStopInterval/autoDeleteInterval
  still exist on the api-client Box model — a backend/model remnant to purge
  separately.)
- BoxDetails: remove the 'Connect with the SDK' nudge row from the detail page
  (misaligned and redundant — the guide is still reachable from the nav). Drop
  the now-orphaned onboardingCoreProgress/showOnboardingNudge and unused
  imports (getOnboardingCoreProgress, Code2, ListChecks, formatDuration).
- BoxTableHeader: remove the Refresh, View (column visibility), and Filter
  (state/last-event) controls. The toolbar is now just the box Search + the
  Create Box action. Removes the active-filter indicator row.
- Drop the now-orphaned refresh plumbing end to end: onRefresh/isRefreshing
  from BoxTableHeaderProps and BoxTableProps, the passthrough in BoxTable, and
  handleRefresh + boxDataIsRefreshing + the refetch handle in Boxes.tsx.
- Profile menu Organization section: keep just the org name (-> Settings) and
  drop the standalone 'Copy organization ID' item (still available via the
  command palette).

Verified in Chrome: list toolbar shows only Search + Create Box; profile menu
Organization shows only the org name.
…pler menus

- Start/Stop/Recover: use the lighter 'secondary' button variant instead of the
  solid-black 'default' (still prominent vs the outline secondary buttons, but
  not heavy black). Applies to the box-table row (desktop + mobile) and detail
  header.
- Typography consistency: drop the ad-hoc monospace from Box ID (header +
  detail) and Image so box detail reads in one consistent font.
- Detail metadata grid: normal-case muted labels (no uppercase/letter-spacing),
  tighter row rhythm, baseline-aligned label/value pairs.
- Profile menu: theme toggle on top (no 'Appearance' label); Organization is a
  single item (-> Settings) parallel to Docs/Discord (no section label, no org
  name); dropped the standalone org-name display.

Verified in Chrome (light + dark): detail metadata uniform + compact; Start/Stop
render as soft buttons; profile menu shows Organization/Docs/Discord parallel.
…boxes)

Add BoxSearchCommands: while the command palette (nav search / ⌘K) is open, the
typed query is debounced and run against listBoxesPaginated(idOrName); matching
boxes are registered as a 'Boxes' result group, each selecting to the box
detail. Mounted in Sidebar (inside the command-palette + api providers).

This makes the global search find boxes by name/ID (industry-standard command
palette entity search), complementing the in-list box filter.

Verified in Chrome: typing a box name/ID in ⌘K shows it under 'Boxes' and
navigates to the detail on select.
Billing is no longer a top-nav tab; it sits in the profile dropdown alongside
Organization / Docs / Discord (-> /dashboard/billing). The top nav now carries
just Boxes (plus Admin when permitted), keeping the bar minimal.

Verified in Chrome: nav shows only Boxes; profile menu lists Organization,
Billing, Docs, Discord.
…edup id, terminal start, status pill, metadata grid

Top-designer walkthrough of the box detail + list.

- Remove the unsupported Screen Recordings feature end-to-end (BoxHeader and
  BoxTableActions menus + the handler/prop chain through Boxes, BoxTable,
  columns, useBoxTable, types, BoxDetails; the port-33333 preview caller).
- Dedup the Box ID: the header now shows just the name + one copy; the Box ID
  with its copy lives only in the metadata grid (was duplicated in both).
- Terminal 'Box is not running' empty state now offers an inline 'Start box'
  button (gated by write permission) so users don't have to find the top-right
  Start (BoxTerminalTab uses useStartBoxMutation directly).
- Status is now a colored pill (green running / muted stopped / red error /
  amber recoverable) via a new BoxState 'pill' variant — far more prominent.
- Metadata grid redesigned into stacked label-over-value cells: Image spans the
  full row, the rest in a 3-col grid — left-aligned, no ragged right edge,
  consistent rhythm.

Verified in Chrome (light+dark): screen recordings gone; single id copy; status
pill; stopped box shows inline Start box in the terminal; metadata grid aligned.
…se, loading state

- BoxTable row: the whole row is clickable again. The cell-level click handler
  only swallows the checkbox cell now; the actions cell lets clicks in the empty
  space around the (already self-stopping) buttons fall through to open the row.
- BoxHeader: move the status pill next to the box name (left) instead of the
  crowded top-right action cluster, grouping identity + status.
- BoxInfoPanel: uppercase the Region value (e.g. 'us' -> 'US').
- LoadingFallback: drop the duplicate centered spinner that overlapped the
  skeleton table, align width to the new 1040 content column, and show the
  'taking longer' note (no competing spinner) only after 5s. One clean skeleton.

Verified in Chrome: clicking near the row actions opens detail; status pill sits
by the name; Region shows 'US'; reload shows a single clean skeleton.
…parse

Anchor the top of the box list with a title + one-line description ('Boxes' /
'Run code in isolated, on-demand environments.') and move Create Box up next to
it (title left, primary action right). Gives the page top matter — like a
breadcrumb/context region — instead of a thin table floating on a tall empty
viewport. The toolbar row is now just search.
…loading rows

- Give the box table an iOS-like floating feel: weaker hairline border
  (border/40-50), softer/larger drop shadow, rounded-xl. Row + header dividers
  weakened to border/50-60 so separation reads from elevation, not heavy lines.
  Applied to both the desktop table card and the compact card.
- Replace the in-table 'Loading...' text (which looked off in the framed table)
  with skeleton rows (5 desktop / 4 compact) so the loading state fills the
  card like real rows forming.
…mand palette)

The in-list 'Search by name or Box ID' field is removed — box lookup is now
served by the global command palette (⌘K), which searches boxes by name/ID. With
the field and the (already-relocated) Create Box action gone, BoxTableHeader had
nothing left to render, so it and its now-unused headerAction prop are deleted.
…low menu, surface SSH

The row's '...' menu repeated actions that already have inline buttons. Now:
- Remove Start/Stop/Recover and (desktop) Terminal from the overflow menu — they
  already exist as the inline primary button + terminal button.
- Surface SSH as its own inline button (KeyRound) on desktop when the box is
  ssh-accessible, instead of burying 'Create SSH Access' in the menu.
- Overflow menu is now just: View Details, Revoke SSH Access, Delete (plus, on
  compact/mobile where there are no inline terminal/ssh buttons, Terminal +
  Create SSH so mobile keeps access).

Inline (desktop): primary state toggle · Terminal · SSH (when accessible) · more.
…der corners

Establish a cohesive 'floating surface' visual system, centralized for easy rollback:
- index.css: bump --radius 0.375rem -> 0.625rem (rounder cards/buttons/inputs
  proportionally) and add theme-aware --shadow-card / --shadow-card-hover (soft
  layered light shadow; deeper dark shadow so cards still lift off the bg).
- tailwind.config: register shadow-card / shadow-card-hover utilities from those vars.
- Card component: rounded-xl + hairline border (border/60) + shadow-card — this
  alone restyles the ~14 pages that use the shared Card (Billing, Settings,
  Wallet, Spending, Webhooks, Admin, …).
- Apply the same shadow-card token to the surfaces that use ad-hoc containers:
  box table (replacing the earlier inline shadow), BoxInfoPanel, BoxContentTabs,
  and the API keys table.

Verified in Chrome (dark): box list table floats with rounded-xl + soft shadow;
buttons rounder but not pill-y. Other Card pages inherit via the central change.
Remove the border-b on the BoxHeader so there's no horizontal rule between the
title row and the metadata/terminal content below it.
…ens a dialog anywhere (no redirect)

- Profile menu: give the theme toggle top padding (px-2 pb-2 -> px-2 py-2) so it
  no longer hugs the dropdown's top edge.
- Theme switch flicker: drop the runWithoutAnimation hack that injected a global
  '* { transition:none !important }' style and forced two synchronous reflows on
  every element (which flashed the open dropdown). Just toggle the html class.
- Guide no longer jumps to the homepage. Add a single app-global OnboardingDialogHost
  (rendered in Dashboard) that listens for ONBOARDING_OPEN_EVENT and opens the
  guide as a dialog from any page; it preventDefaults the event so the Sidebar's
  navigate(/dashboard/boxes?onboarding=1) fallback never fires. Removed the
  per-page ONBOARDING_OPEN_EVENT listeners from Boxes/BoxDetails so the Guide
  button no longer triggers their copies (first-visit auto-open + ?onboarding=1
  stay page-local).
…vanced accordion)

Surface CPU/Memory/Disk directly in the Create Box sheet instead of hiding them
behind an 'Advanced options' accordion, so the sheet reads less empty. Image
stays a dropdown; no live-summary card.
… cells

The all-rounded floating restyle left hard hairlines and edge-hugging
content that clashed with it:
- top nav border-b: border-border -> border-border/50
- table header border-b: border-border/60 -> border-border/40
- first/last table cells: add pl-5 / pr-5 so content clears the card's
  rounded corners instead of sitting flush against them
… login)

Previously the MSW mock only covered billing and even fetched /config from
the real dev API, so the dashboard could not render its core surfaces
offline. Make the local mock chain stand on its own:
- fixtures.ts: typed Organization, member (owner), config and box fixtures
- MockAuthProvider: swaps react-oidc-context's AuthProvider for a fixed
  authenticated session (no OIDC server, no login round-trip)
- handlers.ts: serve a static config plus organizations, org members,
  paginated boxes, regions, and a 403 admin probe
- ConfigProvider: use MockAuthProvider when VITE_ENABLE_MOCKING is set
…heet

Few fields no longer warrant a full-height drawer; mirror the API-key
dialog — centered modal, resources laid out in a single CPU/Memory/Disk row.
law-chain-hot and others added 12 commits June 17, 2026 11:51
Replace the plain textarea + icon button with the tinted key card and a
prominent labelled Copy button that confirms in place.
…ndlers

Lets the box detail page and the onboarding key flow render offline.
… 16px

Self-host Space Grotesk (SIL OFL) and apply it to titles and labels
(cards, dialogs, sheets, the Label primitive, box name, detail meta
labels — now bolder); body stays Inter and code stays monospace. Raise
the root font-size from 14px to 16px so the whole UI scales up via rem.
… panel

Drop the inner scroll region so the whole detail page scrolls. With
observability tabs off, render a plain Terminal header instead of a
single-tab selector, and remove the terminal's inner rounded frame so it
fills the card edge to edge under the header.
…d section

Now that Create Box is a centered dialog, the CPU/Memory/Disk fields tuck
into an Advanced accordion (collapsed by default), stacked vertically.
… empty

Drop the inline SSH button (its key icon clashed with API Keys and only
showed on some rows); SSH now lives in the overflow menu on every layout,
so rows are uniform. Skip the column header when the list is empty so the
empty state isn't stranded under a half-width header.
…pulse

Light tokens now form a clear ladder: a recessed page background with a
brighter shared surface for cards and the top nav (nav switches from the
background tone to the card tone) so chrome reads as one elevated layer.
Also remove the onboarding Guide entry's pulse animation (and its dead
keyframe / state / listener) so it's a plain button.
Rebuilds the dashboard UI to an ASCII/terminal design language (IBM Plex Mono, square corners, #00B0F0 accent, dark-default dual theme) while reusing all existing data hooks/mutations/providers unchanged. No server APIs added or modified; only existing endpoints are consumed.

- Design system: index.css HSL token remap + brand token, IBM Plex Mono, square radii, theme key boxlite-theme; re-skins all shadcn ui primitives via token swap.
- Top nav (Sidebar): logo/Sandboxes/Billing/Admin/Search/API Keys/Quickstart + standalone org switcher + profile menu; grayscale active state.
- Sandboxes (Boxes): header + real-data stat cards (Total/Running via listBoxesPaginated.total, CPU-hours via analytics) + filter + redesigned table; New Box modal with stepper resource config (CPU<=8, Mem<=32, Disk<=50 default 10).
- Box detail: breadcrumb + spec readout + real terminal panel + lifecycle/Remote SSH.
- API Keys: redesigned table + create + one-time reveal modal.
- Billing: 'on the way' empty state.
- Login/register: dark-only, OIDC signinRedirect (no client auth API).
- Quickstart: scenario picker (ASCII cards) -> per-scenario 3-step guided flow.
- OrganizationSettings/EmailVerify/Admin reshelled in the new language.
- Mock-only auth provider made stateful so the login page is reviewable under start:mock.

Deliberate, design-driven feature reductions (underlying code retained): box-detail logs/metrics/traces/spending tabs and boxes-table bulk-select/column-sort are dropped from the new UI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Frontend-only follow-ups to the restyle. The only files outside apps/dashboard are the
dependency manifests (apps/package.json, apps/yarn.lock) for the new icon set. No backend,
generated clients, or data-contract changes; the single providers/ touch is an icon import-source
swap (presentational, no logic).

- Icons: replace lucide-react with a pixel/8-bit set (pixelarticons via @iconify) through a central
  shim (src/components/ui/icon.tsx) that re-exports every used name mapped to the angular glyph;
  122 files re-pointed from 'lucide-react' to '@/components/ui/icon'. The logo is untouched.
- Toasts (sonner): square corners, IBM Plex Mono, pixel status icons, bordered popover surface.
- Org switcher: moved from a standalone nav control into the top-right profile menu (submenu with
  switch-org list + settings + copy id). Still org-scoped; not dropped.
- API Keys page: aligned to the Sandboxes layout (big title, borderless hover-row table, simple footer).
- Sandboxes: dot-matrix LED stat numbers, square status indicator (was a round dot), dashed filter
  input; page titles reduced 30->22px (Sandboxes + API Keys).
- Quickstart 'coming soon' card uses a static halftone texture (added .halftone utilities).
- Box terminal empty-state icon enlarged (was a tiny chip).

Deps added: @iconify/react, @iconify-json/pixelarticons (offline, bundled).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Login/register tab selection now uses the same grayscale fill as the top nav active state (was a brand underline). SSO icons swapped to the 8-bit set: GitHub uses the pixel shim icon, Google uses a hand-drawn pixel 'G' (pixelarticons has no Google mark).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… UI polish

Mobile / responsive:
- Responsive Boxes list (card list <md), Create Box dialog, Sidebar, Box detail
- Desktop L/R page padding unified to 40px across active pages

Box detail:
- Restore web terminal panel (responsive) + /terminal fullscreen route; SSH stays hidden
- Spec readout: narrower column, tighter grouping, image hover tooltip; drop lifecycle

Boxes list:
- Stat cards: drop CPU-hours + index labels, add stopped count
- Mock /box/paginated honors ?states= for real per-state counts

Config / naming:
- lib/environment.ts: resolve env by hostname, pin public REST API URL per env
- Quickstart shows env-correct API URL
- Rename user-facing Sandboxes -> Boxes

Plus lint/type fixes in icon.tsx and mock fixtures.
@law-chain-hot law-chain-hot requested a review from a team as a code owner June 24, 2026 07:24
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 163 files, which is 13 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 31c1b4fb-0049-4989-abae-fcd0ba314d5d

📥 Commits

Reviewing files that changed from the base of the PR and between 8841340 and ccdd7a3.

⛔ Files ignored due to path filters (11)
  • apps/dashboard/src/assets/bbox-logo-dark.png is excluded by !**/*.png
  • apps/dashboard/src/assets/bbox-logo-light.png is excluded by !**/*.png
  • apps/dashboard/src/assets/boxlite-full-black.png is excluded by !**/*.png
  • apps/dashboard/src/assets/boxlite-full-white.png is excluded by !**/*.png
  • apps/dashboard/src/assets/boxlite-logo-black.png is excluded by !**/*.png
  • apps/dashboard/src/assets/boxlite-logo-white.png is excluded by !**/*.png
  • apps/dashboard/src/assets/boxlite-website-logo-dark.png is excluded by !**/*.png
  • apps/dashboard/src/assets/boxlite-website-logo-light.png is excluded by !**/*.png
  • apps/dashboard/src/assets/fonts/space-grotesk-latin-variable.woff2 is excluded by !**/*.woff2
  • apps/dashboard/src/assets/react.svg is excluded by !**/*.svg
  • apps/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (163)
  • apps/dashboard/CLAUDE.md
  • apps/dashboard/RESTYLE_PLAN.md
  • apps/dashboard/index.html
  • apps/dashboard/src/assets/fonts/Space-Grotesk-OFL.txt
  • apps/dashboard/src/components/AccountProviderIcon.tsx
  • apps/dashboard/src/components/AnnouncementBanner.tsx
  • apps/dashboard/src/components/ApiKeyTable.tsx
  • apps/dashboard/src/components/AuditLogTable.tsx
  • apps/dashboard/src/components/Banner.tsx
  • apps/dashboard/src/components/Box/CreateBoxDialog.tsx
  • apps/dashboard/src/components/Box/CreateBoxSheet.tsx
  • apps/dashboard/src/components/BoxDetailsSheet.tsx
  • apps/dashboard/src/components/BoxSearchCommands.tsx
  • apps/dashboard/src/components/BoxTable/BoxState.tsx
  • apps/dashboard/src/components/BoxTable/BoxTableActions.tsx
  • apps/dashboard/src/components/BoxTable/BoxTableHeader.tsx
  • apps/dashboard/src/components/BoxTable/columns.tsx
  • apps/dashboard/src/components/BoxTable/constants.ts
  • apps/dashboard/src/components/BoxTable/filters/LabelFilter.tsx
  • apps/dashboard/src/components/BoxTable/filters/LastEventFilter.tsx
  • apps/dashboard/src/components/BoxTable/filters/RegionFilter.tsx
  • apps/dashboard/src/components/BoxTable/filters/ResourceFilter.tsx
  • apps/dashboard/src/components/BoxTable/filters/StateFilter.tsx
  • apps/dashboard/src/components/BoxTable/index.tsx
  • apps/dashboard/src/components/BoxTable/state-icons.tsx
  • apps/dashboard/src/components/BoxTable/types.ts
  • apps/dashboard/src/components/BoxTable/useBoxCommands.tsx
  • apps/dashboard/src/components/BoxTable/useBoxTable.ts
  • apps/dashboard/src/components/CommandPalette.tsx
  • apps/dashboard/src/components/ComparisonTable.tsx
  • apps/dashboard/src/components/CopyButton.tsx
  • apps/dashboard/src/components/CreateApiKeyDialog.tsx
  • apps/dashboard/src/components/CreateRegionDialog.tsx
  • apps/dashboard/src/components/CreateRunnerDialog.tsx
  • apps/dashboard/src/components/Invoices/InvoicesTableActions.tsx
  • apps/dashboard/src/components/Invoices/InvoicesTableHeader.tsx
  • apps/dashboard/src/components/Invoices/columns.tsx
  • apps/dashboard/src/components/Invoices/index.tsx
  • apps/dashboard/src/components/LoadingFallback.tsx
  • apps/dashboard/src/components/OnboardingDialogHost.tsx
  • apps/dashboard/src/components/OnboardingGuideDialog.tsx
  • apps/dashboard/src/components/OrganizationMembers/CreateOrganizationInvitationDialog.tsx
  • apps/dashboard/src/components/OrganizationMembers/OrganizationInvitationTable.tsx
  • apps/dashboard/src/components/OrganizationMembers/OrganizationMemberTable.tsx
  • apps/dashboard/src/components/OrganizationRoles/CreateOrganizationRoleDialog.tsx
  • apps/dashboard/src/components/OrganizationRoles/OrganizationRoleTable.tsx
  • apps/dashboard/src/components/Organizations/OrganizationPicker.tsx
  • apps/dashboard/src/components/PageLayout.tsx
  • apps/dashboard/src/components/Pagination.tsx
  • apps/dashboard/src/components/PrivacyBanner.tsx
  • apps/dashboard/src/components/RefreshSegmentedButton.tsx
  • apps/dashboard/src/components/RegionDetailsSheet.tsx
  • apps/dashboard/src/components/RegionTable.tsx
  • apps/dashboard/src/components/ResourceChip.tsx
  • apps/dashboard/src/components/RunnerDetailsSheet.tsx
  • apps/dashboard/src/components/RunnerTable.tsx
  • apps/dashboard/src/components/SelectionToast.tsx
  • apps/dashboard/src/components/Sidebar.tsx
  • apps/dashboard/src/components/SortIcon.tsx
  • apps/dashboard/src/components/TierUpgradeCard.tsx
  • apps/dashboard/src/components/UserOrganizationInvitations/UserOrganizationInvitationTable.tsx
  • apps/dashboard/src/components/VolumeTable.tsx
  • apps/dashboard/src/components/VolumeTable/useVolumeCommands.tsx
  • apps/dashboard/src/components/Webhooks/CreateEndpointDialog.tsx
  • apps/dashboard/src/components/Webhooks/EditEndpointDialog.tsx
  • apps/dashboard/src/components/Webhooks/EndpointEventsTable/EndpointEventsTable.tsx
  • apps/dashboard/src/components/Webhooks/EndpointEventsTable/EventDetailsSheet.tsx
  • apps/dashboard/src/components/Webhooks/EndpointEventsTable/columns.tsx
  • apps/dashboard/src/components/Webhooks/MessageAttemptsTable.tsx
  • apps/dashboard/src/components/Webhooks/WebhooksEndpointTable/WebhooksEndpointTable.tsx
  • apps/dashboard/src/components/Webhooks/WebhooksEndpointTable/columns.tsx
  • apps/dashboard/src/components/Webhooks/WebhooksMessagesTable/MessageDetailsSheet.tsx
  • apps/dashboard/src/components/Webhooks/WebhooksMessagesTable/WebhooksMessagesTable.tsx
  • apps/dashboard/src/components/admin/AdminOverviewView.tsx
  • apps/dashboard/src/components/admin/AdminPeopleBoxesView.tsx
  • apps/dashboard/src/components/admin/AdminTelemetryDrawer.tsx
  • apps/dashboard/src/components/admin/AdminTelemetryPanel.tsx
  • apps/dashboard/src/components/boxes/BoxContentTabs.tsx
  • apps/dashboard/src/components/boxes/BoxDetails.tsx
  • apps/dashboard/src/components/boxes/BoxFullscreenShell.tsx
  • apps/dashboard/src/components/boxes/BoxHeader.tsx
  • apps/dashboard/src/components/boxes/BoxInfoPanel.tsx
  • apps/dashboard/src/components/boxes/BoxLogsTab.tsx
  • apps/dashboard/src/components/boxes/BoxMetricsTab.tsx
  • apps/dashboard/src/components/boxes/BoxSpendingTab.tsx
  • apps/dashboard/src/components/boxes/BoxTerminalFrame.tsx
  • apps/dashboard/src/components/boxes/BoxTerminalFullscreen.tsx
  • apps/dashboard/src/components/boxes/BoxTerminalTab.tsx
  • apps/dashboard/src/components/boxes/BoxTracesTab.tsx
  • apps/dashboard/src/components/boxes/CreateSshAccessDialog.tsx
  • apps/dashboard/src/components/boxes/SearchParams.ts
  • apps/dashboard/src/components/boxes/index.ts
  • apps/dashboard/src/components/spending/BoxSpendingTab.tsx
  • apps/dashboard/src/components/spending/BoxUsageTable.tsx
  • apps/dashboard/src/components/spending/CostBreakdown.tsx
  • apps/dashboard/src/components/telemetry/LogsTab.tsx
  • apps/dashboard/src/components/telemetry/MetricsTab.tsx
  • apps/dashboard/src/components/telemetry/TracesTab.tsx
  • apps/dashboard/src/components/ui/accordion.tsx
  • apps/dashboard/src/components/ui/calendar.tsx
  • apps/dashboard/src/components/ui/card.tsx
  • apps/dashboard/src/components/ui/checkbox.tsx
  • apps/dashboard/src/components/ui/command.tsx
  • apps/dashboard/src/components/ui/copyable-value.tsx
  • apps/dashboard/src/components/ui/data-table-faceted-filter.tsx
  • apps/dashboard/src/components/ui/date-picker.tsx
  • apps/dashboard/src/components/ui/date-range-picker.tsx
  • apps/dashboard/src/components/ui/dialog.tsx
  • apps/dashboard/src/components/ui/dropdown-menu.tsx
  • apps/dashboard/src/components/ui/empty.tsx
  • apps/dashboard/src/components/ui/facet-filter.tsx
  • apps/dashboard/src/components/ui/icon.tsx
  • apps/dashboard/src/components/ui/label.tsx
  • apps/dashboard/src/components/ui/radio-group.tsx
  • apps/dashboard/src/components/ui/select.tsx
  • apps/dashboard/src/components/ui/sheet.tsx
  • apps/dashboard/src/components/ui/sidebar.tsx
  • apps/dashboard/src/components/ui/sonner.tsx
  • apps/dashboard/src/components/ui/spinner.tsx
  • apps/dashboard/src/components/ui/stories/alert.stories.tsx
  • apps/dashboard/src/components/ui/stories/colors.stories.tsx
  • apps/dashboard/src/components/ui/stories/copyable-value.stories.tsx
  • apps/dashboard/src/components/ui/stories/input-group.stories.tsx
  • apps/dashboard/src/components/ui/stories/sidebar.stories.tsx
  • apps/dashboard/src/components/ui/stories/toggle-group.stories.tsx
  • apps/dashboard/src/components/ui/stories/toggle.stories.tsx
  • apps/dashboard/src/contexts/ThemeContext.tsx
  • apps/dashboard/src/enums/LocalStorageKey.ts
  • apps/dashboard/src/hooks/useDocsSearchCommands.tsx
  • apps/dashboard/src/hooks/useSuspensionBanner.tsx
  • apps/dashboard/src/index.css
  • apps/dashboard/src/lib/auth-session.test.ts
  • apps/dashboard/src/lib/auth-session.ts
  • apps/dashboard/src/lib/dashboard-features.test.ts
  • apps/dashboard/src/lib/dashboard-features.ts
  • apps/dashboard/src/lib/environment.test.ts
  • apps/dashboard/src/lib/environment.ts
  • apps/dashboard/src/mocks/MockAuthProvider.tsx
  • apps/dashboard/src/mocks/fixtures.ts
  • apps/dashboard/src/mocks/handlers.ts
  • apps/dashboard/src/pages/Admin.tsx
  • apps/dashboard/src/pages/Billing.tsx
  • apps/dashboard/src/pages/Boxes.tsx
  • apps/dashboard/src/pages/Dashboard.tsx
  • apps/dashboard/src/pages/EmailVerify.tsx
  • apps/dashboard/src/pages/Keys.tsx
  • apps/dashboard/src/pages/LandingPage.tsx
  • apps/dashboard/src/pages/Limits.tsx
  • apps/dashboard/src/pages/LinkedAccounts.tsx
  • apps/dashboard/src/pages/Logout.tsx
  • apps/dashboard/src/pages/NotFound.tsx
  • apps/dashboard/src/pages/OrganizationSettings.tsx
  • apps/dashboard/src/pages/Spending.tsx
  • apps/dashboard/src/pages/Volumes.tsx
  • apps/dashboard/src/pages/Wallet.tsx
  • apps/dashboard/src/pages/WebhookEndpointDetails.tsx
  • apps/dashboard/src/pages/Webhooks.tsx
  • apps/dashboard/src/providers/ConfigProvider.tsx
  • apps/dashboard/src/providers/RegionsProvider.tsx
  • apps/dashboard/src/providers/SvixProvider.tsx
  • apps/dashboard/src/vendor/pylon/usePylonCommands.tsx
  • apps/dashboard/tailwind.config.js
  • apps/package.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e55a9b75e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

] as const

const DEFAULTS = { cpu: 1, memory: 1, disk: 10 }
const LIMITS = { cpu: 8, memory: 32, disk: 50 }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't clamp valid box sizes in the dialog

For organizations whose quotas allow larger boxes, the new dialog silently clamps any typed Advanced Options values to 8 vCPU / 32 GiB memory / 50 GiB disk because every Stepper is capped by this LIMITS object; the replaced sheet only required positive integers, and the new comment says the backend accepts arbitrary cpu/memory/disk. This prevents users from creating otherwise-valid larger boxes from the dashboard.

Useful? React with 👍 / 👎.

Comment on lines +672 to +674
const totalBoxesQuery = useQuery({
queryKey: ['boxesCount', orgId, 'all'],
queryFn: async () => (await boxApi.listBoxesPaginated(orgId, 1, 1)).data.total,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Invalidate fleet-count queries after box changes

These new stat-card queries use a separate ['boxesCount', orgId, ...] key, but all create/start/stop/delete handlers and websocket updates only invalidate getBoxesQueryKey(...). After creating, deleting, starting, or stopping a box, the table updates while the total/running/stopped cards keep the old cached counts until a remount/window-focus refetch happens, so the dashboard shows inconsistent fleet totals.

Useful? React with 👍 / 👎.

DorianZheng
DorianZheng previously approved these changes Jun 24, 2026
…ssets

- LandingPage: unauthenticated visitors redirect straight to the OIDC hosted login (Auth0/Dex) via signinRedirect; drop the non-functional email/password/social facade that never authenticated. Authenticated -> /dashboard.
- Delete 10 unreferenced assets (9 duplicate logos + react.svg); keep only the 4 logos used by Logo.tsx and the 4 SDK icons used by the Quickstart.
Addresses 3 confirmed findings from the review of the prior commits:
- [P2] Logout no longer bounces back into login. LandingPage auto-redirects to the hosted login only for fresh visitors; a just-logged-out user (marked in sessionStorage before signoutRedirect in Logout + Sidebar) gets a manual sign-in screen instead, avoiding the SSO-cookie re-auth loop.
- [P2] Create Box dialog caps at 540px again: sm:max-w-[540px] now overrides shadcn base sm:max-w-lg (512px).
- [P2] Tablet header (768-1023px): mobile menu trigger md:hidden -> lg:hidden + add Quickstart to it, so Search/API Keys/Quickstart stay reachable.
# Conflicts:
#	apps/dashboard/src/components/BoxTable/columns.tsx
#	apps/dashboard/src/components/BoxTable/index.tsx
#	apps/dashboard/src/components/BoxTable/useBoxTable.ts
#	apps/dashboard/src/pages/Boxes.tsx
#	apps/scripts/start-dashboard.mjs
… top

Profile dropdown reorder: name+email header, Theme (renamed from Appearance), then Organization / Docs / Discord as plain single-line items, Sign out last. Organization is now one item linking straight to org settings (drops the hover submenu with org switcher + copy-id; org-id copy stays in the command palette).
@DorianZheng DorianZheng merged commit 6fff778 into boxlite-ai:main Jun 24, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants