Skip to content

refactor(dashboard): dead CSS, duplication and oversized components - #585

Merged
SantiagoDePolonia merged 7 commits into
mainfrom
chore/rework
Jul 25, 2026
Merged

SantiagoDePolonia merged 7 commits into
mainfrom
chore/rework

Conversation

@SantiagoDePolonia

@SantiagoDePolonia SantiagoDePolonia commented Jul 25, 2026 •

Copy link
Copy Markdown
Contributor

Housekeeping pass over the Svelte dashboard: 69 files, +689 / −2657 in source (plus the regenerated dist/). No intended behavior change apart from one fix, called out below.

Dead CSS

dashboard.css drops 2618 → 2400 lines. Removed 14 unreachable rule groups: an Alpine.js [x-cloak] leftover, an unwired tab-transition, five budget-bar-fill-period-* colours, two .is-editor-open compounds nothing sets, an empty @media block, .editor-modal-shell-wide (two components carry comments saying the Modal atom has no wide variant — it doesn't), and more.

Svelte's unused-selector warning can't see any of these: they're either global or sit in components whose class attribute is built from an expression, which makes the compiler conservative.

One fix

AuditPane's request/response direction arrows are meant to be tinted accent/blue (there's a comment saying so), but the global modifier .audit-pane-icon-request (0,1,0) lost to the scoped base .audit-pane-icon.svelte-hash (0,2,0) and both rendered muted grey. Confirmed against the previously committed compiled CSS. The modifiers now live in the owning component as compound :global selectors, so they stay reachable for dynamically composed classes and outrank the base. This is the one visible change in the PR. The cascade trap is now documented in CONVENTIONS.md.

Extracted

New Replaces
NoDataIllustration a 60-line SVG copy-pasted byte-identically into 3 pages
FilterInput the search-icon + input block repeated in 11 pages
CopyButton the copy/check icon-swap button in 3 places
AuditEntry{Summary,Metadata} + AuditPaneTabs AuditEntryRow, 622 → 71 lines
WorkflowIdBadge the id pill inside WorkflowChart
DatePickerCalendar + datePickerLogic DatePicker, 576 → 293

Deleted pages/models/TableIcon.svelte — a hand-rolled name→SVG switch duplicating the lucide Icon atom. The rest of the app already rendered the same table actions via Icon, so models/ had visibly different pencil/trash glyphs from API Keys and MCP Servers.

Deduplicated

A scan for identical function bodies found 11 groups; all are now zero. Notably four byte-identical {error:{message}} extractors (plus four near-identical test blocks), the chart tooltip/tick fragments in two modules, and the 11-colour palette in three places with labelColor's djb2 hash duplicated verbatim.

New $lib/api/errors.js exists rather than living in client.js because client.js imports rune-based stores, which pure page logic and node:test can't load.

Renamed .pagination-btn → .btn

It was the app's base button class on ~37 elements unrelated to pagination — every primary action read class="pagination-btn pagination-btn-primary pagination-btn-with-icon". Renamed across 36 files (157 occurrences); .pagination (the container) is unchanged. Token-exact, and .btn-danger doesn't collide with the pre-existing .table-action-btn-danger.

Verification

  • svelte-check: 0 errors, 0 warnings
  • tests: 317 → 330 (new suites for the extracted date math, debounce and error helpers)
  • npm run build clean; embedded dist/ regenerated and in sync
  • Rendered against a live gateway: Overview, Models, Audit Logs (including an expanded entry — workflow chart, request/response tabs, metadata strip), Usage, Settings, API Keys

The new date-picker tests immediately caught a bug I'd introduced while extracting calendarDays: for (let d = 1; d <= 42 - days.length; d++) re-evaluates its bound each iteration, so the grid came out at 38–40 cells instead of 42. Fixed.

Review notes

Reviewing commit-by-commit is easier than the combined diff — the second commit is a pure mechanical rename.

Three files remain slightly over the 400-line guideline (WorkflowChart 575, Sidebar 435, ProviderStatusCard 429). The remainder in each is a flat, commented status/state CSS matrix; splitting is blocked because the state classes are computed strings, so a child component's scoped rules would be pruned — now noted in CONVENTIONS.md. The light/dark token duplication also has to stay: light-dark() would break chartTheme.cssVar(), which reads those variables back with getComputedStyle — now explained at the top of dashboard.css, replacing a TODO that blamed the missing CSS preprocessor.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added reusable FilterInput, NoDataIllustration, CopyButton, and ThemeToggle components (plus a workflow ID badge).
    • Expanded the audit logs UI with dedicated metadata/summary and request/response tabs.
    • Rebuilt the date picker with a calendar sub-component and shared UTC calendar math.
  • Bug Fixes
    • Improved API/admin error-message extraction via shared helpers (with added test coverage).
  • Style
    • Standardized buttons/icons, updated sidebar/modal styling, and improved shared chart theming and CSS scoping guidance.
  • Tests
    • Added/updated unit tests for the new shared utilities and removed obsolete helper tests.

SantiagoDePolonia and others added 2 commits July 25, 2026 11:45
…ponents

Housekeeping pass over the Svelte dashboard. No intended behavior change
apart from one fix noted below.

Dead CSS: dashboard.css drops 2618 -> 2400 lines. Removed an Alpine.js
[x-cloak] leftover, an unwired tab-transition, five budget-bar-fill-period-*
colors, two .is-editor-open compounds nothing sets, an empty media block and
nine other unreachable rules. Svelte's unused-selector warning cannot see
these: they are either global or sit in components whose class attribute is
built from an expression.

Fix: AuditPane's request/response direction arrows were meant to be tinted
accent/blue, but the global modifier (.audit-pane-icon-request, 0,1,0) lost
to the scoped base (.audit-pane-icon.svelte-hash, 0,2,0) and both rendered
muted grey. The modifiers now live in the owning component as compound
:global selectors so they stay reachable for dynamically composed classes
and outrank the base. The cascade trap is documented in CONVENTIONS.md.

Extracted: NoDataIllustration (a 60-line SVG copy-pasted byte-identically
into 3 pages), FilterInput (the search block repeated in 11 pages),
CopyButton, AuditEntry{Summary,Metadata}/AuditPaneTabs (AuditEntryRow
622 -> 71), WorkflowIdBadge, DatePickerCalendar + datePickerLogic
(DatePicker 576 -> 293). Deleted pages/models/TableIcon.svelte, a
hand-rolled duplicate of the lucide Icon atom that gave models/ different
pencil/trash glyphs from the rest of the app.

Deduped: 11 groups of identical functions are now zero -- four identical
{error:{message}} extractors (new $lib/api/errors.js, kept free of
rune imports so pure page logic and node:test can use it), the chart
tooltip/tick fragments, the 11-color palette that existed in three places
with labelColor's hash duplicated verbatim, browserStorage, formatDateParam,
formatNumber, splitCommaList, mcpServerStatus, qualifiedModelName, the two
workflow connector twins, and the debounce shape in three components.

Markup: WorkflowChart's nine near-identical nodes collapse into one snippet,
ProviderStatusCard's eight label/value rows into another, Sidebar's three
theme buttons into an each block, and two dead single-child layout wrappers
are gone.

Tests: 317 -> 330. The new date-picker tests caught a bug introduced while
extracting calendarDays (a loop bound re-evaluated each iteration produced
38-40 grid cells instead of 42).

Findings, including what was deliberately left alone and why, are in
docs/dev/2026-07-25_dashboard-refactor.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
.pagination-btn was the app's base button class, worn by ~37 elements that
have nothing to do with pagination -- every primary action read
class="pagination-btn pagination-btn-primary pagination-btn-with-icon".

Renamed across 36 files (157 occurrences) to .btn, .btn-primary, .btn-danger,
.btn-danger-outline and .btn-with-icon, and documented the pairing rule above
the base rule. The .pagination container class is unchanged.

The rename is token-exact: no other class contains the substring
"pagination-btn", and the new .btn-danger does not collide with the existing
.table-action-btn-danger (a different class token). Verified against a live
gateway that every variant -- primary, danger, danger-outline, plain and
with-icon -- renders as before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 09:48
@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown

Too many files changed for review. (109 files found, 100 file limit)

Bypass the limit by tagging @greptile-apps to review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@SantiagoDePolonia, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 976f20cb-2454-4ca0-a2b1-f79d5b033b07

📥 Commits

Reviewing files that changed from the base of the PR and between 554b422 and 67806a7.

⛔ Files ignored due to path filters (2)
  • internal/admin/dashboard/static/dist/assets/index-B4NYOd0m.js is excluded by !**/dist/**
  • internal/admin/dashboard/static/dist/index.html is excluded by !**/dist/**
📒 Files selected for processing (7)
  • web/dashboard/CONVENTIONS.md
  • web/dashboard/src/lib/api/errors.js
  • web/dashboard/src/lib/components/atoms/NoDataIllustration.svelte
  • web/dashboard/src/lib/components/organisms/ThemeToggle.svelte
  • web/dashboard/src/pages/auth-keys/authKeysLogic.js
  • web/dashboard/src/pages/usage/usage-helpers.js
  • web/dashboard/tests/api-errors.test.js
📝 Walkthrough

Walkthrough

This PR centralizes dashboard utilities, error handling, filters, icons, buttons, chart styling, storage, and debounce behavior. It extracts audit-log and date-picker components, refactors workflow and overview rendering, updates global CSS, and adds unit tests and conventions documentation.

Changes

Dashboard refactor

Layer / File(s) Summary
Shared utilities and date-picker foundations
web/dashboard/src/lib/api/*, web/dashboard/src/lib/utils/*, web/dashboard/src/lib/components/atoms/*, web/dashboard/src/lib/components/molecules/*
Shared error, formatting, storage, chart, debounce, filter, copy, empty-state, and date-picker utilities/components are added or centralized.
Audit components and shared interaction atoms
web/dashboard/src/pages/audit-logs/*
Audit rows are decomposed into summary, tabs, metadata, and pane components, with shared filtering, copying, and empty-state controls.
Page filters, errors, icons, and button migration
web/dashboard/src/pages/*, web/dashboard/src/lib/stores/*
Pages and stores adopt shared filters, error helpers, storage utilities, formatting helpers, generic buttons, and shared icons.
Overview and workflow rendering
web/dashboard/src/pages/overview/*, web/dashboard/src/pages/workflows/*
Chart helpers are centralized, provider configuration rows are composed from snippets, workflow nodes use shared rendering, and cache-bypassed connectors share one helper.
Global CSS cleanup and button system
web/dashboard/src/styles/dashboard.css, web/dashboard/src/lib/components/atoms/Modal.svelte
Legacy selectors are removed, generic button variants are defined, responsive selectors are updated, and modal sizing overrides are simplified.
Validation and conventions
web/dashboard/tests/*, web/dashboard/CONVENTIONS.md
Tests cover centralized errors, date-picker logic, debounce behavior, and shared parsing; conventions document the new utilities and component contracts.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: copilot

Poem

I’m a rabbit with buttons bright,
Sharing filters left and right.
Errors hop to one neat home,
Charts bloom where helpers roam.
Audit badges softly gleam—
Refactored code, a carrot dream!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: a dashboard refactor focused on dead CSS, duplication, and oversized components.
Description check ✅ Passed The description is substantive and covers scope, fixes, extracted code, and verification, but it doesn't follow the repo's template headings exactly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/rework

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.

@mintlify

mintlify Bot commented Jul 25, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
gomodel 🟢 Ready View Preview Jul 25, 2026, 9:49 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Drops docs/dev/2026-07-25_dashboard-refactor.md. Its removal/extraction
tables duplicated the two commit messages and the PR description, which stay
attached to the diff; a dated narration of one PR goes stale as soon as the
code moves.

The two durable warnings move to where someone would actually hit them:

- dashboard.css now explains why the light palette is written twice and why
  light-dark() must not collapse it (chartTheme.js reads those variables via
  getComputedStyle, which would hand Chart.js the literal "light-dark(...)"
  token stream). Replaces a TODO blaming the missing CSS preprocessor, which
  was not the actual blocker.
- CONVENTIONS.md notes why a component with computed state classes cannot
  hand its status CSS to a child component (the compiler prunes what it
  cannot see in the child's markup).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 09:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/dashboard/CONVENTIONS.md`:
- Around line 164-172: Update the Utils section of CONVENTIONS.md to document
the shared format.js exports splitCommaList and formatDateParam, alongside the
existing utility entries. Describe them as the canonical helpers for comma-list
parsing and date-parameter formatting, without changing unrelated documentation.

In `@web/dashboard/src/lib/api/errors.js`:
- Around line 6-9: Update errorPayloadMessage so string messages are normalized
with whitespace trimmed before checking whether they are non-empty and returning
them; use fallback for whitespace-only values, matching errorMessage behavior.

In `@web/dashboard/src/lib/components/atoms/NoDataIllustration.svelte`:
- Around line 8-14: Update the SVG accessibility attributes in
NoDataIllustration so an empty label removes the aria-label and marks the
illustration decorative with aria-hidden. Preserve the existing named-image
behavior when label is provided, using the label value rather than the “No data”
fallback.

In `@web/dashboard/src/lib/components/organisms/Sidebar.svelte`:
- Around line 87-107: Update the desktop theme buttons in the themes each-block
to include aria-pressed based on whether themeStore.theme matches theme.value.
Update the mobile theme-toggle-mobile button’s aria-label and title to describe
the action and current activeTheme, such as “Change theme (currently Light
theme),” rather than only the current theme name.

In `@web/dashboard/src/pages/auth-keys/authKeysLogic.js`:
- Around line 104-108: Replace the separate labelChipStyle/labelColor import and
export declarations in authKeysLogic.js with a single top-of-file re-export from
chartTheme.js, positioned after the existing initial import. Remove the trailing
import/export block while preserving both exported symbols.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7ef2360c-169d-4d31-bc62-0fdfb4fbb0f7

📥 Commits

Reviewing files that changed from the base of the PR and between 7b74d97 and d25bc0b.

⛔ Files ignored due to path filters (5)
  • internal/admin/dashboard/static/dist/assets/index-B2NLf2EL.js is excluded by !**/dist/**
  • internal/admin/dashboard/static/dist/assets/index-D6wCbLbq.css is excluded by !**/dist/**
  • internal/admin/dashboard/static/dist/assets/index-hhannOLz.css is excluded by !**/dist/**
  • internal/admin/dashboard/static/dist/assets/index-yem6AgYM.js is excluded by !**/dist/**
  • internal/admin/dashboard/static/dist/index.html is excluded by !**/dist/**
📒 Files selected for processing (104)
  • docs/dev/2026-07-25_dashboard-refactor.md
  • web/dashboard/CONVENTIONS.md
  • web/dashboard/src/lib/api/client.js
  • web/dashboard/src/lib/api/errors.js
  • web/dashboard/src/lib/components/atoms/CopyButton.svelte
  • web/dashboard/src/lib/components/atoms/Modal.svelte
  • web/dashboard/src/lib/components/atoms/NoDataIllustration.svelte
  • web/dashboard/src/lib/components/molecules/DatePicker.svelte
  • web/dashboard/src/lib/components/molecules/DatePickerCalendar.svelte
  • web/dashboard/src/lib/components/molecules/FilterInput.svelte
  • web/dashboard/src/lib/components/molecules/Pagination.svelte
  • web/dashboard/src/lib/components/molecules/datePickerLogic.js
  • web/dashboard/src/lib/components/organisms/AuthBanner.svelte
  • web/dashboard/src/lib/components/organisms/AuthDialog.svelte
  • web/dashboard/src/lib/components/organisms/Sidebar.svelte
  • web/dashboard/src/lib/components/organisms/TypedConfirmationDialog.svelte
  • web/dashboard/src/lib/stores/dateRange.svelte.js
  • web/dashboard/src/lib/stores/timezone.svelte.js
  • web/dashboard/src/lib/stores/ui.svelte.js
  • web/dashboard/src/lib/utils/chartTheme.js
  • web/dashboard/src/lib/utils/debounce.js
  • web/dashboard/src/lib/utils/format.js
  • web/dashboard/src/lib/utils/storage.js
  • web/dashboard/src/pages/audit-logs/AuditEntryMetadata.svelte
  • web/dashboard/src/pages/audit-logs/AuditEntryRow.svelte
  • web/dashboard/src/pages/audit-logs/AuditEntrySummary.svelte
  • web/dashboard/src/pages/audit-logs/AuditFilters.svelte
  • web/dashboard/src/pages/audit-logs/AuditLogsPage.svelte
  • web/dashboard/src/pages/audit-logs/AuditPane.svelte
  • web/dashboard/src/pages/audit-logs/AuditPaneTabs.svelte
  • web/dashboard/src/pages/audit-logs/audit-logic.js
  • web/dashboard/src/pages/auth-keys/AuthKeyEditor.svelte
  • web/dashboard/src/pages/auth-keys/AuthKeyLabelsEditor.svelte
  • web/dashboard/src/pages/auth-keys/AuthKeysPage.svelte
  • web/dashboard/src/pages/auth-keys/authKeys.svelte.js
  • web/dashboard/src/pages/auth-keys/authKeysLogic.js
  • web/dashboard/src/pages/budgets/BudgetEditor.svelte
  • web/dashboard/src/pages/budgets/BudgetsPage.svelte
  • web/dashboard/src/pages/guardrails/GuardrailEditor.svelte
  • web/dashboard/src/pages/guardrails/GuardrailList.svelte
  • web/dashboard/src/pages/guardrails/guardrails-logic.js
  • web/dashboard/src/pages/guardrails/guardrails.svelte.js
  • web/dashboard/src/pages/mcp-servers/McpCatalogModal.svelte
  • web/dashboard/src/pages/mcp-servers/McpServerEditor.svelte
  • web/dashboard/src/pages/mcp-servers/McpServersPage.svelte
  • web/dashboard/src/pages/mcp-servers/mcp-servers.js
  • web/dashboard/src/pages/mcp-servers/mcpServers.svelte.js
  • web/dashboard/src/pages/models/FailoverDrafts.svelte
  • web/dashboard/src/pages/models/FailoverEditor.svelte
  • web/dashboard/src/pages/models/ModelGlobalActions.svelte
  • web/dashboard/src/pages/models/ModelRow.svelte
  • web/dashboard/src/pages/models/ModelTable.svelte
  • web/dashboard/src/pages/models/ModelsPage.svelte
  • web/dashboard/src/pages/models/PricingOverrideEditor.svelte
  • web/dashboard/src/pages/models/TableIcon.svelte
  • web/dashboard/src/pages/models/VirtualModelEditor.svelte
  • web/dashboard/src/pages/models/VmTargetRow.svelte
  • web/dashboard/src/pages/models/failover-logic.js
  • web/dashboard/src/pages/overview/AuditStatsCharts.svelte
  • web/dashboard/src/pages/overview/LiveTokens.svelte
  • web/dashboard/src/pages/overview/ProviderStatusCard.svelte
  • web/dashboard/src/pages/overview/SummaryCards.svelte
  • web/dashboard/src/pages/overview/UsageChart.svelte
  • web/dashboard/src/pages/overview/auditStatsLogic.js
  • web/dashboard/src/pages/overview/chartStyle.js
  • web/dashboard/src/pages/overview/liveTokensLogic.js
  • web/dashboard/src/pages/overview/mcpOverviewLogic.js
  • web/dashboard/src/pages/overview/overviewChartLogic.js
  • web/dashboard/src/pages/overview/overviewState.svelte.js
  • web/dashboard/src/pages/providers-config/ProviderCredentialEditor.svelte
  • web/dashboard/src/pages/providers-config/ProvidersConfigPage.svelte
  • web/dashboard/src/pages/providers-config/providersConfig.svelte.js
  • web/dashboard/src/pages/providers-config/providersConfigLogic.js
  • web/dashboard/src/pages/rate-limits/RateLimitEditor.svelte
  • web/dashboard/src/pages/rate-limits/RateLimitInspector.svelte
  • web/dashboard/src/pages/rate-limits/RateLimitsPage.svelte
  • web/dashboard/src/pages/settings/BudgetResetSettings.svelte
  • web/dashboard/src/pages/settings/BudgetSettings.svelte
  • web/dashboard/src/pages/settings/FailoverSettings.svelte
  • web/dashboard/src/pages/settings/PricingRecalculation.svelte
  • web/dashboard/src/pages/settings/RuntimeRefresh.svelte
  • web/dashboard/src/pages/settings/TaggingSettings.svelte
  • web/dashboard/src/pages/settings/TimezoneSettings.svelte
  • web/dashboard/src/pages/settings/pricing-logic.js
  • web/dashboard/src/pages/usage/FacetFilters.svelte
  • web/dashboard/src/pages/usage/UsageBreakdownChart.svelte
  • web/dashboard/src/pages/usage/UsageLog.svelte
  • web/dashboard/src/pages/usage/usage-chart-config.js
  • web/dashboard/src/pages/usage/usage-helpers.js
  • web/dashboard/src/pages/workflows/WorkflowCard.svelte
  • web/dashboard/src/pages/workflows/WorkflowChart.svelte
  • web/dashboard/src/pages/workflows/WorkflowEditor.svelte
  • web/dashboard/src/pages/workflows/WorkflowIdBadge.svelte
  • web/dashboard/src/pages/workflows/WorkflowList.svelte
  • web/dashboard/src/pages/workflows/WorkflowsPage.svelte
  • web/dashboard/src/pages/workflows/workflowChartLogic.js
  • web/dashboard/src/styles/dashboard.css
  • web/dashboard/tests/api-errors.test.js
  • web/dashboard/tests/auth-keys.test.js
  • web/dashboard/tests/date-picker-logic.test.js
  • web/dashboard/tests/debounce.test.js
  • web/dashboard/tests/guardrails.test.js
  • web/dashboard/tests/mcp-servers.test.js
  • web/dashboard/tests/providers-config.test.js
💤 Files with no reviewable changes (6)
  • web/dashboard/src/pages/workflows/WorkflowList.svelte
  • web/dashboard/src/pages/models/TableIcon.svelte
  • web/dashboard/src/lib/components/atoms/Modal.svelte
  • web/dashboard/src/pages/guardrails/guardrails-logic.js
  • web/dashboard/tests/auth-keys.test.js
  • web/dashboard/tests/guardrails.test.js

Comment thread web/dashboard/CONVENTIONS.md Outdated
Comment thread web/dashboard/src/lib/api/errors.js
Comment thread web/dashboard/src/lib/components/atoms/NoDataIllustration.svelte
Comment thread web/dashboard/src/lib/components/organisms/Sidebar.svelte Outdated
Comment thread web/dashboard/src/pages/auth-keys/authKeysLogic.js Outdated
SantiagoDePolonia and others added 2 commits July 25, 2026 12:02
The theme control is a self-contained widget with two presentations of one
choice: a three-way pill when there is room, a single cycling button when
there isn't. It now lives in ThemeToggle.svelte and takes a `compact` prop.

This moves coupling out of Sidebar rather than adding it. Sidebar previously
reached into the widget with four rules to swap the two forms -- two under
.sidebar-collapsed and two in the 768px breakpoint. ThemeToggle now owns both
branches, sitting next to each other so it is obvious they express the same
intent, and neither component needs :global() to reach the other.

Sidebar 435 -> 334 lines.

Not extracted: the individual .theme-btn inside the loop. It is used once,
its styling assumes the pill around it (transparent, borderless, sized as a
segment), and pulling it out would split .theme-btn:focus-visible away from
its siblings and duplicate the focus-ring declaration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The "Foundation API" section had grown to 134 of 226 lines: a hand-maintained
catalogue of every store method, component prop and util export. Nothing
enforced it, so it drifted from the source, and it buried the rules that
actually matter among prop lists. Every component already documents its own
props in a header comment, so the catalogue was duplication with a shelf life.

Foundation is now an index -- what exists, so nobody re-implements it -- and
points at the header comments for detail. The rules that are not discoverable
from a signature all stay: the result.stale contract, global 401 handling,
never fetch /admin directly, why errors.js has no Svelte-runtime imports,
Modal's autofocus attribute, ChartCanvas's build-in-an-effect semantics.

Also:
- The three scope-hash traps move out of the CSS rule into their own numbered
  rule; "no new npm dependencies" is promoted from a bullet in the middle of
  the page-conventions list to a golden rule.
- Documents that pure-logic .js files must use relative imports rather than
  $lib, because node:test runs them without Vite so the alias does not
  resolve -- and therefore cannot import a .svelte.js store.
- Verification lists the npm scripts rather than a raw npx invocation.

226 -> 146 lines.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 10:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Removes 53 comments that carried no information a reader couldn't get from
the line below them:

- 45x "/* Styles owned by this component (moved from dashboard.css). */",
  the first line of nearly every scoped <style> block. It is a leftover from
  the Svelte port: "moved from dashboard.css" is git history, and "owned by
  this component" is what a scoped style block means -- CONVENTIONS rule 2
  already says that is what belongs there.
- Section comments naming the component they are already inside
  (/* Category Tabs */ in ModelsPage, /* Usage Log Section */ in UsageLog,
  /* Contribution Calendar */ in ContributionCalendar).
- Markup labels restating the element below (<!-- Auth Error Banner -->
  above <AuthBanner />, <!-- Filter --> above the filter toolbar).
- Two header comments restating the filename ("// Workflows page.",
  "// Rate Limits page.").

Deliberately kept: the section dividers in dashboard.css that head a run of
rules (/* Table */, /* Content */), header comments that add context beyond
the filename, and every markup comment stating a behavior ("Clicking a
highlighted body snippet opens the Interactions drawer", "two or more targets
turn the redirect into a load balancer").

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 10:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

CodeRabbit review of #585. Four accepted, one accepted in part.

- errorPayloadMessage now trims and treats a whitespace-only message as
  absent, matching errorMessage. The two sit side by side in errors.js and
  the comment claims they do the same thing, so the difference was a trap;
  a blank string is also useless to show a user. Covered by a new test.
- NoDataIllustration with label="" is now genuinely decorative
  (role/aria-label dropped, aria-hidden set) instead of still announcing
  "No data" over an empty state that already says so in text. That option is
  documented but currently unused, so this is the documented behavior
  catching up with the code.
- ThemeToggle exposes its selection: aria-pressed per segment and
  role="group" on the pill, matching the SegmentedControl atom's ARIA. The
  state was previously conveyed by background color alone.
- The narrow theme button cycles rather than selects, so it is now labelled
  for its action -- "Change theme (currently Light theme)" -- instead of
  announcing only the current theme, which read as a state, not a control.
- CONVENTIONS.md: widened the format.js description to cover date params and
  comma lists. Not re-enumerating every export -- that catalogue is what the
  previous commit deliberately removed -- but the one-line index has to hint
  that splitCommaList lives there, since two pages had already reimplemented
  it.

Declined: collapsing the remaining `import` + `export {}` pairs into
`export ... from`. That was the original form; it creates no local binding,
so the five modules that also call the symbol internally (mcp-servers,
providersConfigLogic, failover-logic, mcpOverviewLogic, pricing-logic) break
at runtime. Applied only to authKeysLogic and usage-helpers, which re-export
without using the symbols.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 25, 2026 10:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor Author

Thanks — went through all five. Four accepted, one accepted in part, in 67806a7.

errorPayloadMessage whitespace — accepted. Confirmed: " " was returned verbatim while its sibling errorMessage trims. They sit side by side in errors.js under a comment saying they do the same thing, so the difference was a trap. Now trims, with a test. (For the record this matches the four page-local helpers it replaced — none trimmed — so it's not a regression from this PR, just newly visible once they were consolidated.)

NoDataIllustration with label="" — accepted. Now role/aria-label are dropped and aria-hidden set. Worth noting the option is currently unused (all three call sites render the labelled form), so this is the documented behaviour catching up with the code rather than a live bug.

aria-pressed on the theme buttons — accepted, and I matched the house pattern: SegmentedControl.svelte already does role="group" + aria-pressed for exclusive option groups, so the theme pill now does the same. Selection state was previously conveyed by background colour alone.

Mobile theme button label — accepted. It cycles rather than selects, so announcing "Light theme" described a state, not a control. Now "Change theme (currently Light theme)".

Collapse import + export {} into export ... from — accepted for 2 of 7 modules, declined for the rest. export { x } from creates no local binding, so any module that also calls the symbol internally breaks at runtime — that was the original form here and the test suite caught it. Five modules call theirs internally (mcp-servers, providersConfigLogic, failover-logic, mcpOverviewLogic, pricing-logic); authKeysLogic and usage-helpers don't, so those two are collapsed.

CONVENTIONS.md utils — accepted in part. I widened the format.js one-liner to cover date params and comma lists rather than re-listing every export: the previous commit deliberately replaced that per-export catalogue with an index, because it drifted and nothing enforced it. But the underlying point stands — two pages had independently reimplemented splitCommaList, so the index does need to hint that it lives there.

svelte-check 0/0, 331 tests green, dist/ in sync.

@mintlify

mintlify Bot commented Jul 25, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
gomodel 🟡 Building – Jul 25, 2026, 9:48 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

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