From 04ad75280ac31ec22708760c981fefac5fbbaec9 Mon Sep 17 00:00:00 2001 From: Makisuo Date: Fri, 30 Oct 2026 21:18:32 +0100 Subject: [PATCH] style(web): name the opacity ladders, one width scale, severity status colours Text, surface and border opacities were 30 ad-hoc `/NN` levels. They are now named tokens: foreground-soft/subtle/faint, surface-faint/sunken/strong (sunken = row hover at 50%, strong = selected at 60%, matching #1988) and border-subtle. Table column widths between 64 and 260px snap to a 16px scale (36 values -> 13). Bordered boxes use Panel's p-3/p-4. `rounded` and `rounded-sm` were both 4px; now one spelling. Status values still on the old success/warning/info tokens use the severity palette; red stays `destructive` only for destructive actions and form errors. Avatar tiles and onboarding region accents move from hard-coded colours to tokens, and replays and error actors use the same warm avatar tiles as settings. SQL query badges get dark text on amber like the primary button. --- apps/web/src/charts/bucket-tooltip.ts | 4 +- apps/web/src/charts/funnel-chart.ts | 8 +- apps/web/src/charts/funnel-dropoff-chart.ts | 14 ++-- apps/web/src/charts/hbar-chart.ts | 6 +- apps/web/src/charts/heatmap-chart.ts | 4 +- apps/web/src/charts/histogram-chart.ts | 2 +- apps/web/src/charts/paths-chart.ts | 4 +- apps/web/src/charts/paths-tooltip.ts | 8 +- apps/web/src/charts/pie-chart.ts | 4 +- apps/web/src/charts/plot-legend.ts | 4 +- apps/web/src/charts/timeseries-legend.ts | 6 +- .../src/components/infra/severity-tokens.ts | 2 +- apps/web/src/lab/charts/spike-view.ts | 8 +- apps/web/src/lab/entries/agent-sessions.ts | 4 +- apps/web/src/lab/entries/agent-tools.ts | 4 +- apps/web/src/lab/entries/bench/service-map.ts | 2 +- apps/web/src/lab/entries/index.ts | 2 +- apps/web/src/lab/entries/replays.ts | 6 +- apps/web/src/lab/errors-lab/view.ts | 6 +- .../src/lab/query-builder-lab/view-query.ts | 2 +- apps/web/src/lab/query-builder-lab/view.ts | 2 +- .../lab/service-map-3d-lab/view-inspector.ts | 2 +- .../lab/service-map-3d-lab/view-inventory.ts | 2 +- apps/web/src/lab/service-map-3d-lab/view.ts | 2 +- apps/web/src/lab/time-range-lab.ts | 4 +- apps/web/src/lab/widget-lab/view-copy.ts | 6 +- apps/web/src/lib/sql-highlight.ts | 2 +- .../src/page/agent-sessions/kit/more-chip.ts | 2 +- apps/web/src/page/agent-sessions/kit/tabs.ts | 2 +- .../page/agent-sessions/list/view-table.ts | 12 +-- .../session/span-popover-details.ts | 16 ++-- .../session/span-popover-messages.ts | 12 +-- .../agent-sessions/session/span-visuals.ts | 2 +- .../page/agent-sessions/session/tool-io.ts | 10 +-- .../session/transcript-blocks.ts | 2 +- .../session/transcript-calls.ts | 2 +- .../session/transcript-lanes.ts | 2 +- .../session/transcript-messages.ts | 8 +- .../session/transcript-shell.ts | 2 +- .../agent-sessions/session/view-checks.ts | 10 +-- .../page/agent-sessions/session/view-flow.ts | 2 +- .../agent-sessions/session/view-header.ts | 4 +- .../agent-sessions/session/view-overview.ts | 4 +- .../agent-sessions/session/view-waterfall.ts | 12 +-- .../tool/view-error-modal-payload.ts | 18 ++--- .../tool/view-error-modal-rail.ts | 18 ++--- .../tool/view-error-modal-samples.ts | 24 +++--- .../agent-sessions/tool/view-error-modal.ts | 14 ++-- .../page/agent-sessions/tool/view-errors.ts | 48 +++++------ .../page/agent-sessions/tool/view-sessions.ts | 10 +-- .../agent-sessions/tools-kit/error-parts.ts | 10 +-- .../agent-sessions/tools-kit/metric-strip.ts | 4 +- .../agent-sessions/tools-kit/scope-row.ts | 2 +- .../agent-sessions/tools-kit/series-chart.ts | 4 +- .../page/agent-sessions/tools-kit/table.ts | 8 +- .../page/agent-sessions/tools-kit/toolbar.ts | 2 +- .../page/agent-sessions/tools/view-table.ts | 38 ++++----- .../alerts/destination/chat-fields-view.ts | 2 +- .../alerts/destination/hazel-fields-view.ts | 2 +- .../alerts/destination/linear-fields-view.ts | 2 +- apps/web/src/page/alerts/destination/view.ts | 10 +-- .../src/page/alerts/editor/view-condition.ts | 10 +-- .../src/page/alerts/editor/view-details.ts | 4 +- .../web/src/page/alerts/editor/view-impact.ts | 4 +- .../web/src/page/alerts/editor/view-notify.ts | 6 +- apps/web/src/page/alerts/editor/view-query.ts | 4 +- apps/web/src/page/alerts/editor/view-sql.ts | 8 +- apps/web/src/page/alerts/hub/view-empty.ts | 4 +- apps/web/src/page/alerts/hub/view-inbox.ts | 10 +-- apps/web/src/page/alerts/hub/view-routing.ts | 12 +-- apps/web/src/page/alerts/hub/view-rules.ts | 4 +- apps/web/src/page/alerts/hub/view-uptime.ts | 4 +- .../src/page/alerts/incident/view-timeline.ts | 4 +- apps/web/src/page/alerts/rule/view-checks.ts | 14 ++-- .../src/page/alerts/rule/view-diagnosis.ts | 2 +- apps/web/src/page/alerts/rule/view-history.ts | 12 +-- .../web/src/page/alerts/rule/view-overview.ts | 2 +- apps/web/src/page/alerts/shared/providers.ts | 2 +- apps/web/src/page/alerts/shared/rule-chart.ts | 4 +- .../src/page/alerts/uptime-form/view-kinds.ts | 2 +- apps/web/src/page/alerts/uptime-form/view.ts | 4 +- .../page/alerts/uptime-monitor/view-panels.ts | 2 +- apps/web/src/page/analytics/view-ai-parts.ts | 30 +++---- apps/web/src/page/analytics/view-breakdown.ts | 8 +- apps/web/src/page/analytics/view-overview.ts | 2 +- apps/web/src/page/analytics/view.ts | 2 +- .../src/page/anomalies/detail/view-body.ts | 6 +- .../page/anomalies/detail/view-link-dialog.ts | 2 +- apps/web/src/page/anomalies/kit/row.ts | 12 +-- apps/web/src/page/anomalies/list/view-list.ts | 14 ++-- .../page/code-review/analytics/view-lists.ts | 2 +- apps/web/src/page/code-review/ci/view-runs.ts | 2 +- .../src/page/code-review/ci/view-tables.ts | 4 +- apps/web/src/page/code-review/kit/parts.ts | 2 +- .../page/code-review/kit/review-sheet-more.ts | 4 +- .../code-review/pull-requests/view-table.ts | 4 +- .../web/src/page/dashboards/kit/tile-shell.ts | 4 +- .../web/src/page/dashboards/list/view-list.ts | 6 +- apps/web/src/page/dashboards/list/view.ts | 2 +- .../page/dashboards/templates/view-list.ts | 8 +- .../page/dashboards/templates/view-panel.ts | 2 +- .../src/page/dashboards/view/view-history.ts | 6 +- .../src/page/dashboards/view/view-share.ts | 2 +- apps/web/src/page/dashboards/view/view.ts | 4 +- .../dashboards/widget/view-list-column.ts | 2 +- .../src/page/dashboards/widget/view-panels.ts | 4 +- .../page/dashboards/widget/view-product.ts | 4 +- .../dashboards/widget/view-rail-thresholds.ts | 2 +- .../src/page/dashboards/widget/view-sql.ts | 6 +- apps/web/src/page/dashboards/widget/view.ts | 4 +- apps/web/src/page/errors/hub/view-list.ts | 8 +- apps/web/src/page/errors/hub/view-row.ts | 16 ++-- apps/web/src/page/errors/hub/view-signal.ts | 2 +- apps/web/src/page/errors/hub/view-toolbar.ts | 6 +- .../src/page/errors/issue/view-activity.ts | 2 +- .../src/page/errors/issue/view-anomalies.ts | 2 +- apps/web/src/page/errors/issue/view-chart.ts | 2 +- apps/web/src/page/errors/issue/view-header.ts | 2 +- apps/web/src/page/errors/issue/view-lease.ts | 2 +- .../src/page/errors/issue/view-overview.ts | 2 +- apps/web/src/page/errors/issue/view-panels.ts | 2 +- .../web/src/page/errors/issue/view-sidebar.ts | 4 +- apps/web/src/page/errors/issue/view-tables.ts | 2 +- .../page/errors/issue/view-verification.ts | 4 +- apps/web/src/page/errors/kit/actor.ts | 6 +- .../src/page/errors/kit/occurrences-table.ts | 2 +- apps/web/src/page/errors/kit/quick-pick.ts | 4 +- apps/web/src/page/errors/kit/state-chip.ts | 2 +- .../infra-integrations/aws/list/view-table.ts | 2 +- .../page/infra-integrations/aws/list/view.ts | 2 +- .../cloudflare/list/view-accounts.ts | 2 +- .../cloudflare/list/view-tables.ts | 80 +++++++++---------- .../cloudflare/worker/view.ts | 4 +- .../cloudflare/zone/view-breakdown.ts | 16 ++-- .../cloudflare/zone/view-sections.ts | 26 +++--- .../infra-integrations/gcp/gcp-message.ts | 2 +- .../gcp/list/view-resources.ts | 36 ++++----- .../infra-integrations/gcp/list/view-rows.ts | 4 +- .../gcp/list/view-tables.ts | 80 +++++++++---------- .../page/infra-integrations/gcp/list/view.ts | 6 +- .../infra-integrations/gcp/service-icon.ts | 2 +- .../gcp/workload/view-charts.ts | 4 +- .../gcp/workload/view-rail.ts | 6 +- .../gcp/workload/view-sql-peek.ts | 12 +-- .../gcp/workload/view-sql.ts | 26 +++--- .../page/infra-integrations/kit/chart-card.ts | 2 +- .../kit/filter-chip-rail.ts | 4 +- .../kit/integration-empty.ts | 6 +- .../page/infra-integrations/kit/scope-chip.ts | 2 +- .../planetscale/db/view-breakdown.ts | 22 ++--- .../planetscale/db/view-sections.ts | 10 +-- .../infra-integrations/planetscale/db/view.ts | 4 +- .../planetscale/list/view-table.ts | 40 +++++----- .../railway/list/view-table.ts | 30 +++---- .../supabase/list/view-bottom.ts | 6 +- .../supabase/list/view-table.ts | 4 +- .../page/infra-integrations/supabase/panel.ts | 2 +- .../supabase/project/view-attention.ts | 2 +- .../supabase/project/view-callers.ts | 2 +- .../supabase/project/view-issues.ts | 2 +- .../supabase/project/view-postgres.ts | 2 +- .../supabase/project/view-traffic.ts | 2 +- .../page/infra/containers/list/view-table.ts | 26 +++--- .../page/infra/hosts/detail/view-header.ts | 2 +- .../page/infra/hosts/detail/view-panels.ts | 2 +- .../src/page/infra/hosts/list/view-table.ts | 18 ++--- apps/web/src/page/infra/kit/avg-peak.ts | 2 +- .../src/page/infra/kit/correlation-strips.ts | 2 +- apps/web/src/page/infra/kit/data-table.ts | 8 +- apps/web/src/page/infra/kit/meta-line.ts | 6 +- apps/web/src/page/infra/kit/meter-rows.ts | 2 +- .../page/infra/kubernetes/nodes/view-table.ts | 24 +++--- .../infra/kubernetes/pod-restarts-view.ts | 14 ++-- .../src/page/infra/kubernetes/pod-table.ts | 26 +++--- .../infra/kubernetes/workloads/view-table.ts | 32 ++++---- .../src/page/infra/overview/view-findings.ts | 2 +- .../src/page/infra/overview/view-sources.ts | 2 +- .../src/page/integrations/view-aws-choose.ts | 4 +- apps/web/src/page/integrations/view-aws.ts | 8 +- .../integrations/view-cloudflare-board.ts | 28 +++---- .../integrations/view-cloudflare-connected.ts | 6 +- .../integrations/view-cloudflare-zones.ts | 6 +- .../src/page/integrations/view-flow-aws.ts | 2 +- .../page/integrations/view-flow-cloudflare.ts | 4 +- .../src/page/integrations/view-flow-github.ts | 4 +- .../integrations/view-flow-planetscale.ts | 2 +- .../page/integrations/view-flow-prometheus.ts | 4 +- .../page/integrations/view-flow-supabase.ts | 8 +- .../view-gcp-configure-collect.ts | 2 +- .../integrations/view-gcp-configure-filter.ts | 4 +- .../view-gcp-configure-method-choice.ts | 2 +- .../integrations/view-gcp-configure-parts.ts | 8 +- .../integrations/view-gcp-configure-script.ts | 2 +- .../integrations/view-gcp-configure-status.ts | 2 +- .../page/integrations/view-gcp-connection.ts | 2 +- .../src/page/integrations/view-gcp-dialogs.ts | 2 +- .../integrations/view-gcp-setup-methods.ts | 2 +- .../page/integrations/view-gcp-workloads.ts | 16 ++-- .../page/integrations/view-github-repos.ts | 2 +- apps/web/src/page/integrations/view-hazel.ts | 2 +- apps/web/src/page/integrations/view-hub.ts | 10 +-- apps/web/src/page/integrations/view-linear.ts | 2 +- .../integrations/view-planetscale-parts.ts | 4 +- .../src/page/integrations/view-planetscale.ts | 4 +- .../integrations/view-prometheus-details.ts | 8 +- .../src/page/integrations/view-prometheus.ts | 4 +- .../web/src/page/integrations/view-railway.ts | 2 +- .../src/page/integrations/view-supabase.ts | 2 +- .../conversation/kit/view-approval.ts | 6 +- .../conversation/kit/view-cards.ts | 2 +- .../conversation/kit/view-inline.ts | 8 +- .../conversation/kit/view-markdown.ts | 2 +- .../conversation/kit/view-task.ts | 8 +- .../conversation/kit/view-tool.ts | 10 +-- .../page/investigations/conversation/view.ts | 2 +- .../detail/view-action-sheet.ts | 8 +- .../page/investigations/detail/view-canvas.ts | 8 +- .../detail/view-diagnosis-card.ts | 8 +- .../investigations/detail/view-sections.ts | 8 +- .../investigations/detail/view-verdict.ts | 8 +- apps/web/src/page/investigations/kit.ts | 2 +- apps/web/src/page/investigations/list/view.ts | 10 +-- apps/web/src/page/kit/commit-card.ts | 2 +- apps/web/src/page/kit/connect-flow.ts | 20 ++--- apps/web/src/page/kit/detail-header.ts | 2 +- apps/web/src/page/kit/guided-setup.ts | 2 +- apps/web/src/page/kit/list-toolbar.ts | 2 +- apps/web/src/page/kit/message-response.ts | 6 +- apps/web/src/page/kit/query-builder-legend.ts | 6 +- .../page/kit/query-builder/metrics-body.ts | 2 +- apps/web/src/page/kit/query-builder/view.ts | 6 +- apps/web/src/page/kit/series-legend.ts | 6 +- apps/web/src/page/kit/stat-rail.ts | 4 +- apps/web/src/page/kit/time-range-picker.ts | 28 +++---- apps/web/src/page/kit/timezone-select-view.ts | 14 ++-- apps/web/src/page/logs/detail/view-hero.ts | 4 +- apps/web/src/page/logs/detail/view-meta.ts | 2 +- apps/web/src/page/logs/detail/view-panels.ts | 24 +++--- apps/web/src/page/logs/detail/view.ts | 2 +- .../src/page/logs/list/view-search-help.ts | 8 +- apps/web/src/page/logs/list/view-volume.ts | 2 +- apps/web/src/page/logs/list/view.ts | 2 +- apps/web/src/page/metrics/browse/view-grid.ts | 2 +- .../web/src/page/metrics/browse/view-table.ts | 18 ++--- .../web/src/page/onboarding/cli-login-view.ts | 2 +- .../src/page/onboarding/create-org-view.ts | 4 +- .../src/page/onboarding/mcp-authorize-view.ts | 2 +- apps/web/src/page/onboarding/option-card.ts | 4 +- .../src/page/onboarding/pricing-cards-view.ts | 6 +- .../onboarding/quick-start-region-view.ts | 14 ++-- .../src/page/onboarding/quick-start-view.ts | 4 +- apps/web/src/page/onboarding/workspace.ts | 2 +- .../src/page/overview/setup-checklist-view.ts | 6 +- apps/web/src/page/overview/view-health.ts | 4 +- apps/web/src/page/overview/view-hero.ts | 6 +- apps/web/src/page/overview/view-metrics.ts | 2 +- apps/web/src/page/overview/view-widget.ts | 4 +- .../web/src/page/recommendations/view-body.ts | 8 +- apps/web/src/page/recommendations/view.ts | 2 +- .../page/releases/detail/view-comparison.ts | 14 ++-- .../src/page/releases/detail/view-sections.ts | 20 ++--- .../src/page/releases/detail/view-service.ts | 4 +- .../src/page/releases/list/view-overview.ts | 10 +-- apps/web/src/page/releases/list/view-table.ts | 14 ++-- apps/web/src/page/releases/list/view.ts | 8 +- .../src/page/replays/detail/view-player.ts | 4 +- apps/web/src/page/replays/detail/view-rail.ts | 14 ++-- .../src/page/replays/detail/view-session.ts | 6 +- .../src/page/replays/detail/view-timeline.ts | 30 +++---- apps/web/src/page/replays/detail/view.ts | 5 +- .../src/page/replays/kit/session-list-row.ts | 6 +- .../web/src/page/replays/kit/sessions-list.ts | 2 +- apps/web/src/page/replays/list/view.ts | 4 +- .../web/src/page/security/kit/finding-body.ts | 4 +- .../src/page/security/kit/findings-view.ts | 8 +- apps/web/src/page/security/run/view.ts | 2 +- .../src/page/security/tabs/view-overview.ts | 2 +- .../src/page/service-map/view-db-sections.ts | 12 +-- .../page/service-map/view-service-infra.ts | 12 +-- .../page/service-map/view-service-panel.ts | 2 +- .../services/detail/endpoint-peek/view.ts | 8 +- .../src/page/services/detail/view-api-tab.ts | 12 +-- apps/web/src/page/services/detail/view-api.ts | 24 +++--- .../page/services/detail/view-dependencies.ts | 8 +- .../src/page/services/detail/view-deploys.ts | 12 +-- .../page/services/detail/view-footprint.ts | 10 +-- .../src/page/services/detail/view-markers.ts | 4 +- .../page/services/detail/view-operations.ts | 8 +- .../src/page/services/detail/view-panels.ts | 4 +- apps/web/src/page/services/list/view-table.ts | 16 ++-- .../page/settings/account/two-factor/view.ts | 2 +- .../page/settings/audit-log/view-detail.ts | 10 +-- apps/web/src/page/settings/audit-log/view.ts | 12 +-- apps/web/src/page/settings/automation/view.ts | 6 +- .../src/page/settings/billing/details/view.ts | 2 +- .../src/page/settings/billing/view-account.ts | 2 +- .../src/page/settings/billing/view-cycle.ts | 4 +- .../src/page/settings/billing/view-plan.ts | 6 +- .../src/page/settings/billing/view-records.ts | 6 +- .../src/page/settings/billing/view-usage.ts | 2 +- .../src/page/settings/data-platform/view.ts | 8 +- .../settings/ingestion/view-ingest-rules.ts | 2 +- .../src/page/settings/ingestion/view-keys.ts | 8 +- .../src/page/settings/ingestion/view-rules.ts | 4 +- .../src/page/settings/keys/view-reference.ts | 4 +- apps/web/src/page/settings/keys/view-table.ts | 28 +++---- apps/web/src/page/settings/mcp/view-tools.ts | 2 +- apps/web/src/page/settings/members/view.ts | 2 +- .../src/page/settings/setup-health/view.ts | 14 ++-- apps/web/src/page/sign-in/view.ts | 2 +- apps/web/src/page/sources/kit/rules-view.ts | 4 +- apps/web/src/page/sources/kit/setup.ts | 2 +- apps/web/src/page/sources/list/view.ts | 2 +- apps/web/src/page/sources/new/view-picker.ts | 2 +- apps/web/src/page/sources/new/view-trail.ts | 8 +- .../traces/detail/span-panel/attributes.ts | 20 ++--- .../src/page/traces/detail/span-panel/copy.ts | 4 +- .../traces/detail/span-panel/error-section.ts | 12 +-- .../page/traces/detail/span-panel/events.ts | 2 +- .../traces/detail/span-panel/view-tabs.ts | 2 +- .../traces/detail/timeline/view-chrome.ts | 8 +- .../traces/detail/timeline/view-footer.ts | 6 +- .../page/traces/detail/timeline/view-row.ts | 14 ++-- .../src/page/traces/detail/timeline/view.ts | 2 +- .../src/page/traces/detail/waterfall/row.ts | 12 +-- .../src/page/traces/detail/waterfall/view.ts | 2 +- apps/web/src/page/traces/list/view-row.ts | 6 +- apps/web/src/service-map/map/edge.ts | 2 +- apps/web/src/service-map/map/legend.ts | 8 +- apps/web/src/service-map/map/node-card.ts | 2 +- apps/web/src/service-map/map/nodes.ts | 18 ++--- apps/web/src/service-map/map/panels.ts | 2 +- apps/web/src/service-map/map/toolbar.ts | 2 +- apps/web/src/service-map/trace-flow/edge.ts | 4 +- apps/web/src/service-map/trace-flow/legend.ts | 6 +- .../src/service-map/trace-flow/node-card.ts | 10 +-- apps/web/src/service-map/trace-flow/view.ts | 4 +- apps/web/src/shell/clerk-org-switcher-view.ts | 4 +- apps/web/src/shell/connect-panel-view.ts | 2 +- .../src/shell/onboarding-checklist-view.ts | 4 +- apps/web/src/shell/palette/shortcuts-view.ts | 2 +- apps/web/src/ui/alert.ts | 2 +- apps/web/src/ui/attributes/attribute-row.ts | 14 ++-- apps/web/src/ui/attributes/attributes-view.ts | 12 +-- apps/web/src/ui/avatar-tone.ts | 10 +-- apps/web/src/ui/chart-skeleton-shapes.ts | 2 +- apps/web/src/ui/chart-state.ts | 4 +- apps/web/src/ui/detail-rail.ts | 14 ++-- apps/web/src/ui/error-section.ts | 12 +-- apps/web/src/ui/error-state.ts | 18 ++--- .../web/src/ui/filters/active-filter-chips.ts | 2 +- apps/web/src/ui/filters/filter-section.ts | 6 +- .../src/ui/filters/range-filter-section.ts | 4 +- apps/web/src/ui/filters/range-histogram.ts | 2 +- apps/web/src/ui/http-span-label.ts | 2 +- apps/web/src/ui/logs/chip-card.ts | 2 +- apps/web/src/ui/logs/log-row-expanded.ts | 4 +- apps/web/src/ui/logs/log-row.ts | 16 ++-- apps/web/src/ui/logs/logs-stream-view.ts | 4 +- apps/web/src/ui/logs/styles.ts | 8 +- apps/web/src/ui/segmented-select.ts | 2 +- .../charts/_shared/query-builder-legend.tsx | 6 +- .../src/components/plot/floating-tooltip.tsx | 2 +- .../ui/src/components/plot/plot-legend.tsx | 4 +- .../ui/src/components/plot/plot-tooltip.tsx | 2 +- .../components/traces/flamegraph-minimap.tsx | 4 +- .../ui/src/components/traces/flamegraph.tsx | 10 +-- .../ui/src/components/traces/flow-edge.tsx | 4 +- .../ui/src/components/traces/flow-node.tsx | 10 +-- .../ui/src/components/traces/flow-view.tsx | 12 +-- .../src/components/ui/alert-dialog.styles.ts | 2 +- packages/ui/src/components/ui/badge.styles.ts | 6 +- .../ui/src/components/ui/bubble.styles.ts | 2 +- .../ui/src/components/ui/calendar.styles.ts | 6 +- .../ui/src/components/ui/command.styles.ts | 4 +- packages/ui/src/components/ui/delta.styles.ts | 6 +- .../ui/src/components/ui/dialog.styles.ts | 2 +- .../ui/src/components/ui/eyebrow.styles.ts | 2 +- .../src/components/ui/filter-chip.styles.ts | 2 +- .../src/components/ui/inline-code.styles.ts | 2 +- packages/ui/src/components/ui/input.styles.ts | 2 +- packages/ui/src/components/ui/item.styles.ts | 4 +- packages/ui/src/components/ui/kbd.styles.ts | 2 +- .../ui/src/components/ui/key-value.styles.ts | 2 +- .../ui/src/components/ui/list-row.styles.ts | 6 +- packages/ui/src/components/ui/meter.styles.ts | 4 +- .../components/ui/navigation-menu.styles.ts | 4 +- packages/ui/src/components/ui/panel.styles.ts | 2 +- .../ui/src/components/ui/select.styles.ts | 2 +- packages/ui/src/components/ui/sheet.styles.ts | 2 +- packages/ui/src/components/ui/tabs.styles.ts | 2 +- .../ui/src/components/ui/toggle.styles.ts | 2 +- packages/ui/src/components/ui/trace.styles.ts | 2 +- packages/ui/src/lib/error-rate.ts | 2 +- packages/ui/src/lib/latency-tone.ts | 2 +- packages/ui/src/styles/tokens.css | 26 ++++++ 396 files changed, 1399 insertions(+), 1368 deletions(-) diff --git a/apps/web/src/charts/bucket-tooltip.ts b/apps/web/src/charts/bucket-tooltip.ts index 3a8ca13943..4ec1186db0 100644 --- a/apps/web/src/charts/bucket-tooltip.ts +++ b/apps/web/src/charts/bucket-tooltip.ts @@ -16,7 +16,7 @@ export const bucketTooltipBody = ( [h.Class("grid min-w-[9rem] max-w-[22rem] items-start gap-1.5"), portal], [ h.div( - [h.Class("border-border/60 border-b pb-1 font-medium text-muted-foreground tracking-tight")], + [h.Class("border-border-subtle border-b pb-1 font-medium text-muted-foreground tracking-tight")], [tooltip.heading], ), h.div( @@ -74,7 +74,7 @@ export const bucketTooltipBody = ( h.div( [ h.Class( - "flex items-center justify-between gap-3 border-border/60 border-t pt-1.5 leading-none", + "flex items-center justify-between gap-3 border-border-subtle border-t pt-1.5 leading-none", ), ], [ diff --git a/apps/web/src/charts/funnel-chart.ts b/apps/web/src/charts/funnel-chart.ts index aee420163e..3af77169ea 100644 --- a/apps/web/src/charts/funnel-chart.ts +++ b/apps/web/src/charts/funnel-chart.ts @@ -31,7 +31,7 @@ const GROUP_BAR_H = 8 export const PERCENT_FLOOR = { floor: 0.0005 } const LEGEND_H = 18 -const sep = (h: H, glyph: string): Html => h.span([h.Class("px-1 text-muted-foreground/50")], [glyph]) +const sep = (h: H, glyph: string): Html => h.span([h.Class("px-1 text-foreground-faint")], [glyph]) const swatch = (h: H, className: string, color: string): Html => h.span([h.Class(className), h.Style({ "background-color": color })]) @@ -79,13 +79,13 @@ const stageNumbers = (h: H, stage: Stage, hoverGroup: string | null, flags: Flag if (hovered !== undefined) return [ swatch(h, "mr-1 inline-block size-2 rounded-xs align-middle", hovered.color), - h.span([h.Class("text-foreground/90")], [fmtValue(hovered.value, flags.unit)]), + h.span([h.Class("text-foreground-soft")], [fmtValue(hovered.value, flags.unit)]), ...(flags.showShareOfFirst ? [sep(h, "·"), h.span([], [formatPercent(hovered.pctOfFirst, PERCENT_FLOOR)])] : []), ] return [ - h.span([h.Class("text-foreground/90")], [fmtValue(stage.value, flags.unit)]), + h.span([h.Class("text-foreground-soft")], [fmtValue(stage.value, flags.unit)]), ...(flags.showShareOfFirst ? [sep(h, "·"), h.span([], [formatPercent(stage.pctOfFirst, PERCENT_FLOOR)])] : []), @@ -176,7 +176,7 @@ export const view = Submodel.defineView((mode h.Class( cn( "truncate", - stage.unnamed ? "italic text-muted-foreground" : "text-foreground/90", + stage.unnamed ? "italic text-muted-foreground" : "text-foreground-soft", ), ), h.Title(stage.name), diff --git a/apps/web/src/charts/funnel-dropoff-chart.ts b/apps/web/src/charts/funnel-dropoff-chart.ts index 3a52a16405..048fd9a6de 100644 --- a/apps/web/src/charts/funnel-dropoff-chart.ts +++ b/apps/web/src/charts/funnel-dropoff-chart.ts @@ -67,7 +67,7 @@ const leaversBlock = (h: H, hovered: Step): ReadonlyArray => h.Class( cn( "min-w-0 flex-1 truncate", - entry.ended ? "text-muted-foreground" : "text-foreground/90", + entry.ended ? "text-muted-foreground" : "text-foreground-soft", ), ), ], @@ -83,7 +83,7 @@ const leaversBlock = (h: H, hovered: Step): ReadonlyArray => h.Class( cn( "absolute inset-y-0 left-0 rounded-sm", - entry.ended ? "bg-foreground/25" : "bg-[var(--chart-2)]", + entry.ended ? "bg-foreground/25" : "bg-chart-2", ), ), h.Style({ width: `${entry.share * 100}%` }), @@ -127,7 +127,7 @@ const tooltip = (h: H, hovered: Step, prev: Step, left: number, unit: string | u "converted", fmtValue(hovered.value, unit), formatPercent(hovered.ofPrev ?? 0), - "text-success-foreground", + "text-severity-info", ), tipRow( h, @@ -204,7 +204,7 @@ const plainBars = (h: H, step: Step, prev: Step | undefined): ReadonlyArray 0 ? 1.5 : 0)}%`, transition: "height 220ms ease", @@ -219,7 +219,7 @@ const pill = (h: H, ctx: ColumnContext, step: Step, prev: Step, isLast: boolean) return h.span( [ h.Class( - "absolute bottom-1.5 left-1.5 flex items-center gap-2 rounded-md bg-card/95 px-1.5 py-1 text-2xs leading-none tabular-nums whitespace-nowrap shadow-xs ring-1 ring-border/60", + "absolute bottom-1.5 left-1.5 flex items-center gap-2 rounded-md bg-card/95 px-1.5 py-1 text-2xs leading-none tabular-nums whitespace-nowrap shadow-xs ring-1 ring-border-subtle", ), h.DataAttribute("slot", "funnel-dropoff-pill"), ], @@ -237,7 +237,7 @@ const pill = (h: H, ctx: ColumnContext, step: Step, prev: Step, isLast: boolean) ...(ctx.pillLoss && lostShare > 0 ? [ h.span( - [h.Class("flex items-center gap-1 text-foreground/80")], + [h.Class("flex items-center gap-1 text-foreground-soft")], [icon(h, "ArrowDownIcon", { size: 12, className: TONE_TEXT.crit }), formatPercent(lostShare)], ), ] @@ -273,7 +273,7 @@ const column = (h: H, ctx: ColumnContext, step: Step, index: number): Html => { h.Class( cn( "truncate text-2xs font-medium", - step.unnamed ? "italic text-muted-foreground" : "text-foreground/90", + step.unnamed ? "italic text-muted-foreground" : "text-foreground-soft", ), ), h.Title(step.name), diff --git a/apps/web/src/charts/hbar-chart.ts b/apps/web/src/charts/hbar-chart.ts index 3f3c9fe704..4e934bed85 100644 --- a/apps/web/src/charts/hbar-chart.ts +++ b/apps/web/src/charts/hbar-chart.ts @@ -107,7 +107,7 @@ export const view = Submodel.defineView((model, [ truncatedText(h, { text: bar.name, - className: bar.unnamed ? "italic text-muted-foreground" : "text-foreground/90", + className: bar.unnamed ? "italic text-muted-foreground" : "text-foreground-soft", }), h.div( [ @@ -129,8 +129,8 @@ export const view = Submodel.defineView((model, h.span( [h.Class("shrink-0 text-right tabular-nums text-muted-foreground")], [ - h.span([h.Class("text-foreground/90")], [fmtValue(bar.value, inputs.unit)]), - h.span([h.Class("px-1 text-muted-foreground/50")], ["·"]), + h.span([h.Class("text-foreground-soft")], [fmtValue(bar.value, inputs.unit)]), + h.span([h.Class("px-1 text-foreground-faint")], ["·"]), h.span([], [formatPercent(bar.pctOfTotal, PCT_FLOOR)]), ], ), diff --git a/apps/web/src/charts/heatmap-chart.ts b/apps/web/src/charts/heatmap-chart.ts index 5729f6fef6..3d0ba9e499 100644 --- a/apps/web/src/charts/heatmap-chart.ts +++ b/apps/web/src/charts/heatmap-chart.ts @@ -124,7 +124,7 @@ const tooltipBody = ( [h.Class("text-muted-foreground")], [ h.span([], [tooltip.x]), - h.span([h.Class("px-1 text-muted-foreground/50")], ["·"]), + h.span([h.Class("px-1 text-foreground-faint")], ["·"]), h.span([], [label(tooltip.y)]), ], ), @@ -228,7 +228,7 @@ export const view = Submodel.defineView((cha : { footer: h.p( [ - h.Class("pt-1 text-right text-3xs leading-3 tabular-nums text-muted-foreground/70"), + h.Class("pt-1 text-right text-3xs leading-3 tabular-nums text-foreground-subtle"), h.Style({ height: `${FOOTNOTE_BLOCK_H}px`, "padding-left": `${layout.gutter}px`, diff --git a/apps/web/src/charts/histogram-chart.ts b/apps/web/src/charts/histogram-chart.ts index 248d14817c..8d2ce82967 100644 --- a/apps/web/src/charts/histogram-chart.ts +++ b/apps/web/src/charts/histogram-chart.ts @@ -87,7 +87,7 @@ export const countTooltipBody = ( [h.Class("grid min-w-[9rem] items-start gap-1.5"), portal], [ h.div( - [h.Class("border-border/60 border-b pb-1 font-medium text-muted-foreground tracking-tight")], + [h.Class("border-border-subtle border-b pb-1 font-medium text-muted-foreground tracking-tight")], [heading], ), h.div( diff --git a/apps/web/src/charts/paths-chart.ts b/apps/web/src/charts/paths-chart.ts index 14ca195882..9cf38e0a7c 100644 --- a/apps/web/src/charts/paths-chart.ts +++ b/apps/web/src/charts/paths-chart.ts @@ -65,7 +65,7 @@ const ribbons = (h: H, graph: PathsLayout, isLit: (link: PathLink) => boolean, h h.Class( cn( "pointer-events-none", - kind === "event" && "fill-[var(--chart-2)]", + kind === "event" && "fill-chart-2", kind === "end" && "fill-foreground", kind === "other" && "fill-foreground", ), @@ -102,7 +102,7 @@ const nodeGroup = ( ...attrs(h, { x: node.x, y: node.y, width: NODE_W, height: node.h, rx: 2 }), h.Class( cn( - node.kind === "event" && "fill-[var(--chart-2)]", + node.kind === "event" && "fill-chart-2", node.kind === "end" && "fill-foreground/20", node.kind === "other" && "fill-foreground/35", ), diff --git a/apps/web/src/charts/paths-tooltip.ts b/apps/web/src/charts/paths-tooltip.ts index 704ec04d78..8845d9c72f 100644 --- a/apps/web/src/charts/paths-tooltip.ts +++ b/apps/web/src/charts/paths-tooltip.ts @@ -43,7 +43,7 @@ const cameFrom = (h: H, inputs: PathsTooltipInputs): ReadonlyArray => { [ icon(h, "ArrowLeftIcon", { size: 10, className: "shrink-0 text-muted-foreground" }), h.span( - [h.Class("min-w-0 flex-1 truncate text-foreground/90")], + [h.Class("min-w-0 flex-1 truncate text-foreground-soft")], [from === undefined ? "" : labelOf(from)], ), h.span([h.Class("text-muted-foreground")], [link.count.toLocaleString("en-US")]), @@ -53,7 +53,7 @@ const cameFrom = (h: H, inputs: PathsTooltipInputs): ReadonlyArray => { [h.Class("relative mt-0.5 ml-4 h-1 rounded-sm bg-foreground/5")], [ h.div([ - h.Class("absolute inset-y-0 left-0 rounded-sm bg-[var(--chart-2)]/70"), + h.Class("absolute inset-y-0 left-0 rounded-sm bg-chart-2/70"), h.Style({ width: `${share * 100}%` }), ]), ], @@ -84,7 +84,7 @@ export const pathsTooltip = (h: H, inputs: PathsTooltipInputs): Html => { h.Class( cn( "size-2 shrink-0 rounded-xs", - node.kind === "event" && "bg-[var(--chart-2)]", + node.kind === "event" && "bg-chart-2", node.kind === "end" && "bg-foreground/20", node.kind === "other" && "bg-foreground/35", ), @@ -100,7 +100,7 @@ export const pathsTooltip = (h: H, inputs: PathsTooltipInputs): Html => { [h.Class("mb-1.5 h-1.5 overflow-hidden rounded-sm bg-foreground/5")], [ h.div([ - h.Class("h-full rounded-sm bg-[var(--chart-2)]"), + h.Class("h-full rounded-sm bg-chart-2"), h.Style({ width: `${Math.min(100, (node.count / anchor.count) * 100)}%` }), ]), ], diff --git a/apps/web/src/charts/pie-chart.ts b/apps/web/src/charts/pie-chart.ts index dd1da536cf..c168c675bb 100644 --- a/apps/web/src/charts/pie-chart.ts +++ b/apps/web/src/charts/pie-chart.ts @@ -121,8 +121,8 @@ const tooltipBody = ( h.div( [h.Class("mt-0.5 text-muted-foreground tabular-nums")], [ - h.span([h.Class("text-foreground/90")], [fmtValue(slice.value, unit)]), - h.span([h.Class("px-1 text-muted-foreground/60")], ["·"]), + h.span([h.Class("text-foreground-soft")], [fmtValue(slice.value, unit)]), + h.span([h.Class("px-1 text-foreground-subtle")], ["·"]), h.span([], [formatPercent(slice.fraction)]), ], ), diff --git a/apps/web/src/charts/plot-legend.ts b/apps/web/src/charts/plot-legend.ts index f59a221929..c67b20b88d 100644 --- a/apps/web/src/charts/plot-legend.ts +++ b/apps/web/src/charts/plot-legend.ts @@ -59,9 +59,9 @@ const legendItem = (h: HtmlBuilder, state: PlotLegendState, entry: Plot h.Class( cn( // Labels sit one step under the card title; the focused series reads full strength. - "flex items-center gap-1.5 rounded px-1 py-0.5 text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground", + "flex items-center gap-1.5 rounded-sm px-1 py-0.5 text-muted-foreground transition-colors hover:bg-surface-sunken hover:text-foreground", isMuted && "opacity-40", - (isActive || (!hovering && isHighlighted)) && "bg-muted/50 text-foreground", + (isActive || (!hovering && isHighlighted)) && "bg-surface-sunken text-foreground", ), ), ], diff --git a/apps/web/src/charts/timeseries-legend.ts b/apps/web/src/charts/timeseries-legend.ts index 8fa6ae26e4..9779606ef4 100644 --- a/apps/web/src/charts/timeseries-legend.ts +++ b/apps/web/src/charts/timeseries-legend.ts @@ -52,7 +52,7 @@ const compactLegend = ( h.Type("button"), h.Class( cn( - "hover:bg-muted/50 flex min-w-0 max-w-full items-center gap-1.5 rounded px-1 py-0.5 select-none", + "hover:bg-surface-sunken flex min-w-0 max-w-full items-center gap-1.5 rounded-sm px-1 py-0.5 select-none", hidden.includes(entry.key) && "opacity-40", ), ), @@ -132,7 +132,7 @@ const statsTable = ( h.OnClick(Message.ToggledLegendSeries({ key: entry.key, keys })), h.Class( cn( - "hover:bg-muted/50 cursor-pointer select-none", + "hover:bg-surface-sunken cursor-pointer select-none", hidden.includes(entry.key) && "opacity-40", ), ), @@ -170,7 +170,7 @@ const statsTable = ( [ h.Class( cn( - "px-2 text-right font-mono tabular-nums text-muted-foreground/60 last:pr-0", + "px-2 text-right font-mono tabular-nums text-foreground-subtle last:pr-0", column.className, ), ), diff --git a/apps/web/src/components/infra/severity-tokens.ts b/apps/web/src/components/infra/severity-tokens.ts index 2a39562e21..3d75958cbe 100644 --- a/apps/web/src/components/infra/severity-tokens.ts +++ b/apps/web/src/components/infra/severity-tokens.ts @@ -37,7 +37,7 @@ export const BAR_FILL: Record = { /** Dimmer value-text tone used inside compact bar widgets. */ export const BAR_VALUE_TONE: Record = { - ok: "text-foreground/70", + ok: "text-foreground-soft", warn: TONE_TEXT.warn, crit: TONE_TEXT.crit, } satisfies Record diff --git a/apps/web/src/lab/charts/spike-view.ts b/apps/web/src/lab/charts/spike-view.ts index 79ee9f8ed7..72af563536 100644 --- a/apps/web/src/lab/charts/spike-view.ts +++ b/apps/web/src/lab/charts/spike-view.ts @@ -47,7 +47,7 @@ const stackTooltipBody = (h: H, bucket: BucketTooltip, total: string, portal: At [h.Class("grid min-w-[9rem] items-start gap-1.5"), portal], [ h.div( - [h.Class("border-border/50 border-b pb-1 font-medium text-muted-foreground tracking-tight")], + [h.Class("border-border-subtle border-b pb-1 font-medium text-muted-foreground tracking-tight")], [bucket.heading], ), h.div( @@ -78,7 +78,7 @@ const stackTooltipBody = (h: H, bucket: BucketTooltip, total: string, portal: At h.div( [ h.Class( - "flex w-full items-center justify-between gap-3 border-border/50 border-t pt-1 leading-none", + "flex w-full items-center justify-between gap-3 border-border-subtle border-t pt-1 leading-none", ), ], [h.span([h.Class("text-muted-foreground")], ["Total"]), figure(h, total)], @@ -137,7 +137,7 @@ const keyValue = (h: H, label: string, value: string, className: string): Html = /** `BoxPlotSpike`'s body: the operation, then its outlier or its five-number summary. */ const boxTooltipBody = (h: H, bucket: BucketTooltip, portal: Attribute): Html => { const heading = h.div( - [h.Class("border-border/50 border-b pb-1 font-medium text-muted-foreground tracking-tight")], + [h.Class("border-border-subtle border-b pb-1 font-medium text-muted-foreground tracking-tight")], [bucket.heading], ) const row = (label: string, value: string, className: string) => @@ -270,7 +270,7 @@ export const spikeView = Submodel.defineView((model ? undefined : { footer: h.p( - [h.Class("pt-1 text-right text-3xs text-muted-foreground/70")], + [h.Class("pt-1 text-right text-3xs text-foreground-subtle")], [inputs.footer], ), }), diff --git a/apps/web/src/lab/entries/agent-sessions.ts b/apps/web/src/lab/entries/agent-sessions.ts index 0cacedbe79..ff9542b80d 100644 --- a/apps/web/src/lab/entries/agent-sessions.ts +++ b/apps/web/src/lab/entries/agent-sessions.ts @@ -212,8 +212,8 @@ const labButton = (h: HtmlBuilder, label: string, isActive: boolean, on [ h.Class( isActive - ? "rounded border border-border bg-accent px-2 py-1 text-xs" - : "rounded border border-border px-2 py-1 text-xs text-muted-foreground", + ? "rounded-sm border border-border bg-accent px-2 py-1 text-xs" + : "rounded-sm border border-border px-2 py-1 text-xs text-muted-foreground", ), h.Type("button"), h.OnClick(onClick), diff --git a/apps/web/src/lab/entries/agent-tools.ts b/apps/web/src/lab/entries/agent-tools.ts index 466ccb8043..819d189d12 100644 --- a/apps/web/src/lab/entries/agent-tools.ts +++ b/apps/web/src/lab/entries/agent-tools.ts @@ -260,8 +260,8 @@ const update = (model: Model, message: Message): Return => const toggleClass = (isActive: boolean): string => isActive - ? "rounded border border-border bg-accent px-2 py-1 text-xs" - : "rounded border border-border px-2 py-1 text-xs text-muted-foreground" + ? "rounded-sm border border-border bg-accent px-2 py-1 text-xs" + : "rounded-sm border border-border px-2 py-1 text-xs text-muted-foreground" const labButton = (h: HtmlBuilder, label: string, isActive: boolean, onClick: Message): Html => h.button([h.Class(toggleClass(isActive)), h.Type("button"), h.OnClick(onClick)], [label]) diff --git a/apps/web/src/lab/entries/bench/service-map.ts b/apps/web/src/lab/entries/bench/service-map.ts index 3fdf293df3..11f76bb2e7 100644 --- a/apps/web/src/lab/entries/bench/service-map.ts +++ b/apps/web/src/lab/entries/bench/service-map.ts @@ -179,7 +179,7 @@ const groupSwitch = (h: HtmlBuilder, groups: number): Html => h.OnClick(Message.ClickedNamespaceGroups({ groups: option })), h.Class( cn( - "rounded px-1.5 py-0.5 font-mono text-2xs transition-colors", + "rounded-sm px-1.5 py-0.5 font-mono text-2xs transition-colors", option === groups ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground", diff --git a/apps/web/src/lab/entries/index.ts b/apps/web/src/lab/entries/index.ts index 90df3ff4fe..c182b24faa 100644 --- a/apps/web/src/lab/entries/index.ts +++ b/apps/web/src/lab/entries/index.ts @@ -27,7 +27,7 @@ const entryCard = (h: HtmlBuilder, entry: RegistryEntry): Html => [ h.Href(entry.path), h.Class( - "flex h-full flex-col gap-1 rounded-md border bg-card px-3 py-2.5 transition-colors hover:bg-accent", + "flex h-full flex-col gap-1 rounded-md border bg-card p-3 transition-colors hover:bg-accent", ), ], [ diff --git a/apps/web/src/lab/entries/replays.ts b/apps/web/src/lab/entries/replays.ts index 17cc524135..2ce00ed79a 100644 --- a/apps/web/src/lab/entries/replays.ts +++ b/apps/web/src/lab/entries/replays.ts @@ -105,8 +105,8 @@ const widthButton = (h: HtmlBuilder, model: Model, option: (typeof WIDT h.OnClick(Message.ClickedWidth({ width: option.value })), h.Class( model.width === option.value - ? "rounded border border-border bg-accent px-2 py-1 text-xs" - : "rounded border border-border px-2 py-1 text-xs text-muted-foreground", + ? "rounded-sm border border-border bg-accent px-2 py-1 text-xs" + : "rounded-sm border border-border px-2 py-1 text-xs text-muted-foreground", ), ], [option.label], @@ -125,7 +125,7 @@ const page = (model: Model, h: HtmlBuilder): Html => { [ h.Type("button"), h.OnClick(Message.ClickedClear()), - h.Class("rounded border border-border px-2 py-1 text-xs"), + h.Class("rounded-sm border border-border px-2 py-1 text-xs"), ], ["Clear ", clearLabel(model)], ), diff --git a/apps/web/src/lab/errors-lab/view.ts b/apps/web/src/lab/errors-lab/view.ts index 62de6054d1..e7ac6c2da9 100644 --- a/apps/web/src/lab/errors-lab/view.ts +++ b/apps/web/src/lab/errors-lab/view.ts @@ -31,7 +31,7 @@ const toggleGroup = ( [ eyebrow(h, {}, [label]), h.div( - [h.Class("flex items-center gap-0.5 rounded-md border border-border/60 p-0.5")], + [h.Class("flex items-center gap-0.5 rounded-md border border-border-subtle p-0.5")], options.map((option) => h.button( [ @@ -39,7 +39,7 @@ const toggleGroup = ( h.OnClick(onChange(option.value)), h.Class( cn( - "h-6 rounded px-2 text-xs transition-colors", + "h-6 rounded-sm px-2 text-xs transition-colors", option.value === active ? "bg-muted text-foreground" : "text-muted-foreground hover:text-foreground", @@ -70,7 +70,7 @@ const labStatStrip = (h: HtmlBuilder, summary: { totalErrors: number; erro ], ), ), - h.span([h.Class("text-muted-foreground/60")], ["in the last 24 hours"]), + h.span([h.Class("text-foreground-subtle")], ["in the last 24 hours"]), ], ) diff --git a/apps/web/src/lab/query-builder-lab/view-query.ts b/apps/web/src/lab/query-builder-lab/view-query.ts index 28e29e2d7e..ecebcbf03c 100644 --- a/apps/web/src/lab/query-builder-lab/view-query.ts +++ b/apps/web/src/lab/query-builder-lab/view-query.ts @@ -57,7 +57,7 @@ const header = (h: H, model: Model, query: QueryDraft): Html => { [h.Class("flex flex-wrap items-center justify-between gap-2")], [ labSelect(h, model, `source:${query.id}`, query.dataSource, DATA_SOURCES, { - className: "w-[120px]", + className: "w-32", toView: (parts) => h.div( [h.Class("flex items-center gap-2")], diff --git a/apps/web/src/lab/query-builder-lab/view.ts b/apps/web/src/lab/query-builder-lab/view.ts index 03dffb8cdd..f15f8dc2bb 100644 --- a/apps/web/src/lab/query-builder-lab/view.ts +++ b/apps/web/src/lab/query-builder-lab/view.ts @@ -168,7 +168,7 @@ const statePreview = (h: H, model: Model): Html => h.pre( [ h.Class( - "max-h-72 overflow-auto rounded-none border bg-muted/30 p-2 font-mono text-2xs leading-relaxed", + "max-h-72 overflow-auto rounded-none border bg-surface-sunken p-2 font-mono text-2xs leading-relaxed", ), ], [ diff --git a/apps/web/src/lab/service-map-3d-lab/view-inspector.ts b/apps/web/src/lab/service-map-3d-lab/view-inspector.ts index 62720d7cc3..1d89b7a634 100644 --- a/apps/web/src/lab/service-map-3d-lab/view-inspector.ts +++ b/apps/web/src/lab/service-map-3d-lab/view-inspector.ts @@ -20,7 +20,7 @@ const nodesById = new Map(topology.nodes.map((node) => [node.id, node])) const SEVERITY = { healthy: "info", elevated: "warn", degraded: "error" } as const const CALL_CLASS = - "flex w-full flex-col gap-1.5 px-4 py-2.5 text-left text-xs hover:bg-muted/60 focus-visible:outline-2 focus-visible:outline-ring focus-visible:-outline-offset-2" + "flex w-full flex-col gap-1.5 px-4 py-2.5 text-left text-xs hover:bg-surface-strong focus-visible:outline-2 focus-visible:outline-ring focus-visible:-outline-offset-2" const calls = (h: H, selected: Node3D, direction: "Inbound" | "Outbound"): Html => { const edges = topology.edges.filter((edge) => diff --git a/apps/web/src/lab/service-map-3d-lab/view-inventory.ts b/apps/web/src/lab/service-map-3d-lab/view-inventory.ts index 63b12cbc8e..56f4739eab 100644 --- a/apps/web/src/lab/service-map-3d-lab/view-inventory.ts +++ b/apps/web/src/lab/service-map-3d-lab/view-inventory.ts @@ -19,7 +19,7 @@ export const healthDot = (h: H, node: Node3D): Html => }) const ROW_CLASS = - "group flex w-full items-center gap-2 px-4 py-2.5 text-left hover:bg-muted/60 focus-visible:outline-2 focus-visible:outline-ring focus-visible:-outline-offset-2" + "group flex w-full items-center gap-2 px-4 py-2.5 text-left hover:bg-surface-strong focus-visible:outline-2 focus-visible:outline-ring focus-visible:-outline-offset-2" const row = (h: H, node: Node3D): Html => h.button( diff --git a/apps/web/src/lab/service-map-3d-lab/view.ts b/apps/web/src/lab/service-map-3d-lab/view.ts index 51844d78b3..c78b2a93d2 100644 --- a/apps/web/src/lab/service-map-3d-lab/view.ts +++ b/apps/web/src/lab/service-map-3d-lab/view.ts @@ -19,7 +19,7 @@ const titleBar = (h: HtmlBuilder): Html => [h.Class("flex items-center gap-3")], [ h.h1([h.Class("font-display text-lg font-semibold tracking-tight")], ["Service map"]), - h.span([h.Class("rounded border px-1.5 py-0.5 text-3xs text-muted-foreground")], ["Isometric lab"]), + h.span([h.Class("rounded-sm border px-1.5 py-0.5 text-3xs text-muted-foreground")], ["Isometric lab"]), ], ), h.p([h.Class("mt-1 text-xs text-muted-foreground")], ["Every service a machine, every call a belt."]), diff --git a/apps/web/src/lab/time-range-lab.ts b/apps/web/src/lab/time-range-lab.ts index e27f71ee1d..7924494df2 100644 --- a/apps/web/src/lab/time-range-lab.ts +++ b/apps/web/src/lab/time-range-lab.ts @@ -158,7 +158,7 @@ export const view = (model: Model, h: HtmlBuilder): Html => { [h.Class("mx-auto w-full max-w-2xl p-4")], [ h.dl( - [h.Class("divide-y divide-border/60 rounded-lg border border-border/70")], + [h.Class("divide-y divide-border-subtle rounded-lg border border-border-subtle")], rowsOf(model).map((row) => h.div( [ @@ -168,7 +168,7 @@ export const view = (model: Model, h: HtmlBuilder): Html => { [ h.dt([h.Class("text-xs text-muted-foreground")], [row.label]), h.dd( - [h.Class("font-mono text-xs tabular-nums text-foreground/90")], + [h.Class("font-mono text-xs tabular-nums text-foreground-soft")], [row.value ?? "—"], ), ], diff --git a/apps/web/src/lab/widget-lab/view-copy.ts b/apps/web/src/lab/widget-lab/view-copy.ts index 84a6e8d5ba..2c6cfbc832 100644 --- a/apps/web/src/lab/widget-lab/view-copy.ts +++ b/apps/web/src/lab/widget-lab/view-copy.ts @@ -91,10 +91,10 @@ const copyableValue = (h: H, model: Model): Html => { h.AriaLabel("Copy span ID"), h.Class( status === "copied" - ? "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors bg-severity-info/20" + ? "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors bg-severity-info/20" : status === "error" - ? "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors bg-severity-error/20" - : "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors hover:bg-muted/50", + ? "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors bg-severity-error/20" + : "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors hover:bg-surface-sunken", ), h.Title("Click to copy"), h.OnClick( diff --git a/apps/web/src/lib/sql-highlight.ts b/apps/web/src/lib/sql-highlight.ts index a6e4b02206..74b92e776e 100644 --- a/apps/web/src/lib/sql-highlight.ts +++ b/apps/web/src/lib/sql-highlight.ts @@ -76,7 +76,7 @@ export function tokenizeSql(code: string): SqlHighlightToken[] { if (m.index > last) tokens.push({ text: code.slice(last, m.index), start: last }) const [full, comment, str, macro, num, ident] = m if (comment) { - tokens.push({ text: comment, start: m.index, className: "text-muted-foreground/70 italic" }) + tokens.push({ text: comment, start: m.index, className: "text-foreground-subtle italic" }) } else if (str) { tokens.push({ text: str, start: m.index, className: "text-severity-info" }) } else if (macro) { diff --git a/apps/web/src/page/agent-sessions/kit/more-chip.ts b/apps/web/src/page/agent-sessions/kit/more-chip.ts index 487b24bbab..b3f486d605 100644 --- a/apps/web/src/page/agent-sessions/kit/more-chip.ts +++ b/apps/web/src/page/agent-sessions/kit/more-chip.ts @@ -10,7 +10,7 @@ export const moreChip = ( [ h.Class( cn( - "shrink-0 cursor-default rounded-sm bg-muted/60 px-1 font-mono text-2xs tabular-nums text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", + "shrink-0 cursor-default rounded-sm bg-surface-strong px-1 font-mono text-2xs tabular-nums text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", options.className, ), ), diff --git a/apps/web/src/page/agent-sessions/kit/tabs.ts b/apps/web/src/page/agent-sessions/kit/tabs.ts index 60609c3cf3..71e77c7610 100644 --- a/apps/web/src/page/agent-sessions/kit/tabs.ts +++ b/apps/web/src/page/agent-sessions/kit/tabs.ts @@ -56,7 +56,7 @@ const tabLink = ( "text-2xs tabular-nums", options.isActive ? "text-muted-foreground" - : "text-muted-foreground/60", + : "text-foreground-subtle", ), ), ], diff --git a/apps/web/src/page/agent-sessions/list/view-table.ts b/apps/web/src/page/agent-sessions/list/view-table.ts index 3da409dc2b..b101da5ac5 100644 --- a/apps/web/src/page/agent-sessions/list/view-table.ts +++ b/apps/web/src/page/agent-sessions/list/view-table.ts @@ -164,7 +164,7 @@ const sortableHeader = (h: H, column: Column, sort: Sort): Html => { h.span( [ h.Class( - "ml-0.5 whitespace-nowrap text-3xs font-normal text-muted-foreground/70", + "ml-0.5 whitespace-nowrap text-3xs font-normal text-foreground-subtle", ), ], [column.subLabel], @@ -273,7 +273,7 @@ const sessionCell = (h: H, row: DisplayRow, context: RowContext): Html => { [h.Class("mt-0.5 flex min-w-0 items-baseline gap-1.5 text-xs"), ...triggerAttributes(h)], [ h.span( - [h.Class("shrink-0 text-muted-foreground/70")], + [h.Class("shrink-0 text-foreground-subtle")], [id.kind === "trace" ? "Trace" : "Session"], ), h.span([h.Class("min-w-0 truncate font-mono text-muted-foreground")], [id.short]), @@ -357,7 +357,7 @@ const tokenBar = (h: H, row: DisplayRow): Html | null => { // One line, in then out; the exact counts ride on the title. const side = (part: typeof input) => h.span( - [h.Class(part.count > 0 ? part.tone : "text-muted-foreground/50")], + [h.Class(part.count > 0 ? part.tone : "text-foreground-faint")], [part.count > 0 ? formatNumber(part.count) : EMPTY_VALUE], ) return h.span( @@ -383,7 +383,7 @@ const errorChip = ( const errorChips = (h: H, row: DisplayRow): Html => { // A measured zero reads "0"; the dash is kept for a value that does not apply. if (row.errorSpanCount === 0) - return h.span([h.Class("font-mono text-xs tabular-nums text-muted-foreground/50")], ["0"]) + return h.span([h.Class("font-mono text-xs tabular-nums text-foreground-faint")], ["0"]) const classified = row.toolErrorCount + row.turnErrorCount const other = row.errorSpanCount - classified return h.div( @@ -438,7 +438,7 @@ const servicesCell = (h: H, services: ReadonlyArray): Html | null => { } /** A cell with nothing to report reads as a muted dash, never blank. */ -const emptyCell = (h: H): Html => h.span([h.Class("text-xs text-muted-foreground/50")], [EMPTY_VALUE]) +const emptyCell = (h: H): Html => h.span([h.Class("text-xs text-foreground-faint")], [EMPTY_VALUE]) const cellsOf = (h: H, row: DisplayRow, context: RowContext): ReadonlyArray => [ sessionCell(h, row, context), @@ -459,7 +459,7 @@ const sessionRow = (h: H, row: DisplayRow, index: number, context: RowContext): cellsOf(h, row, context).map((cell, column) => tableCell(h, [cell ?? emptyCell(h)], cn(CELL_CLASS, COLUMNS[column]?.responsive)), ), - cn("cursor-pointer hover:bg-muted/50", ROW_LIFT_TOOLTIPS), + cn("cursor-pointer hover:bg-surface-sunken", ROW_LIFT_TOOLTIPS), [ h.Key(row.sessionId), h.DataAttribute("index", String(index)), diff --git a/apps/web/src/page/agent-sessions/session/span-popover-details.ts b/apps/web/src/page/agent-sessions/session/span-popover-details.ts index 5eed4377df..f54b39e2b8 100644 --- a/apps/web/src/page/agent-sessions/session/span-popover-details.ts +++ b/apps/web/src/page/agent-sessions/session/span-popover-details.ts @@ -46,10 +46,10 @@ const toolCallCard = ( options: Readonly<{ isFailed: boolean; statusCode: string; keyPrefix: string }>, ): Html => h.div( - [h.Class("min-w-0 overflow-hidden rounded-md border border-border/60")], + [h.Class("min-w-0 overflow-hidden rounded-md border border-border-subtle")], [ h.div( - [h.Class("flex items-center gap-2 bg-muted/40 px-2.5 py-1.5")], + [h.Class("flex items-center gap-2 bg-surface-sunken px-2.5 py-1.5")], [ h.span([h.AriaHidden(true), h.Class("size-1.5 shrink-0 rounded-xs bg-chart-4")], []), h.span([h.Class("shrink-0 font-medium font-mono text-chart-4 text-xs")], ["tool"]), @@ -68,7 +68,7 @@ const toolCallCard = ( truncatedText(h, { text: call.id, mono: true, - className: "ml-auto max-w-40 shrink-0 text-2xs text-muted-foreground/80", + className: "ml-auto max-w-40 shrink-0 text-2xs text-foreground-subtle", }), ]), ], @@ -79,7 +79,7 @@ const toolCallCard = ( h.p( [ h.Class( - "border-border/60 border-t px-2.5 py-1.5 text-muted-foreground text-xs", + "border-border-subtle border-t px-2.5 py-1.5 text-muted-foreground text-xs", ), ], [call.description], @@ -106,7 +106,7 @@ const failureBanner = (b: HtmlBuilder, span: AiSessionSpan): Html => { return b.div( [ b.Class( - "flex flex-col gap-1.5 rounded-md border border-severity-error/40 bg-severity-error/5 px-3 py-2.5", + "flex flex-col gap-1.5 rounded-md border border-severity-error/40 bg-severity-error/5 p-3", ), ], [ @@ -172,7 +172,7 @@ const identityRows = (p: P, state: PanelState, span: AiSessionSpan, timeZone: st ] return keyValueList( p, - { layout: "grid", divided: true, className: "rounded-md border border-border/60 px-2.5" }, + { layout: "grid", divided: true, className: "rounded-md border border-border-subtle px-2.5" }, rows.flatMap(([label, value]) => value === undefined ? [] @@ -229,7 +229,7 @@ const resourceAttributesView = Submodel.defineView((state, { timeZone }, p) => - p.div([p.Class("overflow-hidden rounded-md border border-border/60")], [spanLogs(p, state, timeZone)]), + p.div([p.Class("overflow-hidden rounded-md border border-border-subtle")], [spanLogs(p, state, timeZone)]), ) /** The call's own settings and identity, shown only where the span reported them. */ @@ -272,7 +272,7 @@ const metaStripView = Submodel.defineView p.span( [ p.Class( - "ml-auto flex items-baseline gap-1.5 font-mono text-2xs text-muted-foreground/70", + "ml-auto flex items-baseline gap-1.5 font-mono text-2xs text-foreground-subtle", ), ], [ diff --git a/apps/web/src/page/agent-sessions/session/span-popover-messages.ts b/apps/web/src/page/agent-sessions/session/span-popover-messages.ts index 7d1f0751bf..17a35f4d0f 100644 --- a/apps/web/src/page/agent-sessions/session/span-popover-messages.ts +++ b/apps/web/src/page/agent-sessions/session/span-popover-messages.ts @@ -72,10 +72,10 @@ export const payloadCard = ( options: Readonly<{ label: string; name?: string; meta?: string; body?: string; key: string }>, ): Html => h.div( - [h.Class("min-w-0 overflow-hidden rounded-md border border-border/60")], + [h.Class("min-w-0 overflow-hidden rounded-md border border-border-subtle")], [ h.div( - [h.Class("flex items-center gap-2 bg-muted/40 px-2.5 py-1.5")], + [h.Class("flex items-center gap-2 bg-surface-sunken px-2.5 py-1.5")], [ h.span([h.AriaHidden(true), h.Class("size-1.5 shrink-0 rounded-xs bg-chart-4")], []), h.span([h.Class("shrink-0 font-medium font-mono text-chart-4 text-xs")], [options.label]), @@ -93,7 +93,7 @@ export const payloadCard = ( h.span( [ h.Class( - "ml-auto min-w-0 truncate font-mono text-2xs text-muted-foreground/80", + "ml-auto min-w-0 truncate font-mono text-2xs text-foreground-subtle", ), ], [options.meta], @@ -111,7 +111,7 @@ const payloadBody = (h: H, model: Model, text: string, copyLabel: string, key: s const { formatted, isJson } = jsonPayload(text) const isRaw = disclosed(model.openRows, `${key}:raw`, false) return h.div( - [h.Class("flex items-start gap-1.5 border-border/60 border-t bg-background/50 px-2.5 py-2")], + [h.Class("flex items-start gap-1.5 border-border-subtle border-t bg-background/50 px-2.5 py-2")], [ h.div( [h.Class("min-w-0 grow")], @@ -202,7 +202,7 @@ const messageBlock = (h: H, model: Model, message: SpanMessage, span: AiSessionS ...(message.origin === "output" ? [ h.span( - [h.Class("min-w-0 truncate font-mono text-2xs text-muted-foreground/80")], + [h.Class("min-w-0 truncate font-mono text-2xs text-foreground-subtle")], [callMetaLine(span)], ), ] @@ -265,7 +265,7 @@ const systemMessageRow = (h: H, model: Model, message: SpanMessage, key: string) const isOpen = disclosed(model.openRows, key, false) const isRaw = disclosed(model.openRows, `${key}:raw`, false) const text = collapsedText(message.parts) - return panel(h, { tone: "muted", className: "border-border/60" }, [ + return panel(h, { tone: "muted", className: "border-border-subtle" }, [ h.button( [ h.AriaExpanded(isOpen), diff --git a/apps/web/src/page/agent-sessions/session/span-visuals.ts b/apps/web/src/page/agent-sessions/session/span-visuals.ts index f00aee4657..572c743d3b 100644 --- a/apps/web/src/page/agent-sessions/session/span-visuals.ts +++ b/apps/web/src/page/agent-sessions/session/span-visuals.ts @@ -47,7 +47,7 @@ export const AGENT_TIME_TEXT = { ttft: "text-chart-ai-ttft", inference: "text-chart-ai-inference", tool: "text-chart-ai-tool", - idle: "text-muted-foreground/70", + idle: "text-foreground-subtle", } satisfies Record export const AGENT_TIME_LABEL = { diff --git a/apps/web/src/page/agent-sessions/session/tool-io.ts b/apps/web/src/page/agent-sessions/session/tool-io.ts index fcdce0d0b0..4e81c35ffb 100644 --- a/apps/web/src/page/agent-sessions/session/tool-io.ts +++ b/apps/web/src/page/agent-sessions/session/tool-io.ts @@ -37,7 +37,7 @@ export const toolIoSummary = ( [ icon(h, "ArrowDownIcon", { size: 10, - className: "text-muted-foreground/70", + className: "text-foreground-subtle", attributes: [h.AriaHidden(true)], }), args === undefined ? "not captured" : formatBytes(args.byteLength), @@ -161,7 +161,7 @@ const ioHalf = (h: H, model: Model, half: Half): Html => h.Class( cn( "flex items-stretch", - half.direction === "in" ? "bg-black/[0.06]" : "border-border/60 border-t", + half.direction === "in" ? "bg-black/[0.06]" : "border-border-subtle border-t", half.direction === "out" && half.isFailed && "bg-severity-error/5", ), ), @@ -220,7 +220,7 @@ const ioHalf = (h: H, model: Model, half: Half): Html => const missingHalf = (h: H, label: string, note: string): Html => h.div( - [h.Class("flex items-center border-input border-t border-dashed bg-muted/20 py-2.5 pr-3")], + [h.Class("flex items-center border-input border-t border-dashed bg-surface-faint py-2.5 pr-3")], [ h.span( [h.Class("flex w-8 shrink-0 justify-center")], @@ -259,14 +259,14 @@ export const toolIo = ( h.div( [ h.Class( - "flex items-center gap-2.5 border-input border-t border-dashed bg-muted/20 px-3 py-2.5", + "flex items-center gap-2.5 border-input border-t border-dashed bg-surface-faint px-3 py-2.5", ), ], [ h.span( [ h.AriaHidden(true), - h.Class("flex shrink-0 items-center gap-0.5 text-muted-foreground/60"), + h.Class("flex shrink-0 items-center gap-0.5 text-foreground-subtle"), ], [icon(h, "ArrowDownIcon", { size: 10 }), icon(h, "ArrowUpIcon", { size: 10 })], ), diff --git a/apps/web/src/page/agent-sessions/session/transcript-blocks.ts b/apps/web/src/page/agent-sessions/session/transcript-blocks.ts index 19dc5ab10e..43685682c6 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-blocks.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-blocks.ts @@ -92,7 +92,7 @@ export const toolBlock = ( ? "border-severity-error/40 bg-severity-error/5" : isOpen ? "border-border bg-card" - : "border-transparent bg-muted/30 hover:bg-muted/50", + : "border-transparent bg-surface-sunken hover:bg-surface-strong", }, [ toolHeader(h, tool, isOpen, timeZone), diff --git a/apps/web/src/page/agent-sessions/session/transcript-calls.ts b/apps/web/src/page/agent-sessions/session/transcript-calls.ts index 00d64f3efa..07357459db 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-calls.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-calls.ts @@ -270,7 +270,7 @@ export const structureRow = ( h.AriaPressed(String(isSelected)), h.Class( cn( - "-mx-1.5 flex min-w-0 grow cursor-pointer items-center gap-2 rounded-md px-1.5 py-1 text-left hover:bg-muted/50", + "-mx-1.5 flex min-w-0 grow cursor-pointer items-center gap-2 rounded-md px-1.5 py-1 text-left hover:bg-surface-sunken", rowSelectedClass(isSelected), ), ), diff --git a/apps/web/src/page/agent-sessions/session/transcript-lanes.ts b/apps/web/src/page/agent-sessions/session/transcript-lanes.ts index 961452b84a..5af992f530 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-lanes.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-lanes.ts @@ -204,7 +204,7 @@ export const noteBlock = (h: H, note: Extract): ]) const scope = note.scope === "session" ? `${note.anyCaptured ? "most of " : ""}this session` : "this turn" return h.div( - [h.Class("mx-2 mt-2 flex max-w-[924px] items-start gap-3 rounded-lg bg-muted/30 px-4 py-3")], + [h.Class("mx-2 mt-2 flex max-w-[924px] items-start gap-3 rounded-lg bg-surface-sunken px-4 py-3")], [ icon(h, "CircleInfoIcon", { size: 16, className: "mt-0.5 shrink-0 text-muted-foreground" }), h.div( diff --git a/apps/web/src/page/agent-sessions/session/transcript-messages.ts b/apps/web/src/page/agent-sessions/session/transcript-messages.ts index 5713a426a3..933280f23c 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-messages.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-messages.ts @@ -48,7 +48,7 @@ const historyToggle = (h: H, model: Model, user: Extract): Html => h.div( - [h.Class("flex flex-col gap-3 rounded-md border border-border/60 bg-muted/20 px-3 py-2.5")], + [h.Class("flex flex-col gap-3 rounded-md border border-border-subtle bg-surface-faint p-3")], [ h.p( [h.Class("text-2xs text-muted-foreground")], @@ -95,7 +95,7 @@ export const userBlock = ( h.div( [ h.Class( - "mr-8 ml-auto w-fit max-w-[85%] rounded-lg rounded-tr-sm bg-muted/50 px-3.5 py-2.5", + "mr-8 ml-auto w-fit max-w-[85%] rounded-lg rounded-tr-sm bg-surface-sunken px-3.5 py-2.5", ), ], [messageBodyView(h, model, { text: user.text, rowKey: user.key })], @@ -135,7 +135,7 @@ export const systemBlock = (h: H, model: Model, system: Extract, classNa [ h.Class( cn( - "flex items-start gap-2.5 rounded-md border border-input border-dashed bg-muted/20 px-3 py-2", + "flex items-start gap-2.5 rounded-md border border-input border-dashed bg-surface-faint px-3 py-2", className, ), ), diff --git a/apps/web/src/page/agent-sessions/session/view-checks.ts b/apps/web/src/page/agent-sessions/session/view-checks.ts index 44203c71a4..bd1beee75a 100644 --- a/apps/web/src/page/agent-sessions/session/view-checks.ts +++ b/apps/web/src/page/agent-sessions/session/view-checks.ts @@ -106,7 +106,7 @@ const evidenceRow = (h: H, model: Model, finding: SessionFinding, status: Sessio [ h.AriaHasPopup("dialog"), h.Class( - "group flex w-full items-baseline gap-2 rounded-sm px-1.5 py-0.5 text-left font-mono text-xs hover:bg-accent/40", + "group flex w-full items-baseline gap-2 rounded-sm px-1.5 py-0.5 text-left font-mono text-xs hover:bg-accent/50", ), h.Type("button"), h.OnClick(openSpan(model, finding.spanId)), @@ -116,7 +116,7 @@ const evidenceRow = (h: H, model: Model, finding: SessionFinding, status: Sessio [h.Class(cn("shrink-0", STATUS_TEXT[status]))], [finding.label, ...(finding.count > 1 ? [` ×${finding.count}`] : [])], ), - h.span([h.Class("shrink-0 text-muted-foreground/70")], [finding.turnText]), + h.span([h.Class("shrink-0 text-foreground-subtle")], [finding.turnText]), ...(finding.detail === undefined ? [] : [h.span([h.Class("min-w-0 truncate text-muted-foreground")], [finding.detail])]), @@ -268,7 +268,7 @@ const disclosure = ( h.button( [ h.AriaExpanded(isExpanded), - h.Class(cn(ROW_GRID, "w-full py-2.5 text-left hover:bg-accent/40")), + h.Class(cn(ROW_GRID, "w-full py-2.5 text-left hover:bg-accent/50")), h.Type("button"), h.OnClick(Message.ToggledChecks({ which: options.which, isOpen: !isExpanded })), ], @@ -289,7 +289,7 @@ const disclosure = ( const SIGNAL_MARK = { captured: { glyph: "✓", tone: "text-severity-info", says: "captured:" }, missing: { glyph: "✕", tone: "text-severity-error", says: "not captured:" }, - absent: { glyph: "–", tone: "text-muted-foreground/60", says: "nothing to capture:" }, + absent: { glyph: "–", tone: "text-foreground-subtle", says: "nothing to capture:" }, } satisfies Record /** `coverageSignals`, labels and states only (the explanations live in the tooltips). */ @@ -335,7 +335,7 @@ const coverageLine = (h: H, coverage: SessionCoverage): Html => "flex cursor-default items-baseline gap-1.5", signal.state === "captured" ? "text-muted-foreground" - : "text-muted-foreground/60", + : "text-foreground-subtle", signal.state === "missing" && "line-through", ), ), diff --git a/apps/web/src/page/agent-sessions/session/view-flow.ts b/apps/web/src/page/agent-sessions/session/view-flow.ts index b86e897f23..699cd76f5a 100644 --- a/apps/web/src/page/agent-sessions/session/view-flow.ts +++ b/apps/web/src/page/agent-sessions/session/view-flow.ts @@ -117,7 +117,7 @@ const laneLabel = (h: H, lane: FlowLane): Html => { style: { "pointer-events": "none" }, children: [ h.div( - [h.Class("pointer-events-none w-[110px] text-xs")], + [h.Class("pointer-events-none w-28 text-xs")], [ eyebrow(h, { as: "p", className: "text-primary" }, ["Turn ", String(lane.turn.index)]), h.p( diff --git a/apps/web/src/page/agent-sessions/session/view-header.ts b/apps/web/src/page/agent-sessions/session/view-header.ts index 26a6269041..2e72463c25 100644 --- a/apps/web/src/page/agent-sessions/session/view-header.ts +++ b/apps/web/src/page/agent-sessions/session/view-header.ts @@ -46,8 +46,8 @@ const copyableId = ( h.AriaLabel(`Copy ${label}`), h.Class( cn( - "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors", - model.copy.status === "idle" && "hover:bg-muted/50", + "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors", + model.copy.status === "idle" && "hover:bg-surface-sunken", model.copy.status === "copied" && "bg-severity-info/20", model.copy.status === "error" && "bg-severity-error/20", "inline-flex min-w-0 max-w-full items-center gap-1 font-mono", diff --git a/apps/web/src/page/agent-sessions/session/view-overview.ts b/apps/web/src/page/agent-sessions/session/view-overview.ts index adf5101298..9ef7c95fd8 100644 --- a/apps/web/src/page/agent-sessions/session/view-overview.ts +++ b/apps/web/src/page/agent-sessions/session/view-overview.ts @@ -252,7 +252,7 @@ const ledgerRow = ( cn( LEDGER_COUNT, "font-mono text-xs tabular-nums", - tool.failed > 0 ? "text-severity-error" : "text-muted-foreground/50", + tool.failed > 0 ? "text-severity-error" : "text-foreground-faint", ), ), ], @@ -327,7 +327,7 @@ const waiting = (h: H, model: Model, progress: LoadProgress): Html => ), loadIndicator(h, model, progress, "items-center"), h.p( - [h.Class("text-xs text-muted-foreground/70")], + [h.Class("text-xs text-foreground-subtle")], ["The Traces, Flow and Transcript views already show what has loaded."], ), ], diff --git a/apps/web/src/page/agent-sessions/session/view-waterfall.ts b/apps/web/src/page/agent-sessions/session/view-waterfall.ts index 2d1976ee03..250edeea64 100644 --- a/apps/web/src/page/agent-sessions/session/view-waterfall.ts +++ b/apps/web/src/page/agent-sessions/session/view-waterfall.ts @@ -49,10 +49,10 @@ const INDENT_PX = 14 const AXIS_EDGE_FRACTION = 0.9 const COL_SPAN = "w-[398px] max-w-[46%] min-w-0 shrink-0 flex items-center gap-1.5" -const COL_MODEL = "hidden w-[150px] shrink-0 truncate px-2 text-muted-foreground @3xl:block" +const COL_MODEL = "hidden w-36 shrink-0 truncate px-2 text-muted-foreground @3xl:block" const COL_TOKENS = - "hidden w-[132px] shrink-0 truncate px-2 text-right tabular-nums text-muted-foreground @3xl:block" -const COL_TOKENS_SPLIT = "hidden w-[132px] shrink-0 items-center gap-1.5 px-2 @3xl:flex" + "hidden w-32 shrink-0 truncate px-2 text-right tabular-nums text-muted-foreground @3xl:block" +const COL_TOKENS_SPLIT = "hidden w-32 shrink-0 items-center gap-1.5 px-2 @3xl:flex" const COL_AXIS = "relative ml-3 min-w-0 flex-1 self-stretch" const COL_DUR = "w-[60px] shrink-0 pl-2 text-right tabular-nums" @@ -177,7 +177,7 @@ const turnHeader = ( return h.div( [ h.Class( - "flex h-full w-full items-center rounded-md bg-card px-2.5 text-left text-xs hover:bg-accent/40", + "flex h-full w-full items-center rounded-md bg-card px-2.5 text-left text-xs hover:bg-accent/50", ), ], [ @@ -293,7 +293,7 @@ const spanCell = ( }), ...(heading.operation === undefined ? [] - : [h.span([h.Class("shrink-0 text-muted-foreground/70")], [heading.operation])]), + : [h.span([h.Class("shrink-0 text-foreground-subtle")], [heading.operation])]), ...(heading.subject === undefined ? [] : [h.span([h.Class("max-w-[60%] shrink-0 truncate font-medium")], [heading.subject])]), @@ -326,7 +326,7 @@ const spanRow = ( h.AriaHasPopup("dialog"), h.Class( cn( - "flex h-full w-full cursor-pointer items-center px-2.5 text-left text-xs hover:bg-accent/40", + "flex h-full w-full cursor-pointer items-center px-2.5 text-left text-xs hover:bg-accent/50", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", isErrored && "bg-severity-error/6", state.isFocused && "bg-accent/60", diff --git a/apps/web/src/page/agent-sessions/tool/view-error-modal-payload.ts b/apps/web/src/page/agent-sessions/tool/view-error-modal-payload.ts index 0feaaa3b6d..7c9925d241 100644 --- a/apps/web/src/page/agent-sessions/tool/view-error-modal-payload.ts +++ b/apps/web/src/page/agent-sessions/tool/view-error-modal-payload.ts @@ -28,7 +28,7 @@ const payloadHead = ( [ eyebrow(h, { variant: "mono" }, [options.label]), h.span( - [h.Class("truncate text-2xs text-muted-foreground/50")], + [h.Class("truncate text-2xs text-foreground-faint")], [options.attribute, ...(options.bytes > 0 ? [` · ${formatToolCount(options.bytes)} B`] : [])], ), h.span([h.Class("grow")], []), @@ -42,7 +42,7 @@ const notRecorded = (h: H, what: "arguments" | "result"): Html => [ h.span([h.Class("text-xs text-muted-foreground")], ["Not recorded"]), h.span( - [h.Class("text-2xs leading-[15px] text-muted-foreground/70")], + [h.Class("text-2xs leading-[15px] text-foreground-subtle")], ["The span has no ", what, " attribute."], ), ], @@ -75,7 +75,7 @@ const payloadLineView = (h: H, line: PayloadLine): Html => ? "text-foreground" : line.folded !== undefined ? "text-muted-foreground" - : "text-foreground/80", + : "text-foreground-soft", ), ), ], @@ -168,7 +168,7 @@ const argumentsBlock = ( ? h.pre( [ h.Class( - "max-h-[480px] overflow-auto whitespace-pre-wrap break-words rounded-md border border-border bg-sidebar px-3.5 py-3 font-mono text-xs leading-[18px] text-foreground/80", + "max-h-[480px] overflow-auto whitespace-pre-wrap break-words rounded-md border border-border bg-sidebar p-3 font-mono text-xs leading-[18px] text-foreground-soft", ), ], [args === undefined ? row.arguments : JSON.stringify(args, null, 2)], @@ -184,7 +184,7 @@ const argumentsBlock = ( h.div( [ h.Class( - "flex items-center gap-2.5 font-mono text-2xs leading-3.5 text-muted-foreground/70", + "flex items-center gap-2.5 font-mono text-2xs leading-3.5 text-foreground-subtle", ), ], [ @@ -222,7 +222,7 @@ const resultBlock = (h: H, row: ToolErrorOccurrenceRow): Html => { : h.pre( [ h.Class( - "max-h-[480px] overflow-auto whitespace-pre-wrap break-words rounded-md border border-severity-error/25 bg-sidebar px-3.5 py-3 font-mono text-xs leading-[18px] text-foreground/80", + "max-h-[480px] overflow-auto whitespace-pre-wrap break-words rounded-md border border-severity-error/25 bg-sidebar p-3 font-mono text-xs leading-[18px] text-foreground-soft", ), ], [parsed === undefined ? row.result : JSON.stringify(parsed, null, 2)], @@ -231,7 +231,7 @@ const resultBlock = (h: H, row: ToolErrorOccurrenceRow): Html => { ? [] : [ h.span( - [h.Class("font-mono text-2xs leading-3.5 text-muted-foreground/70")], + [h.Class("font-mono text-2xs leading-3.5 text-foreground-subtle")], ["Error message read from ", source], ), ]), @@ -263,7 +263,7 @@ export const sampleBody = (h: H, model: Model, row: ToolErrorOccurrenceRow): Htm ["What's wrong"], ), h.span( - [h.Class("text-xs leading-4 text-foreground/80")], + [h.Class("text-xs leading-4 text-foreground-soft")], [ h.span([h.Class("font-medium text-foreground")], [hint.subject]), " ", @@ -278,7 +278,7 @@ export const sampleBody = (h: H, model: Model, row: ToolErrorOccurrenceRow): Htm h.div( [ h.Class( - "flex items-start gap-3 rounded-md border border-border bg-sidebar px-3.5 py-3 font-mono", + "flex items-start gap-3 rounded-md border border-border bg-sidebar p-3 font-mono", ), ], [ diff --git a/apps/web/src/page/agent-sessions/tool/view-error-modal-rail.ts b/apps/web/src/page/agent-sessions/tool/view-error-modal-rail.ts index 78d168ca95..06f0d5a80b 100644 --- a/apps/web/src/page/agent-sessions/tool/view-error-modal-rail.ts +++ b/apps/web/src/page/agent-sessions/tool/view-error-modal-rail.ts @@ -60,7 +60,7 @@ const variantsSection = ( [ h.span([h.Class(RAIL_TITLE)], ["Variants"]), h.span( - [h.Class("font-mono text-2xs leading-3.5 tabular-nums text-muted-foreground/70")], + [h.Class("font-mono text-2xs leading-3.5 tabular-nums text-foreground-subtle")], [formatToolCount(total), " raw messages"], ), ], @@ -74,7 +74,7 @@ const variantsSection = ( h.Class( cn( "-mx-2 flex h-8 shrink-0 items-center gap-2.5 rounded-md px-2 text-left font-mono text-xs transition-colors", - isSelected ? "bg-primary/10" : "hover:bg-muted/50", + isSelected ? "bg-primary/10" : "hover:bg-surface-sunken", ), ), h.Title(unwrapToolErrorText(row.message).text), @@ -105,7 +105,7 @@ const variantsSection = ( ) }), h.p( - [h.Class("pt-1 font-mono text-2xs leading-[15px] text-muted-foreground/70")], + [h.Class("pt-1 font-mono text-2xs leading-[15px] text-foreground-subtle")], [ isOnlyIndex ? "Grouped because only the array index differs." @@ -187,12 +187,12 @@ export const sessionLink = ( const sessionRowClass = (isSelected: boolean) => cn( - "group flex w-full shrink-0 items-center gap-3 border-b border-border/60 pr-4 pl-4 text-left transition-colors", + "group flex w-full shrink-0 items-center gap-3 border-b border-border-subtle pr-4 pl-4 text-left transition-colors", rowSelectedClass(isSelected), - !isSelected && "hover:bg-muted/50", + !isSelected && "hover:bg-surface-sunken", ) -const LAST_CLASS = "w-14 shrink-0 text-right font-mono text-2xs tabular-nums text-muted-foreground/70" +const LAST_CLASS = "w-14 shrink-0 text-right font-mono text-2xs tabular-nums text-foreground-subtle" /** Which sessions hit this group; `All sessions` is the way back out of a selection. */ const sessionsSection = (h: H, model: Model, inputs: ModalInputs, detail: ErrorDetail): Html => { @@ -206,7 +206,7 @@ const sessionsSection = (h: H, model: Model, inputs: ModalInputs, detail: ErrorD [ h.span([h.Class(RAIL_TITLE)], ["Sessions"]), h.span( - [h.Class("font-mono text-2xs leading-3.5 tabular-nums text-muted-foreground/70")], + [h.Class("font-mono text-2xs leading-3.5 tabular-nums text-foreground-subtle")], [formatToolCount(group.sessions)], ), ], @@ -286,7 +286,7 @@ const sessionsSection = (h: H, model: Model, inputs: ModalInputs, detail: ErrorD h.span( [ h.Class( - "w-full truncate font-mono text-2xs leading-3.5 text-muted-foreground/70", + "w-full truncate font-mono text-2xs leading-3.5 text-foreground-subtle", ), ], [ @@ -330,7 +330,7 @@ const sessionsSection = (h: H, model: Model, inputs: ModalInputs, detail: ErrorD formatToolCount(group.sessions), ], ), - h.span([h.Class("text-muted-foreground/60")], ["by hits"]), + h.span([h.Class("text-foreground-subtle")], ["by hits"]), ], ), ], diff --git a/apps/web/src/page/agent-sessions/tool/view-error-modal-samples.ts b/apps/web/src/page/agent-sessions/tool/view-error-modal-samples.ts index f1e1d8e5b0..82640a3b59 100644 --- a/apps/web/src/page/agent-sessions/tool/view-error-modal-samples.ts +++ b/apps/web/src/page/agent-sessions/tool/view-error-modal-samples.ts @@ -47,7 +47,7 @@ const footer = (h: H, model: Model, shown: number, total: number): Html => { ), ] : paging === "loading" - ? [h.span([h.Class("text-muted-foreground/60")], ["Loading…"])] + ? [h.span([h.Class("text-foreground-subtle")], ["Loading…"])] : paging === "failed" ? [ h.button( @@ -112,7 +112,7 @@ export const samplesPane = ( [ h.span([h.Class("text-xs font-medium text-foreground")], ["Samples"]), h.span( - [h.Class("text-2xs leading-3.5 tabular-nums text-muted-foreground/70")], + [h.Class("text-2xs leading-3.5 tabular-nums text-foreground-subtle")], [ formatToolCount(options.total), " failed ", @@ -126,7 +126,7 @@ export const samplesPane = ( [h.Class("flex items-center gap-2")], [ h.span( - [h.Class("pr-1 text-2xs text-muted-foreground/60 max-md:hidden")], + [h.Class("pr-1 text-2xs text-foreground-subtle max-md:hidden")], ["j / k"], ), iconButton( @@ -142,7 +142,7 @@ export const samplesPane = ( [icon(h, "ChevronLeftIcon", { attributes: [h.AriaHidden(true)] })], ), h.span( - [h.Class("w-[72px] text-center text-xs tabular-nums text-foreground")], + [h.Class("w-20 text-center text-xs tabular-nums text-foreground")], [ rows.length === 0 ? "0" : String(current + 1), " of ", @@ -185,14 +185,14 @@ const sampleRow = ( [ h.Key(row.spanId), h.DataAttribute("slot", "tool-error-sample"), - h.Class("border-b border-border/60"), + h.Class("border-b border-border-subtle"), ], [ h.div( [ h.Class( cn( - "group relative flex w-full items-center gap-3.5 px-6 font-mono transition-colors hover:bg-muted/50", + "group relative flex w-full items-center gap-3.5 px-6 font-mono transition-colors hover:bg-surface-sunken", options.isOpen ? "h-11" : "h-10", ), ), @@ -219,7 +219,7 @@ const sampleRow = ( h.span( [h.Class("flex min-w-0 shrink items-center gap-[5px] text-xs")], [ - h.span([h.Class("shrink-0 text-muted-foreground/70")], ["session"]), + h.span([h.Class("shrink-0 text-foreground-subtle")], ["session"]), sessionLink(h, { tool: inputs.tool, sessionId: row.sessionId, @@ -238,7 +238,7 @@ const sampleRow = ( h.span( [ h.Class( - "hidden min-w-0 shrink truncate text-xs text-muted-foreground/70 xl:block", + "hidden min-w-0 shrink truncate text-xs text-foreground-subtle xl:block", ), ], [row.service], @@ -250,10 +250,10 @@ const sampleRow = ( h.span( [ h.Class( - "hidden shrink-0 rounded-sm border border-border px-[5px] text-2xs leading-3.5 text-muted-foreground/70 md:block", + "hidden shrink-0 rounded-sm border border-border px-[5px] text-2xs leading-3.5 text-foreground-subtle md:block", ), ], - ["variant ", h.span([h.Class("text-foreground/80")], [options.variant])], + ["variant ", h.span([h.Class("text-foreground-soft")], [options.variant])], ), ]), h.span([h.Class("grow")], []), @@ -263,14 +263,14 @@ const sampleRow = ( h.span( [ h.Class( - "hidden shrink-0 text-2xs tabular-nums text-muted-foreground/70 md:block", + "hidden shrink-0 text-2xs tabular-nums text-foreground-subtle md:block", ), ], ["args ", formatToolCount(row.argumentsBytes), " B"], ), ]), h.span( - [h.Class("w-12 shrink-0 text-right text-xs tabular-nums text-foreground/80")], + [h.Class("w-12 shrink-0 text-right text-xs tabular-nums text-foreground-soft")], [formatDurationNs(row.durationNs)], ), h.a( diff --git a/apps/web/src/page/agent-sessions/tool/view-error-modal.ts b/apps/web/src/page/agent-sessions/tool/view-error-modal.ts index 8d008ca0c9..e8cd1f172f 100644 --- a/apps/web/src/page/agent-sessions/tool/view-error-modal.ts +++ b/apps/web/src/page/agent-sessions/tool/view-error-modal.ts @@ -68,7 +68,7 @@ const facts = (h: H, items: ReadonlyArray): ReadonlyArray = [h.Class("contents")], [ ...(index > 0 - ? [h.span([h.AriaHidden(true), h.Class("text-muted-foreground/40")], ["·"])] + ? [h.span([h.AriaHidden(true), h.Class("text-foreground-faint")], ["·"])] : []), typeof item === "string" ? h.span([h.Class("text-muted-foreground")], [item]) : item, ], @@ -120,14 +120,14 @@ const headerLead = (h: H, inputs: ModalInputs): Html => { h.div( [ h.Class( - "flex flex-wrap items-center gap-2.5 font-mono text-2xs leading-3.5 text-muted-foreground/80", + "flex flex-wrap items-center gap-2.5 font-mono text-2xs leading-3.5 text-foreground-subtle", ), ], [ h.span([], [inputs.tool]), - h.span([h.Class("text-muted-foreground/40")], ["/"]), + h.span([h.Class("text-foreground-faint")], ["/"]), h.span([], ["errors"]), - h.span([h.Class("text-muted-foreground/40")], ["/"]), + h.span([h.Class("text-foreground-faint")], ["/"]), h.span([], [String(position.index + 1), " of ", String(position.total)]), ...(group.errorType === "" ? [] @@ -135,7 +135,7 @@ const headerLead = (h: H, inputs: ModalInputs): Html => { h.span( [ h.Class( - "ml-1 rounded-sm border border-border px-[5px] text-2xs text-muted-foreground/70", + "ml-1 rounded-sm border border-border px-[5px] text-2xs text-foreground-subtle", ), ], ["error.type ", group.errorType], @@ -178,7 +178,7 @@ const headerTrend = (h: H, inputs: ModalInputs): Html => { bucket.unit, ]), h.span( - [h.Class("text-2xs leading-3.5 tabular-nums text-muted-foreground/70")], + [h.Class("text-2xs leading-3.5 tabular-nums text-foreground-subtle")], ["max ", formatToolCount(Math.max(0, ...group.spark))], ), ], @@ -193,7 +193,7 @@ const headerTrend = (h: H, inputs: ModalInputs): Html => { className: "h-11 w-[340px] shrink-0", }), h.div( - [h.Class("flex justify-between font-mono text-2xs leading-3.5 text-muted-foreground/70")], + [h.Class("flex justify-between font-mono text-2xs leading-3.5 text-foreground-subtle")], [ h.span([], [windowRangeLabel(range.startMs, range.startMs, timeZone)]), h.span([], [windowRangeLabel(range.endMs, range.endMs, timeZone)]), diff --git a/apps/web/src/page/agent-sessions/tool/view-errors.ts b/apps/web/src/page/agent-sessions/tool/view-errors.ts index 12d3d03ebe..3ea4120775 100644 --- a/apps/web/src/page/agent-sessions/tool/view-errors.ts +++ b/apps/web/src/page/agent-sessions/tool/view-errors.ts @@ -161,7 +161,7 @@ const errorRow = ( h.span( [ h.Class( - "shrink-0 pl-1.5 text-2xs leading-3.5 text-muted-foreground/70", + "shrink-0 pl-1.5 text-2xs leading-3.5 text-foreground-subtle", ), ], [String(row.variants), " variants"], @@ -171,7 +171,7 @@ const errorRow = ( ], ), h.span( - [h.Class("hidden w-[96px] shrink-0 items-center @min-[720px]/panel:flex")], + [h.Class("hidden w-24 shrink-0 items-center @min-[720px]/panel:flex")], [ miniBars(h, { values: row.spark, @@ -180,7 +180,7 @@ const errorRow = ( floorColor: "var(--input)", minHeight: 18.75, gap: row.spark.length > 12 ? 1 : 4.3, - className: "h-4 w-[92px] shrink-0", + className: "h-4 w-24 shrink-0", }), ], ), @@ -191,13 +191,13 @@ const errorRow = ( tone: { bar: TONE_FILL.crit, text: "text-muted-foreground" }, }), h.span( - [h.Class("w-[76px] shrink-0 text-right font-mono text-xs tabular-nums text-foreground")], + [h.Class("w-20 shrink-0 text-right font-mono text-xs tabular-nums text-foreground")], [formatToolCount(row.calls)], ), h.span( [ h.Class( - "hidden w-[76px] shrink-0 text-right font-mono text-xs tabular-nums text-muted-foreground @min-[640px]/panel:block", + "hidden w-20 shrink-0 text-right font-mono text-xs tabular-nums text-muted-foreground @min-[640px]/panel:block", ), ], [formatToolCount(row.sessions)], @@ -209,10 +209,10 @@ const errorRow = ( nowMs: inputs.nowMs, timeZone: inputs.timeZone, className: - "hidden w-[96px] shrink-0 text-right font-mono text-2xs tabular-nums text-muted-foreground/70 @min-[800px]/panel:block", + "hidden w-24 shrink-0 text-right font-mono text-2xs tabular-nums text-foreground-subtle @min-[800px]/panel:block", }), h.span( - [h.Class("flex w-3.5 shrink-0 items-center justify-end text-muted-foreground/60")], + [h.Class("flex w-3.5 shrink-0 items-center justify-end text-foreground-subtle")], [icon(h, "ChevronRightIcon", { size: 14, attributes: [h.AriaHidden(true)] })], ), ], @@ -225,7 +225,7 @@ const loadingRows = (h: H): ReadonlyArray => h.div( [ h.Key(String(width)), - h.Class("flex h-[38px] items-center gap-3 border-b border-border/60 px-2.5 last:border-0"), + h.Class("flex h-[38px] items-center gap-3 border-b border-border-subtle px-2.5 last:border-0"), h.Style({ opacity: String(1 - index * 0.2) }), ], [ @@ -234,20 +234,20 @@ const loadingRows = (h: H): ReadonlyArray => [skeleton(h, "h-2.5", { width: `${width}px`, "max-width": "100%" })], ), h.span( - [h.Class("hidden w-[96px] shrink-0 @min-[720px]/panel:block")], - [skeleton(h, "h-2.5 w-[92px]")], + [h.Class("hidden w-24 shrink-0 @min-[720px]/panel:block")], + [skeleton(h, "h-2.5 w-24")], ), h.span( - [h.Class("flex w-[150px] shrink-0 justify-end gap-2.5")], + [h.Class("flex w-36 shrink-0 justify-end gap-2.5")], [skeleton(h, "h-1 w-[60px]"), h.span([h.Class("w-[46px]")], [])], ), - h.span([h.Class("flex w-[76px] shrink-0 justify-end")], [skeleton(h, "h-2.5 w-7")]), + h.span([h.Class("flex w-20 shrink-0 justify-end")], [skeleton(h, "h-2.5 w-7")]), h.span( - [h.Class("hidden w-[76px] shrink-0 justify-end @min-[640px]/panel:flex")], + [h.Class("hidden w-20 shrink-0 justify-end @min-[640px]/panel:flex")], [skeleton(h, "h-2.5 w-[22px]")], ), h.span( - [h.Class("hidden w-[96px] shrink-0 justify-end @min-[800px]/panel:flex")], + [h.Class("hidden w-24 shrink-0 justify-end @min-[800px]/panel:flex")], [skeleton(h, "h-2.5 w-11")], ), h.span([h.Class("w-3.5 shrink-0")], []), @@ -259,7 +259,7 @@ const head = (h: H, inputs: ErrorsTableInputs, headHint: string): Html => { const sortable = (label: string, key: string, hidden?: string) => th(h, { label, - width: "w-[76px] shrink-0", + width: "w-20 shrink-0", align: "right", sortKey: key, sort: inputs.sort, @@ -273,20 +273,20 @@ const head = (h: H, inputs: ErrorsTableInputs, headHint: string): Html => { eyebrow(h, { variant: "mono" }, ["Error"]), ...(headHint === "" ? [] - : [truncatedText(h, { text: headHint, className: "text-muted-foreground/60" })]), + : [truncatedText(h, { text: headHint, className: "text-foreground-subtle" })]), ], ), th(h, { label: windowRangeLabel(inputs.range.startMs, inputs.range.endMs, inputs.timeZone), - width: "w-[96px] shrink-0", + width: "w-24 shrink-0", hidden: "hidden @min-[720px]/panel:flex", }), - th(h, { label: "Share", width: "w-[150px] shrink-0 pl-6" }), + th(h, { label: "Share", width: "w-36 shrink-0 pl-6" }), sortable("Count", "calls"), sortable("Sessions", "sessions", "hidden @min-[640px]/panel:flex"), th(h, { label: "Last seen", - width: "w-[96px] shrink-0", + width: "w-24 shrink-0", align: "right", sortKey: "lastSeen", sort: inputs.sort, @@ -303,7 +303,7 @@ const showMore = (h: H, hidden: ReadonlyArray, isExpanded: boolean): H [ h.AriaExpanded(isExpanded), h.Class( - "flex h-[38px] w-full items-center gap-2.5 px-2.5 text-left font-mono text-xs transition-colors hover:bg-muted/50", + "flex h-[38px] w-full items-center gap-2.5 px-2.5 text-left font-mono text-xs transition-colors hover:bg-surface-sunken", ), h.Type("button"), h.OnClick(Message.ToggledErrorsExpanded()), @@ -330,7 +330,7 @@ const showMore = (h: H, hidden: ReadonlyArray, isExpanded: boolean): H ? [] : [ h.span( - [h.Class("text-muted-foreground/70")], + [h.Class("text-foreground-subtle")], [ formatToolCount(hiddenCalls), ` failed ${pluralize(hiddenCalls, "call")}`, @@ -395,11 +395,11 @@ export const errorsTable = (h: H, inputs: ErrorsTableInputs): Html => { [ h.span([h.Class("text-xs font-medium text-foreground")], ["Errors"]), inputs.isLoading - ? skeleton(h, "h-2.5 w-[150px] self-center") + ? skeleton(h, "h-2.5 w-36 self-center") : h.span( [ h.Class( - "text-2xs leading-3.5 tabular-nums text-muted-foreground/70", + "text-2xs leading-3.5 tabular-nums text-foreground-subtle", ), ], [ @@ -487,7 +487,7 @@ export const errorsTable = (h: H, inputs: ErrorsTableInputs): Html => { h.div( [ h.Class( - "flex flex-wrap items-center gap-2 border-t border-border px-2.5 pt-3 font-mono text-2xs leading-3.5 text-muted-foreground/70", + "flex flex-wrap items-center gap-2 border-t border-border px-2.5 pt-3 font-mono text-2xs leading-3.5 text-foreground-subtle", ), ], [ diff --git a/apps/web/src/page/agent-sessions/tool/view-sessions.ts b/apps/web/src/page/agent-sessions/tool/view-sessions.ts index 13eb17b34c..cdd700cf75 100644 --- a/apps/web/src/page/agent-sessions/tool/view-sessions.ts +++ b/apps/web/src/page/agent-sessions/tool/view-sessions.ts @@ -39,7 +39,7 @@ const sessionRow = (h: H, session: SessionRow, tool: string, nowMs: number, time [ h.Key(session.sessionId), h.Class( - "relative flex w-full items-center gap-4 border-b border-border px-3 py-2.5 text-left transition-colors last:border-0 hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none", + "relative flex w-full items-center gap-4 border-b border-border px-3 py-2.5 text-left transition-colors last:border-0 hover:bg-surface-sunken focus-visible:bg-surface-sunken focus-visible:outline-none", ), // `{ ...sessionLinkWindow(session), tool, view }` in that order. h.Href( @@ -84,13 +84,13 @@ const sessionRow = (h: H, session: SessionRow, tool: string, nowMs: number, time h.span( [ h.Class( - "hidden w-[176px] shrink-0 truncate text-xs text-muted-foreground @min-[720px]/panel:block", + "hidden w-44 shrink-0 truncate text-xs text-muted-foreground @min-[720px]/panel:block", ), ], [[session.firstAgentName, ...session.serviceNames].filter((part) => part !== "").join(" · ")], ), h.span( - [h.Class("hidden w-[216px] shrink-0 items-baseline gap-2 @min-[560px]/panel:flex")], + [h.Class("hidden w-56 shrink-0 items-baseline gap-2 @min-[560px]/panel:flex")], [ h.span( [h.Class("font-mono text-ui font-semibold tabular-nums text-foreground")], @@ -108,7 +108,7 @@ const sessionRow = (h: H, session: SessionRow, tool: string, nowMs: number, time ], ), h.span( - [h.Class("hidden w-[140px] shrink-0 @min-[900px]/panel:flex")], + [h.Class("hidden w-36 shrink-0 @min-[900px]/panel:flex")], hasErrors ? [errorCountPill(h, session.errorSpanCount)] : [], ), relativeTime(h, { @@ -152,7 +152,7 @@ export const sessionsPanel = (h: H, inputs: SessionsPanelInputs): Html => ["Sessions running ", inputs.tool], ), h.span( - [h.Class("text-2xs leading-3.5 tabular-nums text-muted-foreground/70")], + [h.Class("text-2xs leading-3.5 tabular-nums text-foreground-subtle")], [countLabel(inputs.rows.length, "session")], ), ], diff --git a/apps/web/src/page/agent-sessions/tools-kit/error-parts.ts b/apps/web/src/page/agent-sessions/tools-kit/error-parts.ts index 32f3bb0ac7..5e8aa81c66 100644 --- a/apps/web/src/page/agent-sessions/tools-kit/error-parts.ts +++ b/apps/web/src/page/agent-sessions/tools-kit/error-parts.ts @@ -99,7 +99,7 @@ export const errorTextHeading = (h: HtmlBuilder, tokens: ReadonlyArray(h: HtmlBuilder, tokens: ReadonlyArray(h: HtmlBuilder, token: ErrorTextToken): Html[] => { switch (token.kind) { case "text": - return [h.span([h.Class("text-foreground/80")], [token.text])] + return [h.span([h.Class("text-foreground-soft")], [token.text])] case "value": return [h.span([h.Class("font-medium text-foreground")], [token.text])] case "mask": return [maskChip(h, token.label, token.raw)] case "at": - return [h.span([h.Class("text-muted-foreground/60")], [" at "])] + return [h.span([h.Class("text-foreground-subtle")], [" at "])] case "break": - return [h.span([h.Class("text-muted-foreground/60")], [" ⏎ "])] + return [h.span([h.Class("text-foreground-subtle")], [" ⏎ "])] case "path": return pathParts(h, token.parts, "font-medium text-foreground") } @@ -215,7 +215,7 @@ export const failureStatusLine = ( [ statusDot(h, { tone: STATUS_TONE[status.kind] }), h.span([h.Class("text-foreground")], [lead]), - ...(detail === undefined ? [] : [h.span([h.Class("text-muted-foreground/70")], [detail])]), + ...(detail === undefined ? [] : [h.span([h.Class("text-foreground-subtle")], [detail])]), ], ) } diff --git a/apps/web/src/page/agent-sessions/tools-kit/metric-strip.ts b/apps/web/src/page/agent-sessions/tools-kit/metric-strip.ts index 1a9a6dd4e2..39f33a6294 100644 --- a/apps/web/src/page/agent-sessions/tools-kit/metric-strip.ts +++ b/apps/web/src/page/agent-sessions/tools-kit/metric-strip.ts @@ -62,7 +62,7 @@ const deltaSubline = (h: HtmlBuilder, change: ToolDelta | null, windowLabe ? null : sublineText(h, [ deltaValue(h, change), - h.span([h.Class("text-muted-foreground/60")], ["vs prev ", windowLabel]), + h.span([h.Class("text-foreground-subtle")], ["vs prev ", windowLabel]), ]) export type MetricStripConfig = Readonly<{ @@ -93,7 +93,7 @@ export const metricStrip = (h: HtmlBuilder, config: MetricStripConfig): : sublineText(h, [ h.span([], [formatPercent(share)]), h.span( - [h.Class("text-muted-foreground/60")], + [h.Class("text-foreground-subtle")], ["of all ", formatToolCount(config.allSessions), " sessions"], ), ]), diff --git a/apps/web/src/page/agent-sessions/tools-kit/scope-row.ts b/apps/web/src/page/agent-sessions/tools-kit/scope-row.ts index c64ccb5838..577423ba1a 100644 --- a/apps/web/src/page/agent-sessions/tools-kit/scope-row.ts +++ b/apps/web/src/page/agent-sessions/tools-kit/scope-row.ts @@ -54,7 +54,7 @@ export const scopeRow = (h: HtmlBuilder, config: ScopeRowConfig): Html [ eyebrow(h, { variant: "mono" }, ["Scope"]), ...(config.chips.length === 0 - ? [h.span([h.Class("text-2xs text-muted-foreground/60")], ["all tools · all models"])] + ? [h.span([h.Class("text-2xs text-foreground-subtle")], ["all tools · all models"])] : [ ...config.chips.map((chip) => chipButton(h, chip, config.onRemove(chip))), button( diff --git a/apps/web/src/page/agent-sessions/tools-kit/series-chart.ts b/apps/web/src/page/agent-sessions/tools-kit/series-chart.ts index c36542f6cd..e4f4c5477e 100644 --- a/apps/web/src/page/agent-sessions/tools-kit/series-chart.ts +++ b/apps/web/src/page/agent-sessions/tools-kit/series-chart.ts @@ -174,7 +174,7 @@ export const seriesChart = ( h.span( [ h.AriaHidden(true), - h.Class("text-xs text-muted-foreground/60"), + h.Class("text-xs text-foreground-subtle"), ], ["·"], ), @@ -199,7 +199,7 @@ export const seriesChart = ( ] : []), h.span( - [h.Class("font-mono text-2xs text-muted-foreground/60")], + [h.Class("font-mono text-2xs text-foreground-subtle")], bucketMs === null ? [] : [`${bucketLabel(bucketMs)} buckets`], ), ], diff --git a/apps/web/src/page/agent-sessions/tools-kit/table.ts b/apps/web/src/page/agent-sessions/tools-kit/table.ts index b9b226fc6d..236c3c186a 100644 --- a/apps/web/src/page/agent-sessions/tools-kit/table.ts +++ b/apps/web/src/page/agent-sessions/tools-kit/table.ts @@ -131,17 +131,17 @@ export const toolTableBody = ( ) const ROW = - "flex h-[38px] w-full shrink-0 items-center gap-3 border-b border-border/60 px-2.5 text-left transition-colors last:border-0 focus-visible:outline-none" + "flex h-[38px] w-full shrink-0 items-center gap-3 border-b border-border-subtle px-2.5 text-left transition-colors last:border-0 focus-visible:outline-none" export const toolRowClass = (isSelected: boolean): string => - cn(ROW, rowSelectedClass(isSelected), !isSelected && "hover:bg-muted/50 focus-visible:bg-muted/50") + cn(ROW, rowSelectedClass(isSelected), !isSelected && "hover:bg-surface-sunken focus-visible:bg-surface-sunken") export const toolTableFooter = (h: HtmlBuilder, subject: string, detail: string): Html => h.div( [h.Class("flex h-9 items-center gap-[9px] px-2.5 font-mono text-xs")], [ h.span([h.Class("text-muted-foreground")], [subject]), - h.span([h.Class("text-muted-foreground/60")], [detail]), + h.span([h.Class("text-foreground-subtle")], [detail]), ], ) @@ -164,7 +164,7 @@ export const shareCell = ( }>, ): Html => h.span( - [h.Class("flex w-[150px] shrink-0 items-center justify-end gap-2.5")], + [h.Class("flex w-36 shrink-0 items-center justify-end gap-2.5")], [ meter(h, { value: options.ratio, diff --git a/apps/web/src/page/agent-sessions/tools-kit/toolbar.ts b/apps/web/src/page/agent-sessions/tools-kit/toolbar.ts index 7bf1cbfcc9..cef7cea8b0 100644 --- a/apps/web/src/page/agent-sessions/tools-kit/toolbar.ts +++ b/apps/web/src/page/agent-sessions/tools-kit/toolbar.ts @@ -80,7 +80,7 @@ const nameSearchInput = (h: HtmlBuilder, search: NonNullable { }) return toolTableHead(h, [ sortable("Tool", "w-0 flex-1 min-w-0", "key"), - th(h, { label: "Volume", width: "w-[110px] shrink-0", hidden: "hidden @min-[720px]/panel:flex" }), - sortable("Calls", "w-[76px] shrink-0", "calls", "right"), - sortable("P50", "w-[76px] shrink-0", "p50", "right", "hidden @min-[900px]/panel:flex"), - sortable("P90", "w-[76px] shrink-0", "p90", "right"), - sortable("P95", "w-[76px] shrink-0", "p95", "right", "hidden @min-[900px]/panel:flex"), - sortable("Error rate", "w-[150px] shrink-0 pl-6", "errorRate"), - sortable("Errors", "w-[76px] shrink-0", "errors", "right", "hidden @min-[640px]/panel:flex"), - sortable("Sessions", "w-[76px] shrink-0", "sessions", "right", "hidden @min-[640px]/panel:flex"), - sortable("Last call", "w-[96px] shrink-0", "lastSeen", "right", "hidden @min-[800px]/panel:flex"), + th(h, { label: "Volume", width: "w-28 shrink-0", hidden: "hidden @min-[720px]/panel:flex" }), + sortable("Calls", "w-20 shrink-0", "calls", "right"), + sortable("P50", "w-20 shrink-0", "p50", "right", "hidden @min-[900px]/panel:flex"), + sortable("P90", "w-20 shrink-0", "p90", "right"), + sortable("P95", "w-20 shrink-0", "p95", "right", "hidden @min-[900px]/panel:flex"), + sortable("Error rate", "w-36 shrink-0 pl-6", "errorRate"), + sortable("Errors", "w-20 shrink-0", "errors", "right", "hidden @min-[640px]/panel:flex"), + sortable("Sessions", "w-20 shrink-0", "sessions", "right", "hidden @min-[640px]/panel:flex"), + sortable("Last call", "w-24 shrink-0", "lastSeen", "right", "hidden @min-[800px]/panel:flex"), h.span([h.AriaHidden(true), h.Class("w-3.5 shrink-0")], []), ]) } @@ -99,8 +99,8 @@ const duration = (h: H, value: number, isDriving: boolean, hidden?: string): Htm [ h.Class( cn( - "w-[76px] shrink-0 text-right font-mono text-xs tabular-nums", - isDriving ? "text-foreground/80" : "text-muted-foreground", + "w-20 shrink-0 text-right font-mono text-xs tabular-nums", + isDriving ? "text-foreground-soft" : "text-muted-foreground", hidden, ), ), @@ -140,7 +140,7 @@ const cells = (h: H, row: Prepared, inputs: ToolsTableInputs, maxErrorRate: numb ], ), h.span( - [h.Class("hidden h-[22px] w-[110px] shrink-0 @min-[720px]/panel:block")], + [h.Class("hidden h-[22px] w-28 shrink-0 @min-[720px]/panel:block")], [ h.submodel({ slotId: `tool-spark-${row.key}`, @@ -160,7 +160,7 @@ const cells = (h: H, row: Prepared, inputs: ToolsTableInputs, maxErrorRate: numb ], ), h.span( - [h.Class("w-[76px] shrink-0 text-right font-mono text-xs tabular-nums text-foreground")], + [h.Class("w-20 shrink-0 text-right font-mono text-xs tabular-nums text-foreground")], [formatToolCount(row.calls)], ), duration(h, row.p50, inputs.percentile === "p50", "hidden @min-[900px]/panel:block"), @@ -176,9 +176,9 @@ const cells = (h: H, row: Prepared, inputs: ToolsTableInputs, maxErrorRate: numb [ h.Class( cn( - "hidden w-[76px] shrink-0 text-right font-mono text-xs tabular-nums @min-[640px]/panel:block", + "hidden w-20 shrink-0 text-right font-mono text-xs tabular-nums @min-[640px]/panel:block", // The count takes the rate's tone, so one threshold colours both. - row.errors > 0 ? errorTone(row.errorRate).text : "text-muted-foreground/60", + row.errors > 0 ? errorTone(row.errorRate).text : "text-foreground-subtle", ), ), ], @@ -187,7 +187,7 @@ const cells = (h: H, row: Prepared, inputs: ToolsTableInputs, maxErrorRate: numb h.span( [ h.Class( - "hidden w-[76px] shrink-0 text-right font-mono text-xs tabular-nums text-muted-foreground @min-[640px]/panel:block", + "hidden w-20 shrink-0 text-right font-mono text-xs tabular-nums text-muted-foreground @min-[640px]/panel:block", ), ], [formatToolCount(row.sessions)], @@ -199,10 +199,10 @@ const cells = (h: H, row: Prepared, inputs: ToolsTableInputs, maxErrorRate: numb nowMs: inputs.nowMs, timeZone: inputs.timeZone, className: - "hidden w-[96px] shrink-0 text-right font-mono text-2xs tabular-nums text-muted-foreground/70 @min-[800px]/panel:block", + "hidden w-24 shrink-0 text-right font-mono text-2xs tabular-nums text-foreground-subtle @min-[800px]/panel:block", }), h.span( - [h.Class("flex w-3.5 shrink-0 items-center justify-end text-muted-foreground/60")], + [h.Class("flex w-3.5 shrink-0 items-center justify-end text-foreground-subtle")], row.key === "" ? [] : [icon(h, "ChevronRightIcon", { size: 14, attributes: [h.AriaHidden(true)] })], @@ -253,7 +253,7 @@ export const toolsTable = (h: H, inputs: ToolsTableInputs): Html => [ h.span([h.Class("text-xs font-medium text-foreground")], ["Tools"]), h.span( - [h.Class("text-2xs leading-3.5 tabular-nums text-muted-foreground/70")], + [h.Class("text-2xs leading-3.5 tabular-nums text-foreground-subtle")], [formatToolCount(inputs.rows.length)], ), ], diff --git a/apps/web/src/page/alerts/destination/chat-fields-view.ts b/apps/web/src/page/alerts/destination/chat-fields-view.ts index 0540bf1ad0..a2c06627a5 100644 --- a/apps/web/src/page/alerts/destination/chat-fields-view.ts +++ b/apps/web/src/page/alerts/destination/chat-fields-view.ts @@ -123,7 +123,7 @@ export const chatFields = (h: HtmlBuilder, inputs: Inputs): Html => { const { model, form } = inputs if (form.chatWorkspaceId === null) return h.div( - [h.Class("space-y-2 rounded-md border border-dashed border-border/60 p-3")], + [h.Class("space-y-2 rounded-md border border-dashed border-border-subtle p-3")], [ h.p( [h.Class("text-xs text-muted-foreground")], diff --git a/apps/web/src/page/alerts/destination/hazel-fields-view.ts b/apps/web/src/page/alerts/destination/hazel-fields-view.ts index ea5922db05..a195927966 100644 --- a/apps/web/src/page/alerts/destination/hazel-fields-view.ts +++ b/apps/web/src/page/alerts/destination/hazel-fields-view.ts @@ -72,7 +72,7 @@ const isFailed = (data: AsyncData.AsyncData) => const connectPanel = (h: HtmlBuilder, inputs: Inputs): Html => { const accent = providerOf("hazel-oauth") return h.div( - [h.Class("space-y-2 rounded-md border border-dashed border-border/60 p-3")], + [h.Class("space-y-2 rounded-md border border-dashed border-border-subtle p-3")], [ ...(isFailed(inputs.model.status.data) ? [ diff --git a/apps/web/src/page/alerts/destination/linear-fields-view.ts b/apps/web/src/page/alerts/destination/linear-fields-view.ts index 0ccdefcc1b..98a51ebf30 100644 --- a/apps/web/src/page/alerts/destination/linear-fields-view.ts +++ b/apps/web/src/page/alerts/destination/linear-fields-view.ts @@ -72,7 +72,7 @@ const connectNote = (h: HtmlBuilder, inputs: Inputs, isRevoked: boolean const accent = providerOf("linear") const isAdmin = model.isAdmin === true return h.div( - [h.Class("space-y-2 rounded-md border border-dashed border-border/60 p-3")], + [h.Class("space-y-2 rounded-md border border-dashed border-border-subtle p-3")], [ h.p( [h.Class("text-xs text-muted-foreground")], diff --git a/apps/web/src/page/alerts/destination/view.ts b/apps/web/src/page/alerts/destination/view.ts index c3997d1ba5..d2a60416d7 100644 --- a/apps/web/src/page/alerts/destination/view.ts +++ b/apps/web/src/page/alerts/destination/view.ts @@ -114,8 +114,8 @@ const providerTile = ( cn( "relative flex flex-col items-start gap-2 overflow-hidden rounded-md border p-3 text-left transition-colors", options.isSelected - ? "border-(--tile-accent) bg-muted/40" - : "border-border/60 bg-card hover:border-border hover:bg-muted/50", + ? "border-(--tile-accent) bg-surface-sunken" + : "border-border-subtle bg-card hover:border-border hover:bg-surface-sunken", ), ), h.Style({ "--tile-accent": provider.accent }), @@ -464,7 +464,7 @@ const telegramFields = (h: H, model: Model, isEditing: boolean): ReadonlyArray 0 ? [ h.div( - [h.Class("space-y-1 rounded-md border border-border/60 p-1")], + [h.Class("space-y-1 rounded-md border border-border-subtle p-1")], model.telegramChats.map((chat) => h.button( [ @@ -472,7 +472,7 @@ const telegramFields = (h: H, model: Model, isEditing: boolean): ReadonlyArray description: "destination-enabled-description", }, framed: true, - className: "border-border/60 bg-card px-4 py-3", + className: "border-border-subtle bg-card px-4 py-3", label: "Enabled", description: "Disabled destinations stay attached to rules but won't receive notifications.", diff --git a/apps/web/src/page/alerts/editor/view-condition.ts b/apps/web/src/page/alerts/editor/view-condition.ts index 861432851a..2ef5fa9c21 100644 --- a/apps/web/src/page/alerts/editor/view-condition.ts +++ b/apps/web/src/page/alerts/editor/view-condition.ts @@ -87,7 +87,7 @@ const severityPicker = (h: H, value: AlertSeverity): Html => { h.div( [ h.AriaLabelledBy("rule-severity-label"), - h.Class("grid grid-cols-2 gap-1 rounded-md bg-muted/30 p-0.5"), + h.Class("grid grid-cols-2 gap-1 rounded-md bg-surface-sunken p-0.5"), h.DataAttribute("filled", ""), h.Role("radiogroup"), ], @@ -102,7 +102,7 @@ const severityPicker = (h: H, value: AlertSeverity): Html => { "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", isSelected ? option.selected - : "text-muted-foreground hover:bg-muted/40 hover:text-foreground", + : "text-muted-foreground hover:bg-surface-sunken hover:text-foreground", ), { children: [ @@ -269,7 +269,7 @@ const intervalPicker = ( [ h.AriaLabelledBy("rule-interval-label"), h.Class( - "grid grid-cols-[repeat(auto-fill,minmax(5.5rem,1fr))] gap-1 rounded-md bg-muted/30 p-0.5", + "grid grid-cols-[repeat(auto-fill,minmax(5.5rem,1fr))] gap-1 rounded-md bg-surface-sunken p-0.5", ), h.DataAttribute("filled", ""), h.Role("radiogroup"), @@ -288,8 +288,8 @@ const intervalPicker = ( ? isBlocked ? "border-severity-warn/60 bg-severity-warn/10 text-severity-warn" : "border-primary/50 bg-primary/10 text-foreground" - : "text-muted-foreground hover:bg-muted/40 hover:text-foreground", - !isSelected && isBlocked && "text-muted-foreground/60", + : "text-muted-foreground hover:bg-surface-sunken hover:text-foreground", + !isSelected && isBlocked && "text-foreground-subtle", ), { children: [ diff --git a/apps/web/src/page/alerts/editor/view-details.ts b/apps/web/src/page/alerts/editor/view-details.ts index 4088b49e80..160257e893 100644 --- a/apps/web/src/page/alerts/editor/view-details.ts +++ b/apps/web/src/page/alerts/editor/view-details.ts @@ -67,7 +67,7 @@ const tagInput = (h: H, model: DetailsView, form: RuleForm): Html => { h.OnBlur(Message.BlurredTagInput()), ...(form.tags.length === 0 ? [h.Placeholder("prod, payments, team-checkout…")] : []), h.Class( - "min-w-[80px] flex-1 bg-transparent leading-6 outline-none placeholder:text-muted-foreground/70", + "min-w-[80px] flex-1 bg-transparent leading-6 outline-none placeholder:text-foreground-subtle", ), ]), ...(available.length > 0 @@ -127,7 +127,7 @@ const notes = (h: H, model: DetailsView, form: RuleForm): Html => { h.Type("button"), h.OnClick(Message.ClickedAddNotes()), h.Class( - "flex w-full items-center gap-1.5 rounded-md border border-dashed border-border/60 px-3 py-1.5 text-left text-xs text-muted-foreground hover:border-border hover:text-foreground", + "flex w-full items-center gap-1.5 rounded-md border border-dashed border-border-subtle px-3 py-1.5 text-left text-xs text-muted-foreground hover:border-border hover:text-foreground", ), ], [icon(h, "PlusIcon", { size: 12 }), "Add notes"], diff --git a/apps/web/src/page/alerts/editor/view-impact.ts b/apps/web/src/page/alerts/editor/view-impact.ts index a096f5ec4f..898675a0c9 100644 --- a/apps/web/src/page/alerts/editor/view-impact.ts +++ b/apps/web/src/page/alerts/editor/view-impact.ts @@ -117,7 +117,7 @@ export const editImpact = (h: H, model: ImpactView, form: RuleForm): Html => { [h.Class("flex flex-wrap gap-1.5 text-xs")], changes.map((change) => h.li( - [h.Key(change.field), h.Class("rounded-sm border bg-muted/30 px-2 py-1")], + [h.Key(change.field), h.Class("rounded-sm border bg-surface-sunken px-2 py-1")], [ h.span([h.Class("text-muted-foreground")], [change.field, " "]), h.span( @@ -213,7 +213,7 @@ const fireRail = ( h.span([h.Class("text-right text-2xs text-muted-foreground")], [label]), h.div( [ - h.Class("relative h-2 rounded-sm bg-muted/50"), + h.Class("relative h-2 rounded-sm bg-surface-sunken"), h.AriaLabel(`${label}: ${marks.length} alerts`), ], marks.map((mark) => diff --git a/apps/web/src/page/alerts/editor/view-notify.ts b/apps/web/src/page/alerts/editor/view-notify.ts index 474cc03d99..9d9fb4ca7a 100644 --- a/apps/web/src/page/alerts/editor/view-notify.ts +++ b/apps/web/src/page/alerts/editor/view-notify.ts @@ -180,9 +180,9 @@ const addMenu = ( h.Type("button"), h.Class( cn( - "flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground", + "flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-muted-foreground transition-colors hover:bg-surface-sunken hover:text-foreground", // Open, Base UI's guards follow the trigger, so the panel's divider lands on it. - menu.isOpen && "border-b border-border/60", + menu.isOpen && "border-b border-border-subtle", ), ), h.DataAttribute("slot", "dropdown-menu-trigger"), @@ -221,7 +221,7 @@ export const destinationList = ( const available = destinations.filter((d) => !ids.includes(d.id)) const unresolved = ids.filter((id) => !destinations.some((d) => d.id === id)) const canAdd = available.length > 0 || model.isAdmin - return panel(h, { className: "mt-3 divide-y divide-border/60 border-border/60" }, [ + return panel(h, { className: "mt-3 divide-y divide-border-subtle border-border-subtle" }, [ ...selected.map((destination) => selectedRow(h, model, tier, destination)), ...unresolved.map((id) => unresolvedRow(h, tier, id)), ...(selected.length === 0 && unresolved.length === 0 diff --git a/apps/web/src/page/alerts/editor/view-query.ts b/apps/web/src/page/alerts/editor/view-query.ts index d7b87ab30e..79d0b2b1d4 100644 --- a/apps/web/src/page/alerts/editor/view-query.ts +++ b/apps/web/src/page/alerts/editor/view-query.ts @@ -59,8 +59,8 @@ const BUILTIN_SIGNALS: ReadonlyArray<{ const SIGNAL_CLASS = cn( "group flex cursor-pointer flex-col items-start gap-0.5 border-b-2 border-transparent px-3 py-2.5 text-left", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset", - "data-[checked]:border-primary data-[checked]:bg-muted/40", - "[&:not([data-checked])]:hover:bg-muted/20", + "data-[checked]:border-primary data-[checked]:bg-surface-sunken", + "[&:not([data-checked])]:hover:bg-surface-faint", ) const signalRadios = (h: H, form: RuleForm): Html => { diff --git a/apps/web/src/page/alerts/editor/view-sql.ts b/apps/web/src/page/alerts/editor/view-sql.ts index 7338a63858..450e1339db 100644 --- a/apps/web/src/page/alerts/editor/view-sql.ts +++ b/apps/web/src/page/alerts/editor/view-sql.ts @@ -44,7 +44,7 @@ const REDUCER_OPTIONS = Object.entries(RAW_QUERY_REDUCER_LABELS).map(([value, la const header = (h: H, model: SqlView, sql: string): Html => { const issue = rawSqlIssue(sql) return h.div( - [h.Class("flex items-center gap-2 px-3 py-2 bg-muted/30")], + [h.Class("flex items-center gap-2 px-3 py-2 bg-surface-sunken")], [ iconButton( h, @@ -63,7 +63,7 @@ const header = (h: H, model: SqlView, sql: string): Html => { cn( badgeVariants({ variant: "outline", - className: cn("font-mono text-2xs text-white border-0 shrink-0 bg-primary/80"), + className: cn("font-mono text-2xs text-primary-foreground border-0 shrink-0 bg-primary/80"), }), ), ), @@ -135,7 +135,7 @@ const macros = (h: H): Html => variant: "ghost", size: "xs", className: - "h-auto rounded-sm bg-muted/40 px-2 py-0.5 font-mono text-2xs text-muted-foreground hover:bg-muted hover:text-foreground sm:h-auto sm:text-2xs", + "h-auto rounded-sm bg-surface-sunken px-2 py-0.5 font-mono text-2xs text-muted-foreground hover:bg-muted hover:text-foreground sm:h-auto sm:text-2xs", attributes: [h.OnClick(Message.ClickedSqlToken({ token }))], }, [token], @@ -181,7 +181,7 @@ const queryTimeMeter = (h: H, form: RuleForm, timing: AlertQueryTiming): Html => const fill = elapsed === null ? 1 : Math.min(elapsed / timing.probeLimitMs, 1) const shortest = shortestFittingInterval(form, timing) return h.div( - [h.Class("space-y-1.5 rounded-md border px-3 py-2.5"), h.DataAttribute("testid", "query-time-meter")], + [h.Class("space-y-1.5 rounded-md border p-3"), h.DataAttribute("testid", "query-time-meter")], [ h.div( [h.Class("flex items-baseline justify-between gap-3 text-xs")], diff --git a/apps/web/src/page/alerts/hub/view-empty.ts b/apps/web/src/page/alerts/hub/view-empty.ts index c04635f942..97497114a1 100644 --- a/apps/web/src/page/alerts/hub/view-empty.ts +++ b/apps/web/src/page/alerts/hub/view-empty.ts @@ -129,7 +129,7 @@ const templateTile = (h: HtmlBuilder, template: AlertTemplate, serviceName h.Class( cn( "group flex flex-col gap-1.5 rounded-md border bg-card p-3 text-left transition-colors", - "hover:bg-accent/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", + "hover:bg-accent/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background", tone?.hoverBorder, ), ), @@ -156,7 +156,7 @@ const svgAttrs = (h: HtmlBuilder, entries: Readonly /** `QuietMonitor`: a steady signal below the dashed threshold a rule would place. */ const quietMonitor = (h: HtmlBuilder): Html => h.div( - [h.Class("relative w-full max-w-[300px] overflow-hidden rounded-md border bg-card/50 px-4 py-3")], + [h.Class("relative w-full max-w-[300px] overflow-hidden rounded-md border bg-card/50 p-4")], [ h.svg( svgAttrs(h, { diff --git a/apps/web/src/page/alerts/hub/view-inbox.ts b/apps/web/src/page/alerts/hub/view-inbox.ts index 6ccda6a8b4..418eefd79b 100644 --- a/apps/web/src/page/alerts/hub/view-inbox.ts +++ b/apps/web/src/page/alerts/hub/view-inbox.ts @@ -155,7 +155,7 @@ const openIncidentRow = (h: HtmlBuilder, incident: AlertIncidentDocument, const isHeld = incident.holdReason !== null const tone = incident.severity === "critical" ? "text-severity-error" : "text-severity-warn" return h.li( - [h.Key(incident.id), h.Class(cn(INCIDENT_GRID, "relative px-4 py-3 hover:bg-muted/50"))], + [h.Key(incident.id), h.Class(cn(INCIDENT_GRID, "relative px-4 py-3 hover:bg-surface-sunken"))], [ h.span([ h.AriaHidden(true), @@ -316,7 +316,7 @@ const fireLaneRow = (h: HtmlBuilder, lane: FireLane): Html => [lane.ruleName], ), h.div( - [h.Class("relative h-2.5 rounded-xs bg-muted/60")], + [h.Class("relative h-2.5 rounded-xs bg-surface-strong")], lane.bars.map((bar) => h.span([ h.Key(bar.id), @@ -381,7 +381,7 @@ const blindSpotRow = (h: HtmlBuilder, spot: BlindSpot): Html => { [ h.Key(spot.rule.id), h.Class( - "group relative grid grid-cols-[72px_minmax(0,1fr)_auto] items-center gap-4 py-2.5 hover:bg-muted/50", + "group relative grid grid-cols-[72px_minmax(0,1fr)_auto] items-center gap-4 py-2.5 hover:bg-surface-sunken", ), ], [ @@ -466,7 +466,7 @@ const headroomRow = (h: HtmlBuilder, row: RuleHeadroom, now: number): Html const isNear = closeness !== null && closeness >= 0.75 const isFloor = rule.comparator === "lt" || rule.comparator === "lte" return h.li( - [h.Key(rule.id), h.Class(cn(HEADROOM_GRID, "relative py-2.5 hover:bg-muted/50"))], + [h.Key(rule.id), h.Class(cn(HEADROOM_GRID, "relative py-2.5 hover:bg-surface-sunken"))], [ h.div( [h.Class("min-w-0")], @@ -491,7 +491,7 @@ const headroomRow = (h: HtmlBuilder, row: RuleHeadroom, now: number): Html ], ), h.div( - [h.Class("relative h-2 rounded-xs bg-muted/60"), h.AriaHidden(true)], + [h.Class("relative h-2 rounded-xs bg-surface-strong"), h.AriaHidden(true)], [ ...(closeness !== null ? [ diff --git a/apps/web/src/page/alerts/hub/view-routing.ts b/apps/web/src/page/alerts/hub/view-routing.ts index e319470690..a71a3abb6e 100644 --- a/apps/web/src/page/alerts/hub/view-routing.ts +++ b/apps/web/src/page/alerts/hub/view-routing.ts @@ -373,11 +373,11 @@ const logTable = ( return table(h, {}, [ tableHeader(h, [ tableRow(h, [ - tableHead(h, ["Status"], "w-[150px]"), - tableHead(h, ["Event"], "w-[128px]"), - tableHead(h, ["Destination"], "w-[240px]"), + tableHead(h, ["Status"], "w-36"), + tableHead(h, ["Event"], "w-32"), + tableHead(h, ["Destination"], "w-60"), tableHead(h, ["Detail"]), - tableHead(h, ["Time"], "w-[88px] text-right"), + tableHead(h, ["Time"], "w-24 text-right"), ]), ]), tableBody( @@ -386,7 +386,7 @@ const logTable = ( tableRow(h, [ h.td( [ - h.Attribute("class", cn(tableCellStyles, "bg-muted/30 py-1.5")), + h.Attribute("class", cn(tableCellStyles, "bg-surface-sunken py-1.5")), h.Attribute("colspan", "5"), h.DataAttribute("slot", "table-cell"), ], @@ -394,7 +394,7 @@ const logTable = ( eyebrow(h, { className: "flex items-center gap-2" }, [ group.label, h.span( - [h.Class("tracking-normal normal-case text-muted-foreground/60 tabular-nums")], + [h.Class("tracking-normal normal-case text-foreground-subtle tabular-nums")], [String(group.events.length), " ", pluralize(group.events.length, "attempt")], ), ]), diff --git a/apps/web/src/page/alerts/hub/view-rules.ts b/apps/web/src/page/alerts/hub/view-rules.ts index 6e478db639..0801cadda7 100644 --- a/apps/web/src/page/alerts/hub/view-rules.ts +++ b/apps/web/src/page/alerts/hub/view-rules.ts @@ -212,7 +212,7 @@ export const rulesTab = (h: H, model: Model, inputs: RulesTabInputs): Html => { [h.Key(group.key), h.Class("border-b last:border-b-0")], [ h.div( - [h.Class("border-b bg-muted/30 px-4 py-2 text-xs")], + [h.Class("border-b bg-surface-sunken px-4 py-2 text-xs")], [ h.span( [h.Class("font-medium")], @@ -305,7 +305,7 @@ const ruleRow = (h: H, model: Model, row: RowInputs): Html => { }, ] return h.li( - [h.Key(rule.id), h.Class(cn(ROW_GRID, "relative px-4 py-3 hover:bg-muted/50"))], + [h.Key(rule.id), h.Class(cn(ROW_GRID, "relative px-4 py-3 hover:bg-surface-sunken"))], [ statusDot(h, { tone: BUCKET_TONE.get(row.bucket) ?? "neutral", size: "lg" }), h.div( diff --git a/apps/web/src/page/alerts/hub/view-uptime.ts b/apps/web/src/page/alerts/hub/view-uptime.ts index 58c70b07d1..59ad46c541 100644 --- a/apps/web/src/page/alerts/hub/view-uptime.ts +++ b/apps/web/src/page/alerts/hub/view-uptime.ts @@ -232,7 +232,7 @@ const monitorRow = (h: H, model: Model, monitor: UptimeMonitor, nowMs: number): const isPaused = displayStatus(monitor) === "paused" const recent = monitor.state.recent return h.li( - [h.Key(monitor.id), h.Class("relative py-3 pr-2 pl-4 hover:bg-muted/25")], + [h.Key(monitor.id), h.Class("relative py-3 pr-2 pl-4 hover:bg-surface-faint")], [ h.div( [h.Class(ROW_GRID)], @@ -291,7 +291,7 @@ const namespaceLabel = (h: H, namespace: string): Html => const groupHeader = (h: H, [namespace, monitors]: MonitorGroup): Html => h.li( - [h.Key(`ns-${namespace}`), h.Class("flex items-center gap-2 bg-muted/50 py-2 pr-2 pl-4")], + [h.Key(`ns-${namespace}`), h.Class("flex items-center gap-2 bg-surface-sunken py-2 pr-2 pl-4")], [ namespaceLabel(h, namespace), h.span([h.Class("text-xs text-muted-foreground")], [countLabel(monitors.length, "monitor")]), diff --git a/apps/web/src/page/alerts/incident/view-timeline.ts b/apps/web/src/page/alerts/incident/view-timeline.ts index 63ef56a523..2d72ca6d48 100644 --- a/apps/web/src/page/alerts/incident/view-timeline.ts +++ b/apps/web/src/page/alerts/incident/view-timeline.ts @@ -30,7 +30,7 @@ export const incidentTimeline = ( [ eyebrow(h, { as: "h2" }, ["Timeline"]), h.ol( - [h.Class("divide-y divide-border/60 border-t border-border/60")], + [h.Class("divide-y divide-border-subtle border-t border-border-subtle")], [ ...options.entries.map((entry) => entryRow(h, entry, firstAt, timeZone)), ...(options.isLoading ? [h.li([h.Class("py-3")], [skeleton(h, "h-4 w-2/3")])] : []), @@ -90,7 +90,7 @@ const entryRow = ( ...(entry.investigation ? [ h.div( - [h.Class("mt-2 space-y-2 rounded-md border bg-muted/30 px-3 py-2.5")], + [h.Class("mt-2 space-y-2 rounded-md border bg-surface-sunken p-3")], [ ...(entry.investigation.headline ? [ diff --git a/apps/web/src/page/alerts/rule/view-checks.ts b/apps/web/src/page/alerts/rule/view-checks.ts index cefcf6e355..ba8b8156d0 100644 --- a/apps/web/src/page/alerts/rule/view-checks.ts +++ b/apps/web/src/page/alerts/rule/view-checks.ts @@ -208,12 +208,12 @@ export const checksPanel = (h: H, model: Model, inputs: ChecksPanelInputs): Html table(h, {}, [ tableHeader(h, [ tableRow(h, [ - tableHead(h, ["Time"], "w-[170px]"), - tableHead(h, ["Status"], "w-[110px]"), + tableHead(h, ["Time"], "w-44"), + tableHead(h, ["Status"], "w-28"), tableHead(h, ["Value / threshold"]), - tableHead(h, ["Samples"], "w-[90px]"), - ...(isGrouped ? [tableHead(h, ["Group"], "w-[160px]")] : []), - tableHead(h, ["Incident"], "w-[140px]"), + tableHead(h, ["Samples"], "w-24"), + ...(isGrouped ? [tableHead(h, ["Group"], "w-40")] : []), + tableHead(h, ["Incident"], "w-36"), ]), ]), tableBody( @@ -231,7 +231,7 @@ export const checksPanel = (h: H, model: Model, inputs: ChecksPanelInputs): Html h.Attribute("colspan", isGrouped ? "6" : "5"), h.Attribute( "class", - cn(tableCellStyles, "bg-muted/40 py-1.5 text-2xs text-muted-foreground"), + cn(tableCellStyles, "bg-surface-sunken py-1.5 text-2xs text-muted-foreground"), ), h.DataAttribute("slot", "table-cell"), ], @@ -321,7 +321,7 @@ const checkRow = (h: H, rule: AlertRuleDocument, check: AlertCheckDocument, isGr [formatSignalValue(rule.signalType, check.observedValue)], ), h.span( - [h.Class("font-mono text-xs text-muted-foreground/60 tabular-nums")], + [h.Class("font-mono text-xs text-foreground-subtle tabular-nums")], ["/", " ", formatSignalValue(rule.signalType, check.threshold)], ), ...checkDelta(h, rule, check.observedValue, check.threshold, check.status === "breached"), diff --git a/apps/web/src/page/alerts/rule/view-diagnosis.ts b/apps/web/src/page/alerts/rule/view-diagnosis.ts index c0b7782c64..a122489911 100644 --- a/apps/web/src/page/alerts/rule/view-diagnosis.ts +++ b/apps/web/src/page/alerts/rule/view-diagnosis.ts @@ -230,7 +230,7 @@ const stageRow = (h: H, model: Model, stage: DiagnosisStage): Html => { { variant: "link", size: "xs", - className: "text-muted-foreground/80 hover:text-foreground", + className: "text-foreground-subtle hover:text-foreground", attributes: [h.OnClick(Message.ClickedShowAllEvidence({ stageId: stage.id }))], }, ["+", String(hiddenEvidence), " more"], diff --git a/apps/web/src/page/alerts/rule/view-history.ts b/apps/web/src/page/alerts/rule/view-history.ts index a8a9c471df..abc68e851a 100644 --- a/apps/web/src/page/alerts/rule/view-history.ts +++ b/apps/web/src/page/alerts/rule/view-history.ts @@ -159,12 +159,12 @@ export const historyTab = ( : table(h, {}, [ tableHeader(h, [ tableRow(h, [ - tableHead(h, ["State"], "w-[100px]"), - tableHead(h, ["Group"], "w-[180px]"), + tableHead(h, ["State"], "w-24"), + tableHead(h, ["Group"], "w-44"), tableHead(h, ["Labels"]), - tableHead(h, ["Triggered at"], "w-[180px]"), - tableHead(h, ["Duration"], "w-[110px]"), - tableHead(h, ["Issue"], "w-[70px]"), + tableHead(h, ["Triggered at"], "w-44"), + tableHead(h, ["Duration"], "w-28"), + tableHead(h, ["Issue"], "w-16"), tableHead(h, [], "w-[50px]"), ]), ]), @@ -240,7 +240,7 @@ const incidentRow = ( ], ["View"], ) - : h.span([h.Class("text-xs text-muted-foreground/60")], [EMPTY_VALUE]), + : h.span([h.Class("text-xs text-foreground-subtle")], [EMPTY_VALUE]), ]), tableCell(h, [ h.div( diff --git a/apps/web/src/page/alerts/rule/view-overview.ts b/apps/web/src/page/alerts/rule/view-overview.ts index 1365017399..7b080af331 100644 --- a/apps/web/src/page/alerts/rule/view-overview.ts +++ b/apps/web/src/page/alerts/rule/view-overview.ts @@ -176,7 +176,7 @@ const configuration = (h: H, rule: AlertRuleDocument): Html => h.pre( [ h.Class( - "overflow-x-auto whitespace-pre rounded-md border bg-muted/30 px-3 py-2.5 font-mono text-xs leading-relaxed", + "overflow-x-auto whitespace-pre rounded-md border bg-surface-sunken p-3 font-mono text-xs leading-relaxed", ), ], [ diff --git a/apps/web/src/page/alerts/shared/providers.ts b/apps/web/src/page/alerts/shared/providers.ts index f351674fb7..9a6f1783a3 100644 --- a/apps/web/src/page/alerts/shared/providers.ts +++ b/apps/web/src/page/alerts/shared/providers.ts @@ -284,7 +284,7 @@ export const providerLogo = (h: HtmlBuilder, options: ProviderLogoOptions< [ h.Class( cn( - "relative inline-flex shrink-0 items-center justify-center rounded-md border border-border/60 bg-card", + "relative inline-flex shrink-0 items-center justify-center rounded-md border border-border-subtle bg-card", options.className, ), ), diff --git a/apps/web/src/page/alerts/shared/rule-chart.ts b/apps/web/src/page/alerts/shared/rule-chart.ts index 732a2b796e..2e2581be0c 100644 --- a/apps/web/src/page/alerts/shared/rule-chart.ts +++ b/apps/web/src/page/alerts/shared/rule-chart.ts @@ -67,7 +67,7 @@ const RAIL_COLOR = new Map([ ["error", TONE_FILL.warn], ["skipped", "bg-muted-foreground/30"], ["healthy", "bg-chart-apdex/70"], - ["empty", "bg-muted/50"], + ["empty", "bg-surface-sunken"], ]) const clamp01 = (value: number): number => (value < 0 ? 0 : value > 1 ? 1 : value) @@ -629,7 +629,7 @@ const rail = ( [ gutter("Incident"), h.div( - [h.Class("relative h-1 flex-1 rounded-[1px] bg-muted/60")], + [h.Class("relative h-1 flex-1 rounded-[1px] bg-surface-strong")], spans.map((span) => h.div([ h.Class( diff --git a/apps/web/src/page/alerts/uptime-form/view-kinds.ts b/apps/web/src/page/alerts/uptime-form/view-kinds.ts index ff322578b2..9cba1e93c9 100644 --- a/apps/web/src/page/alerts/uptime-form/view-kinds.ts +++ b/apps/web/src/page/alerts/uptime-form/view-kinds.ts @@ -260,7 +260,7 @@ export const notifySection = (h: H, model: Model): Html => { [ h.Type("button"), h.Class( - "flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-muted-foreground hover:bg-muted/50 hover:text-foreground", + "flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-muted-foreground hover:bg-surface-sunken hover:text-foreground", ), ...trigger, ], diff --git a/apps/web/src/page/alerts/uptime-form/view.ts b/apps/web/src/page/alerts/uptime-form/view.ts index 5ef1632990..57a25180f9 100644 --- a/apps/web/src/page/alerts/uptime-form/view.ts +++ b/apps/web/src/page/alerts/uptime-form/view.ts @@ -64,7 +64,7 @@ const kindPicker = (h: H, model: Model): Html => [ h.Role("radiogroup"), h.AriaLabel("Monitor type"), - h.Class("flex w-fit flex-wrap gap-1 rounded-md border bg-muted/30 p-0.5"), + h.Class("flex w-fit flex-wrap gap-1 rounded-md border bg-surface-sunken p-0.5"), ], KINDS.map((option) => { const isSelected = model.form.kind === option.kind @@ -175,7 +175,7 @@ const testResultBody = (h: H, model: Model): ReadonlyArray => { h.pre( [ h.Class( - "max-h-40 overflow-auto rounded-md bg-muted/50 p-2 font-mono text-xs whitespace-pre-wrap", + "max-h-40 overflow-auto rounded-md bg-surface-sunken p-2 font-mono text-xs whitespace-pre-wrap", ), ], [result.body_prefix, ...(result.body_truncated ? ["…"] : [])], diff --git a/apps/web/src/page/alerts/uptime-monitor/view-panels.ts b/apps/web/src/page/alerts/uptime-monitor/view-panels.ts index 0ae17280c0..2e9b2899be 100644 --- a/apps/web/src/page/alerts/uptime-monitor/view-panels.ts +++ b/apps/web/src/page/alerts/uptime-monitor/view-panels.ts @@ -785,7 +785,7 @@ export const checksScatterPanel = (h: H, model: Model, timeZone: string): Html | "pointer-events-none absolute inset-x-0 border-t", share === 0 ? "border-border" - : "border-dashed border-border/60", + : "border-dashed border-border-subtle", ), ), h.Style({ bottom: `${share * 100}%` }), diff --git a/apps/web/src/page/analytics/view-ai-parts.ts b/apps/web/src/page/analytics/view-ai-parts.ts index 2b4320436a..c989de970b 100644 --- a/apps/web/src/page/analytics/view-ai-parts.ts +++ b/apps/web/src/page/analytics/view-ai-parts.ts @@ -106,7 +106,7 @@ export const aiPanel = ( panelTitle(h, [options.title]), ...(options.hint === undefined ? [] - : [h.div([h.Class("mt-0.5 text-2xs text-muted-foreground/70")], [options.hint])]), + : [h.div([h.Class("mt-0.5 text-2xs text-foreground-subtle")], [options.hint])]), ], ), ], @@ -121,7 +121,7 @@ export const aiPanel = ( h.Type("button"), h.OnClick(Message.ClickedExpandPanel({ panel: options.expand.id })), h.Class( - "flex w-full items-center justify-between gap-2 rounded-b-md border-t border-border/60 px-4 py-2 text-2xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:bg-muted/50 focus-visible:outline-none", + "flex w-full items-center justify-between gap-2 rounded-b-md border-t border-border-subtle px-4 py-2 text-2xs text-muted-foreground transition-colors hover:bg-surface-sunken hover:text-foreground focus-visible:bg-surface-sunken focus-visible:outline-none", ), ], [ @@ -200,7 +200,7 @@ export const aiProductCard = ( h.span( [ h.Class( - "shrink-0 font-mono text-3xs tabular-nums text-muted-foreground/80", + "shrink-0 font-mono text-3xs tabular-nums text-foreground-subtle", ), h.Title( "Crawler fetches the site served, per visit this product sent", @@ -252,11 +252,11 @@ const shareBarStyle = (share: number): Readonly> => { const shareChange = (h: H, share: number, points: number | null): Html => { if (points === null) return h.span( - [h.Class("text-muted-foreground/70"), h.Title("No visits from it in the previous period")], + [h.Class("text-foreground-subtle"), h.Title("No visits from it in the previous period")], ["New"], ) const before = share - points / 100 - if (Math.abs(points) < 0.05) return h.span([h.Class("text-muted-foreground/70")], ["No change"]) + if (Math.abs(points) < 0.05) return h.span([h.Class("text-foreground-subtle")], ["No change"]) return h.span( [ h.Title( @@ -290,18 +290,18 @@ export const rankingTable = (h: H, ranks: ReadonlyArray, surface [ h.Key(rank.product.id), h.Style(shareBarStyle(rank.share)), - h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-2 last:border-0"), + h.Class("flex items-center gap-4 border-b border-border-subtle px-4 py-2 last:border-0"), ], [ h.span( - [h.Class("w-5 text-right font-mono text-2xs tabular-nums text-muted-foreground/60")], + [h.Class("w-5 text-right font-mono text-2xs tabular-nums text-foreground-subtle")], [String(index + 1)], ), h.span( [h.Class("flex w-0 min-w-0 flex-1 items-center gap-2")], [ aiProductIcon(h, rank.product.id), - h.span([h.Class("truncate text-xs text-foreground/90")], [rank.product.label]), + h.span([h.Class("truncate text-xs text-foreground-soft")], [rank.product.label]), ], ), h.span( @@ -355,7 +355,7 @@ export const crawlerTable = ( { ariaLabel: "AI crawlers", maxHeight: surface.maxHeight, stickySurfaceClass: surface.surfaceClass }, [ columnHead(h, { label: "Crawler", width: "w-0 flex-1 min-w-0" }), - columnHead(h, { label: "Purpose", width: "w-[72px]" }), + columnHead(h, { label: "Purpose", width: "w-20" }), columnHead(h, { label: "Pages", width: "w-12", align: "right" }), columnHead(h, { label: "Fetches", @@ -376,18 +376,18 @@ export const crawlerTable = ( return h.div( [ h.Key(row.crawler), - h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-2 last:border-0"), + h.Class("flex items-center gap-4 border-b border-border-subtle px-4 py-2 last:border-0"), ], [ h.span( [h.Class("flex w-0 min-w-0 flex-1 items-center gap-2")], [ aiProductIcon(h, product?.id ?? ""), - h.span([h.Class("truncate text-xs text-foreground/90")], [row.crawler]), + h.span([h.Class("truncate text-xs text-foreground-soft")], [row.crawler]), ], ), h.span( - [h.Class("flex w-[72px] shrink-0")], + [h.Class("flex w-20 shrink-0")], purpose === undefined ? [] : [purposeBadge(h, purpose)], ), h.span( @@ -395,7 +395,7 @@ export const crawlerTable = ( h.Class( cn( "w-12 text-right font-mono text-2xs tabular-nums", - row.pages === 0 && "text-muted-foreground/60", + row.pages === 0 && "text-foreground-subtle", ), ), ], @@ -487,7 +487,7 @@ export const contentFormats = (h: H, formats: AiCrawlers["formats"]): Html => { h.span( [ h.Class( - "flex size-7 shrink-0 items-center justify-center rounded-sm border bg-muted/40 text-muted-foreground", + "flex size-7 shrink-0 items-center justify-center rounded-sm border bg-surface-sunken text-muted-foreground", ), ], [icon(h, entry.icon, { size: 14 })], @@ -540,7 +540,7 @@ export const contentFormats = (h: H, formats: AiCrawlers["formats"]): Html => { ...(other !== undefined && other.requests > 0 ? [ h.div( - [h.Class("flex items-center gap-1.5 px-1 text-2xs text-muted-foreground/70")], + [h.Class("flex items-center gap-1.5 px-1 text-2xs text-foreground-subtle")], [ icon(h, "FileIcon", { size: 12 }), plural(other.requests, "other fetch", "other fetches"), diff --git a/apps/web/src/page/analytics/view-breakdown.ts b/apps/web/src/page/analytics/view-breakdown.ts index a153f696ff..e6e0a60d5e 100644 --- a/apps/web/src/page/analytics/view-breakdown.ts +++ b/apps/web/src/page/analytics/view-breakdown.ts @@ -236,7 +236,7 @@ export const breakdownTable = ( h.Style(shareBarStyle(row.share)), h.Class( cn( - "group flex w-full items-center gap-3 border-b border-border/60 px-3 py-2 text-left transition-colors last:border-0 @min-[420px]/panel:gap-4 @min-[420px]/panel:px-4", + "group flex w-full items-center gap-3 border-b border-border-subtle px-3 py-2 text-left transition-colors last:border-0 @min-[420px]/panel:gap-4 @min-[420px]/panel:px-4", "hover:bg-foreground/[0.06] focus-visible:bg-foreground/[0.06] focus-visible:outline-none", rowSelectedClass(isSelected), ), @@ -248,7 +248,7 @@ export const breakdownTable = ( h.span( [ h.Class( - "w-6 text-right font-mono text-2xs tabular-nums text-muted-foreground/60 max-sm:hidden", + "w-6 text-right font-mono text-2xs tabular-nums text-foreground-subtle max-sm:hidden", ), ], [String(index + 1)], @@ -270,7 +270,7 @@ export const breakdownTable = ( "min-w-0 truncate text-xs transition-colors", isSelected ? "font-medium text-foreground" - : "text-foreground/90 group-hover:text-foreground", + : "text-foreground-soft group-hover:text-foreground", ), ), h.Title( @@ -384,7 +384,7 @@ export const breakdownPanel = ( h.Type("button"), h.OnClick(Message.ClickedExpandPanel({ panel: card.id })), h.Class( - "flex w-full items-center justify-between gap-2 rounded-b-md px-4 py-2 text-2xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:bg-muted/50 focus-visible:outline-none", + "flex w-full items-center justify-between gap-2 rounded-b-md px-4 py-2 text-2xs text-muted-foreground transition-colors hover:bg-surface-sunken hover:text-foreground focus-visible:bg-surface-sunken focus-visible:outline-none", ), ], [ diff --git a/apps/web/src/page/analytics/view-overview.ts b/apps/web/src/page/analytics/view-overview.ts index 1395c2b627..2c3625a971 100644 --- a/apps/web/src/page/analytics/view-overview.ts +++ b/apps/web/src/page/analytics/view-overview.ts @@ -101,7 +101,7 @@ const metricStrip = ( onSelect: Message.PickedMetric({ metric: metric.key }), delay: (index % 4) * 60, className: TILE_NARROW, - valueClassName: "@max-[560px]/page:text-[22px]", + valueClassName: "@max-[560px]/page:text-xl", }) }), ) diff --git a/apps/web/src/page/analytics/view.ts b/apps/web/src/page/analytics/view.ts index 958adcdb84..b39de8a20c 100644 --- a/apps/web/src/page/analytics/view.ts +++ b/apps/web/src/page/analytics/view.ts @@ -47,7 +47,7 @@ const liveBadge = (h: H, model: Model): ReadonlyArray => { "inline-flex h-8 items-center gap-1.5 rounded-md border px-2.5 text-xs font-medium tabular-nums", count > 0 ? cn(TONE_SOFT.ok, TONE_BORDER.ok) - : "border-border/60 text-muted-foreground", + : "border-border-subtle text-muted-foreground", ), ), h.Title(`${count} ${noun} active in the last ${minutes} ${pluralize(minutes, "minute")}`), diff --git a/apps/web/src/page/anomalies/detail/view-body.ts b/apps/web/src/page/anomalies/detail/view-body.ts index cb893e12d2..675e88d09a 100644 --- a/apps/web/src/page/anomalies/detail/view-body.ts +++ b/apps/web/src/page/anomalies/detail/view-body.ts @@ -88,7 +88,7 @@ export const anomalyHero = (h: H, incident: AnomalyIncidentDocument, nowMs: numb }, [ SIGNAL_LABEL[incident.signalType], - h.span([h.Class("text-muted-foreground/60")], [" · "]), + h.span([h.Class("text-foreground-subtle")], [" · "]), incident.serviceName, ], ), @@ -174,7 +174,7 @@ export const signalChart = ( h, { dashed: true, - className: "flex h-64 w-full items-center justify-center border-border/60 py-0 text-xs", + className: "flex h-64 w-full items-center justify-center border-border-subtle py-0 text-xs", }, ["No signal data in window"], ) @@ -298,7 +298,7 @@ export const linkedIssueCard = ( const issueId = incident.errorIssueId if (issueId === null) return h.div( - [h.Class("rounded-md border border-dashed border-border/60 p-4")], + [h.Class("rounded-md border border-dashed border-border-subtle p-4")], [ h.div( [h.Class("flex flex-wrap items-center justify-between gap-3")], diff --git a/apps/web/src/page/anomalies/detail/view-link-dialog.ts b/apps/web/src/page/anomalies/detail/view-link-dialog.ts index d324da8567..890f5c27e4 100644 --- a/apps/web/src/page/anomalies/detail/view-link-dialog.ts +++ b/apps/web/src/page/anomalies/detail/view-link-dialog.ts @@ -175,7 +175,7 @@ export const linkIssueDialog = (h: H, model: Model, incident: AnomalyIncidentDoc ), ]), h.div( - [h.Class("flex items-center justify-between border-t border-border/60 px-3 py-2")], + [h.Class("flex items-center justify-between border-t border-border-subtle px-3 py-2")], [ h.span( [h.Class("text-xs text-muted-foreground")], diff --git a/apps/web/src/page/anomalies/kit/row.ts b/apps/web/src/page/anomalies/kit/row.ts index 47f7150f69..bafc5280fe 100644 --- a/apps/web/src/page/anomalies/kit/row.ts +++ b/apps/web/src/page/anomalies/kit/row.ts @@ -69,8 +69,8 @@ export const anomalyRow = (h: HtmlBuilder, options: AnomalyRowOptions): h.Class( cn( "group/row relative flex h-9 items-center gap-2 pr-3 pl-3 text-sm", - "hover:bg-muted/50", - "data-focused:bg-muted/40", + "hover:bg-surface-sunken", + "data-focused:bg-surface-sunken", "transition-colors", ), ), @@ -94,7 +94,7 @@ export const anomalyRow = (h: HtmlBuilder, options: AnomalyRowOptions): h.span( [ h.Class( - "relative z-10 flex min-w-0 flex-1 items-center gap-1.5 font-medium text-foreground sm:w-[130px] sm:flex-none", + "relative z-10 flex min-w-0 flex-1 items-center gap-1.5 font-medium text-foreground sm:w-32 sm:flex-none", ), ], [ @@ -106,7 +106,7 @@ export const anomalyRow = (h: HtmlBuilder, options: AnomalyRowOptions): [ h.Class( cn( - "relative z-10 w-[110px] shrink-0 whitespace-nowrap text-right font-mono text-xs tabular-nums", + "relative z-10 w-28 shrink-0 whitespace-nowrap text-right font-mono text-xs tabular-nums", isLive ? tone.text : "text-muted-foreground", ), ), @@ -119,12 +119,12 @@ export const anomalyRow = (h: HtmlBuilder, options: AnomalyRowOptions): h.span( [ h.Class( - "relative z-10 hidden w-[170px] shrink-0 text-right font-mono text-xs tabular-nums text-muted-foreground lg:inline-block", + "relative z-10 hidden w-44 shrink-0 text-right font-mono text-xs tabular-nums text-muted-foreground lg:inline-block", ), ], [ formatSignalValue(incident.signalType, incident.lastObservedValue), - h.span([h.Class("text-muted-foreground/50")], [" ← "]), + h.span([h.Class("text-foreground-faint")], [" ← "]), formatSignalValue(incident.signalType, incident.baselineMedian), ], ), diff --git a/apps/web/src/page/anomalies/list/view-list.ts b/apps/web/src/page/anomalies/list/view-list.ts index c3084a5848..91bbc74104 100644 --- a/apps/web/src/page/anomalies/list/view-list.ts +++ b/apps/web/src/page/anomalies/list/view-list.ts @@ -40,9 +40,9 @@ const group = ( h.AriaControls(`anomaly-group-${key}`), h.Class( cn( - "sticky top-0 z-10 flex h-8 w-full items-center gap-2 border-b border-border/60 bg-muted/40 pr-2 pl-2 text-left outline-none", - "backdrop-blur supports-[backdrop-filter]:bg-muted/60", - "hover:bg-muted/60", + "sticky top-0 z-10 flex h-8 w-full items-center gap-2 border-b border-border-subtle bg-surface-sunken pr-2 pl-2 text-left outline-none", + "backdrop-blur supports-[backdrop-filter]:bg-surface-strong", + "hover:bg-surface-strong", ), ), ], @@ -59,7 +59,7 @@ const group = ( ...(isOpen ? [ h.div( - [h.Id(`anomaly-group-${key}`), h.Role("list"), h.Class("divide-y divide-border/60")], + [h.Id(`anomaly-group-${key}`), h.Role("list"), h.Class("divide-y divide-border-subtle")], clusterByService(incidents).map((cluster) => h.div( [h.Key(cluster.key + (cluster.incidents[0]?.id ?? ""))], @@ -69,12 +69,12 @@ const group = ( h.div( [ h.Class( - "flex h-7 items-center gap-1.5 border-b border-border/60 bg-muted/20 pl-5 text-2xs text-muted-foreground", + "flex h-7 items-center gap-1.5 border-b border-border-subtle bg-surface-faint pl-5 text-2xs text-muted-foreground", ), ], [ serviceDot(h, { serviceName: cluster.serviceName, size: "sm" }), - h.span([h.Class("font-medium text-foreground/80")], [cluster.serviceName]), + h.span([h.Class("font-medium text-foreground-soft")], [cluster.serviceName]), ...(cluster.deploymentEnv ? [h.span([], [cluster.deploymentEnv])] : []), h.span([h.Class("tabular-nums")], [String(cluster.incidents.length), " anomalies"]), ], @@ -82,7 +82,7 @@ const group = ( ] : []), h.div( - [h.Class("divide-y divide-border/60")], + [h.Class("divide-y divide-border-subtle")], cluster.incidents.map((incident) => h.div( [h.Key(incident.id), h.Role("listitem")], diff --git a/apps/web/src/page/code-review/analytics/view-lists.ts b/apps/web/src/page/code-review/analytics/view-lists.ts index 7624b2d419..6e4728229e 100644 --- a/apps/web/src/page/code-review/analytics/view-lists.ts +++ b/apps/web/src/page/code-review/analytics/view-lists.ts @@ -20,7 +20,7 @@ export const repositoryList = (h: HtmlBuilder, title: string, rows: Readon h.span([h.Class("text-xs text-muted-foreground")], [title]), rows.length === 0 ? h.span( - [h.Class("py-1 text-sm text-muted-foreground/70")], + [h.Class("py-1 text-sm text-foreground-subtle")], ["No repositories in this window"], ) : h.ul( diff --git a/apps/web/src/page/code-review/ci/view-runs.ts b/apps/web/src/page/code-review/ci/view-runs.ts index 2e22a8c194..5ec65766e4 100644 --- a/apps/web/src/page/code-review/ci/view-runs.ts +++ b/apps/web/src/page/code-review/ci/view-runs.ts @@ -254,7 +254,7 @@ export const runsList = (h: H, model: Model, time: TimeContext, canClear: boolea ), ]), ], - { className: "bg-muted/30" }, + { className: "bg-surface-sunken" }, ), tableBody( h, diff --git a/apps/web/src/page/code-review/ci/view-tables.ts b/apps/web/src/page/code-review/ci/view-tables.ts index 633e897ff0..6f9f66aa50 100644 --- a/apps/web/src/page/code-review/ci/view-tables.ts +++ b/apps/web/src/page/code-review/ci/view-tables.ts @@ -42,7 +42,7 @@ const head = (h: H, cells: ReadonlyArray) => ), ), ], - { className: "bg-muted/30" }, + { className: "bg-surface-sunken" }, ) /** Where the streak began and the commit that last passed. */ @@ -183,7 +183,7 @@ const workflowRow = ( "hidden px-4 sm:table-cell", ), ], - cn("cursor-pointer transition-colors hover:bg-muted/50", isActive && "bg-muted/60"), + cn("cursor-pointer transition-colors hover:bg-surface-sunken", isActive && "bg-surface-strong"), [h.Key(`${row.owner}/${row.repository}/${row.pipeline}`), h.OnClick(select)], ) } diff --git a/apps/web/src/page/code-review/kit/parts.ts b/apps/web/src/page/code-review/kit/parts.ts index b967e00d17..17dd2ea546 100644 --- a/apps/web/src/page/code-review/kit/parts.ts +++ b/apps/web/src/page/code-review/kit/parts.ts @@ -19,7 +19,7 @@ export const bulletList = (h: HtmlBuilder, items: ReadonlyArray): h.ul( [ h.Class( - "flex list-disc flex-col gap-1 pl-5 text-sm text-muted-foreground marker:text-muted-foreground/50", + "flex list-disc flex-col gap-1 pl-5 text-sm text-muted-foreground marker:text-foreground-faint", ), ], items.map((item) => h.li([], [item])), diff --git a/apps/web/src/page/code-review/kit/review-sheet-more.ts b/apps/web/src/page/code-review/kit/review-sheet-more.ts index 4298b8f7aa..a344ad4751 100644 --- a/apps/web/src/page/code-review/kit/review-sheet-more.ts +++ b/apps/web/src/page/code-review/kit/review-sheet-more.ts @@ -134,7 +134,7 @@ export const ciRunsSection = (h: H, sheet: ReviewSheet): Html => [ h.Key(run.traceId), h.Class( - "flex items-center gap-3 rounded-md px-2 py-1 text-sm hover:bg-muted/50", + "flex items-center gap-3 rounded-md px-2 py-1 text-sm hover:bg-surface-sunken", ), ], [ @@ -187,7 +187,7 @@ export const historySection = (h: H, sheet: ReviewSheet, detail: CodeReviewDetai h.Class( cn( "flex w-full items-center gap-3 rounded-md px-2 py-1.5 text-left text-sm transition-colors", - isCurrent ? "bg-muted" : "hover:bg-muted/50", + isCurrent ? "bg-muted" : "hover:bg-surface-sunken", ), ), ...(isCurrent ? [h.Disabled(true)] : []), diff --git a/apps/web/src/page/code-review/pull-requests/view-table.ts b/apps/web/src/page/code-review/pull-requests/view-table.ts index 75184af250..fbfafe8290 100644 --- a/apps/web/src/page/code-review/pull-requests/view-table.ts +++ b/apps/web/src/page/code-review/pull-requests/view-table.ts @@ -165,7 +165,7 @@ const reviewRow = (h: H, review: CodeReviewListItem, context: RowContext): Html "hidden px-4 text-right text-muted-foreground tabular-nums sm:table-cell", ), ], - cn("cursor-pointer transition-colors hover:bg-muted/50", isSelected && "bg-muted/60"), + cn("cursor-pointer transition-colors hover:bg-surface-sunken", isSelected && "bg-surface-strong"), [h.Key(review.id), h.OnClick(open)], ) } @@ -185,7 +185,7 @@ export const reviewTable = (h: H, reviews: ReadonlyArray, co tableHead(h, ["Reviewed"], "hidden w-28 px-4 text-right font-normal sm:table-cell"), ]), ], - { className: "bg-muted/30" }, + { className: "bg-surface-sunken" }, ), tableBody( h, diff --git a/apps/web/src/page/dashboards/kit/tile-shell.ts b/apps/web/src/page/dashboards/kit/tile-shell.ts index 1f33fcd98a..058f00b7c6 100644 --- a/apps/web/src/page/dashboards/kit/tile-shell.ts +++ b/apps/web/src/page/dashboards/kit/tile-shell.ts @@ -182,7 +182,7 @@ export const widgetEmptyState = (h: HtmlBuilder): Html => emptyMessage(h, { className: "flex h-full flex-col items-center justify-center gap-1.5 px-3 py-0" }, [ h.span([h.Class("font-medium")], ["No data in the selected time range"]), h.span( - [h.Class("text-3xs text-muted-foreground/70 max-w-full line-clamp-3")], + [h.Class("text-3xs text-foreground-subtle max-w-full line-clamp-3")], ["Widen the time range or check the query's filters."], ), ]) @@ -206,7 +206,7 @@ const mutedError = ( h.span( [ h.Class( - "text-3xs text-muted-foreground/70 max-w-full text-center line-clamp-3", + "text-3xs text-foreground-subtle max-w-full text-center line-clamp-3", ), ], [state.message], diff --git a/apps/web/src/page/dashboards/list/view-list.ts b/apps/web/src/page/dashboards/list/view-list.ts index e7c18721dc..44dd890997 100644 --- a/apps/web/src/page/dashboards/list/view-list.ts +++ b/apps/web/src/page/dashboards/list/view-list.ts @@ -209,7 +209,7 @@ const dashboardRow = (h: H, context: RowContext, dashboard: ListDashboard, isFav dashboard.id, [ h.Class( - "group relative flex items-center border-b border-border last:border-b-0 transition-colors hover:bg-muted/50 focus-within:bg-muted/50", + "group relative flex items-center border-b border-border last:border-b-0 transition-colors hover:bg-surface-sunken focus-within:bg-surface-sunken", ), ], [ @@ -329,7 +329,7 @@ const dashboardRow = (h: H, context: RowContext, dashboard: ListDashboard, isFav { size: "icon-xs", label: isFavorite ? `Unstar ${name}` : `Star ${name}`, - className: isFavorite ? "text-primary" : "text-muted-foreground/40", + className: isFavorite ? "text-primary" : "text-foreground-faint", attributes: [ h.AriaPressed(String(isFavorite)), h.OnClick(Message.ToggledFavorite({ id: dashboard.id })), @@ -352,7 +352,7 @@ const createRow = (h: H, isReadOnly: boolean): Html => h.OnClick(Message.ClickedCreate()), ...(isReadOnly ? [h.Disabled(true)] : []), h.Class( - "mt-4 flex w-full shrink-0 items-center gap-3 rounded-md border border-dashed border-input bg-card py-3 pr-4 pl-3 text-left transition-colors hover:bg-muted/50 disabled:cursor-not-allowed disabled:opacity-50", + "mt-4 flex w-full shrink-0 items-center gap-3 rounded-md border border-dashed border-input bg-card py-3 pr-4 pl-3 text-left transition-colors hover:bg-surface-sunken disabled:cursor-not-allowed disabled:opacity-50", ), ], [ diff --git a/apps/web/src/page/dashboards/list/view.ts b/apps/web/src/page/dashboards/list/view.ts index f8690428f2..c21e44d982 100644 --- a/apps/web/src/page/dashboards/list/view.ts +++ b/apps/web/src/page/dashboards/list/view.ts @@ -140,7 +140,7 @@ const degradedBanner = (h: H): Html => h.div( [ h.Class( - "mb-3 flex items-start gap-2 rounded-md border border-border bg-muted/40 p-2.5 text-xs text-muted-foreground", + "mb-3 flex items-start gap-2 rounded-md border border-border bg-surface-sunken p-2.5 text-xs text-muted-foreground", ), ], [ diff --git a/apps/web/src/page/dashboards/templates/view-list.ts b/apps/web/src/page/dashboards/templates/view-list.ts index abbd352545..394a00913e 100644 --- a/apps/web/src/page/dashboards/templates/view-list.ts +++ b/apps/web/src/page/dashboards/templates/view-list.ts @@ -51,7 +51,7 @@ const templateRow = ( cn( "flex min-h-9 w-full items-center text-left transition-colors", rowSelectedClass(isSelected), - !isSelected && "hover:bg-muted/50", + !isSelected && "hover:bg-surface-sunken", ), ), ], @@ -95,7 +95,7 @@ const templateRow = ( cn( truncatedTextStyles, truncatedTextMonoStyles, - "text-muted-foreground/80 max-w-31.5 shrink-0 text-right text-2xs", + "text-foreground-subtle max-w-31.5 shrink-0 text-right text-2xs", ), ), h.Title(status), @@ -204,7 +204,7 @@ const groups = ( [], [ h.div( - [h.Class("text-muted-foreground/70 pt-3.5 pr-4 pb-1 pl-12.5 text-2xs")], + [h.Class("text-foreground-subtle pt-3.5 pr-4 pb-1 pl-12.5 text-2xs")], [CATEGORY_LABELS.get(category) ?? category], ), ...templates.map(row), @@ -315,7 +315,7 @@ export const templateList = ( h.Type("button"), h.OnClick(Message.ClickedCreate({ templateId: BLANK_TEMPLATE_ID })), h.Class( - "flex shrink-0 items-center gap-2.5 border-t border-border bg-sidebar py-3 pr-4 pl-4 text-left transition-colors hover:bg-muted/50", + "flex shrink-0 items-center gap-2.5 border-t border-border bg-sidebar py-3 pr-4 pl-4 text-left transition-colors hover:bg-surface-sunken", ), ], [ diff --git a/apps/web/src/page/dashboards/templates/view-panel.ts b/apps/web/src/page/dashboards/templates/view-panel.ts index fdc6b9b238..a3fa74cd57 100644 --- a/apps/web/src/page/dashboards/templates/view-panel.ts +++ b/apps/web/src/page/dashboards/templates/view-panel.ts @@ -519,7 +519,7 @@ export const detailPanel = ( [ livePreview(h, model, timeZone), h.p( - [h.Class("text-muted-foreground/80 text-2xs")], + [h.Class("text-foreground-subtle text-2xs")], ["That's the dashboard you'd get right now."], ), ], diff --git a/apps/web/src/page/dashboards/view/view-history.ts b/apps/web/src/page/dashboards/view/view-history.ts index c9da0ba26b..6be2e404d2 100644 --- a/apps/web/src/page/dashboards/view/view-history.ts +++ b/apps/web/src/page/dashboards/view/view-history.ts @@ -42,7 +42,7 @@ const versionItem = ( h.Class( cn( "group relative w-full pl-7 pr-3 py-2.5 text-left transition-colors", - "hover:bg-muted/50", + "hover:bg-surface-sunken", rowSelectedClass(isPreviewing), ), ), @@ -71,7 +71,7 @@ const versionItem = ( variant: "label", className: isPreviewing ? "text-primary" - : "text-muted-foreground/70 group-hover:text-foreground/80", + : "text-foreground-subtle group-hover:text-foreground-soft", }, [KIND_LABEL[version.changeKind]], ), @@ -241,7 +241,7 @@ export const previewBanner = (h: H, model: Model, version: VersionRow, clock: Cl [ icon(h, "HistoryIcon", { className: "size-4 shrink-0 text-primary" }), h.div( - [h.Class("flex min-w-0 flex-1 items-center gap-1.5 font-mono text-2xs text-foreground/80")], + [h.Class("flex min-w-0 flex-1 items-center gap-1.5 font-mono text-2xs text-foreground-soft")], [ h.span([h.Class("font-semibold text-primary")], ["PREVIEW"]), dot(h), diff --git a/apps/web/src/page/dashboards/view/view-share.ts b/apps/web/src/page/dashboards/view/view-share.ts index d7e1625cd9..cdbcc794a6 100644 --- a/apps/web/src/page/dashboards/view/view-share.ts +++ b/apps/web/src/page/dashboards/view/view-share.ts @@ -112,7 +112,7 @@ const accessOption = ( h.For(`share-${option.value}`), h.Id(`share-${option.value}-label`), h.Class( - "group flex cursor-pointer items-start gap-3 px-3.5 py-3 transition-colors hover:bg-accent/40 has-[[data-checked]]:bg-accent/64", + "group flex cursor-pointer items-start gap-3 px-3.5 py-3 transition-colors hover:bg-accent/50 has-[[data-checked]]:bg-accent/64", ), ], [ diff --git a/apps/web/src/page/dashboards/view/view.ts b/apps/web/src/page/dashboards/view/view.ts index bbf52b74a5..669b5c5398 100644 --- a/apps/web/src/page/dashboards/view/view.ts +++ b/apps/web/src/page/dashboards/view/view.ts @@ -69,7 +69,7 @@ const title = (h: H, model: Model, name: string): Html => { { title: shown, className: cn( - !isReadOnly && "cursor-pointer hover:text-foreground/80", + !isReadOnly && "cursor-pointer hover:text-foreground-soft", isBlank && "text-muted-foreground", ), attributes: [ @@ -156,7 +156,7 @@ const blankDashboard = (h: H, isReadOnly: boolean): Html => `${className} flex items-center justify-center rounded-md border border-dashed border-border bg-card/40`, ), ], - [icon(h, glyph, { size: 16, className: "text-muted-foreground/50" })], + [icon(h, glyph, { size: 16, className: "text-foreground-faint" })], ), ), ), diff --git a/apps/web/src/page/dashboards/widget/view-list-column.ts b/apps/web/src/page/dashboards/widget/view-list-column.ts index 19ff112eb7..7d32e61434 100644 --- a/apps/web/src/page/dashboards/widget/view-list-column.ts +++ b/apps/web/src/page/dashboards/widget/view-list-column.ts @@ -66,7 +66,7 @@ export const listColumnRow = ( h.DataAttribute(GRIP_ATTRIBUTE, ""), h.AriaLabel(`Reorder ${column.header || column.field || `column ${index + 1}`}`), h.Class( - "shrink-0 cursor-grab touch-none text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing", + "shrink-0 cursor-grab touch-none text-foreground-faint hover:text-muted-foreground active:cursor-grabbing", ), h.OnKeyDownPreventDefault((key) => key === "ArrowUp" diff --git a/apps/web/src/page/dashboards/widget/view-panels.ts b/apps/web/src/page/dashboards/widget/view-panels.ts index 1104924c2b..80cf43c21a 100644 --- a/apps/web/src/page/dashboards/widget/view-panels.ts +++ b/apps/web/src/page/dashboards/widget/view-panels.ts @@ -94,7 +94,7 @@ export const funnelPanel = (h: H, model: Model, state: EditorState): ReadonlyArr windowRow(h, model, "funnel", funnel.windowSeconds, { label: "Window", ariaLabel: "Conversion window", - className: "h-8 w-[160px] text-xs", + className: "h-8 w-40 text-xs", hint: "the whole chain must complete within this long of step 1", }), ] @@ -143,7 +143,7 @@ const pathsAddOns = (h: H, model: Model, paths: EditorState["paths"]): ReadonlyA label: "Within", ariaLabel: "Window", size: "sm", - className: "w-[160px]", + className: "w-40", hint: "of the anchor", }), ] diff --git a/apps/web/src/page/dashboards/widget/view-product.ts b/apps/web/src/page/dashboards/widget/view-product.ts index 2bb3d41157..9414a1f5f3 100644 --- a/apps/web/src/page/dashboards/widget/view-product.ts +++ b/apps/web/src/page/dashboards/widget/view-product.ts @@ -68,7 +68,7 @@ export const panelShell = ( ariaLabel: "Query source", toView: (parts) => h.div( - [h.Class("flex items-center gap-2 px-3 py-2 bg-muted/30")], + [h.Class("flex items-center gap-2 px-3 py-2 bg-surface-sunken")], [ iconButton( h, @@ -187,7 +187,7 @@ export const keyByRow = (h: H, model: Model, scope: StepScope, value: string): H FUNNEL_KEY_BY_OPTIONS.map((option) => ({ value: option.value, label: option.label })), { size: "sm", - className: "w-[220px]", + className: "w-56", ariaLabel: "Count by", renderItem: (option) => { const description = diff --git a/apps/web/src/page/dashboards/widget/view-rail-thresholds.ts b/apps/web/src/page/dashboards/widget/view-rail-thresholds.ts index c720bd11bc..6618e98ad8 100644 --- a/apps/web/src/page/dashboards/widget/view-rail-thresholds.ts +++ b/apps/web/src/page/dashboards/widget/view-rail-thresholds.ts @@ -33,7 +33,7 @@ export const thresholds = (h: H, state: EditorState): Html => h.Value(threshold.color.startsWith("#") ? threshold.color : "#ef4444"), h.OnInput((color) => Message.ChangedThresholdColor({ index, color })), h.Class( - "h-8 w-8 shrink-0 cursor-pointer rounded border bg-transparent p-0.5", + "h-8 w-8 shrink-0 cursor-pointer rounded-sm border bg-transparent p-0.5", ), h.AriaLabel("Threshold color"), ]), diff --git a/apps/web/src/page/dashboards/widget/view-sql.ts b/apps/web/src/page/dashboards/widget/view-sql.ts index 139eb3dae1..ff55e04ceb 100644 --- a/apps/web/src/page/dashboards/widget/view-sql.ts +++ b/apps/web/src/page/dashboards/widget/view-sql.ts @@ -39,7 +39,7 @@ const CHIP = "h-auto rounded-sm px-2 py-0.5 font-mono text-2xs sm:h-auto sm:text const header = (h: H, rawSql: RawSqlState): Html => { const issue = rawSqlIssue(rawSql.draft.sql) return h.div( - [h.Class("flex items-center gap-2 px-3 py-2 bg-muted/30")], + [h.Class("flex items-center gap-2 px-3 py-2 bg-surface-sunken")], [ iconButton( h, @@ -57,7 +57,7 @@ const header = (h: H, rawSql: RawSqlState): Html => { h.Class( badgeVariants({ variant: "outline", - className: "font-mono text-2xs text-white border-0 shrink-0 bg-primary/80", + className: "font-mono text-2xs text-primary-foreground border-0 shrink-0 bg-primary/80", }), ), h.DataAttribute("slot", "badge"), @@ -158,7 +158,7 @@ const chipRow = ( h, token, index < MACRO_HINTS.length - ? "bg-muted/40 text-muted-foreground hover:bg-muted hover:text-foreground" + ? "bg-surface-sunken text-muted-foreground hover:bg-muted hover:text-foreground" : "bg-primary/10 text-primary hover:bg-primary/20", trigger(chipTriggerId(index)), ), diff --git a/apps/web/src/page/dashboards/widget/view.ts b/apps/web/src/page/dashboards/widget/view.ts index 124b6e8ba5..d7f16d14cf 100644 --- a/apps/web/src/page/dashboards/widget/view.ts +++ b/apps/web/src/page/dashboards/widget/view.ts @@ -96,7 +96,7 @@ const sparklineState = (model: Model, widget: Widget) => { const preview = (h: H, model: Model, timeZone: string): Html => { const widget = previewWidgetOf(model) return h.div( - [h.Class("border-b bg-muted/30 p-6")], + [h.Class("border-b bg-surface-sunken p-6")], [ h.div( [h.Class("flex justify-end mb-3")], @@ -162,7 +162,7 @@ const editor = (h: H, model: Model, timeZone: string): Html => [preview(h, model, timeZone), queryEditor(h, model, timeZone)], ), h.aside( - [h.Class("w-[272px] shrink-0 border-l overflow-y-auto p-5 bg-muted/20")], + [h.Class("w-[272px] shrink-0 border-l overflow-y-auto p-5 bg-surface-faint")], [settingsRail(h, model, timeZone)], ), ], diff --git a/apps/web/src/page/errors/hub/view-list.ts b/apps/web/src/page/errors/hub/view-list.ts index bb2b49b0db..510c7c715c 100644 --- a/apps/web/src/page/errors/hub/view-list.ts +++ b/apps/web/src/page/errors/hub/view-list.ts @@ -28,7 +28,7 @@ const loadingBody = (h: H): ReadonlyArray => [ skeletonList(h, { rows: SKELETON_ROWS, renderRow: (index) => signalRowSkeleton(h, index), - className: "gap-0 divide-y divide-border/60", + className: "gap-0 divide-y divide-border-subtle", }), ] @@ -50,13 +50,13 @@ const pagingFooter = (h: H, paging: PagingState): ReadonlyArray => { skeletonList(h, { rows: LOAD_MORE_SKELETON_ROWS, renderRow: (index) => signalRowSkeleton(h, index), - className: "gap-0 divide-y divide-border/60 border-t border-border/60", + className: "gap-0 divide-y divide-border-subtle border-t border-border-subtle", }), ] } return [ h.div( - [h.Class("flex items-center justify-center gap-3 border-t border-border/60 p-4")], + [h.Class("flex items-center justify-center gap-3 border-t border-border-subtle p-4")], [ ...(paging === "failed" ? [h.span([h.Class("text-xs text-muted-foreground")], ["Couldn't load more errors."])] @@ -142,7 +142,7 @@ const readyBody = (h: H, model: Model, inputs: ListInputs): ReadonlyArray [ signalHeader(h, selection), h.div( - [h.Role("list"), h.Class("divide-y divide-border/60"), h.OnMount(MountRowSelect())], + [h.Role("list"), h.Class("divide-y divide-border-subtle"), h.OnMount(MountRowSelect())], signals.map((signal, index) => h.div( [h.Key(signal.id), h.Role("listitem")], diff --git a/apps/web/src/page/errors/hub/view-row.ts b/apps/web/src/page/errors/hub/view-row.ts index e65088991b..ddd24f557d 100644 --- a/apps/web/src/page/errors/hub/view-row.ts +++ b/apps/web/src/page/errors/hub/view-row.ts @@ -42,14 +42,14 @@ export const LANE = { select: "w-4 shrink-0", severity: "w-6 shrink-0", identity: "min-w-0 flex-1", - volume: "hidden w-[52px] shrink-0 items-center justify-end gap-2 @lg/page:flex @2xl/page:w-[148px]", + volume: "hidden w-[52px] shrink-0 items-center justify-end gap-2 @lg/page:flex @2xl/page:w-36", spark: "hidden min-w-0 flex-1 @2xl/page:block", count: "w-[52px] shrink-0 text-right", // Inset so the right-aligned Events count and the left-aligned Service read as two columns. - service: "hidden w-[116px] shrink-0 pl-3 @xl/page:block", - state: "hidden w-[104px] shrink-0 @3xl/page:block", + service: "hidden w-28 shrink-0 pl-3 @xl/page:block", + state: "hidden w-28 shrink-0 @3xl/page:block", actor: "w-5 shrink-0", - lastSeen: "w-[76px] shrink-0 whitespace-nowrap", + lastSeen: "w-20 shrink-0 whitespace-nowrap", } as const export const ROW_SHELL = "flex items-center gap-3 px-3" @@ -60,7 +60,7 @@ type H = HtmlBuilder /** The column labels; the select lane carries the page-wide checkbox once rows exist. */ export const signalHeader = (h: H, selection: HeaderSelection | null): Html => - eyebrow(h, { as: "div", className: cn(ROW_SHELL, "h-7 border-b border-border/60 bg-muted/30") }, [ + eyebrow(h, { as: "div", className: cn(ROW_SHELL, "h-7 border-b border-border-subtle bg-surface-sunken") }, [ h.span( [h.Class(cn(LANE.select, "flex items-center justify-center"))], selection === null @@ -157,9 +157,9 @@ export const signalRow = (h: H, signal: ErrorSignal, state: RowState): Html => { cn( ROW_SHELL, "group/row h-11 text-sm", - "hover:bg-muted/50 data-focused:bg-muted/40", + "hover:bg-surface-sunken data-focused:bg-surface-sunken", "data-selected:bg-primary/10 data-selected:hover:bg-primary/15", - "focus-visible:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", + "focus-visible:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", "transition-colors", ), ), @@ -283,7 +283,7 @@ const volumeLane = ( ], [ signal.windowCount === null - ? h.span([h.Class("text-muted-foreground/50")], [EMPTY_VALUE]) + ? h.span([h.Class("text-foreground-faint")], [EMPTY_VALUE]) : h.span( [ h.Class( diff --git a/apps/web/src/page/errors/hub/view-signal.ts b/apps/web/src/page/errors/hub/view-signal.ts index 7aecf4b4a8..7e4300cca4 100644 --- a/apps/web/src/page/errors/hub/view-signal.ts +++ b/apps/web/src/page/errors/hub/view-signal.ts @@ -123,7 +123,7 @@ export const signalActivity = (h: H, signal: ErrorSignal): Html | null => { cn( "flex items-center gap-1 text-2xs tabular-nums", signal.mergedPullRequestCount > 0 - ? "text-foreground/70" + ? "text-foreground-soft" : "text-muted-foreground", ), ), diff --git a/apps/web/src/page/errors/hub/view-toolbar.ts b/apps/web/src/page/errors/hub/view-toolbar.ts index 68fe3438d5..2e53641a7b 100644 --- a/apps/web/src/page/errors/hub/view-toolbar.ts +++ b/apps/web/src/page/errors/hub/view-toolbar.ts @@ -60,7 +60,7 @@ export const statStrip = (h: H, model: Model): Html | null => stat(h, formatErrorRate(summary.errorRate), "of all spans"), ], ), - h.span([h.Class("text-xs text-muted-foreground/60")], ["in the last 24 hours"]), + h.span([h.Class("text-xs text-foreground-subtle")], ["in the last 24 hours"]), ], ), }) @@ -154,7 +154,7 @@ export const toolbar = (h: H, model: Model, count: ReadonlyArray | null) viewInputs: { entries: SORT_ENTRIES, size: "sm", - className: "h-7 w-[126px] text-xs", + className: "h-7 w-32 text-xs", toView: (parts) => h.div([h.Class("contents")], parts), }, toParentMessage: (message) => Message.GotSortSelectMessage({ message }), @@ -166,7 +166,7 @@ export const toolbar = (h: H, model: Model, count: ReadonlyArray | null) viewInputs: { entries: SEVERITY_ENTRIES, size: "sm", - className: "h-7 w-[122px] text-xs", + className: "h-7 w-32 text-xs", renderValue: (value) => severityContent(h, value, SEVERITY_TRIGGER_LABEL), renderItem: (option) => severityContent(h, option.value, SEVERITY_FILTER_LABEL), toView: (parts) => h.div([h.Class("contents")], parts), diff --git a/apps/web/src/page/errors/issue/view-activity.ts b/apps/web/src/page/errors/issue/view-activity.ts index a15e96d272..aca35dafe7 100644 --- a/apps/web/src/page/errors/issue/view-activity.ts +++ b/apps/web/src/page/errors/issue/view-activity.ts @@ -203,7 +203,7 @@ const messageRow = ( h.Class( cn( "mt-1.5 max-w-prose overflow-x-auto rounded-md border px-3 py-2 text-sm", - isAgent ? AGENT_ACCENT.surface : "border-border/60 bg-muted/40", + isAgent ? AGENT_ACCENT.surface : "border-border-subtle bg-surface-sunken", ), ), ], diff --git a/apps/web/src/page/errors/issue/view-anomalies.ts b/apps/web/src/page/errors/issue/view-anomalies.ts index e5a74e346b..ac414083e1 100644 --- a/apps/web/src/page/errors/issue/view-anomalies.ts +++ b/apps/web/src/page/errors/issue/view-anomalies.ts @@ -40,7 +40,7 @@ export const relatedAnomaliesSection = ( hint: countLabel(sorted.length, "detector incident"), }), h.div( - [h.Class("overflow-hidden rounded-md border border-border/60 divide-y divide-border/60")], + [h.Class("overflow-hidden rounded-md border border-border-subtle divide-y divide-border-subtle")], sorted.map((incident) => anomalyRow(h, { incident, diff --git a/apps/web/src/page/errors/issue/view-chart.ts b/apps/web/src/page/errors/issue/view-chart.ts index 671801ec3e..15278358aa 100644 --- a/apps/web/src/page/errors/issue/view-chart.ts +++ b/apps/web/src/page/errors/issue/view-chart.ts @@ -47,7 +47,7 @@ const chartView = Submodel.defineView(( h, { dashed: true, - className: "flex h-44 w-full items-center justify-center border-border/60 py-0 text-xs", + className: "flex h-44 w-full items-center justify-center border-border-subtle py-0 text-xs", }, ["No activity in this window"], ) diff --git a/apps/web/src/page/errors/issue/view-header.ts b/apps/web/src/page/errors/issue/view-header.ts index c505bc8897..f571dc847f 100644 --- a/apps/web/src/page/errors/issue/view-header.ts +++ b/apps/web/src/page/errors/issue/view-header.ts @@ -31,7 +31,7 @@ const detailEyebrow = (h: H, segments: ReadonlyArray): Html => { h, { as: "div", className: "flex flex-wrap items-center gap-x-2 gap-y-1" }, shown.flatMap((segment, index) => [ - ...(index > 0 ? [h.span([h.AriaHidden(true), h.Class("text-muted-foreground/40")], ["·"])] : []), + ...(index > 0 ? [h.span([h.AriaHidden(true), h.Class("text-foreground-faint")], ["·"])] : []), h.span([h.Class("truncate")], [segment]), ]), ) diff --git a/apps/web/src/page/errors/issue/view-lease.ts b/apps/web/src/page/errors/issue/view-lease.ts index 9d69eff099..556fdffe63 100644 --- a/apps/web/src/page/errors/issue/view-lease.ts +++ b/apps/web/src/page/errors/issue/view-lease.ts @@ -53,7 +53,7 @@ export const leaseHud = ( h, { className: cn( - "flex-row items-center gap-3 border-border/60 bg-card/50 px-3 py-2.5", + "flex-row items-center gap-3 border-border-subtle bg-card/50 px-3 py-2.5", isDanger && "border-severity-error/40", ), }, diff --git a/apps/web/src/page/errors/issue/view-overview.ts b/apps/web/src/page/errors/issue/view-overview.ts index acfc433d77..1515aa73e7 100644 --- a/apps/web/src/page/errors/issue/view-overview.ts +++ b/apps/web/src/page/errors/issue/view-overview.ts @@ -39,7 +39,7 @@ const mono = ( h.div( [h.Class("group/mono flex min-w-0 items-start gap-1.5")], [ - h.code([h.Class("min-w-0 break-all font-mono text-xs leading-5 text-foreground/90")], [value]), + h.code([h.Class("min-w-0 break-all font-mono text-xs leading-5 text-foreground-soft")], [value]), CopyButton.view(h, { model, value, diff --git a/apps/web/src/page/errors/issue/view-panels.ts b/apps/web/src/page/errors/issue/view-panels.ts index bb592d9f13..38347feef6 100644 --- a/apps/web/src/page/errors/issue/view-panels.ts +++ b/apps/web/src/page/errors/issue/view-panels.ts @@ -65,7 +65,7 @@ const pullRequestRow = (h: H, pr: ErrorIssuePullRequestDocument, isBusy: boolean ], ), ...(pr.title ? [itemDescription(h, [pr.title], "line-clamp-1")] : []), - ...(hint ? [itemDescription(h, [hint], "text-muted-foreground/80")] : []), + ...(hint ? [itemDescription(h, [hint], "text-foreground-subtle")] : []), ]), iconButton( h, diff --git a/apps/web/src/page/errors/issue/view-sidebar.ts b/apps/web/src/page/errors/issue/view-sidebar.ts index 0297657c14..c0dc67c596 100644 --- a/apps/web/src/page/errors/issue/view-sidebar.ts +++ b/apps/web/src/page/errors/issue/view-sidebar.ts @@ -32,7 +32,7 @@ type H = HtmlBuilder const GHOST_TRIGGER = cn( "-mr-1.5 h-7 min-h-0 w-auto min-w-0 max-w-full gap-1.5 px-1.5 text-sm font-medium", "border-transparent bg-transparent shadow-none before:hidden dark:bg-transparent", - "hover:bg-muted/60 data-popup-open:bg-muted/60", + "hover:bg-surface-strong data-popup-open:bg-surface-strong", ) const SEVERITY_SOURCE_HINT = { @@ -167,7 +167,7 @@ const issueIdCopy = (h: H, model: Model, id: string): Html => Message.GotIssueIdCopyMessage({ message: CopyButton.Message.ClickedCopy({ text: id }) }), ), h.Class( - "group/copy -mr-1.5 inline-flex h-7 items-center gap-1.5 rounded-md px-1.5 font-mono text-xs tabular-nums text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", + "group/copy -mr-1.5 inline-flex h-7 items-center gap-1.5 rounded-md px-1.5 font-mono text-xs tabular-nums text-muted-foreground transition-colors hover:bg-surface-strong hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", ), h.DataAttribute("base-ui-tooltip-trigger", ""), h.DataAttribute("slot", "tooltip-trigger"), diff --git a/apps/web/src/page/errors/issue/view-tables.ts b/apps/web/src/page/errors/issue/view-tables.ts index 95b0c524d6..8af098f069 100644 --- a/apps/web/src/page/errors/issue/view-tables.ts +++ b/apps/web/src/page/errors/issue/view-tables.ts @@ -130,7 +130,7 @@ const occurrenceRow = (h: HtmlBuilder, trace: ErrorIssueSampleTrace, clock ), h.Class( cn( - "inline-flex items-center gap-1 rounded-full border border-border/60 bg-muted/40 px-2 py-0.5", + "inline-flex items-center gap-1 rounded-full border border-border-subtle bg-surface-sunken px-2 py-0.5", "font-mono text-2xs text-muted-foreground tabular-nums", "transition-colors hover:border-primary/40 hover:bg-primary/10 hover:text-primary", ), diff --git a/apps/web/src/page/errors/issue/view-verification.ts b/apps/web/src/page/errors/issue/view-verification.ts index f277dd4ec1..876d763597 100644 --- a/apps/web/src/page/errors/issue/view-verification.ts +++ b/apps/web/src/page/errors/issue/view-verification.ts @@ -117,7 +117,7 @@ export const verificationCard = ( ? [ note( h, - "mt-2 text-xs text-muted-foreground/80", + "mt-2 text-xs text-foreground-subtle", "Occurrences from builds that predate the merge were ignored. Those are older clients still running the broken version.", ), ] @@ -141,7 +141,7 @@ export const verificationCard = ( ? [ note( h, - "mt-2 text-xs text-muted-foreground/80", + "mt-2 text-xs text-foreground-subtle", "First check was inconclusive; watching for longer.", ), ] diff --git a/apps/web/src/page/errors/kit/actor.ts b/apps/web/src/page/errors/kit/actor.ts index 7fd6803a23..c6b9727967 100644 --- a/apps/web/src/page/errors/kit/actor.ts +++ b/apps/web/src/page/errors/kit/actor.ts @@ -2,13 +2,13 @@ import type { ActorDocument } from "@maple/domain/http" import { internalAgentLabel } from "@maple/domain/system-agents" import { EMPTY_VALUE } from "@maple/ui/lib/format" import { initialsFrom } from "@maple/ui/lib/initials" -import { gradientFor } from "@maple/ui/lib/replay" import { AGENT_ACCENT } from "@maple/ui/lib/tone" import { shortId as truncateId } from "@maple/ui/lib/ids" import { cn } from "@maple/ui/lib/utils" import { avatarFallbackStyles, avatarStyles } from "@maple/ui/styles/ui/avatar" import type { Html, HtmlBuilder } from "foldkit/html" import { icon } from "../../../ui/icon" +import { warmAvatarTone } from "../../../ui/avatar-tone" // Actor avatars and chips. // TODO(actor-directory): people should resolve through the Clerk member directory; here every @@ -83,7 +83,7 @@ export const identityAvatar = ( ], ) } - const gradient = cn("bg-gradient-to-br text-white", gradientFor(identity.seed)) + const gradient = warmAvatarTone(identity.seed) const mark = identity.initials === "" ? icon(h, "UserIcon", { className: "size-[60%]" }) : identity.initials // The initials show until the photo loads; photos are not loaded here yet. @@ -91,7 +91,7 @@ export const identityAvatar = ( return h.span( [ h.AriaHidden(true), - h.Class(cn(avatarStyles, cn(base, "ring-1 ring-border/60"))), + h.Class(cn(avatarStyles, cn(base, "ring-1 ring-border-subtle"))), h.DataAttribute("slot", "avatar"), ], [ diff --git a/apps/web/src/page/errors/kit/occurrences-table.ts b/apps/web/src/page/errors/kit/occurrences-table.ts index 0374bd0bba..d2c4f6bdfc 100644 --- a/apps/web/src/page/errors/kit/occurrences-table.ts +++ b/apps/web/src/page/errors/kit/occurrences-table.ts @@ -15,7 +15,7 @@ import { relativeTime } from "../../kit/relative-time" export type OccurrencesTableInputs = Readonly<{ nowMs: number; timeZone: string }> const TRACE_PILL = cn( - "inline-flex items-center gap-1 rounded-full border border-border/60 bg-muted/40 px-2 py-0.5", + "inline-flex items-center gap-1 rounded-full border border-border-subtle bg-surface-sunken px-2 py-0.5", "font-mono text-2xs text-muted-foreground tabular-nums", "transition-colors hover:border-primary/40 hover:bg-primary/10 hover:text-primary", ) diff --git a/apps/web/src/page/errors/kit/quick-pick.ts b/apps/web/src/page/errors/kit/quick-pick.ts index 5a1a914b65..9021df8418 100644 --- a/apps/web/src/page/errors/kit/quick-pick.ts +++ b/apps/web/src/page/errors/kit/quick-pick.ts @@ -206,7 +206,7 @@ const row = (h: HtmlBuilder, options: ViewOptions, item: QuickPickItem, h.span( [ h.Class( - "w-3 shrink-0 text-right text-2xs tabular-nums text-muted-foreground/70", + "w-3 shrink-0 text-right text-2xs tabular-nums text-foreground-subtle", ), ], [item.shortcut], @@ -232,7 +232,7 @@ const content = (h: HtmlBuilder, options: ViewOptions): ReadonlyArray( statusDot(h, { tone: "custom", className: "bg-current" }), h.span([h.Class(cn("truncate", options.compact === true && "hidden @xl/page:inline"))], [label]), ...(withConfidence && investigation.confidence && investigation.status === "diagnosed" - ? [h.span([h.Class("text-muted-foreground/60")], ["· ", investigation.confidence])] + ? [h.span([h.Class("text-foreground-subtle")], ["· ", investigation.confidence])] : []), ], ) diff --git a/apps/web/src/page/infra-integrations/aws/list/view-table.ts b/apps/web/src/page/infra-integrations/aws/list/view-table.ts index df7077a753..a9500d9860 100644 --- a/apps/web/src/page/infra-integrations/aws/list/view-table.ts +++ b/apps/web/src/page/infra-integrations/aws/list/view-table.ts @@ -58,7 +58,7 @@ type Column = Readonly<{ }> const MUTED = "font-mono text-2xs text-muted-foreground" -const NUMBER = "font-mono text-xs tabular-nums text-foreground/80" +const NUMBER = "font-mono text-xs tabular-nums text-foreground-soft" const reading = (view: ResourceView, key: string) => view.readings[key]?.value ?? null diff --git a/apps/web/src/page/infra-integrations/aws/list/view.ts b/apps/web/src/page/infra-integrations/aws/list/view.ts index a3bc22ba92..c44bea3bf4 100644 --- a/apps/web/src/page/infra-integrations/aws/list/view.ts +++ b/apps/web/src/page/infra-integrations/aws/list/view.ts @@ -291,7 +291,7 @@ const description = (h: H, status: AwsStatus | null): Html | string => { const regions = [ ...new Set(status.connections.flatMap((connection) => connection.metric_stream?.regions ?? [])), ] - const mono = (text: string) => h.span([h.Class("font-mono text-xs text-foreground/80")], [text]) + const mono = (text: string) => h.span([h.Class("font-mono text-xs text-foreground-soft")], [text]) return h.span( [], [ diff --git a/apps/web/src/page/infra-integrations/cloudflare/list/view-accounts.ts b/apps/web/src/page/infra-integrations/cloudflare/list/view-accounts.ts index 2e47b99df4..418d350fd3 100644 --- a/apps/web/src/page/infra-integrations/cloudflare/list/view-accounts.ts +++ b/apps/web/src/page/infra-integrations/cloudflare/list/view-accounts.ts @@ -97,7 +97,7 @@ export const accountsStrip = ( h.Type("button"), h.OnClick(Message.ClickedAccount({ accountId: account.accountId })), h.Class( - "flex flex-1 flex-col gap-2 border-b px-4 py-3 text-left transition-colors last:border-0 hover:bg-muted/50 md:border-b-0 md:border-l md:first:border-l-0", + "flex flex-1 flex-col gap-2 border-b px-4 py-3 text-left transition-colors last:border-0 hover:bg-surface-sunken md:border-b-0 md:border-l md:first:border-l-0", ), ], [ diff --git a/apps/web/src/page/infra-integrations/cloudflare/list/view-tables.ts b/apps/web/src/page/infra-integrations/cloudflare/list/view-tables.ts index 82338048e0..a577974fcb 100644 --- a/apps/web/src/page/infra-integrations/cloudflare/list/view-tables.ts +++ b/apps/web/src/page/infra-integrations/cloudflare/list/view-tables.ts @@ -83,11 +83,11 @@ const zoneColumns = ( showLatency: boolean, ): ReadonlyArray => [ zoneHead(h, "Zone", NAME, { key: "zoneName", sort }), - ...(showAccount ? [zoneHead(h, "Account", "w-[120px]", { hidden: "hidden lg:flex" })] : []), - zoneHead(h, "Requests", "w-[190px]", { key: "requests", sort }), - zoneHead(h, "Status mix", "w-[200px]", { key: "clientErrorRate", sort, hidden: "hidden md:flex" }), - zoneHead(h, "5xx", "w-[80px]", { key: "errorRate", sort, align: "right" }), - zoneHead(h, "Cache hit", "w-[120px]", { + ...(showAccount ? [zoneHead(h, "Account", "w-32", { hidden: "hidden lg:flex" })] : []), + zoneHead(h, "Requests", "w-48", { key: "requests", sort }), + zoneHead(h, "Status mix", "w-52", { key: "clientErrorRate", sort, hidden: "hidden md:flex" }), + zoneHead(h, "5xx", "w-20", { key: "errorRate", sort, align: "right" }), + zoneHead(h, "Cache hit", "w-32", { key: "cacheHitRate", sort, align: "right", @@ -95,7 +95,7 @@ const zoneColumns = ( }), ...(showLatency ? [ - zoneHead(h, "TTFB p99", "w-[80px]", { + zoneHead(h, "TTFB p99", "w-20", { key: "ttfbP99Ms", sort, align: "right", @@ -103,7 +103,7 @@ const zoneColumns = ( }), ] : []), - zoneHead(h, "Bandwidth", "w-[100px]", { key: "bytes", sort, align: "right", hidden: "hidden md:flex" }), + zoneHead(h, "Bandwidth", "w-24", { key: "bytes", sort, align: "right", hidden: "hidden md:flex" }), ] export const zoneTableLoading = (h: H): Html => @@ -113,11 +113,11 @@ export const zoneTableLoading = (h: H): Html => zoneColumns(h, undefined, false, false), skeletonRows(h, 4, () => [ h.div([h.Class(cn(NAME, "space-y-1.5"))], [skeleton(h, "h-3.5 w-40"), skeleton(h, "h-2.5 w-24")]), - skeleton(h, "h-4 w-[190px]"), - skeleton(h, "hidden h-1.5 w-[200px] md:block"), - skeleton(h, "h-3 w-[80px]"), - skeleton(h, "hidden h-3 w-[120px] lg:block"), - skeleton(h, "hidden h-3 w-[100px] md:block"), + skeleton(h, "h-4 w-48"), + skeleton(h, "hidden h-1.5 w-52 md:block"), + skeleton(h, "h-3 w-20"), + skeleton(h, "hidden h-3 w-32 lg:block"), + skeleton(h, "hidden h-3 w-24 md:block"), ]), ) @@ -176,10 +176,10 @@ const statusMix = (h: H, zone: ZoneRow, rated: boolean): Html => { title: undefined, } return h.div( - [h.Class("hidden w-[200px] items-center gap-2.5 md:flex")], + [h.Class("hidden w-52 items-center gap-2.5 md:flex")], [ segmentedBar(h, { - className: "w-[100px] shrink-0 gap-px bg-transparent", + className: "w-24 shrink-0 gap-px bg-transparent", minVisible: 2, label: `2xx ${zone.requests2xx}, 3xx ${zone.requests3xx}, 4xx ${zone.errors4xx}, 5xx ${zone.errors5xx}`, segments: [ @@ -248,17 +248,17 @@ const zoneRow = ( h.div( [ h.Class( - "hidden w-[120px] truncate font-mono text-2xs text-muted-foreground lg:block", + "hidden w-32 truncate font-mono text-2xs text-muted-foreground lg:block", ), ], [options.accounts.get(zone.serviceName) ?? EMPTY_VALUE], ), ]), h.div( - [h.Class("flex w-[190px] items-center gap-3")], + [h.Class("flex w-48 items-center gap-3")], [ h.span( - [h.Class("w-[56px] shrink-0 font-mono text-xs tabular-nums text-foreground/80")], + [h.Class("w-[56px] shrink-0 font-mono text-xs tabular-nums text-foreground-soft")], [formatNumber(zone.requests)], ), requestSpark(h, options.spark, zone, options.sparks?.get(zone.serviceName)), @@ -269,7 +269,7 @@ const zoneRow = ( [ h.Class( cn( - "w-[80px]", + "w-20", NUMBER, rated ? errorRateClass(zone.errorRate) : "text-muted-foreground", ), @@ -278,10 +278,10 @@ const zoneRow = ( [rated ? formatErrorRate(zone.errorRate) : EMPTY_VALUE], ), h.div( - [h.Class("hidden w-[120px] flex-col items-end gap-0.5 lg:flex")], + [h.Class("hidden w-32 flex-col items-end gap-0.5 lg:flex")], [ h.span( - [h.Class("font-mono text-xs tabular-nums text-foreground/80")], + [h.Class("font-mono text-xs tabular-nums text-foreground-soft")], [zone.cacheHitRate === null ? EMPTY_VALUE : formatPercentColumn(zone.cacheHitRate)], ), h.span( @@ -297,13 +297,13 @@ const zoneRow = ( ...(options.showLatency ? [ h.div( - [h.Class(cn("hidden w-[80px] text-foreground/80 lg:block", NUMBER))], + [h.Class(cn("hidden w-20 text-foreground-soft lg:block", NUMBER))], [zone.ttfbP99Ms > 0 ? formatLatency(zone.ttfbP99Ms) : EMPTY_VALUE], ), ] : []), h.div( - [h.Class(cn("hidden w-[100px] text-foreground/80 md:block", NUMBER))], + [h.Class(cn("hidden w-24 text-foreground-soft md:block", NUMBER))], [formatBytes(zone.bytes)], ), ], @@ -404,21 +404,21 @@ const workerRow = (h: H, row: WorkerListRow, accounts: ReadonlyMap= CPU_HEAVY_P99_MS ? "text-severity-warn" : "text-foreground/80", + row.cpuP99Ms >= CPU_HEAVY_P99_MS ? "text-severity-warn" : "text-foreground-soft", ), ), ], @@ -442,9 +442,9 @@ const workerRow = (h: H, row: WorkerListRow, accounts: ReadonlyMap= SLOW_P99_MS ? "text-severity-warn" : "text-foreground/80", + row.durationP99Ms >= SLOW_P99_MS ? "text-severity-warn" : "text-foreground-soft", ), ), ], @@ -471,11 +471,11 @@ export const workerTable = ( columnHead(h, { label: "Worker", width: "w-0 flex-1 min-w-[220px]" }), ...(options.accounts === undefined ? [] - : [columnHead(h, { label: "Account", width: "w-[110px]", hidden: "hidden lg:flex" })]), - columnHead(h, { label: "Invocations", align: "right", width: "w-[90px]" }), - columnHead(h, { label: "Errors", align: "right", width: "w-[80px]" }), - columnHead(h, { label: "CPU p99", align: "right", width: "w-[80px]", hidden: "hidden md:flex" }), - columnHead(h, { label: "Duration p99", align: "right", width: "w-[100px]" }), + : [columnHead(h, { label: "Account", width: "w-28", hidden: "hidden lg:flex" })]), + columnHead(h, { label: "Invocations", align: "right", width: "w-24" }), + columnHead(h, { label: "Errors", align: "right", width: "w-20" }), + columnHead(h, { label: "CPU p99", align: "right", width: "w-20", hidden: "hidden md:flex" }), + columnHead(h, { label: "Duration p99", align: "right", width: "w-24" }), ], options.rows.length === 0 ? [dataTableEmpty(h, [options.emptyMessage ?? "No Worker invocations in the selected window."])] @@ -485,13 +485,13 @@ export const workerTable = ( // QUEUES const QUEUE_ROW = - "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50" + "flex items-center gap-4 border-b border-border-subtle px-4 py-3 last:border-0 hover:bg-surface-sunken" const numCell = (h: H, value: string, hidden?: boolean): Html => h.div( [ h.Class( - `w-[110px] text-right font-mono text-xs tabular-nums text-foreground/80 ${hidden === true ? "hidden md:block" : ""}`, + `w-28 text-right font-mono text-xs tabular-nums text-foreground-soft ${hidden === true ? "hidden md:block" : ""}`, ), ], [value], @@ -524,15 +524,15 @@ export const queueTable = ( { ariaLabel: "Cloudflare queues", isWaiting: options.isWaiting }, [ queueHead(h, "Queue", "queueName", sort, "w-0 flex-1 min-w-[220px]"), - queueHead(h, "Backlog avg", "backlogMessages", sort, "w-[110px]", "right"), - queueHead(h, "Backlog peak", "backlogMessagesMax", sort, "w-[110px]", "right"), + queueHead(h, "Backlog avg", "backlogMessages", sort, "w-28", "right"), + queueHead(h, "Backlog peak", "backlogMessagesMax", sort, "w-28", "right"), columnHead(h, { label: "Backlog size", align: "right", - width: "w-[110px]", + width: "w-28", hidden: "hidden md:flex", }), - queueHead(h, "Consumers", "consumerConcurrency", sort, "w-[110px]", "right"), + queueHead(h, "Consumers", "consumerConcurrency", sort, "w-28", "right"), ], sorted.length === 0 ? [dataTableEmpty(h, ["No queue activity in the selected window."])] diff --git a/apps/web/src/page/infra-integrations/cloudflare/worker/view.ts b/apps/web/src/page/infra-integrations/cloudflare/worker/view.ts index 0818d1372d..b525f08b57 100644 --- a/apps/web/src/page/infra-integrations/cloudflare/worker/view.ts +++ b/apps/web/src/page/infra-integrations/cloudflare/worker/view.ts @@ -289,7 +289,7 @@ const outcomes = (h: H, detail: WorkerDetail): Html => { return panel(h, {}, [ panelHeader(h, { title: "Outcomes" }), h.div( - [h.Class("divide-y divide-border/60")], + [h.Class("divide-y divide-border-subtle")], totals.byStatus.map(({ status, count }) => { const success = status === "success" const share = totals.invocations > 0 ? count / totals.invocations : 0 @@ -337,7 +337,7 @@ const outcomes = (h: H, detail: WorkerDetail): Html => { ], }), h.span( - [h.Class("w-20 text-right font-mono text-xs tabular-nums text-foreground/80")], + [h.Class("w-20 text-right font-mono text-xs tabular-nums text-foreground-soft")], [formatNumber(count)], ), h.span( diff --git a/apps/web/src/page/infra-integrations/cloudflare/zone/view-breakdown.ts b/apps/web/src/page/infra-integrations/cloudflare/zone/view-breakdown.ts index a688a32b34..72c8399731 100644 --- a/apps/web/src/page/infra-integrations/cloudflare/zone/view-breakdown.ts +++ b/apps/web/src/page/infra-integrations/cloudflare/zone/view-breakdown.ts @@ -25,7 +25,7 @@ import { panelScope, type Trigger } from "./view-scope" type H = HtmlBuilder const ROW_CLASS = - "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50" + "flex items-center gap-4 border-b border-border-subtle px-4 py-3 last:border-0 hover:bg-surface-sunken" const MONO_LINK = "font-mono text-3xs text-muted-foreground underline-offset-2 transition-colors hover:text-foreground hover:underline" @@ -52,7 +52,7 @@ const compactFilterInput = (h: H, value: string, placeholder: string, label: str h.label( [ h.Class( - "flex h-6 items-center gap-1.5 rounded-sm border border-border/60 bg-background/60 px-2 transition-colors focus-within:border-ring min-w-0 max-w-xs flex-1", + "flex h-6 items-center gap-1.5 rounded-sm border border-border-subtle bg-background/60 px-2 transition-colors focus-within:border-ring min-w-0 max-w-xs flex-1", ), ], [ @@ -130,9 +130,9 @@ const table = ( }, [ head(dimension.column, "key", "w-0 flex-1 min-w-[220px]"), - head("Requests", "requests", "w-[110px]"), - head("Error rate", "errorRate", "w-[90px]"), - head("Bandwidth", "bytes", "w-[90px]", "hidden md:flex"), + head("Requests", "requests", "w-28"), + head("Error rate", "errorRate", "w-24"), + head("Bandwidth", "bytes", "w-24", "hidden md:flex"), ], sorted.length === 0 ? [dataTableEmpty(h, [options.emptyMessage])] @@ -184,7 +184,7 @@ const table = ( h.div( [ h.Class( - "w-[110px] text-right font-mono text-xs tabular-nums text-foreground/80", + "w-28 text-right font-mono text-xs tabular-nums text-foreground-soft", ), h.Title(`${formatPercent(row.share)} of listed requests`), ], @@ -194,7 +194,7 @@ const table = ( [ h.Class( cn( - "w-[90px] text-right font-mono text-xs tabular-nums", + "w-24 text-right font-mono text-xs tabular-nums", errorRateClass(row.errorRate), ), ), @@ -204,7 +204,7 @@ const table = ( h.div( [ h.Class( - "hidden w-[90px] text-right font-mono text-xs tabular-nums text-foreground/80 md:block", + "hidden w-24 text-right font-mono text-xs tabular-nums text-foreground-soft md:block", ), ], [formatBytes(row.bytes)], diff --git a/apps/web/src/page/infra-integrations/cloudflare/zone/view-sections.ts b/apps/web/src/page/infra-integrations/cloudflare/zone/view-sections.ts index 5b4d9aa4e5..7d4f1de35e 100644 --- a/apps/web/src/page/infra-integrations/cloudflare/zone/view-sections.ts +++ b/apps/web/src/page/infra-integrations/cloudflare/zone/view-sections.ts @@ -31,7 +31,7 @@ export type SectionContext = Readonly<{ const MAX_LEGEND_CHIPS = 8 const ROW_CLASS = - "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50" + "flex items-center gap-4 border-b border-border-subtle px-4 py-3 last:border-0 hover:bg-surface-sunken" export const SCOPE_IDS = { dns: "cf-scope-dns", @@ -150,8 +150,8 @@ export const dnsSection = ( { ariaLabel: "Top DNS query names", isWaiting }, [ columnHead(h, { label: "Query name", width: "w-0 flex-1 min-w-[220px]" }), - columnHead(h, { label: "Queries", align: "right", width: "w-[100px]" }), - columnHead(h, { label: "NXDOMAIN", align: "right", width: "w-[110px]" }), + columnHead(h, { label: "Queries", align: "right", width: "w-24" }), + columnHead(h, { label: "NXDOMAIN", align: "right", width: "w-28" }), ], rows.length === 0 ? [dataTableEmpty(h, ["No DNS queries in the selected window."])] @@ -170,7 +170,7 @@ export const dnsSection = ( h.div( [ h.Class( - "w-[100px] text-right font-mono text-xs tabular-nums text-foreground/80", + "w-24 text-right font-mono text-xs tabular-nums text-foreground-soft", ), ], [formatNumber(row.queries)], @@ -178,7 +178,7 @@ export const dnsSection = ( h.div( [ h.Class( - "w-[110px] text-right font-mono text-xs tabular-nums text-foreground/80", + "w-28 text-right font-mono text-xs tabular-nums text-foreground-soft", ), ], [ @@ -262,10 +262,10 @@ export const securitySection = ( { ariaLabel: "Top security rules", isWaiting }, [ columnHead(h, { label: "Rule", width: "w-0 flex-1 min-w-[200px]" }), - columnHead(h, { label: "Source", width: "w-[130px]", hidden: "hidden md:flex" }), - columnHead(h, { label: "Action", width: "w-[130px]" }), - columnHead(h, { label: "Host", width: "w-[180px]", hidden: "hidden lg:flex" }), - columnHead(h, { label: "Events", align: "right", width: "w-[90px]" }), + columnHead(h, { label: "Source", width: "w-32", hidden: "hidden md:flex" }), + columnHead(h, { label: "Action", width: "w-32" }), + columnHead(h, { label: "Host", width: "w-44", hidden: "hidden lg:flex" }), + columnHead(h, { label: "Events", align: "right", width: "w-24" }), ], rows.length === 0 ? [dataTableEmpty(h, ["No security events in the selected window."])] @@ -281,16 +281,16 @@ export const securitySection = ( row.ruleId, ), cell( - "hidden w-[130px] truncate font-mono text-xs text-foreground/80 md:block", + "hidden w-32 truncate font-mono text-xs text-foreground-soft md:block", row.source, ), - cell("w-[130px] truncate font-mono text-xs text-foreground/80", row.action), + cell("w-32 truncate font-mono text-xs text-foreground-soft", row.action), cell( - "hidden w-[180px] truncate font-mono text-xs text-foreground/80 lg:block", + "hidden w-44 truncate font-mono text-xs text-foreground-soft lg:block", row.host, ), cell( - "w-[90px] text-right font-mono text-xs tabular-nums text-foreground/80", + "w-24 text-right font-mono text-xs tabular-nums text-foreground-soft", formatNumber(row.events), ), ], diff --git a/apps/web/src/page/infra-integrations/gcp/gcp-message.ts b/apps/web/src/page/infra-integrations/gcp/gcp-message.ts index 5302137dbb..a0bf833412 100644 --- a/apps/web/src/page/infra-integrations/gcp/gcp-message.ts +++ b/apps/web/src/page/infra-integrations/gcp/gcp-message.ts @@ -66,7 +66,7 @@ export const gcpMessage = (h: HtmlBuilder, text: string): Html => { body.map((sentence) => h.li([], linked(h, sentence))), ), ]), - ...(answer === null ? [] : [h.p([h.Class("text-2xs text-muted-foreground/80")], [answer])]), + ...(answer === null ? [] : [h.p([h.Class("text-2xs text-foreground-subtle")], [answer])]), ], ) } diff --git a/apps/web/src/page/infra-integrations/gcp/list/view-resources.ts b/apps/web/src/page/infra-integrations/gcp/list/view-resources.ts index 4fc6af84e8..68c1fdf4a0 100644 --- a/apps/web/src/page/infra-integrations/gcp/list/view-resources.ts +++ b/apps/web/src/page/infra-integrations/gcp/list/view-resources.ts @@ -29,15 +29,15 @@ import { workloadHref } from "./view-rows" // TODO(select-align): these Selects should open below the trigger (`alignItemWithTrigger={false}`). const ALL = "all" -const CELL = "truncate font-mono text-xs text-foreground/80" +const CELL = "truncate font-mono text-xs text-foreground-soft" const columns = (h: H): ReadonlyArray => [ columnHead(h, { label: "Resource", width: "w-0 flex-1 min-w-[220px]" }), - columnHead(h, { label: "Type", width: "w-[170px]" }), - columnHead(h, { label: "Project", width: "w-[200px]" }), - columnHead(h, { label: "Location", width: "w-[120px]" }), - columnHead(h, { label: "State", width: "w-[120px]" }), - columnHead(h, { label: "Labels", width: "w-[150px]", hidden: "hidden lg:flex" }), + columnHead(h, { label: "Type", width: "w-44" }), + columnHead(h, { label: "Project", width: "w-52" }), + columnHead(h, { label: "Location", width: "w-32" }), + columnHead(h, { label: "State", width: "w-32" }), + columnHead(h, { label: "Labels", width: "w-36", hidden: "hidden lg:flex" }), ] const loading = (h: H): Html => @@ -47,11 +47,11 @@ const loading = (h: H): Html => columns(h), skeletonRows(h, 5, () => [ skeleton(h, "h-4 w-0 min-w-[220px] flex-1"), - skeleton(h, "h-3 w-[170px]"), - skeleton(h, "h-3 w-[200px]"), - skeleton(h, "h-3 w-[120px]"), - skeleton(h, "h-3 w-[120px]"), - skeleton(h, "hidden h-3 w-[150px] lg:block"), + skeleton(h, "h-3 w-44"), + skeleton(h, "h-3 w-52"), + skeleton(h, "h-3 w-32"), + skeleton(h, "h-3 w-32"), + skeleton(h, "hidden h-3 w-36 lg:block"), ]), ) @@ -84,7 +84,7 @@ const filterSelect = ( }) const metaChip = (h: H, text: string): Html => - h.span([h.Class("font-mono text-3xs text-muted-foreground/80")], [text]) + h.span([h.Class("font-mono text-3xs text-foreground-subtle")], [text]) const resourceRow = (h: H, resource: Resources["resources"][number], timeSearch: TimeSearch): Html => { const labels = Object.entries(resource.labels).map(([key, value]) => `${key}: ${value}`) @@ -101,25 +101,25 @@ const resourceRow = (h: H, resource: Resources["resources"][number], timeSearch: ], [gcpResourceName(resource)], ), - h.div([h.Class("w-[170px] truncate text-xs text-foreground/80"), h.Title(type)], [type]), - h.div([h.Class(`w-[200px] ${CELL}`), h.Title(resource.projectId)], [resource.projectId]), + h.div([h.Class("w-44 truncate text-xs text-foreground-soft"), h.Title(type)], [type]), + h.div([h.Class(`w-52 ${CELL}`), h.Title(resource.projectId)], [resource.projectId]), h.div( [ - h.Class(`w-[120px] ${CELL}`), + h.Class(`w-32 ${CELL}`), ...(resource.location === null ? [] : [h.Title(resource.location)]), ], [resource.location ?? EMPTY_VALUE], ), h.div( [ - h.Class("w-[120px] truncate text-xs text-foreground/80"), + h.Class("w-32 truncate text-xs text-foreground-soft"), ...(state === null ? [] : [h.Title(state)]), ], [state ?? EMPTY_VALUE], ), h.div( [ - h.Class("hidden w-[150px] items-center gap-2 whitespace-nowrap lg:flex"), + h.Class("hidden w-36 items-center gap-2 whitespace-nowrap lg:flex"), h.Title(labels.join("\n")), ], [ @@ -134,7 +134,7 @@ const resourceRow = (h: H, resource: Resources["resources"][number], timeSearch: ? h.div( [ h.Class( - "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50", + "flex items-center gap-4 border-b border-border-subtle px-4 py-3 last:border-0 hover:bg-surface-sunken", ), ], cells, diff --git a/apps/web/src/page/infra-integrations/gcp/list/view-rows.ts b/apps/web/src/page/infra-integrations/gcp/list/view-rows.ts index 2c82c25a90..9c3adc59d3 100644 --- a/apps/web/src/page/infra-integrations/gcp/list/view-rows.ts +++ b/apps/web/src/page/infra-integrations/gcp/list/view-rows.ts @@ -143,7 +143,7 @@ export const spark = ( /** "880K" over "880.0K": a trailing ".0" carries nothing, so the column drops it. */ const formatVolume = (value: number): string => formatNumber(value).replace(/\.0(?=[KMBT]$)/, "") -const VOLUME_CELL = "flex w-[180px] items-center gap-3" +const VOLUME_CELL = "flex w-44 items-center gap-3" const VOLUME_NUMBER_SLOT = "w-[56px] shrink-0" /** The head over a `volumeCell` column: its label ends where the right-aligned counts end. */ @@ -174,7 +174,7 @@ export const volumeCell = ( h.Class( cn( VOLUME_NUMBER_SLOT, - "text-right font-mono text-xs tabular-nums text-foreground/80", + "text-right font-mono text-xs tabular-nums text-foreground-soft", ), ), ], diff --git a/apps/web/src/page/infra-integrations/gcp/list/view-tables.ts b/apps/web/src/page/infra-integrations/gcp/list/view-tables.ts index e56da33cff..fabbdbca98 100644 --- a/apps/web/src/page/infra-integrations/gcp/list/view-tables.ts +++ b/apps/web/src/page/infra-integrations/gcp/list/view-tables.ts @@ -96,12 +96,12 @@ const statusMix = (h: H, row: GcpServiceRow): Html => { return GCP_SERVICE_RULES.inScope(row, "idle") ? h.div( [ - h.Class(cn("hidden w-[170px] md:block", SUB)), + h.Class(cn("hidden w-44 md:block", SUB)), h.Title("No requests, instance time billed"), ], ["idle, still billed"], ) - : h.div([h.Class(cn("hidden w-[170px] md:block", SUB))], ["no traffic"]) + : h.div([h.Class(cn("hidden w-44 md:block", SUB))], ["no traffic"]) const failedShare = row.failed / row.requests const clientShare = row.clientErrors / row.requests const rated = GCP_SERVICE_RULES.inScope(row, "serving5xx") @@ -117,10 +117,10 @@ const statusMix = (h: H, row: GcpServiceRow): Html => { : { text: row.service === "cloudRun" ? "no errors" : "all ok", className: undefined } const ok = row.requests - row.clientErrors - row.failed return h.div( - [h.Class("hidden w-[170px] items-center gap-2.5 md:flex")], + [h.Class("hidden w-44 items-center gap-2.5 md:flex")], [ segmentedBar(h, { - className: "w-[72px] shrink-0 gap-px bg-transparent", + className: "w-20 shrink-0 gap-px bg-transparent", minVisible: 2, label: `ok ${ok}, 4xx ${row.clientErrors}, ${failedWord} ${row.failed}`, segments: [ @@ -155,7 +155,7 @@ const serviceMeta = (h: H, row: GcpServiceRow, showProject: boolean): ReadonlyAr // Flex drops a leading space, so the note carries its own separator and gap, like metaLine's. const note = h.span( [h.Class("flex items-center gap-x-2 md:hidden")], - [h.span([h.Class("text-foreground/20")], ["·"]), "idle, still billed"], + [h.span([h.Class("text-foreground-faint")], ["·"]), "idle, still billed"], ) const last = items[items.length - 1] // A string keeps metaLine's 28ch cap, which it applies only to plain strings. @@ -178,11 +178,11 @@ export const servicesTable = ( dotLane(h), head(h, "Service", NAME), volumeHead(h, "Requests"), - head(h, "Status mix", "w-[170px]", undefined, "hidden md:flex"), - head(h, "5xx", "w-[64px]", "right"), - head(h, "Latency p95", "w-[88px]", "right"), - head(h, "Instances", "w-[76px]", "right", "hidden lg:flex"), - head(h, "CPU p95", "w-[64px]", "right", "hidden md:flex"), + head(h, "Status mix", "w-44", undefined, "hidden md:flex"), + head(h, "5xx", "w-16", "right"), + head(h, "Latency p95", "w-24", "right"), + head(h, "Instances", "w-20", "right", "hidden lg:flex"), + head(h, "CPU p95", "w-16", "right", "hidden md:flex"), ], rowsOrEmpty( h, @@ -211,7 +211,7 @@ export const servicesTable = ( [ h.Class( cn( - "w-[64px]", + "w-16", NUMBER, rate === undefined ? "text-muted-foreground" : errorRateClass(rate), ), @@ -223,18 +223,18 @@ export const servicesTable = ( [ h.Class( cn( - "w-[88px]", + "w-24", NUMBER, (row.latencyP95 ?? 0) >= GCP_SLOW_P95_SECONDS ? TONE_TEXT.warn - : "text-foreground/80", + : "text-foreground-soft", ), ), ], [row.latencyP95 === undefined ? EMPTY_VALUE : seconds(row.latencyP95)], ), h.div( - [h.Class(cn("hidden w-[76px] text-foreground/80 lg:block", NUMBER))], + [h.Class(cn("hidden w-20 text-foreground-soft lg:block", NUMBER))], [ row.instances === undefined ? EMPTY_VALUE @@ -242,7 +242,7 @@ export const servicesTable = ( ], ), h.div( - [h.Class(cn("hidden w-[64px] md:block", NUMBER, BAR_VALUE_TONE[cpuLevel]))], + [h.Class(cn("hidden w-16 md:block", NUMBER, BAR_VALUE_TONE[cpuLevel]))], [row.cpuP95 === undefined ? EMPTY_VALUE : formatPercentColumn(row.cpuP95)], ), ], @@ -270,10 +270,10 @@ export const subscriptionsTable = ( dotLane(h), head(h, "Subscription", NAME), volumeHead(h, "Delivered"), - head(h, "Backlog", "w-[200px]"), - head(h, "Oldest unacked", "w-[104px]", "right"), - head(h, "Push failed", "w-[84px]", "right", "hidden md:flex"), - head(h, "Dead-lettered", "w-[96px]", "right", "hidden md:flex"), + head(h, "Backlog", "w-52"), + head(h, "Oldest unacked", "w-28", "right"), + head(h, "Push failed", "w-20", "right", "hidden md:flex"), + head(h, "Dead-lettered", "w-24", "right", "hidden md:flex"), ], rowsOrEmpty( h, @@ -302,17 +302,17 @@ export const subscriptionsTable = ( row.deliveredSpark, ), h.div( - [h.Class("flex w-[200px] items-center gap-3")], + [h.Class("flex w-52 items-center gap-3")], [ h.div( - [h.Class("flex w-[64px] shrink-0 flex-col")], + [h.Class("flex w-16 shrink-0 flex-col")], [ h.span( [ h.Class( cn( "font-mono text-xs tabular-nums", - growing ? TONE_TEXT.crit : "text-foreground/80", + growing ? TONE_TEXT.crit : "text-foreground-soft", ), ), ], @@ -340,11 +340,11 @@ export const subscriptionsTable = ( [ h.Class( cn( - "w-[104px]", + "w-28", NUMBER, (row.oldestUnackedSeconds ?? 0) >= GCP_STALE_SECONDS ? TONE_TEXT.warn - : "text-foreground/80", + : "text-foreground-soft", ), ), ], @@ -358,7 +358,7 @@ export const subscriptionsTable = ( [ h.Class( cn( - "hidden w-[84px] md:block", + "hidden w-20 md:block", NUMBER, pushRate === undefined ? "text-muted-foreground" @@ -378,9 +378,9 @@ export const subscriptionsTable = ( [ h.Class( cn( - "hidden w-[96px] md:block", + "hidden w-24 md:block", NUMBER, - row.deadLettered > 0 ? TONE_TEXT.crit : "text-foreground/80", + row.deadLettered > 0 ? TONE_TEXT.crit : "text-foreground-soft", ), ), ], @@ -400,12 +400,12 @@ const quotaTone = (value: number) => const quotaText = (value: number | undefined) => { const tone = quotaTone(value ?? 0) - return tone === "neutral" ? "text-foreground/80" : TONE_TEXT[tone] + return tone === "neutral" ? "text-foreground-soft" : TONE_TEXT[tone] } const quotaCell = (h: H, value: number | undefined, hidden?: string): Html => h.div( - [h.Class(cn("flex w-[72px] flex-col items-end gap-1", hidden))], + [h.Class(cn("flex w-20 flex-col items-end gap-1", hidden))], [ h.span( [h.Class(cn("font-mono text-xs tabular-nums", quotaText(value)))], @@ -451,7 +451,7 @@ const queriesCell = (h: H, row: GcpDatabaseRow, ctx: RowsContext): Html => [volumeCell(h, ctx, rowSlot("gcp-sql-queries", row.keys), row.queries, row.queriesSpark)], ) : h.div( - [h.Class("hidden w-[180px] items-center gap-3 md:flex")], + [h.Class("hidden w-44 items-center gap-3 md:flex")], [ h.span( [h.Class("w-[56px] shrink-0 font-mono text-xs text-muted-foreground")], @@ -464,10 +464,10 @@ const queriesCell = (h: H, row: GcpDatabaseRow, ctx: RowsContext): Html => const queryP95Cell = (h: H, row: GcpDatabaseRow): Html => { const slow = (row.queryP95 ?? 0) >= GCP_SLOW_P95_SECONDS return h.div( - [h.Class("flex w-[80px] flex-col items-end")], + [h.Class("flex w-20 flex-col items-end")], [ h.span( - [h.Class(cn(NUMBER, slow ? TONE_TEXT.warn : "text-foreground/80"))], + [h.Class(cn(NUMBER, slow ? TONE_TEXT.warn : "text-foreground-soft"))], [row.queryP95 === undefined ? EMPTY_VALUE : seconds(row.queryP95)], ), ...(isMysql(row) || row.slowQueries > 0 @@ -488,7 +488,7 @@ const connectionsCell = (h: H, row: GcpDatabaseRow, locale: string): Html => { const idle = Math.round(row.idleInTransaction ?? 0) const count = (value: number) => value.toLocaleString(locale, { maximumFractionDigits: 0 }) return h.div( - [h.Class("flex w-[150px] flex-col items-end")], + [h.Class("flex w-36 flex-col items-end")], [ h.span( [h.Class(cn(NUMBER, quotaText(share)))], @@ -568,11 +568,11 @@ export const databasesTable = ( dotLane(h), head(h, "Instance", NAME), volumeHead(h, "Queries", "hidden md:flex"), - head(h, "Query p95", "w-[80px]", "right"), - head(h, "CPU", "w-[72px]", "right"), - head(h, "Memory", "w-[72px]", "right", "hidden md:flex"), - head(h, "Disk", "w-[72px]", "right"), - head(h, "Connections", "w-[150px]", "right"), + head(h, "Query p95", "w-20", "right"), + head(h, "CPU", "w-20", "right"), + head(h, "Memory", "w-20", "right", "hidden md:flex"), + head(h, "Disk", "w-20", "right"), + head(h, "Connections", "w-36", "right"), ], [ ...rowsOrEmpty( @@ -606,7 +606,7 @@ export const databasesTable = ( // The other services (GKE, Compute Engine, Load Balancing) --------------------------------------- const GENERIC_NAME = "w-0 flex-1 min-w-[240px]" -const VALUE_WIDTH = "w-[104px]" +const VALUE_WIDTH = "w-28" const genericHead = (h: H, service: GcpInfraServiceId): ReadonlyArray => [ dotLane(h), @@ -638,7 +638,7 @@ export const valueClass = (spec: GcpColumn, value: number | undefined): string = if (value !== undefined && spec.format === "percent" && utilizationLevel(value) !== "ok") { return BAR_VALUE_TONE[utilizationLevel(value)] } - return "text-foreground/80" + return "text-foreground-soft" } /** `GcpServiceTable`: a service without a list of its own, its curated columns. */ diff --git a/apps/web/src/page/infra-integrations/gcp/list/view.ts b/apps/web/src/page/infra-integrations/gcp/list/view.ts index 7cb4cb6e00..71c3979dcb 100644 --- a/apps/web/src/page/infra-integrations/gcp/list/view.ts +++ b/apps/web/src/page/infra-integrations/gcp/list/view.ts @@ -210,11 +210,11 @@ const regionChip = (h: H, region: string): Html => { h.span( [ h.Class( - "inline-flex items-center gap-1 rounded-sm border border-border/60 bg-background/60 py-0.5 pr-0.5 pl-1.5 font-mono text-3xs text-muted-foreground", + "inline-flex items-center gap-1 rounded-sm border border-border-subtle bg-background/60 py-0.5 pr-0.5 pl-1.5 font-mono text-3xs text-muted-foreground", ), ], [ - h.span([h.Class("max-w-[22ch] truncate text-foreground/80")], [label]), + h.span([h.Class("max-w-[22ch] truncate text-foreground-soft")], [label]), button( h, { @@ -285,7 +285,7 @@ const projectsStrip = ( h.Type("button"), h.OnClick(Message.SelectedProject({ project })), h.Class( - "flex min-w-0 flex-1 flex-col gap-2 border-b px-4 py-3 text-left transition-colors last:border-0 hover:bg-muted/50 md:border-b-0 md:border-l md:first:border-l-0", + "flex min-w-0 flex-1 flex-col gap-2 border-b px-4 py-3 text-left transition-colors last:border-0 hover:bg-surface-sunken md:border-b-0 md:border-l md:first:border-l-0", ), ], [ diff --git a/apps/web/src/page/infra-integrations/gcp/service-icon.ts b/apps/web/src/page/infra-integrations/gcp/service-icon.ts index 192a29a633..c87565fa1e 100644 --- a/apps/web/src/page/infra-integrations/gcp/service-icon.ts +++ b/apps/web/src/page/infra-integrations/gcp/service-icon.ts @@ -51,7 +51,7 @@ export const gcpServiceIcon = ( h.AriaHidden(true), h.Class( cn( - "flex shrink-0 items-center justify-center border bg-muted/40 text-foreground/70", + "flex shrink-0 items-center justify-center border bg-surface-sunken text-foreground-soft", tile.box, options.className, ), diff --git a/apps/web/src/page/infra-integrations/gcp/workload/view-charts.ts b/apps/web/src/page/infra-integrations/gcp/workload/view-charts.ts index a0a53538d5..2aa91271dd 100644 --- a/apps/web/src/page/infra-integrations/gcp/workload/view-charts.ts +++ b/apps/web/src/page/infra-integrations/gcp/workload/view-charts.ts @@ -103,7 +103,7 @@ export const correlationStrips = ( [h.Class(cn("flex items-center gap-4 px-4 py-3", index > 0 && "border-t"))], [ h.div( - [h.Class("flex w-[140px] shrink-0 flex-col gap-0.5")], + [h.Class("flex w-36 shrink-0 flex-col gap-0.5")], [ h.span( [h.Class("font-prose text-xs font-medium text-foreground")], @@ -174,7 +174,7 @@ export const workloadCharts = ( const explore = h.a( [ h.AriaLabel(`Open ${metric.name} in the metrics explorer`), - h.Class("text-muted-foreground/60 transition-colors hover:text-foreground"), + h.Class("text-foreground-subtle transition-colors hover:text-foreground"), h.Href( hrefOf( AppRoute.Metric({ diff --git a/apps/web/src/page/infra-integrations/gcp/workload/view-rail.ts b/apps/web/src/page/infra-integrations/gcp/workload/view-rail.ts index 031ac45d27..4754d1a040 100644 --- a/apps/web/src/page/infra-integrations/gcp/workload/view-rail.ts +++ b/apps/web/src/page/infra-integrations/gcp/workload/view-rail.ts @@ -33,14 +33,14 @@ const FACT_TONE = { } as const const RAIL_LINK = - "group -mx-2 flex h-8 items-center gap-2 rounded-md px-2 text-xs text-foreground/80 transition-colors hover:bg-muted/50 hover:text-foreground" + "group -mx-2 flex h-8 items-center gap-2 rounded-md px-2 text-xs text-foreground-soft transition-colors hover:bg-surface-sunken hover:text-foreground" const label = (h: H, text: string): Html => h.span([h.Class("min-w-0 flex-1 truncate")], [text]) const chevron = (h: H): Html => icon(h, "ChevronRightIcon", { size: 12, - className: "shrink-0 text-muted-foreground/50 transition-colors group-hover:text-foreground", + className: "shrink-0 text-foreground-faint transition-colors group-hover:text-foreground", }) const linkBody = (h: H, name: IconName, text: string): ReadonlyArray => [ @@ -60,7 +60,7 @@ const externalLink = (h: H, href: string, name: IconName, text: string): Html => label(h, text), icon(h, "ExternalLinkIcon", { size: 12, - className: "shrink-0 text-muted-foreground/50 transition-colors group-hover:text-foreground", + className: "shrink-0 text-foreground-faint transition-colors group-hover:text-foreground", }), ], ) diff --git a/apps/web/src/page/infra-integrations/gcp/workload/view-sql-peek.ts b/apps/web/src/page/infra-integrations/gcp/workload/view-sql-peek.ts index 71a18d971f..0144125b40 100644 --- a/apps/web/src/page/infra-integrations/gcp/workload/view-sql-peek.ts +++ b/apps/web/src/page/infra-integrations/gcp/workload/view-sql-peek.ts @@ -170,7 +170,7 @@ const stats = (h: H, peek: QueryPeek): ReadonlyArray => { ? [] : [ h.div( - [h.Class("space-y-1 rounded-md border border-severity-error/40 px-3 py-2.5")], + [h.Class("space-y-1 rounded-md border border-severity-error/40 p-3")], [ h.p( [h.Class("text-xs font-medium text-foreground")], @@ -199,13 +199,13 @@ const callers = (h: H, peek: QueryPeek, timeSearch: TimeSearch): Html => { [ sectionHead(h, "Called by", more > 0 ? `the busiest, +${more} more` : "client spans"), h.div( - [h.Class("border-y border-border/60")], + [h.Class("border-y border-border-subtle")], services.map((service) => h.a( [ h.Href(hrefOf(AppRoute.Service({ serviceName: service, search: timeSearch }))), h.Class( - "flex items-center gap-3 border-b border-border/60 px-1 py-2 transition-colors last:border-0 hover:bg-muted/50", + "flex items-center gap-3 border-b border-border-subtle px-1 py-2 transition-colors last:border-0 hover:bg-surface-sunken", ), ], [ @@ -241,7 +241,7 @@ const spanRow = (h: H, span: StatementSpan, slowestMs: number, timeZone: string) ), h.AriaLabel(`Open trace: ${span.serviceName}, ${formatLatency(span.durationMs)}`), h.Class( - "flex items-center gap-3 border-b border-border/60 px-1 py-2 transition-colors last:border-0 hover:bg-muted/50", + "flex items-center gap-3 border-b border-border-subtle px-1 py-2 transition-colors last:border-0 hover:bg-surface-sunken", ), ], [ @@ -268,7 +268,7 @@ const slowestCalls = (h: H, inputs: QueryPeekInputs): Html => { onEmpty: () => h.div( [h.Class("space-y-2 py-2"), h.AriaBusy(true)], - Array.from({ length: SPAN_ROWS }, () => skeleton(h, "h-5 w-full rounded")), + Array.from({ length: SPAN_ROWS }, () => skeleton(h, "h-5 w-full rounded-sm")), ), onFailure: (failure) => errorState(h, { @@ -286,7 +286,7 @@ const slowestCalls = (h: H, inputs: QueryPeekInputs): Html => { [ h.Class( cn( - "border-y border-border/60", + "border-y border-border-subtle", refreshingClass(AsyncData.isRefreshing(inputs.spans)), ), ), diff --git a/apps/web/src/page/infra-integrations/gcp/workload/view-sql.ts b/apps/web/src/page/infra-integrations/gcp/workload/view-sql.ts index a7face7dbf..420ad1e568 100644 --- a/apps/web/src/page/infra-integrations/gcp/workload/view-sql.ts +++ b/apps/web/src/page/infra-integrations/gcp/workload/view-sql.ts @@ -80,7 +80,7 @@ const statementRow = ( ...(isPeeked ? [h.AriaCurrent("true")] : []), h.Class( cn( - "flex w-full cursor-pointer items-center gap-4 border-b border-border/60 px-4 py-2.5 text-left transition-colors last:border-0 hover:bg-muted/50 focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset focus-visible:outline-none", + "flex w-full cursor-pointer items-center gap-4 border-b border-border-subtle px-4 py-2.5 text-left transition-colors last:border-0 hover:bg-surface-sunken focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset focus-visible:outline-none", rowSelectedClass(isPeeked), ), ), @@ -96,26 +96,26 @@ const statementRow = ( callers(h, traced), ], ), - h.div([h.Class(cn("w-[64px] text-foreground/80", NUMBER))], [formatNumber(row.calls)]), + h.div([h.Class(cn("w-16 text-foreground-soft", NUMBER))], [formatNumber(row.calls)]), h.div( [ h.Class( - cn("w-[72px]", NUMBER, db === null ? "text-muted-foreground" : latencyToneClass(db)), + cn("w-20", NUMBER, db === null ? "text-muted-foreground" : latencyToneClass(db)), ), ], [db === null ? EMPTY_VALUE : formatLatency(db)], ), h.div( - [h.Class(cn("w-[72px]", NUMBER, appP95Tone(db, app)))], + [h.Class(cn("w-20", NUMBER, appP95Tone(db, app)))], [app === undefined ? EMPTY_VALUE : formatLatency(app)], ), h.div( [ h.Class( cn( - "hidden w-[64px] md:block", + "hidden w-16 md:block", NUMBER, - (rowsPerCall ?? 0) >= MANY_ROWS ? TONE_TEXT.warn : "text-foreground/80", + (rowsPerCall ?? 0) >= MANY_ROWS ? TONE_TEXT.warn : "text-foreground-soft", ), ), ], @@ -123,11 +123,11 @@ const statementRow = ( ), h.div([h.Class(cn("w-[56px]", NUMBER, lockTone(row.lockShare)))], [formatPercent(row.lockShare)]), h.div( - [h.Class("hidden w-[112px] items-center gap-2 md:flex")], + [h.Class("hidden w-28 items-center gap-2 md:flex")], [ meter(h, { value: row.executionShare, tone: "neutral", className: "w-14" }), h.span( - [h.Class("font-mono text-2xs tabular-nums text-foreground/80")], + [h.Class("font-mono text-2xs tabular-nums text-foreground-soft")], [formatPercent(row.executionShare)], ), ], @@ -167,12 +167,12 @@ export const topQueries = (h: H, inputs: TopQueriesInputs): Html => { { ariaLabel: "Top queries", isWaiting }, [ head(h, "Statement", STATEMENT), - head(h, "Calls", "w-[64px]", "right"), - head(h, "DB p95", "w-[72px]", "right"), - head(h, "App p95", "w-[72px]", "right"), - head(h, "Rows", "w-[64px]", "right", "hidden md:flex"), + head(h, "Calls", "w-16", "right"), + head(h, "DB p95", "w-20", "right"), + head(h, "App p95", "w-20", "right"), + head(h, "Rows", "w-16", "right", "hidden md:flex"), head(h, "Lock", "w-[56px]", "right"), - head(h, "Total time", "w-[112px]", undefined, "hidden md:flex"), + head(h, "Total time", "w-28", undefined, "hidden md:flex"), h.span([h.Class(CHEVRON)], []), ], [ diff --git a/apps/web/src/page/infra-integrations/kit/chart-card.ts b/apps/web/src/page/infra-integrations/kit/chart-card.ts index ed9540754b..ef30fd7e32 100644 --- a/apps/web/src/page/infra-integrations/kit/chart-card.ts +++ b/apps/web/src/page/infra-integrations/kit/chart-card.ts @@ -42,7 +42,7 @@ const header = (h: HtmlBuilder, options: ChartCardOptions): Html | null => ...(options.scope === undefined ? [] : [options.scope]), ], ), - h.p([h.Class("text-2xs text-muted-foreground/70")], [options.description]), + h.p([h.Class("text-2xs text-foreground-subtle")], [options.description]), ], ), ], diff --git a/apps/web/src/page/infra-integrations/kit/filter-chip-rail.ts b/apps/web/src/page/infra-integrations/kit/filter-chip-rail.ts index f5f08b761d..2c1fbf0830 100644 --- a/apps/web/src/page/infra-integrations/kit/filter-chip-rail.ts +++ b/apps/web/src/page/infra-integrations/kit/filter-chip-rail.ts @@ -8,7 +8,7 @@ import { icon } from "../../../ui/icon" const VISIBLE_LIMIT = 6 const CHIP_CLASS = - "inline-flex items-center gap-1 rounded-sm border border-border/60 bg-background/60 py-0.5 pr-0.5 pl-1.5 font-mono text-3xs text-muted-foreground" + "inline-flex items-center gap-1 rounded-sm border border-border-subtle bg-background/60 py-0.5 pr-0.5 pl-1.5 font-mono text-3xs text-muted-foreground" const MONO_LINK = "font-mono text-3xs text-muted-foreground underline-offset-2 transition-colors hover:text-foreground hover:underline" @@ -42,7 +42,7 @@ export const filterChipRail = ( h.span( [h.Key(`${chip.key}:${chip.value}`), h.Class(CHIP_CLASS)], [ - h.span([h.Class("max-w-[22ch] truncate text-foreground/80")], [chip.label]), + h.span([h.Class("max-w-[22ch] truncate text-foreground-soft")], [chip.label]), button( h, { diff --git a/apps/web/src/page/infra-integrations/kit/integration-empty.ts b/apps/web/src/page/infra-integrations/kit/integration-empty.ts index a8ccd6f970..43f5dac542 100644 --- a/apps/web/src/page/infra-integrations/kit/integration-empty.ts +++ b/apps/web/src/page/infra-integrations/kit/integration-empty.ts @@ -33,7 +33,7 @@ export const integrationIconPlate = ( h.AriaHidden(true), h.Class( cn( - "relative inline-flex shrink-0 items-center justify-center border border-border/60 bg-card", + "relative inline-flex shrink-0 items-center justify-center border border-border-subtle bg-card", options.plateClassName ?? "size-12 rounded-lg", ), ), @@ -85,7 +85,7 @@ export const integrationEmptyFeatures = ( }), ], [ - panel(h, { className: "flex-1 gap-2 border-border/60 px-4 py-3.5" }, [ + panel(h, { className: "flex-1 gap-2 border-border-subtle px-4 py-3.5" }, [ eyebrow(h, { variant: "label" }, [feature.label]), h.span([h.Class("text-base/5 font-semibold tracking-tight")], [feature.title]), h.p([h.Class("text-xs/4 text-muted-foreground")], [feature.description]), @@ -96,7 +96,7 @@ export const integrationEmptyFeatures = ( ) const BACKER = - "absolute bottom-0.5 flex size-11 items-center justify-center rounded-[10px] border border-border/60 bg-muted text-muted-foreground/70 opacity-80" + "absolute bottom-0.5 flex size-11 items-center justify-center rounded-[10px] border border-border-subtle bg-muted text-foreground-subtle opacity-80" /** `IntegrationEmptyMedia`: two dim backer plates fanned behind the brand plate. */ export const integrationEmptyMedia = (h: HtmlBuilder, brand: IntegrationBrand): Html => { diff --git a/apps/web/src/page/infra-integrations/kit/scope-chip.ts b/apps/web/src/page/infra-integrations/kit/scope-chip.ts index 4c437051e5..06854f23ad 100644 --- a/apps/web/src/page/infra-integrations/kit/scope-chip.ts +++ b/apps/web/src/page/infra-integrations/kit/scope-chip.ts @@ -19,7 +19,7 @@ export const scopeChip = ( ): Html => { const chipClass = cn( "bg-background/60 font-normal", - options.tone === "muted" ? "text-muted-foreground/70" : "text-muted-foreground", + options.tone === "muted" ? "text-foreground-subtle" : "text-muted-foreground", options.className, ) return options.trigger === undefined diff --git a/apps/web/src/page/infra-integrations/planetscale/db/view-breakdown.ts b/apps/web/src/page/infra-integrations/planetscale/db/view-breakdown.ts index ad3203fd86..2e6177306e 100644 --- a/apps/web/src/page/infra-integrations/planetscale/db/view-breakdown.ts +++ b/apps/web/src/page/infra-integrations/planetscale/db/view-breakdown.ts @@ -142,7 +142,7 @@ const rowsOf = (candidates: ReadonlyArray, spec: MeasureSpec) = } const metaChip = (h: H, text: string): Html => - h.span([h.Class("font-mono text-3xs text-muted-foreground/80")], [text]) + h.span([h.Class("font-mono text-3xs text-foreground-subtle")], [text]) const cells = (h: H, row: Row, spec: MeasureSpec, isSelected: boolean): ReadonlyArray => [ h.div( @@ -153,7 +153,7 @@ const cells = (h: H, row: Row, spec: MeasureSpec, isSelected: boolean): Readonly h.Class( cn( "truncate text-sm", - row.isOther ? "text-muted-foreground" : "font-mono text-foreground/90", + row.isOther ? "text-muted-foreground" : "font-mono text-foreground-soft", isSelected && "text-primary", ), ), @@ -170,7 +170,7 @@ const cells = (h: H, row: Row, spec: MeasureSpec, isSelected: boolean): Readonly [ h.Class( cn( - "w-[120px] text-right font-mono text-xs tabular-nums text-foreground/80", + "w-32 text-right font-mono text-xs tabular-nums text-foreground-soft", row.hasValue && spec.className?.(row.value), ), ), @@ -194,10 +194,10 @@ export const breakdownPanel = (h: H, inputs: BreakdownInputs): Html => { const spec: MeasureSpec = MEASURES[inputs.measure] const { rows, total, max } = rowsOf(inputs.candidates, spec) const sorted = sortRowsByField(rows.map(toSortRow), inputs.sort, (row) => !row.isOther && row.production) - return panel(h, { className: "border-border/60" }, [ + return panel(h, { className: "border-border-subtle" }, [ panelHeader(h, { title: "Branches", - className: "border-border/60 px-3 py-2", + className: "border-border-subtle px-3 py-2", action: segmentedSelect(h, { size: "xs", ariaLabel: "Measure", @@ -221,7 +221,7 @@ export const breakdownPanel = (h: H, inputs: BreakdownInputs): Html => { }), columnHead(h, { label: spec.label, - width: "w-[120px]", + width: "w-32", align: "right", sort: { onSort: Message.ClickedBreakdownSort({ key: "value" }), @@ -247,8 +247,8 @@ export const breakdownPanel = (h: H, inputs: BreakdownInputs): Html => { h.AriaPressed(String(isSelected)), h.Class( cn( - "flex w-full items-center gap-3 px-3 py-1.5 text-left transition-colors hover:bg-muted/50", - isSelected && "bg-muted/60", + "flex w-full items-center gap-3 px-3 py-1.5 text-left transition-colors hover:bg-surface-sunken", + isSelected && "bg-surface-strong", ), ), ...styleAttrs, @@ -261,7 +261,7 @@ export const breakdownPanel = (h: H, inputs: BreakdownInputs): Html => { }), ), h.div( - [h.Class("border-t border-border/60 px-3 py-1.5 text-2xs text-muted-foreground")], + [h.Class("border-t border-border-subtle px-3 py-1.5 text-2xs text-muted-foreground")], [ spec.additive ? `Bars show share of ${formatNumber(total)} total across ${countLabel(inputs.candidates.length, "branch", "branches")}.` @@ -272,7 +272,7 @@ export const breakdownPanel = (h: H, inputs: BreakdownInputs): Html => { } export const breakdownLoading = (h: H): Html => - panel(h, { className: "border-border/60" }, [ - panelHeader(h, { className: "border-border/60 px-3 py-2", children: [skeleton(h, "h-4 w-56")] }), + panel(h, { className: "border-border-subtle" }, [ + panelHeader(h, { className: "border-border-subtle px-3 py-2", children: [skeleton(h, "h-4 w-56")] }), skeletonList(h, { rows: 5, rowClassName: "h-4", gap: "2", className: "p-3" }), ]) diff --git a/apps/web/src/page/infra-integrations/planetscale/db/view-sections.ts b/apps/web/src/page/infra-integrations/planetscale/db/view-sections.ts index aec6633484..99fea67d9d 100644 --- a/apps/web/src/page/infra-integrations/planetscale/db/view-sections.ts +++ b/apps/web/src/page/infra-integrations/planetscale/db/view-sections.ts @@ -29,11 +29,11 @@ export const insightTriggerId = (fingerprint: string) => `ps-insight-${fingerpri const activityRow = (h: H, event: EventEntry, clock: Clock, trigger: Trigger): Html => { const presentation = presentEvent(event.eventType) return h.li( - [h.Class("flex items-baseline gap-2.5 border-l border-border/60 py-1.5 pl-3 text-xs")], + [h.Class("flex items-baseline gap-2.5 border-l border-border-subtle py-1.5 pl-3 text-xs")], [ statusDot(h, { tone: presentation.tone, className: "mt-1" }), h.span( - [h.Class("min-w-0 flex-1 truncate text-foreground/90"), h.Title(event.title)], + [h.Class("min-w-0 flex-1 truncate text-foreground-soft"), h.Title(event.title)], [event.title], ), ...(event.branchName === "" @@ -90,7 +90,7 @@ const activityLoading = (h: H): Html => [h.Class("flex flex-col")], Array.from({ length: 4 }, (_, index) => h.li( - [h.Class("border-l border-border/60 py-1.5 pl-3")], + [h.Class("border-l border-border-subtle py-1.5 pl-3")], [skeleton(h, cn("h-3", index % 2 === 0 ? "w-64" : "w-48"))], ), ), @@ -184,7 +184,7 @@ const insightsList = ( return insightsNotice(h, [ "No queries recorded on", " ", - h.span([h.Class("font-mono text-foreground/80")], [database, "/", response.branch]), + h.span([h.Class("font-mono text-foreground-soft")], [database, "/", response.branch]), " ", "in this window.", ]) @@ -263,7 +263,7 @@ const insightsList = ( ...clock, prefix: "last run", mono: true, - className: "ml-auto text-muted-foreground/70", + className: "ml-auto text-foreground-subtle", trigger: trigger(insightTriggerId(row.fingerprint)), }), ]), diff --git a/apps/web/src/page/infra-integrations/planetscale/db/view.ts b/apps/web/src/page/infra-integrations/planetscale/db/view.ts index 2fa8285133..ea366b8b69 100644 --- a/apps/web/src/page/infra-integrations/planetscale/db/view.ts +++ b/apps/web/src/page/infra-integrations/planetscale/db/view.ts @@ -255,7 +255,7 @@ const filterChipRail = (h: H, model: Model): ReadonlyArray => { const chips = activeFilterChips(filtersOf(model)) if (chips.length === 0) return [] const chipClass = - "inline-flex items-center gap-1 rounded-sm border border-border/60 bg-background/60 py-0.5 pr-0.5 pl-1.5 font-mono text-3xs text-muted-foreground" + "inline-flex items-center gap-1 rounded-sm border border-border-subtle bg-background/60 py-0.5 pr-0.5 pl-1.5 font-mono text-3xs text-muted-foreground" return [ h.div( [h.Class("flex flex-wrap items-center gap-1.5"), h.AriaLabel("Active filters")], @@ -264,7 +264,7 @@ const filterChipRail = (h: H, model: Model): ReadonlyArray => { h.span( [h.Class(chipClass)], [ - h.span([h.Class("max-w-[22ch] truncate text-foreground/80")], [chip.label]), + h.span([h.Class("max-w-[22ch] truncate text-foreground-soft")], [chip.label]), button( h, { diff --git a/apps/web/src/page/infra-integrations/planetscale/list/view-table.ts b/apps/web/src/page/infra-integrations/planetscale/list/view-table.ts index f272c2dfd7..e226ba0990 100644 --- a/apps/web/src/page/infra-integrations/planetscale/list/view-table.ts +++ b/apps/web/src/page/infra-integrations/planetscale/list/view-table.ts @@ -54,19 +54,19 @@ const COLUMNS: ReadonlyArray<{ metric?: boolean }> = [ { label: "Database", key: "name", width: "w-0 flex-1 min-w-[220px]" }, - { label: "Branches", key: "branchCount", width: "w-[80px]", align: "right", hidden: "hidden md:flex" }, - { label: "Connections", key: "connectionsAvg", width: "w-[96px]", align: "right", metric: true }, - { label: "CPU (max)", key: "cpuMaxPercent", width: "w-[88px]", align: "right", metric: true }, + { label: "Branches", key: "branchCount", width: "w-20", align: "right", hidden: "hidden md:flex" }, + { label: "Connections", key: "connectionsAvg", width: "w-24", align: "right", metric: true }, + { label: "CPU (max)", key: "cpuMaxPercent", width: "w-24", align: "right", metric: true }, { label: "Memory (max)", key: "memMaxPercent", - width: "w-[104px]", + width: "w-28", align: "right", hidden: "hidden md:flex", metric: true, }, - { label: "Storage", key: "storageUsedPercent", width: "w-[80px]", align: "right", metric: true }, - { label: "Replica lag", key: "replicaLagMaxSeconds", width: "w-[88px]", align: "right", metric: true }, + { label: "Storage", key: "storageUsedPercent", width: "w-20", align: "right", metric: true }, + { label: "Replica lag", key: "replicaLagMaxSeconds", width: "w-24", align: "right", metric: true }, ] /** `headerCells`: sortable heads only when a sort is given; `metricsPaused` drops the metric columns. */ @@ -95,12 +95,12 @@ export const databaseTableLoading = (h: H): Html => headerCells(h, undefined, false), skeletonRows(h, 3, () => [ h.div([h.Class("w-0 min-w-[220px] flex-1")], [skeleton(h, "h-4 w-44")]), - skeleton(h, "hidden h-3 w-[80px] md:block"), - skeleton(h, "h-3 w-[96px]"), - skeleton(h, "h-3 w-[88px]"), - skeleton(h, "hidden h-3 w-[104px] md:block"), - skeleton(h, "h-3 w-[80px]"), - skeleton(h, "h-3 w-[88px]"), + skeleton(h, "hidden h-3 w-20 md:block"), + skeleton(h, "h-3 w-24"), + skeleton(h, "h-3 w-24"), + skeleton(h, "hidden h-3 w-28 md:block"), + skeleton(h, "h-3 w-20"), + skeleton(h, "h-3 w-24"), ]), ) @@ -123,24 +123,24 @@ const toRow = (db: V2PlanetScaleDatabase, statsByName: ReadonlyMap h.span( [h.Class("hidden shrink-0 xl:inline-flex")], - [h.span([h.Class("font-mono text-3xs text-muted-foreground/80")], [text])], + [h.span([h.Class("font-mono text-3xs text-foreground-subtle")], [text])], ) const metricCells = (h: H, row: DatabaseRow): ReadonlyArray => [ - h.div([h.Class(cn("w-[96px]", CELL))], [row.hasStats ? formatNumber(row.connectionsAvg) : EMPTY_VALUE]), + h.div([h.Class(cn("w-24", CELL))], [row.hasStats ? formatNumber(row.connectionsAvg) : EMPTY_VALUE]), h.div( - [h.Class(cn("w-[88px]", CELL, row.hasStats && utilizationClass(row.cpuMaxPercent)))], + [h.Class(cn("w-24", CELL, row.hasStats && utilizationClass(row.cpuMaxPercent)))], [row.hasStats ? formatWholePercent(row.cpuMaxPercent / 100) : EMPTY_VALUE], ), h.div( [ h.Class( - cn("hidden w-[104px]", CELL, "md:block", row.hasStats && utilizationClass(row.memMaxPercent)), + cn("hidden w-28", CELL, "md:block", row.hasStats && utilizationClass(row.memMaxPercent)), ), ], [row.hasStats ? formatWholePercent(row.memMaxPercent / 100) : EMPTY_VALUE], @@ -149,7 +149,7 @@ const metricCells = (h: H, row: DatabaseRow): ReadonlyArray => [ [ h.Class( cn( - "w-[80px]", + "w-20", CELL, row.storageUsedPercent !== MISSING && utilizationClass(row.storageUsedPercent), ), @@ -158,7 +158,7 @@ const metricCells = (h: H, row: DatabaseRow): ReadonlyArray => [ [row.storageUsedPercent === MISSING ? EMPTY_VALUE : formatStoragePercent(row.storageUsedPercent)], ), h.div( - [h.Class(cn("w-[88px]", CELL, row.hasStats && lagClass(row.replicaLagMaxSeconds)))], + [h.Class(cn("w-24", CELL, row.hasStats && lagClass(row.replicaLagMaxSeconds)))], [row.hasStats ? formatLag(row.replicaLagMaxSeconds) : EMPTY_VALUE], ), ] @@ -193,7 +193,7 @@ const databaseRow = (h: H, row: DatabaseRow, metricsPaused: boolean): Html => { ...(row.plan ? [metaChip(h, row.plan)] : []), ], ), - h.div([h.Class(cn("hidden w-[80px]", CELL, "md:block"))], [String(row.branchCount)]), + h.div([h.Class(cn("hidden w-20", CELL, "md:block"))], [String(row.branchCount)]), ...(metricsPaused ? [] : metricCells(h, row)), ], ) diff --git a/apps/web/src/page/infra-integrations/railway/list/view-table.ts b/apps/web/src/page/infra-integrations/railway/list/view-table.ts index 1f48305f9b..7f0e5f7ecb 100644 --- a/apps/web/src/page/infra-integrations/railway/list/view-table.ts +++ b/apps/web/src/page/infra-integrations/railway/list/view-table.ts @@ -29,11 +29,11 @@ const COLUMNS: ReadonlyArray<{ limitsOnly?: boolean }> = [ { label: "Service", key: "displayName", width: "w-0 flex-1 min-w-[240px]" }, - { label: "Memory", key: "memoryMax", width: "w-[150px]", align: "right" }, - { label: "vCPU", key: "cpuMax", width: "w-[140px]", align: "right" }, - { label: "Of limit", key: "peakOfLimit", width: "w-[160px]", hidden: "hidden lg:flex", limitsOnly: true }, - { label: "Replicas", key: "replicas", width: "w-[80px]", align: "right" }, - { label: "Last seen", key: "lastSeen", width: "w-[100px]", align: "right" }, + { label: "Memory", key: "memoryMax", width: "w-36", align: "right" }, + { label: "vCPU", key: "cpuMax", width: "w-36", align: "right" }, + { label: "Of limit", key: "peakOfLimit", width: "w-40", hidden: "hidden lg:flex", limitsOnly: true }, + { label: "Replicas", key: "replicas", width: "w-20", align: "right" }, + { label: "Last seen", key: "lastSeen", width: "w-24", align: "right" }, ] const columns = (h: H, showLimits: boolean, sort: Sort | undefined): ReadonlyArray => @@ -61,10 +61,10 @@ export const railwayTableLoading = (h: H): Html => columns(h, false, undefined), skeletonRows(h, 5, () => [ h.div([h.Class("w-0 min-w-[240px] flex-1")], [skeleton(h, "h-4 w-36")]), - skeleton(h, "ml-auto h-3 w-[150px]"), - skeleton(h, "ml-auto h-3 w-[140px]"), - skeleton(h, "ml-auto h-3 w-[80px]"), - skeleton(h, "h-3 w-[100px]"), + skeleton(h, "ml-auto h-3 w-36"), + skeleton(h, "ml-auto h-3 w-36"), + skeleton(h, "ml-auto h-3 w-20"), + skeleton(h, "h-3 w-24"), ]), ) @@ -135,7 +135,7 @@ const row = (h: H, view: RailwayRowView, showLimits: boolean, clock: Clock, trig ], ), h.div( - [h.Class("w-[150px] text-right")], + [h.Class("w-36 text-right")], [ avgPeak( h, @@ -145,7 +145,7 @@ const row = (h: H, view: RailwayRowView, showLimits: boolean, clock: Clock, trig ], ), h.div( - [h.Class("w-[140px] text-right")], + [h.Class("w-36 text-right")], [ avgPeak( h, @@ -157,7 +157,7 @@ const row = (h: H, view: RailwayRowView, showLimits: boolean, clock: Clock, trig ...(showLimits ? [ h.div( - [h.Class("hidden w-[160px] lg:block")], + [h.Class("hidden w-40 lg:block")], [ meterRows(h, [ { label: "CPU", fraction: view.cpuOfLimit }, @@ -168,11 +168,11 @@ const row = (h: H, view: RailwayRowView, showLimits: boolean, clock: Clock, trig ] : []), h.div( - [h.Class("w-[80px] text-right font-mono text-xs tabular-nums text-foreground/80")], + [h.Class("w-20 text-right font-mono text-xs tabular-nums text-foreground-soft")], [String(view.replicas)], ), h.div( - [h.Class("w-[100px] text-right")], + [h.Class("w-24 text-right")], [ relativeTime(h, { value: view.lastSeen, @@ -206,7 +206,7 @@ export const railwayTable = (h: H, inputs: RailwayTableInputs): Html => h.div( [ h.Class( - "flex items-center gap-2.5 border-b border-border/60 bg-muted/30 px-4 py-2 font-mono text-2xs", + "flex items-center gap-2.5 border-b border-border-subtle bg-surface-sunken px-4 py-2 font-mono text-2xs", ), ], [ diff --git a/apps/web/src/page/infra-integrations/supabase/list/view-bottom.ts b/apps/web/src/page/infra-integrations/supabase/list/view-bottom.ts index 442a421a70..e8ef775e36 100644 --- a/apps/web/src/page/infra-integrations/supabase/list/view-bottom.ts +++ b/apps/web/src/page/infra-integrations/supabase/list/view-bottom.ts @@ -22,13 +22,13 @@ const MAX_ROWS = 6 const listRow = (h: H, key: string, href: string | null, children: ReadonlyArray): Html => { const className = - "flex items-center gap-4 border-t border-border/60 px-4 py-2.5 first:border-t-0 transition-colors" + "flex items-center gap-4 border-t border-border-subtle px-4 py-2.5 first:border-t-0 transition-colors" return h.li( [h.Key(key)], [ href === null ? h.div([h.Class(className)], children) - : h.a([h.Href(href), h.Class(cn(className, "hover:bg-muted/50"))], children), + : h.a([h.Href(href), h.Class(cn(className, "hover:bg-surface-sunken"))], children), ], ) } @@ -159,7 +159,7 @@ const findingsBody = ( h.p( [ h.Key(note), - h.Class("border-t border-border/60 px-4 py-2 text-2xs text-muted-foreground"), + h.Class("border-t border-border-subtle px-4 py-2 text-2xs text-muted-foreground"), ], [note], ), diff --git a/apps/web/src/page/infra-integrations/supabase/list/view-table.ts b/apps/web/src/page/infra-integrations/supabase/list/view-table.ts index 3afb96682d..ad7e194853 100644 --- a/apps/web/src/page/infra-integrations/supabase/list/view-table.ts +++ b/apps/web/src/page/infra-integrations/supabase/list/view-table.ts @@ -57,7 +57,7 @@ export const supabaseTableLoading = (h: H): Html => ) const MUTED = "font-mono text-2xs text-muted-foreground" -const NUMBER = "font-mono text-xs tabular-nums text-foreground/80" +const NUMBER = "font-mono text-xs tabular-nums text-foreground-soft" /** A utilisation bar and its percent; a project without metrics shows an empty track. */ const usageCell = (h: H, label: string, fraction: number | null): Html => @@ -75,7 +75,7 @@ const usageCell = (h: H, label: string, fraction: number | null): Html => h.Class( cn( "font-mono text-2xs tabular-nums", - fraction === null ? "text-muted-foreground" : "text-foreground/80", + fraction === null ? "text-muted-foreground" : "text-foreground-soft", ), ), ], diff --git a/apps/web/src/page/infra-integrations/supabase/panel.ts b/apps/web/src/page/infra-integrations/supabase/panel.ts index a1e70ad7f1..d517971a8e 100644 --- a/apps/web/src/page/infra-integrations/supabase/panel.ts +++ b/apps/web/src/page/infra-integrations/supabase/panel.ts @@ -29,7 +29,7 @@ export const sectionPanel = ( panelTitle(h, [options.title]), ...(options.description === undefined ? [] - : [h.p([h.Class("text-2xs text-muted-foreground/70")], [options.description])]), + : [h.p([h.Class("text-2xs text-foreground-subtle")], [options.description])]), ], ), ], diff --git a/apps/web/src/page/infra-integrations/supabase/project/view-attention.ts b/apps/web/src/page/infra-integrations/supabase/project/view-attention.ts index 49fecd4c2f..0b497fc8e9 100644 --- a/apps/web/src/page/infra-integrations/supabase/project/view-attention.ts +++ b/apps/web/src/page/infra-integrations/supabase/project/view-attention.ts @@ -18,7 +18,7 @@ const itemRow = (h: H, item: AttentionItem, timeZone: string): Html => h.li( [ h.Key(item.key), - h.Class("flex flex-col gap-1 border-t border-border/60 px-4 py-3 first:border-t-0"), + h.Class("flex flex-col gap-1 border-t border-border-subtle px-4 py-3 first:border-t-0"), ], [ eyebrow(h, { className: TONE_TEXT[item.tone] }, [item.label]), diff --git a/apps/web/src/page/infra-integrations/supabase/project/view-callers.ts b/apps/web/src/page/infra-integrations/supabase/project/view-callers.ts index 12021d3250..189230e0eb 100644 --- a/apps/web/src/page/infra-integrations/supabase/project/view-callers.ts +++ b/apps/web/src/page/infra-integrations/supabase/project/view-callers.ts @@ -43,7 +43,7 @@ const callerRow = (h: H, model: Model, caller: SupabaseProjectCaller, spark: Spa h.div( [ h.Key(caller.serviceName), - h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-2.5 last:border-0"), + h.Class("flex items-center gap-4 border-b border-border-subtle px-4 py-2.5 last:border-0"), ], [ h.a( diff --git a/apps/web/src/page/infra-integrations/supabase/project/view-issues.ts b/apps/web/src/page/infra-integrations/supabase/project/view-issues.ts index 50f0e73998..fcfbc563b9 100644 --- a/apps/web/src/page/infra-integrations/supabase/project/view-issues.ts +++ b/apps/web/src/page/infra-integrations/supabase/project/view-issues.ts @@ -19,7 +19,7 @@ const issueRow = (h: H, issue: SupabaseLogIssue, timeZone: string): Html => { return h.li( [ h.Key(`${issue.source}:${issue.message}`), - h.Class("flex items-center gap-4 border-t border-border/60 px-4 py-2 text-xs first:border-t-0"), + h.Class("flex items-center gap-4 border-t border-border-subtle px-4 py-2 text-xs first:border-t-0"), ], [ h.span( diff --git a/apps/web/src/page/infra-integrations/supabase/project/view-postgres.ts b/apps/web/src/page/infra-integrations/supabase/project/view-postgres.ts index 0ebe536d3d..47e8ceb21d 100644 --- a/apps/web/src/page/infra-integrations/supabase/project/view-postgres.ts +++ b/apps/web/src/page/infra-integrations/supabase/project/view-postgres.ts @@ -142,7 +142,7 @@ const queriesBody = (h: H, insights: SupabaseProjectInsights, clock: Clock): Htm [ h.Key(query.queryId), h.Class( - "flex items-start gap-3 border-t border-border/60 px-4 py-2.5 first:border-t-0", + "flex items-start gap-3 border-t border-border-subtle px-4 py-2.5 first:border-t-0", ), ], [ diff --git a/apps/web/src/page/infra-integrations/supabase/project/view-traffic.ts b/apps/web/src/page/infra-integrations/supabase/project/view-traffic.ts index 41d2131818..88d3d4acbe 100644 --- a/apps/web/src/page/infra-integrations/supabase/project/view-traffic.ts +++ b/apps/web/src/page/infra-integrations/supabase/project/view-traffic.ts @@ -114,7 +114,7 @@ const bars = ( }), ]) -const PATH_ROW = "flex items-center gap-4 border-t border-border/60 px-4 py-2 text-xs" +const PATH_ROW = "flex items-center gap-4 border-t border-border-subtle px-4 py-2 text-xs" const topPathsList = (h: H, paths: SupabaseApiTopPathsResponse): Html => paths.paths.length === 0 diff --git a/apps/web/src/page/infra/containers/list/view-table.ts b/apps/web/src/page/infra/containers/list/view-table.ts index 05a83927be..fc42b5a450 100644 --- a/apps/web/src/page/infra/containers/list/view-table.ts +++ b/apps/web/src/page/infra/containers/list/view-table.ts @@ -22,16 +22,16 @@ const head = (sort: Sort, key: ContainerSortKey) => headSort(sort, key, (k) => M const columns = (h: H, sort: Sort): ReadonlyArray => [ columnHead(h, { label: "Container", sort: head(sort, "containerName"), width: "w-0 flex-1 min-w-[260px]" }), - columnHead(h, { label: "Peak saturation", sort: head(sort, "saturation"), width: "w-[176px]", hidden: "hidden md:flex" }), - columnHead(h, { label: "CPU", sort: head(sort, "cpuPct"), align: "right", width: "w-[132px]", hidden: "hidden lg:flex" }), + columnHead(h, { label: "Peak saturation", sort: head(sort, "saturation"), width: "w-44", hidden: "hidden md:flex" }), + columnHead(h, { label: "CPU", sort: head(sort, "cpuPct"), align: "right", width: "w-32", hidden: "hidden lg:flex" }), columnHead(h, { label: "Mem of limit", sort: head(sort, "memoryPct"), align: "right", - width: "w-[120px]", + width: "w-32", hidden: "hidden lg:flex", }), - columnHead(h, { label: "Last seen", sort: head(sort, "lastSeen"), align: "right", width: "w-[100px]" }), + columnHead(h, { label: "Last seen", sort: head(sort, "lastSeen"), align: "right", width: "w-24" }), ] export const containerTableLoading = (h: H): Html => @@ -42,12 +42,12 @@ export const containerTableLoading = (h: H): Html => skeletonRows(h, 6, () => [ h.div([h.Class("w-0 min-w-[260px] flex-1")], [skeleton(h, "h-4 w-48"), skeleton(h, "mt-1.5 h-3 w-40")]), h.div( - [h.Class("hidden w-[176px] space-y-1.5 md:block")], - [skeleton(h, "h-2.5 w-[176px]"), skeleton(h, "h-2.5 w-[176px]")], + [h.Class("hidden w-44 space-y-1.5 md:block")], + [skeleton(h, "h-2.5 w-44"), skeleton(h, "h-2.5 w-44")], ), - skeleton(h, "hidden h-3 w-[132px] lg:block"), - skeleton(h, "hidden h-3 w-[120px] lg:block"), - skeleton(h, "h-3 w-[100px]"), + skeleton(h, "hidden h-3 w-32 lg:block"), + skeleton(h, "hidden h-3 w-32 lg:block"), + skeleton(h, "h-3 w-24"), ]), ) @@ -98,7 +98,7 @@ const containerRow = (h: H, container: ContainerRow, inputs: ContainerTableInput ], ), h.div( - [h.Class("hidden w-[176px] md:block")], + [h.Class("hidden w-44 md:block")], [ meterRows(h, [ { label: "CPU", fraction: container.cpuPctPeak }, @@ -107,15 +107,15 @@ const containerRow = (h: H, container: ContainerRow, inputs: ContainerTableInput ], ), h.div( - [h.Class("hidden w-[132px] text-right lg:block")], + [h.Class("hidden w-32 text-right lg:block")], [avgPeak(h, { avg: container.cpuPct, peak: container.cpuPctPeak, format: formatWholePercent })], ), h.div( - [h.Class("hidden w-[120px] text-right lg:block")], + [h.Class("hidden w-32 text-right lg:block")], [avgPeak(h, { avg: container.memoryPct, peak: container.memoryPctPeak, format: formatWholePercent })], ), h.div( - [h.Class("w-[100px] text-right")], + [h.Class("w-24 text-right")], [ relativeTime(h, { value: container.lastSeen, diff --git a/apps/web/src/page/infra/hosts/detail/view-header.ts b/apps/web/src/page/infra/hosts/detail/view-header.ts index eac3280075..313f0fa338 100644 --- a/apps/web/src/page/infra/hosts/detail/view-header.ts +++ b/apps/web/src/page/infra/hosts/detail/view-header.ts @@ -73,7 +73,7 @@ export const hostDetailHeader = (h: H, inputs: HeaderInputs): HostHeaderParts => nowMs: inputs.nowMs, timeZone: inputs.timeZone, prefix: "last reported", - className: "text-2xs text-muted-foreground/80", + className: "text-2xs text-foreground-subtle", }), ] const percentItem = (eyebrow: string, value: number) => diff --git a/apps/web/src/page/infra/hosts/detail/view-panels.ts b/apps/web/src/page/infra/hosts/detail/view-panels.ts index e4bdce3e26..82c0f1c646 100644 --- a/apps/web/src/page/infra/hosts/detail/view-panels.ts +++ b/apps/web/src/page/infra/hosts/detail/view-panels.ts @@ -52,7 +52,7 @@ export const hostMetadataPanel = (h: H, model: Model, summary: NonNullable(h: HtmlBuilder, sort: SortState | null, onSort?: OnSort (onSort === undefined ? INERT_SORT : headSort(sort, key, onSort)) return [ columnHead(h, { label: "Host", sort: sortOf("hostName"), width: "w-0 flex-1 min-w-[260px]" }), - columnHead(h, { label: "Usage", width: "w-[200px]" }), + columnHead(h, { label: "Usage", width: "w-52" }), columnHead(h, { label: "Load 15m", sort: sortOf("load15"), align: "right", - width: "w-[80px]", + width: "w-20", hidden: "hidden lg:flex", }), - columnHead(h, { label: "Last seen", sort: sortOf("lastSeen"), align: "right", width: "w-[100px]" }), + columnHead(h, { label: "Last seen", sort: sortOf("lastSeen"), align: "right", width: "w-24" }), ] } @@ -53,9 +53,9 @@ export const hostTableLoading = (h: HtmlBuilder): Html => [h.Class("w-0 min-w-[260px] flex-1")], [skeleton(h, "h-4 w-40"), skeleton(h, "mt-1.5 h-3 w-32")], ), - skeleton(h, "h-9 w-[200px]"), - skeleton(h, "ml-auto hidden h-3 w-[80px] lg:block"), - skeleton(h, "h-3 w-[100px]"), + skeleton(h, "h-9 w-52"), + skeleton(h, "ml-auto hidden h-3 w-20 lg:block"), + skeleton(h, "h-3 w-24"), ]), ) @@ -103,7 +103,7 @@ const hostRow = (h: HtmlBuilder, host: HostRow, inputs: HostTableInputs ], ), h.div( - [h.Class("w-[200px]")], + [h.Class("w-52")], [ meterRows(h, [ { label: "CPU", fraction: host.cpuPct }, @@ -115,13 +115,13 @@ const hostRow = (h: HtmlBuilder, host: HostRow, inputs: HostTableInputs h.div( [ h.Class( - "hidden w-[80px] text-right font-mono text-xs tabular-nums text-foreground/80 lg:block", + "hidden w-20 text-right font-mono text-xs tabular-nums text-foreground-soft lg:block", ), ], [formatLoad(host.load15)], ), h.div( - [h.Class("w-[100px] text-right")], + [h.Class("w-24 text-right")], [ relativeTime(h, { value: host.lastSeen, diff --git a/apps/web/src/page/infra/kit/avg-peak.ts b/apps/web/src/page/infra/kit/avg-peak.ts index 43af876748..20aa5c7ac3 100644 --- a/apps/web/src/page/infra/kit/avg-peak.ts +++ b/apps/web/src/page/infra/kit/avg-peak.ts @@ -25,7 +25,7 @@ export const avgPeak = ( ], [ h.span([h.Class("text-muted-foreground")], [options.format(options.avg)]), - h.span([h.Class("mx-1 text-foreground/30")], ["→"]), + h.span([h.Class("mx-1 text-foreground-faint")], ["→"]), options.format(options.peak), ], ) diff --git a/apps/web/src/page/infra/kit/correlation-strips.ts b/apps/web/src/page/infra/kit/correlation-strips.ts index 2c23ac03ec..a05d2c141a 100644 --- a/apps/web/src/page/infra/kit/correlation-strips.ts +++ b/apps/web/src/page/infra/kit/correlation-strips.ts @@ -101,7 +101,7 @@ export const correlationStrips = (h: HtmlBuilder, options: CorrelationStri [h.Key(strip.id), h.Class(cn("flex items-center gap-4 px-4 py-3", index > 0 && "border-t"))], [ h.div( - [h.Class("flex w-[140px] shrink-0 flex-col gap-0.5")], + [h.Class("flex w-36 shrink-0 flex-col gap-0.5")], [ h.span([h.Class("text-xs font-medium text-foreground")], [strip.label]), h.span([h.Class("font-mono text-3xs text-muted-foreground")], [strip.source]), diff --git a/apps/web/src/page/infra/kit/data-table.ts b/apps/web/src/page/infra/kit/data-table.ts index 92bd96aca5..486dc0a368 100644 --- a/apps/web/src/page/infra/kit/data-table.ts +++ b/apps/web/src/page/infra/kit/data-table.ts @@ -8,7 +8,7 @@ import type { SortDir } from "../../kit/table-sort" // `DataTable`, `ColumnHead` and `ROW_LINK_CLASS`. export const ROW_LINK_CLASS = - "group flex items-center gap-4 border-b border-border/60 px-4 py-3 transition-colors last:border-0 hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none" + "group flex items-center gap-4 border-b border-border-subtle px-4 py-3 transition-colors last:border-0 hover:bg-surface-sunken focus-visible:bg-surface-sunken focus-visible:outline-none" /** A sortable head's state: `null` sort is the skeleton's inert head (no current key). */ export const headSort = ( @@ -93,12 +93,12 @@ export const dataTable = ( const isWaiting = options.isWaiting === true const scrolls = options.maxHeight !== undefined const headClass = cn( - "flex items-center gap-4 border-b border-border/60 px-4 py-2", + "flex items-center gap-4 border-b border-border-subtle px-4 py-2", scrolls && `sticky top-0 z-10 ${options.stickySurfaceClass ?? "bg-background"}`, ) return h.div( [ - h.Class(cn("border-y border-border/60", refreshingClass(isWaiting), options.className)), + h.Class(cn("border-y border-border-subtle", refreshingClass(isWaiting), options.className)), h.AriaLabel(options.ariaLabel), ...(isWaiting ? [h.AriaBusy(true)] : []), ], @@ -128,7 +128,7 @@ export const skeletonRows = ( ): ReadonlyArray => Array.from({ length: count }, () => h.div( - [h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0")], + [h.Class("flex items-center gap-4 border-b border-border-subtle px-4 py-3 last:border-0")], cells(), ), ) diff --git a/apps/web/src/page/infra/kit/meta-line.ts b/apps/web/src/page/infra/kit/meta-line.ts index 29f4a77289..8a9da48c9e 100644 --- a/apps/web/src/page/infra/kit/meta-line.ts +++ b/apps/web/src/page/infra/kit/meta-line.ts @@ -23,7 +23,7 @@ export const metaLine = ( [ h.Class( cn( - "mt-1 flex min-w-0 items-center gap-x-2 truncate font-mono text-xs text-muted-foreground/80", + "mt-1 flex min-w-0 items-center gap-x-2 truncate font-mono text-xs text-foreground-subtle", options.className, ), ), @@ -33,7 +33,7 @@ export const metaLine = ( h.span( [h.Class("flex shrink-0 items-center gap-x-2")], [ - ...(index > 0 ? [h.span([h.Class("text-foreground/20")], ["·"])] : []), + ...(index > 0 ? [h.span([h.Class("text-foreground-faint")], ["·"])] : []), typeof item === "string" ? h.span([h.Class("max-w-[28ch] truncate")], [item]) : item, ], ), @@ -74,7 +74,7 @@ export const platformLabel = (h: HtmlBuilder, kind: PlatformKind, value: s known.color === undefined ? icon(h, known.icon, { size: 12, - className: cn("shrink-0", "text-foreground/70"), + className: cn("shrink-0", "text-foreground-soft"), }) : icon(h, known.icon, { size: 12, diff --git a/apps/web/src/page/infra/kit/meter-rows.ts b/apps/web/src/page/infra/kit/meter-rows.ts index 4746396fa3..7fa5bf3bf2 100644 --- a/apps/web/src/page/infra/kit/meter-rows.ts +++ b/apps/web/src/page/infra/kit/meter-rows.ts @@ -24,7 +24,7 @@ const meterRow = (h: HtmlBuilder, row: MeterRow, hideLabel: boolean): Html h.Class( cn( "w-8", - "shrink-0 font-mono text-3xs tracking-wider text-muted-foreground/70", + "shrink-0 font-mono text-3xs tracking-wider text-foreground-subtle", ), ), ], diff --git a/apps/web/src/page/infra/kubernetes/nodes/view-table.ts b/apps/web/src/page/infra/kubernetes/nodes/view-table.ts index e1e4de97e9..9468e6cb3e 100644 --- a/apps/web/src/page/infra/kubernetes/nodes/view-table.ts +++ b/apps/web/src/page/infra/kubernetes/nodes/view-table.ts @@ -21,15 +21,15 @@ const columns = (h: H, sort: SortState | null): ReadonlyArray => { const head = (key: NodeSortKey) => headSort(sort, key, (k) => Message.ClickedSort({ key: k })) return [ columnHead(h, { label: "Node", sort: head("nodeName"), width: "w-0 flex-1 min-w-[260px]" }), - columnHead(h, { label: "CPU / allocatable", sort: head("cpuUtilization"), width: "w-[176px]", hidden: "hidden md:flex" }), + columnHead(h, { label: "CPU / allocatable", sort: head("cpuUtilization"), width: "w-44", hidden: "hidden md:flex" }), columnHead(h, { label: "Memory / allocatable", sort: head("memoryUtilization"), - width: "w-[176px]", + width: "w-44", hidden: "hidden lg:flex", }), - columnHead(h, { label: "Uptime", sort: head("uptime"), align: "right", width: "w-[100px]", hidden: "hidden md:flex" }), - columnHead(h, { label: "Last seen", sort: head("lastSeen"), align: "right", width: "w-[100px]" }), + columnHead(h, { label: "Uptime", sort: head("uptime"), align: "right", width: "w-24", hidden: "hidden md:flex" }), + columnHead(h, { label: "Last seen", sort: head("lastSeen"), align: "right", width: "w-24" }), ] } @@ -40,10 +40,10 @@ export const nodeTableLoading = (h: H): Html => columns(h, null), skeletonRows(h, 4, () => [ h.div([h.Class("w-0 min-w-[260px] flex-1")], [skeleton(h, "h-4 w-48"), skeleton(h, "mt-1.5 h-3 w-32")]), - skeleton(h, "hidden h-3 w-[176px] md:block"), - skeleton(h, "hidden h-3 w-[176px] lg:block"), - skeleton(h, "hidden h-3 w-[100px] md:block"), - skeleton(h, "h-3 w-[100px]"), + skeleton(h, "hidden h-3 w-44 md:block"), + skeleton(h, "hidden h-3 w-44 lg:block"), + skeleton(h, "hidden h-3 w-24 md:block"), + skeleton(h, "h-3 w-24"), ]), ) @@ -91,7 +91,7 @@ const nodeRow = (h: H, node: NodeRow, inputs: NodeTableInputs): Html => ], ), h.div( - [h.Class("hidden w-[176px] md:block")], + [h.Class("hidden w-44 md:block")], [ capacityCell( h, @@ -101,7 +101,7 @@ const nodeRow = (h: H, node: NodeRow, inputs: NodeTableInputs): Html => ], ), h.div( - [h.Class("hidden w-[176px] lg:block")], + [h.Class("hidden w-44 lg:block")], [ capacityCell( h, @@ -111,11 +111,11 @@ const nodeRow = (h: H, node: NodeRow, inputs: NodeTableInputs): Html => ], ), h.div( - [h.Class("hidden w-[100px] text-right font-mono text-xs tabular-nums text-foreground/80 md:block")], + [h.Class("hidden w-24 text-right font-mono text-xs tabular-nums text-foreground-soft md:block")], [formatUptime(node.uptime)], ), h.div( - [h.Class("w-[100px] text-right")], + [h.Class("w-24 text-right")], [ relativeTime(h, { value: node.lastSeen, diff --git a/apps/web/src/page/infra/kubernetes/pod-restarts-view.ts b/apps/web/src/page/infra/kubernetes/pod-restarts-view.ts index f09e99fa27..af9ee7d0a1 100644 --- a/apps/web/src/page/infra/kubernetes/pod-restarts-view.ts +++ b/apps/web/src/page/infra/kubernetes/pod-restarts-view.ts @@ -47,7 +47,7 @@ const containerRow = (h: HtmlBuilder, row: RestartRow): Html => h.div( [ h.Key(row.containerName), - h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0"), + h.Class("flex items-center gap-4 border-b border-border-subtle px-4 py-3 last:border-0"), ], [ h.span( @@ -58,7 +58,7 @@ const containerRow = (h: HtmlBuilder, row: RestartRow): Html => [ h.Class( cn( - "w-[96px] text-right font-mono text-xs tabular-nums", + "w-24 text-right font-mono text-xs tabular-nums", TONE_TEXT[restartTone(row.restarts, row.lastTerminatedReason)], ), ), @@ -66,11 +66,11 @@ const containerRow = (h: HtmlBuilder, row: RestartRow): Html => [String(row.restarts)], ), h.span( - [h.Class("w-[96px] text-right font-mono text-xs tabular-nums text-muted-foreground")], + [h.Class("w-24 text-right font-mono text-xs tabular-nums text-muted-foreground")], [String(row.totalRestarts)], ), h.span( - [h.Class("w-[160px] truncate text-right text-xs text-muted-foreground")], + [h.Class("w-40 truncate text-right text-xs text-muted-foreground")], [row.lastTerminatedReason || EMPTY_VALUE], ), ], @@ -89,9 +89,9 @@ export const podContainerRestarts = (h: HtmlBuilder, restarts: Restarts): { ariaLabel: "Container restarts" }, [ columnHead(h, { label: "Container", width: "w-0 flex-1 min-w-[200px]" }), - columnHead(h, { label: "In window", align: "right", width: "w-[96px]" }), - columnHead(h, { label: "Total", align: "right", width: "w-[96px]" }), - columnHead(h, { label: "Last terminated", align: "right", width: "w-[160px]" }), + columnHead(h, { label: "In window", align: "right", width: "w-24" }), + columnHead(h, { label: "Total", align: "right", width: "w-24" }), + columnHead(h, { label: "Last terminated", align: "right", width: "w-40" }), ], rows.map((row) => containerRow(h, row)), ), diff --git a/apps/web/src/page/infra/kubernetes/pod-table.ts b/apps/web/src/page/infra/kubernetes/pod-table.ts index cd7fa8c674..683e5ebca7 100644 --- a/apps/web/src/page/infra/kubernetes/pod-table.ts +++ b/apps/web/src/page/infra/kubernetes/pod-table.ts @@ -68,24 +68,24 @@ const columns = ( columnHead(h, { label: "Peak saturation", sort: head("saturation"), - width: "w-[176px]", + width: "w-44", hidden: "hidden md:flex", }), columnHead(h, { label: "CPU cores", sort: head("cpuUsage"), align: "right", - width: "w-[132px]", + width: "w-32", hidden: "hidden lg:flex", }), columnHead(h, { label: "Mem of limit", sort: head("memoryLimitPct"), align: "right", - width: "w-[120px]", + width: "w-32", hidden: "hidden lg:flex", }), - columnHead(h, { label: "Last seen", sort: head("lastSeen"), align: "right", width: "w-[100px]" }), + columnHead(h, { label: "Last seen", sort: head("lastSeen"), align: "right", width: "w-24" }), ] } @@ -100,12 +100,12 @@ export const podTableLoading = (h: HtmlBuilder): Html => [skeleton(h, "h-4 w-48"), skeleton(h, "mt-1.5 h-3 w-40")], ), h.div( - [h.Class("hidden w-[176px] space-y-1.5 md:block")], - [skeleton(h, "h-2.5 w-[176px]"), skeleton(h, "h-2.5 w-[176px]")], + [h.Class("hidden w-44 space-y-1.5 md:block")], + [skeleton(h, "h-2.5 w-44"), skeleton(h, "h-2.5 w-44")], ), - skeleton(h, "hidden h-3 w-[132px] lg:block"), - skeleton(h, "hidden h-3 w-[120px] lg:block"), - skeleton(h, "h-3 w-[100px]"), + skeleton(h, "hidden h-3 w-32 lg:block"), + skeleton(h, "hidden h-3 w-32 lg:block"), + skeleton(h, "h-3 w-24"), ]), ) @@ -202,7 +202,7 @@ const podRow = (h: HtmlBuilder, pod: PodRow, inputs: PodTableInputs): H ], ), h.div( - [h.Class("hidden w-[176px] md:block")], + [h.Class("hidden w-44 md:block")], [ meterRows(h, [ { label: "CPU", fraction: pod.cpuLimitPctPeak }, @@ -211,11 +211,11 @@ const podRow = (h: HtmlBuilder, pod: PodRow, inputs: PodTableInputs): H ], ), h.div( - [h.Class("hidden w-[132px] text-right lg:block")], + [h.Class("hidden w-32 text-right lg:block")], [avgPeak(h, { avg: pod.cpuUsage, peak: pod.cpuUsagePeak, format: formatCores })], ), h.div( - [h.Class("hidden w-[120px] text-right lg:block")], + [h.Class("hidden w-32 text-right lg:block")], [ avgPeak(h, { avg: pod.memoryLimitPct, @@ -225,7 +225,7 @@ const podRow = (h: HtmlBuilder, pod: PodRow, inputs: PodTableInputs): H ], ), h.div( - [h.Class("w-[100px] text-right")], + [h.Class("w-24 text-right")], [ relativeTime(h, { value: pod.lastSeen, diff --git a/apps/web/src/page/infra/kubernetes/workloads/view-table.ts b/apps/web/src/page/infra/kubernetes/workloads/view-table.ts index f417a8a1b5..6057b7107c 100644 --- a/apps/web/src/page/infra/kubernetes/workloads/view-table.ts +++ b/apps/web/src/page/infra/kubernetes/workloads/view-table.ts @@ -23,18 +23,18 @@ const columns = (h: H, sort: SortState | null, kind: WorkloadKind | undefined): const head = (key: WorkloadSortKey) => headSort(sort, key, (k) => Message.ClickedSort({ key: k })) return [ columnHead(h, { label: "Workload", sort: head("workloadName"), width: "w-0 flex-1 min-w-[260px]" }), - columnHead(h, { label: kind === "job" ? "Completions" : "Ready", width: "w-[110px]" }), + columnHead(h, { label: kind === "job" ? "Completions" : "Ready", width: "w-28" }), columnHead(h, { label: "Pods", sort: head("podCount"), align: "right", width: "w-[60px]" }), - columnHead(h, { label: "Restarts", sort: head("restarts"), align: "right", width: "w-[140px]" }), - columnHead(h, { label: "CPU peak", sort: head("peakCpuLimitPct"), align: "right", width: "w-[140px]", hidden: "hidden md:flex" }), + columnHead(h, { label: "Restarts", sort: head("restarts"), align: "right", width: "w-36" }), + columnHead(h, { label: "CPU peak", sort: head("peakCpuLimitPct"), align: "right", width: "w-36", hidden: "hidden md:flex" }), columnHead(h, { label: "Memory peak", sort: head("peakMemoryLimitPct"), align: "right", - width: "w-[140px]", + width: "w-36", hidden: "hidden lg:flex", }), - columnHead(h, { label: "Last seen", sort: head("lastSeen"), align: "right", width: "w-[100px]" }), + columnHead(h, { label: "Last seen", sort: head("lastSeen"), align: "right", width: "w-24" }), ] } @@ -45,12 +45,12 @@ export const workloadTableLoading = (h: H): Html => columns(h, null, undefined), skeletonRows(h, 4, () => [ h.div([h.Class("w-0 min-w-[260px] flex-1")], [skeleton(h, "h-4 w-48"), skeleton(h, "mt-1.5 h-3 w-32")]), - skeleton(h, "h-3 w-[110px]"), + skeleton(h, "h-3 w-28"), skeleton(h, "h-3 w-[60px]"), - skeleton(h, "h-3 w-[140px]"), - skeleton(h, "hidden h-3 w-[140px] md:block"), - skeleton(h, "hidden h-3 w-[140px] lg:block"), - skeleton(h, "h-3 w-[100px]"), + skeleton(h, "h-3 w-36"), + skeleton(h, "hidden h-3 w-36 md:block"), + skeleton(h, "hidden h-3 w-36 lg:block"), + skeleton(h, "h-3 w-24"), ]), ) @@ -122,16 +122,16 @@ const workloadRow = (h: H, wl: WorkloadRow, inputs: WorkloadTableInputs): Html = metaLine(h, [wl.namespace && `ns ${wl.namespace}`, `kind ${inputs.kind}`]), ], ), - h.div([h.Class("w-[110px] font-mono text-xs tabular-nums")], [replicaCell(h, wl, inputs.kind)]), + h.div([h.Class("w-28 font-mono text-xs tabular-nums")], [replicaCell(h, wl, inputs.kind)]), h.div( - [h.Class("w-[60px] text-right font-mono text-xs tabular-nums text-foreground/80")], + [h.Class("w-[60px] text-right font-mono text-xs tabular-nums text-foreground-soft")], [wl.podCount.toLocaleString("en-US")], ), h.div( [ h.Class( cn( - "flex w-[140px] flex-col items-end font-mono text-xs tabular-nums", + "flex w-36 flex-col items-end font-mono text-xs tabular-nums", TONE_TEXT[restartTone(wl.restarts, wl.lastTerminatedReason)], ), ), @@ -144,15 +144,15 @@ const workloadRow = (h: H, wl: WorkloadRow, inputs: WorkloadTableInputs): Html = ], ), h.div( - [h.Class("hidden w-[140px] md:block")], + [h.Class("hidden w-36 md:block")], [meterRows(h, [{ label: "CPU", fraction: wl.peakCpuLimitPct }], { hideLabels: true })], ), h.div( - [h.Class("hidden w-[140px] lg:block")], + [h.Class("hidden w-36 lg:block")], [meterRows(h, [{ label: "MEM", fraction: wl.peakMemoryLimitPct }], { hideLabels: true })], ), h.div( - [h.Class("w-[100px] text-right")], + [h.Class("w-24 text-right")], [ relativeTime(h, { value: wl.lastSeen, diff --git a/apps/web/src/page/infra/overview/view-findings.ts b/apps/web/src/page/infra/overview/view-findings.ts index a232ecbb3b..93a6d17888 100644 --- a/apps/web/src/page/infra/overview/view-findings.ts +++ b/apps/web/src/page/infra/overview/view-findings.ts @@ -23,7 +23,7 @@ export const sectionCaption = (h: HtmlBuilder, text: string): Html => const STALE_DOT = "border-[1.5px] border-muted-foreground bg-transparent" export const ROW_CLASS = - "group flex items-center gap-4 px-4 py-3 transition-colors hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none" + "group flex items-center gap-4 px-4 py-3 transition-colors hover:bg-surface-sunken focus-visible:bg-surface-sunken focus-visible:outline-none" export const FINDINGS_LIST_CLASS = "flex flex-col overflow-hidden rounded-md border" const FINDINGS_ROW_CLASS = "-mt-px border-t" diff --git a/apps/web/src/page/infra/overview/view-sources.ts b/apps/web/src/page/infra/overview/view-sources.ts index d6b5fa52bb..7d02e0a66c 100644 --- a/apps/web/src/page/infra/overview/view-sources.ts +++ b/apps/web/src/page/infra/overview/view-sources.ts @@ -158,7 +158,7 @@ const sourceRowPending = (h: HtmlBuilder): Html => h.span( [h.Class("flex w-52 shrink-0 items-center gap-3")], [ - skeleton(h, "size-[18px] shrink-0 rounded"), + skeleton(h, "size-[18px] shrink-0 rounded-sm"), h.span( [h.Class("flex min-w-0 flex-col gap-0.5")], [skeleton(h, "my-0.5 h-4 w-24"), skeleton(h, "my-0.5 h-3 w-16")], diff --git a/apps/web/src/page/integrations/view-aws-choose.ts b/apps/web/src/page/integrations/view-aws-choose.ts index 5e2fd2d8ed..29c5a30d7b 100644 --- a/apps/web/src/page/integrations/view-aws-choose.ts +++ b/apps/web/src/page/integrations/view-aws-choose.ts @@ -59,7 +59,7 @@ const regionList = (h: H, connection: V2AwsConnection, selection: AwsSelection): [...REGIONS, ...extra].map((region) => { const isPicked = selection.regions.includes(region.code) return h.li( - [h.Class("border-b border-border/60")], + [h.Class("border-b border-border-subtle")], [ h.label( [h.Class("flex cursor-pointer items-center gap-3 py-2 text-sm")], @@ -97,7 +97,7 @@ const serviceGrid = (h: H, connection: V2AwsConnection, selection: AwsSelection) [ h.Class( cn( - "flex items-center justify-between gap-3 rounded-md border border-border px-3 py-2.5", + "flex items-center justify-between gap-3 rounded-md border border-border p-3", !isPicked && "text-muted-foreground", ), ), diff --git a/apps/web/src/page/integrations/view-aws.ts b/apps/web/src/page/integrations/view-aws.ts index f33edcd387..0497c239ac 100644 --- a/apps/web/src/page/integrations/view-aws.ts +++ b/apps/web/src/page/integrations/view-aws.ts @@ -50,7 +50,7 @@ const editDataPanel = (h: H, model: Model, connection: V2AwsConnection): Html => const selection = selectionOf(connection, card.selection) return h.form( [ - h.Class("flex w-full flex-col gap-4 rounded-md border bg-muted/20 p-3"), + h.Class("flex w-full flex-col gap-4 rounded-md border bg-surface-faint p-3"), h.OnSubmit(Message.SubmittedAwsMetrics({ id: connection.id })), ], [ @@ -102,7 +102,7 @@ interface Step { } const STEP_GLYPH = { - done: { icon: "CircleCheckIcon", className: "text-success-foreground" }, + done: { icon: "CircleCheckIcon", className: "text-severity-info" }, current: { icon: "ClockIcon", className: "text-muted-foreground" }, warn: { icon: "CircleWarningIcon", className: "text-severity-warn" }, crit: { icon: "CircleXmarkIcon", className: "text-severity-error" }, @@ -357,7 +357,7 @@ const ingestBody = ( [h.Class("w-full text-xs")], [ h.thead( - [h.Class("bg-muted/30 text-left text-muted-foreground")], + [h.Class("bg-surface-sunken text-left text-muted-foreground")], [ h.tr( [], @@ -563,7 +563,7 @@ const connectionRow = (h: H, model: Model, connection: V2AwsConnection, timeZone const setupPanel = (h: H, model: Model, connection: V2AwsConnection): Html => { const waiting = connection.verified_at === null return h.div( - [h.Class("mt-2 flex w-full flex-col gap-3 rounded-md border bg-muted/20 p-3")], + [h.Class("mt-2 flex w-full flex-col gap-3 rounded-md border bg-surface-faint p-3")], [ h.div( [h.Class("flex flex-wrap items-center gap-2")], diff --git a/apps/web/src/page/integrations/view-cloudflare-board.ts b/apps/web/src/page/integrations/view-cloudflare-board.ts index c2a1af2234..96a4f0fcb7 100644 --- a/apps/web/src/page/integrations/view-cloudflare-board.ts +++ b/apps/web/src/page/integrations/view-cloudflare-board.ts @@ -117,7 +117,7 @@ const resourceRow = ( [ h.Class( cn( - "hidden w-[190px] min-w-0 shrink-0 self-center text-2xs @lg:block", + "hidden w-48 min-w-0 shrink-0 self-center text-2xs @lg:block", status.detailClass, ), ), @@ -125,7 +125,7 @@ const resourceRow = ( detailView(h, status.detail), ), h.div( - [h.Class("flex w-[124px] shrink-0 items-center justify-end gap-2.5 self-center")], + [h.Class("flex w-32 shrink-0 items-center justify-end gap-2.5 self-center")], [ ...(hasData && usage !== null ? [sparkline(h, model, name, usage)] : []), h.span( @@ -136,7 +136,7 @@ const resourceRow = ( ), ] const rowClass = - "group flex items-start gap-3 border-b border-border/60 px-3 py-2 transition-colors last:border-0" + "group flex items-start gap-3 border-b border-border-subtle px-3 py-2 transition-colors last:border-0" return zoneLink ? h.a( [ @@ -144,7 +144,7 @@ const resourceRow = ( h.Class( cn( rowClass, - "hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none", + "hover:bg-surface-sunken focus-visible:bg-surface-sunken focus-visible:outline-none", ), ), ], @@ -210,9 +210,9 @@ export const zoneBoard = ( onSort: Message.ClickedZoneSort({ key }), }, }) - return panel(h, { className: cn("@container border-border/60", className) }, [ + return panel(h, { className: cn("@container border-border-subtle", className) }, [ panelHeader(h, { - className: "gap-2 border-border/60 pl-4 pr-2.5", + className: "gap-2 border-border-subtle pl-4 pr-2.5", children: [ h.h3([h.Class("text-sm font-semibold")], ["Zones"]), ToggleGroup.view(h, { @@ -235,7 +235,7 @@ export const zoneBoard = ( }), searchInput(h, { id: "cloudflare-zone-search", - className: "w-full sm:w-[170px]", + className: "w-full sm:w-44", value: card.zoneSearch, placeholder: "Filter zones…", onInput: (value) => Message.ChangedZoneSearch({ value }), @@ -262,12 +262,12 @@ export const zoneBoard = ( [h.Class("flex flex-col")], [ h.div( - [h.Class("flex items-center gap-3 border-b border-border/60 px-3 py-2")], + [h.Class("flex items-center gap-3 border-b border-border-subtle px-3 py-2")], [ h.span([h.AriaHidden(true), h.Class("size-1.5 shrink-0")]), head("Zone", "name", "min-w-0 flex-1", {}), - head("Status", "status", "w-[190px]", { hidden: "hidden @lg:flex" }), - head("24h requests", "requests", "w-[124px]", { align: "right" }), + head("Status", "status", "w-48", { hidden: "hidden @lg:flex" }), + head("24h requests", "requests", "w-32", { align: "right" }), ], ), sorted.length === 0 @@ -307,9 +307,9 @@ export const workersCard = ( const scripts = workerServices.toSorted((a, b) => b.totalRequests - a.totalRequests) const expanded = model.cloudflareCard.workersExpanded const visible = expanded ? scripts : scripts.slice(0, WORKERS_COLLAPSED_COUNT) - return panel(h, { className: "h-fit border-border/60 lg:w-72 lg:shrink-0 xl:w-80" }, [ + return panel(h, { className: "h-fit border-border-subtle lg:w-72 lg:shrink-0 xl:w-80" }, [ panelHeader(h, { - className: "border-border/60 py-3", + className: "border-border-subtle py-3", children: [h.h3([h.Class("text-sm font-semibold")], ["Workers"])], action: h.a( [ @@ -322,7 +322,7 @@ export const workersCard = ( ...(aggregate.kind === "issue" || aggregate.kind === "no-data" ? [ h.div( - [h.Class(cn("border-b border-border/60 px-4 py-2 text-2xs", aggregate.detailClass))], + [h.Class(cn("border-b border-border-subtle px-4 py-2 text-2xs", aggregate.detailClass))], detailView(h, aggregate.detail), ), ] @@ -345,7 +345,7 @@ export const workersCard = ( h.div( [ h.Class( - "flex items-center justify-between gap-3 border-b border-border/60 py-2.5 last:border-0", + "flex items-center justify-between gap-3 border-b border-border-subtle py-2.5 last:border-0", ), ], [ diff --git a/apps/web/src/page/integrations/view-cloudflare-connected.ts b/apps/web/src/page/integrations/view-cloudflare-connected.ts index aed2b67083..8965e6096e 100644 --- a/apps/web/src/page/integrations/view-cloudflare-connected.ts +++ b/apps/web/src/page/integrations/view-cloudflare-connected.ts @@ -36,13 +36,13 @@ type H = HtmlBuilder const accountsStrip = (h: H, accounts: ReadonlyArray): Html | null => accounts.length < 2 ? null - : panel(h, { className: "border-border/60" }, [ + : panel(h, { className: "border-border-subtle" }, [ panelHeader(h, { title: `Connected accounts (${accounts.length})`, - className: "border-border/60", + className: "border-border-subtle", }), h.ul( - [h.Class("divide-y divide-border/60")], + [h.Class("divide-y divide-border-subtle")], accounts.map((account) => item(h, { variant: "flush", size: "lg", className: "py-2.5", tag: "li" }, [ itemMedia(h, {}, [ diff --git a/apps/web/src/page/integrations/view-cloudflare-zones.ts b/apps/web/src/page/integrations/view-cloudflare-zones.ts index 007fafcfb0..2e93c504a3 100644 --- a/apps/web/src/page/integrations/view-cloudflare-zones.ts +++ b/apps/web/src/page/integrations/view-cloudflare-zones.ts @@ -21,7 +21,7 @@ const zoneRow = (h: H, accountId: string, zone: ZoneChoice["zones"][number]): Ht [ h.Key(inputId), h.Id(Checkbox.labelId(inputId)), - h.Class("flex min-w-0 items-center gap-2.5 px-3 py-1.5 text-sm hover:bg-muted/50"), + h.Class("flex min-w-0 items-center gap-2.5 px-3 py-1.5 text-sm hover:bg-surface-sunken"), ], [ ...Checkbox.view(h, { @@ -92,7 +92,7 @@ const accountSection = (h: H, account: ZoneChoice, query: string, isMulti: boole ? h.p( [ h.Class( - "rounded-md border border-border/60 px-3 py-4 text-xs text-muted-foreground", + "rounded-md border border-border-subtle px-3 py-4 text-xs text-muted-foreground", ), ], [account.zones.length === 0 ? "No zones found yet." : "No zones match the filter."], @@ -100,7 +100,7 @@ const accountSection = (h: H, account: ZoneChoice, query: string, isMulti: boole : h.div( [ h.Class( - "flex max-h-64 flex-col overflow-y-auto overscroll-contain rounded-md border border-border/60 py-1", + "flex max-h-64 flex-col overflow-y-auto overscroll-contain rounded-md border border-border-subtle py-1", ), ], shown.map((zone) => zoneRow(h, account.accountId, zone)), diff --git a/apps/web/src/page/integrations/view-flow-aws.ts b/apps/web/src/page/integrations/view-flow-aws.ts index fa5dcb5c0a..7c9f1a8f82 100644 --- a/apps/web/src/page/integrations/view-flow-aws.ts +++ b/apps/web/src/page/integrations/view-flow-aws.ts @@ -166,7 +166,7 @@ const accountLine = (h: H, connection: V2AwsConnection): Html => h.div( [h.Class("flex flex-wrap items-center gap-2 text-sm")], [ - icon(h, "CircleCheckIcon", { size: 14, className: "text-success" }), + icon(h, "CircleCheckIcon", { size: 14, className: "text-severity-info" }), h.span([], ["AWS account ID"]), h.span([h.Class("font-mono tabular-nums")], [connection.account_id]), button(h, { size: "sm", variant: "ghost", attributes: [h.OnClick(Message.ClickedAwsAdd())] }, [ diff --git a/apps/web/src/page/integrations/view-flow-cloudflare.ts b/apps/web/src/page/integrations/view-flow-cloudflare.ts index c0c811d43b..37ebe82dd5 100644 --- a/apps/web/src/page/integrations/view-flow-cloudflare.ts +++ b/apps/web/src/page/integrations/view-flow-cloudflare.ts @@ -100,11 +100,11 @@ const accountList = (h: H, accounts: ReadonlyArray): Html [h.Class("flex flex-col rounded-md border border-border"), h.AriaLabel("Cloudflare accounts")], accounts.map((account) => h.li( - [h.Class("flex items-center gap-3 border-t border-border/60 px-3.5 py-2.5 first:border-t-0")], + [h.Class("flex items-center gap-3 border-t border-border-subtle px-3.5 py-2.5 first:border-t-0")], [ icon(h, account.revoked ? "CircleWarningIcon" : "CircleCheckIcon", { size: 14, - className: account.revoked ? "shrink-0 text-severity-error" : "shrink-0 text-success", + className: account.revoked ? "shrink-0 text-severity-error" : "shrink-0 text-severity-info", }), h.div( [h.Class("flex min-w-0 flex-1 flex-col")], diff --git a/apps/web/src/page/integrations/view-flow-github.ts b/apps/web/src/page/integrations/view-flow-github.ts index 6538f77de3..75570b57e9 100644 --- a/apps/web/src/page/integrations/view-flow-github.ts +++ b/apps/web/src/page/integrations/view-flow-github.ts @@ -102,7 +102,7 @@ const installation = (h: H, model: Model, status: GithubIntegrationStatus): Html [h.Class("flex flex-col gap-3")], [ h.div( - [h.Class("flex flex-wrap items-center gap-3 rounded-md border border-border px-3.5 py-3")], + [h.Class("flex flex-wrap items-center gap-3 rounded-md border border-border p-3")], [ icon(h, "GithubIcon", { size: 18, className: "shrink-0" }), h.div( @@ -258,7 +258,7 @@ const repoTable = (h: H, repos: ReadonlyArray): Html => return h.div( [ h.Class( - "flex items-center gap-4 border-b border-border/60 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border-subtle px-4 py-2.5 text-sm last:border-0", ), ], [ diff --git a/apps/web/src/page/integrations/view-flow-planetscale.ts b/apps/web/src/page/integrations/view-flow-planetscale.ts index e843e423a7..e55f93a54b 100644 --- a/apps/web/src/page/integrations/view-flow-planetscale.ts +++ b/apps/web/src/page/integrations/view-flow-planetscale.ts @@ -133,7 +133,7 @@ const authorizePart = (h: H, model: Model, status: V2PlanetScaleIntegration | nu h.span( [h.Class("inline-flex items-center gap-2 text-sm")], [ - icon(h, "CircleCheckIcon", { size: 14, className: "text-success" }), + icon(h, "CircleCheckIcon", { size: 14, className: "text-severity-info" }), status.organization === null ? "Authorized" : `Authorized for ${status.organization}`, ], ), diff --git a/apps/web/src/page/integrations/view-flow-prometheus.ts b/apps/web/src/page/integrations/view-flow-prometheus.ts index c255d07436..a461e6df62 100644 --- a/apps/web/src/page/integrations/view-flow-prometheus.ts +++ b/apps/web/src/page/integrations/view-flow-prometheus.ts @@ -137,7 +137,7 @@ const showsUpRail = (h: H, integration: ScrapeIntegration): Html => /** WarpStream's two endpoints and where each one's URL and key come from. */ const warpstreamGuide = (h: H): Html => h.div( - [h.Class("flex flex-col gap-2 rounded-md bg-muted/40 p-4")], + [h.Class("flex flex-col gap-2 rounded-md bg-surface-sunken p-4")], [ h.h3([h.Class("text-sm font-medium")], ["Where to find it in WarpStream"]), h.ul( @@ -214,7 +214,7 @@ const failedRow = ( h.pre( [ h.Class( - "overflow-x-auto rounded-md bg-muted/40 p-3 font-mono text-xs text-severity-error whitespace-pre-wrap [overflow-wrap:anywhere]", + "overflow-x-auto rounded-md bg-surface-sunken p-3 font-mono text-xs text-severity-error whitespace-pre-wrap [overflow-wrap:anywhere]", ), ], [error], diff --git a/apps/web/src/page/integrations/view-flow-supabase.ts b/apps/web/src/page/integrations/view-flow-supabase.ts index bb63dfa7b2..dc02cc9fb5 100644 --- a/apps/web/src/page/integrations/view-flow-supabase.ts +++ b/apps/web/src/page/integrations/view-flow-supabase.ts @@ -74,7 +74,7 @@ const muted = (h: H, text: string): Html => h.p([h.Class("text-sm text-muted-for /** What happens in the Supabase window, before it opens. */ const windowSteps = (h: H): Html => h.div( - [h.Class("flex flex-col gap-2 rounded-md bg-muted/40 p-4")], + [h.Class("flex flex-col gap-2 rounded-md bg-surface-sunken p-4")], [ eyebrow(h, { variant: "mono" }, ["In the Supabase window"]), h.ul( @@ -90,7 +90,7 @@ const windowSteps = (h: H): Html => const waitingBlock = (h: H): Html => h.div( - [h.Class("flex items-center gap-3 rounded-md bg-muted/40 p-4")], + [h.Class("flex items-center gap-3 rounded-md bg-surface-sunken p-4")], [ icon(h, "ClockIcon", { size: 16, className: "shrink-0 text-muted-foreground" }), h.div( @@ -140,7 +140,7 @@ const selfHostedLine = (h: H): Html => const revokedNotice = (h: H, status: SupabaseIntegrationStatus): Html => h.div( - [h.Class("flex gap-3 rounded-md border border-severity-warn/40 bg-card px-4 py-3"), h.Role("alert")], + [h.Class("flex gap-3 rounded-md border border-severity-warn/40 bg-card p-4"), h.Role("alert")], [ icon(h, "CircleWarningIcon", { size: 14, className: "mt-0.5 shrink-0 text-severity-warn" }), h.div( @@ -251,7 +251,7 @@ const chooseRow = (h: H, model: Model, project: Project): Html => { h.Key(project.ref), h.Class( cn( - "flex items-center gap-4 border-b border-border/60 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border-subtle px-4 py-2.5 text-sm last:border-0", isPaused && "opacity-60", ), ), diff --git a/apps/web/src/page/integrations/view-gcp-configure-collect.ts b/apps/web/src/page/integrations/view-gcp-configure-collect.ts index a44a0f5794..f802bd8ba5 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-collect.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-collect.ts @@ -34,7 +34,7 @@ export const collectFields = ( [ h.legend([h.Class(cn(GCP_TITLE, "mb-3"))], ["What should Maple collect?"]), h.div( - [h.Class("divide-y divide-border/60 rounded-md border")], + [h.Class("divide-y divide-border-subtle rounded-md border")], CAPABILITY_IDS.map((capability, index) => { const { title, flag, description, effects } = CAPABILITIES[capability] const note = options.effect?.(capability) ?? null diff --git a/apps/web/src/page/integrations/view-gcp-configure-filter.ts b/apps/web/src/page/integrations/view-gcp-configure-filter.ts index 84cbf51ab4..7bcb0239b5 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-filter.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-filter.ts @@ -42,7 +42,7 @@ export const logFilter = ( const state = h.DataAttribute(isOpen ? "open" : "closed", "") return h.div( [ - h.Class("rounded-md border border-border/60 bg-muted/32"), + h.Class("rounded-md border border-border-subtle bg-surface-sunken"), state, h.DataAttribute("slot", "collapsible"), ], @@ -89,7 +89,7 @@ export const logFilter = ( ], [ h.div( - [h.Class("border-t border-border/60 p-3")], + [h.Class("border-t border-border-subtle p-3")], [filterField(h, configure, options)], ), ], diff --git a/apps/web/src/page/integrations/view-gcp-configure-method-choice.ts b/apps/web/src/page/integrations/view-gcp-configure-method-choice.ts index 80c4b74f11..227b072c38 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-method-choice.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-method-choice.ts @@ -88,7 +88,7 @@ export const methodChoice = (h: H, configure: ConfigureModel, changing: boolean) [h.Class(cn(GCP_TITLE, "mb-3"))], [changing ? "How do you want to apply the change?" : "How do you want to connect?"], ), - RadioGroup.radioGroup(h, { className: "gap-0 divide-y divide-border/60 rounded-md border" }, [ + RadioGroup.radioGroup(h, { className: "gap-0 divide-y divide-border-subtle rounded-md border" }, [ ...METHODS.map((option) => h.div( [h.Key(option.value), h.Class("flex flex-col gap-3 p-4")], diff --git a/apps/web/src/page/integrations/view-gcp-configure-parts.ts b/apps/web/src/page/integrations/view-gcp-configure-parts.ts index 783550591a..61798f301a 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-parts.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-parts.ts @@ -38,7 +38,7 @@ export const chip = (h: H, children: Children): Html => h.span( [ h.Class( - "inline-flex items-center gap-1.5 rounded-md border border-border/60 bg-muted/40 px-2 py-0.5 text-xs/5", + "inline-flex items-center gap-1.5 rounded-md border border-border-subtle bg-surface-sunken px-2 py-0.5 text-xs/5", ), ], children, @@ -73,7 +73,7 @@ const stepper = (h: H, current: StepIndex): Html => ), ], [ - ...(done ? [icon(h, "CheckIcon", { size: 12, className: "text-success" })] : []), + ...(done ? [icon(h, "CheckIcon", { size: 12, className: "text-severity-info" })] : []), label, ...(done ? [h.span([h.Class("sr-only")], [" (done)"])] : []), ], @@ -82,7 +82,7 @@ const stepper = (h: H, current: StepIndex): Html => ? [step] : [ h.li( - [h.AriaHidden(true), h.Class("inline-flex text-muted-foreground/60")], + [h.AriaHidden(true), h.Class("inline-flex text-foreground-subtle")], [icon(h, "ArrowRightIcon", { size: 12 })], ), step, @@ -104,7 +104,7 @@ export const configureHeader = (h: H, title: Children, step: StepIndex | null): h.span( [ h.Class( - "flex size-8 shrink-0 items-center justify-center rounded-md border bg-muted/60", + "flex size-8 shrink-0 items-center justify-center rounded-md border bg-surface-strong", ), ], [icon(h, "GoogleCloudIcon", { size: 18 })], diff --git a/apps/web/src/page/integrations/view-gcp-configure-script.ts b/apps/web/src/page/integrations/view-gcp-configure-script.ts index e3dcdcf637..6de45305f9 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-script.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-script.ts @@ -77,7 +77,7 @@ export const fileCard = (h: H, model: Model, configure: ConfigureModel, options: [h.Class("overflow-clip rounded-md border")], [ h.div( - [h.Class("flex flex-wrap items-center gap-2 border-b bg-muted/40 px-3 py-2")], + [h.Class("flex flex-wrap items-center gap-2 border-b bg-surface-sunken px-3 py-2")], [ h.span( [h.Class("font-mono text-xs text-muted-foreground")], diff --git a/apps/web/src/page/integrations/view-gcp-configure-status.ts b/apps/web/src/page/integrations/view-gcp-configure-status.ts index 181e46416f..32bad28e50 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-status.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-status.ts @@ -235,7 +235,7 @@ export const applied = (h: H, connector: V2GcpConnector, created: boolean, nowMs ], ), h.ul( - [h.Class("w-full divide-y divide-border/60 rounded-md border text-left")], + [h.Class("w-full divide-y divide-border-subtle rounded-md border text-left")], rows.map((row) => h.li( [h.Class("flex items-center gap-3 px-4 py-2.5")], diff --git a/apps/web/src/page/integrations/view-gcp-connection.ts b/apps/web/src/page/integrations/view-gcp-connection.ts index b7c36032b1..f79d15da2d 100644 --- a/apps/web/src/page/integrations/view-gcp-connection.ts +++ b/apps/web/src/page/integrations/view-gcp-connection.ts @@ -423,7 +423,7 @@ export const gcpConnection = (h: H, model: Model, connector: V2GcpConnector, tim h.div( [ h.Class( - "flex flex-col divide-y divide-border/60 border-t border-border/60 @md:flex-row @md:divide-x @md:divide-y-0", + "flex flex-col divide-y divide-border-subtle border-t border-border-subtle @md:flex-row @md:divide-x @md:divide-y-0", ), ], [ diff --git a/apps/web/src/page/integrations/view-gcp-dialogs.ts b/apps/web/src/page/integrations/view-gcp-dialogs.ts index d575d56248..e4cf8f5e22 100644 --- a/apps/web/src/page/integrations/view-gcp-dialogs.ts +++ b/apps/web/src/page/integrations/view-gcp-dialogs.ts @@ -188,7 +188,7 @@ const cleanupDisconnect = (h: H, model: Model, connector: V2GcpConnector, timeZo ], ), h.p( - [h.Class(cn(SMALL, "text-foreground/80"))], + [h.Class(cn(SMALL, "text-foreground-soft"))], [ connector.setup_reported_at === null ? "Maple sees the cleanup script finish. Removed them another way? Disconnect anyway." diff --git a/apps/web/src/page/integrations/view-gcp-setup-methods.ts b/apps/web/src/page/integrations/view-gcp-setup-methods.ts index 5756aac78e..fb791cad54 100644 --- a/apps/web/src/page/integrations/view-gcp-setup-methods.ts +++ b/apps/web/src/page/integrations/view-gcp-setup-methods.ts @@ -138,7 +138,7 @@ export const manualSteps = ( ], ), h.ol( - [h.Class("divide-y divide-border/60 rounded-md border")], + [h.Class("divide-y divide-border-subtle rounded-md border")], options.steps.map((step, index) => { const expanded = open === step.title return h.li( diff --git a/apps/web/src/page/integrations/view-gcp-workloads.ts b/apps/web/src/page/integrations/view-gcp-workloads.ts index 0e7a87575a..597c77e9e8 100644 --- a/apps/web/src/page/integrations/view-gcp-workloads.ts +++ b/apps/web/src/page/integrations/view-gcp-workloads.ts @@ -60,9 +60,9 @@ const workloads = (h: H, model: Model, className: string): Html => { ) const manyProjects = new Set(all.map((row) => gcpWorkloadProject(row.service, row.workload.keys))).size > 1 - return panel(h, { className: cn("@container border-border/60", className) }, [ + return panel(h, { className: cn("@container border-border-subtle", className) }, [ panelHeader(h, { - className: "gap-2 border-border/60 pr-2.5", + className: "gap-2 border-border-subtle pr-2.5", children: [ h.div( [h.Class("flex min-w-0 flex-1 items-baseline gap-3")], @@ -98,7 +98,7 @@ const workloads = (h: H, model: Model, className: string): Html => { ? [] : [ h.p( - [h.Class("border-b border-border/60 px-4 py-2 text-2xs text-severity-warn")], + [h.Class("border-b border-border-subtle px-4 py-2 text-2xs text-severity-warn")], [`${gcpTitles(unread)} metrics could not be read. Reload to try again.`], ), ]), @@ -132,7 +132,7 @@ const workloads = (h: H, model: Model, className: string): Html => { ), ), h.Class( - "group flex items-center gap-3 border-b border-border/60 px-4 py-2.5 transition-colors last:border-0 hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none", + "group flex items-center gap-3 border-b border-border-subtle px-4 py-2.5 transition-colors last:border-0 hover:bg-surface-sunken focus-visible:bg-surface-sunken focus-visible:outline-none", ), ], [ @@ -204,9 +204,9 @@ const resources = (h: H, model: Model, className: string): Html => { const inventory = inventoryOf(model) if (inventory === null) return skeleton(h, cn("h-40 rounded-md", className)) const types = inventory === "failed" ? [] : inventory.types.toSorted((a, b) => b.count - a.count) - return panel(h, { className: cn("h-fit border-border/60", className) }, [ + return panel(h, { className: cn("h-fit border-border-subtle", className) }, [ panelHeader(h, { - className: "border-border/60", + className: "border-border-subtle", children: [h.h3([h.Class("text-sm font-semibold")], ["Resources"])], action: h.span([h.Class("text-2xs text-muted-foreground")], ["listed hourly"]), }), @@ -231,7 +231,7 @@ const resources = (h: H, model: Model, className: string): Html => { ), ), h.Class( - "flex items-center justify-between gap-3 rounded-sm px-2 py-1.5 text-xs transition-colors hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none", + "flex items-center justify-between gap-3 rounded-sm px-2 py-1.5 text-xs transition-colors hover:bg-surface-sunken focus-visible:bg-surface-sunken focus-visible:outline-none", ), ], [ @@ -252,7 +252,7 @@ const resources = (h: H, model: Model, className: string): Html => { h.footer( [ h.Class( - "flex items-center justify-between gap-3 border-t border-border/60 px-4 py-2.5 text-xs text-muted-foreground", + "flex items-center justify-between gap-3 border-t border-border-subtle px-4 py-2.5 text-xs text-muted-foreground", ), ], [ diff --git a/apps/web/src/page/integrations/view-github-repos.ts b/apps/web/src/page/integrations/view-github-repos.ts index 4694e1eee7..0a5747b854 100644 --- a/apps/web/src/page/integrations/view-github-repos.ts +++ b/apps/web/src/page/integrations/view-github-repos.ts @@ -104,7 +104,7 @@ const branchContent = (h: H, model: Model, repo: GithubRepoSummary): ReadonlyArr h.Type("button"), h.OnClick(Message.ClickedBranch({ repoId: repo.id, branch: branch.name })), h.Class( - "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs hover:bg-muted/50", + "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs hover:bg-surface-sunken", ), ], [ diff --git a/apps/web/src/page/integrations/view-hazel.ts b/apps/web/src/page/integrations/view-hazel.ts index fbf04660d6..49d84a9e37 100644 --- a/apps/web/src/page/integrations/view-hazel.ts +++ b/apps/web/src/page/integrations/view-hazel.ts @@ -97,7 +97,7 @@ const connected = ( h.div( [ h.Class( - "flex flex-col gap-1 rounded-md bg-muted/40 px-3 py-2 text-2xs text-muted-foreground", + "flex flex-col gap-1 rounded-md bg-surface-sunken px-3 py-2 text-2xs text-muted-foreground", ), ], [ diff --git a/apps/web/src/page/integrations/view-hub.ts b/apps/web/src/page/integrations/view-hub.ts index 3b9c27be93..59e30846d8 100644 --- a/apps/web/src/page/integrations/view-hub.ts +++ b/apps/web/src/page/integrations/view-hub.ts @@ -65,7 +65,7 @@ const connectedRow = ( h.Type("button"), h.OnClick(onSelect(entry.id)), h.Class( - "group flex w-full items-center gap-4 px-4 py-3 text-left outline-none transition-colors hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/40", + "group flex w-full items-center gap-4 px-4 py-3 text-left outline-none transition-colors hover:bg-surface-sunken focus-visible:bg-surface-sunken focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/40", ), ], [ @@ -110,7 +110,7 @@ const connectedRow = ( ...(connected?.stat ? [ h.span( - [h.Class("hidden min-w-0 flex-1 truncate text-sm text-foreground/90 md:block")], + [h.Class("hidden min-w-0 flex-1 truncate text-sm text-foreground-soft md:block")], [connected.stat], ), ] @@ -145,7 +145,7 @@ const connectedRow = ( : []), icon(h, "ChevronRightIcon", { size: 14, - className: "text-muted-foreground/70 transition-colors group-hover:text-foreground", + className: "text-foreground-subtle transition-colors group-hover:text-foreground", }), ], ), @@ -161,7 +161,7 @@ const availableCard = (h: H, entry: CatalogEntry, cta: AvailableOverview["cta"], h.Type("button"), h.OnClick(onSelect(entry.id)), h.Class( - "group flex items-center gap-4 rounded-md border border-border/60 bg-card p-4 text-left outline-none transition-colors hover:border-border hover:bg-muted/50 focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40", + "group flex items-center gap-4 rounded-md border border-border-subtle bg-card p-4 text-left outline-none transition-colors hover:border-border hover:bg-surface-sunken focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40", ), ], [ @@ -313,7 +313,7 @@ export const integrationCatalog = (h: H, model: Model, onSelect: Select): Html = ]), ], ), - panel(h, { className: "divide-y divide-border/60 border-border/60" }, [ + panel(h, { className: "divide-y divide-border-subtle border-border-subtle" }, [ ...connected.map(({ entry, overview }) => connectedRow(h, entry, overview, onSelect), ), diff --git a/apps/web/src/page/integrations/view-linear.ts b/apps/web/src/page/integrations/view-linear.ts index 8b13c28948..cfe1168885 100644 --- a/apps/web/src/page/integrations/view-linear.ts +++ b/apps/web/src/page/integrations/view-linear.ts @@ -102,7 +102,7 @@ const connected = (h: H, model: Model, status: LinearIntegrationStatus): Html => ...(status.workspaceName !== null && status.workspaceName !== "" ? [ h.div( - [h.Class("rounded-md bg-muted/40 px-3 py-2 text-2xs text-muted-foreground")], + [h.Class("rounded-md bg-surface-sunken px-3 py-2 text-2xs text-muted-foreground")], [ h.div( [h.Class("[overflow-wrap:anywhere]")], diff --git a/apps/web/src/page/integrations/view-planetscale-parts.ts b/apps/web/src/page/integrations/view-planetscale-parts.ts index a6564479ef..ceaa54f7da 100644 --- a/apps/web/src/page/integrations/view-planetscale-parts.ts +++ b/apps/web/src/page/integrations/view-planetscale-parts.ts @@ -40,7 +40,7 @@ export const metricsHealth = ( const excluded = status.scrape_target?.exclude_branches ?? [] const isOpen = model.planetscaleCard.isDetailsOpen return h.div( - [h.Class("border-t border-border/60 p-4")], + [h.Class("border-t border-border-subtle p-4")], [ h.div( [h.Class("flex flex-wrap items-center gap-2 text-xs")], @@ -112,7 +112,7 @@ export const metricsHealth = ( h.p( [ h.Class( - "mt-2 break-all rounded-md bg-muted/40 p-2 font-mono text-xs text-muted-foreground", + "mt-2 break-all rounded-md bg-surface-sunken p-2 font-mono text-xs text-muted-foreground", ), ], [metricsLastError(status) ?? ""], diff --git a/apps/web/src/page/integrations/view-planetscale.ts b/apps/web/src/page/integrations/view-planetscale.ts index 0a35f583f5..f9ff4652ae 100644 --- a/apps/web/src/page/integrations/view-planetscale.ts +++ b/apps/web/src/page/integrations/view-planetscale.ts @@ -106,7 +106,7 @@ const webhookStatus = (h: H, model: Model, webhooks: Webhooks): Html => h.p( [ h.Class( - "mt-2 break-all rounded-md bg-muted/40 p-2 font-mono text-xs text-muted-foreground", + "mt-2 break-all rounded-md bg-surface-sunken p-2 font-mono text-xs text-muted-foreground", ), ], [webhooks.last_error], @@ -198,7 +198,7 @@ const connectedView = (h: H, model: Model, status: V2PlanetScaleIntegration, tim isLive ? metricsHealth(h, model, status, timeZone) : h.div( - [h.Class("border-t border-border/60 p-4")], + [h.Class("border-t border-border-subtle p-4")], [ liveChecklist(h, { title: "Checking the connection", rows: setup.checks }), ...(isWatchExpired(model.planetscaleCard, model.nowMs) diff --git a/apps/web/src/page/integrations/view-prometheus-details.ts b/apps/web/src/page/integrations/view-prometheus-details.ts index 348062a9f6..20ee477664 100644 --- a/apps/web/src/page/integrations/view-prometheus-details.ts +++ b/apps/web/src/page/integrations/view-prometheus-details.ts @@ -97,9 +97,9 @@ const checksRows = (h: H, checks: ReadonlyArray, timeZone: tableHeader(h, [ tableRow(h, [ tableHead(h, ["Time"], "w-full pl-3"), - tableHead(h, ["State"], "w-[64px]"), - tableHead(h, ["Duration"], "w-[70px]"), - tableHead(h, ["Samples"], "w-[72px] pr-3"), + tableHead(h, ["State"], "w-16"), + tableHead(h, ["Duration"], "w-16"), + tableHead(h, ["Samples"], "w-20 pr-3"), ]), ]), tableBody( @@ -278,7 +278,7 @@ export const targetDetails = (h: H, model: Model, target: V2ScrapeTarget, timeZo ...(failureMessage !== null && failureMessage !== "" ? [ h.p( - [h.Class("font-mono text-2xs text-muted-foreground/80")], + [h.Class("font-mono text-2xs text-foreground-subtle")], [failureMessage], ), ] diff --git a/apps/web/src/page/integrations/view-prometheus.ts b/apps/web/src/page/integrations/view-prometheus.ts index 1388bef704..17e922932b 100644 --- a/apps/web/src/page/integrations/view-prometheus.ts +++ b/apps/web/src/page/integrations/view-prometheus.ts @@ -162,8 +162,8 @@ const targetRow = (h: H, model: Model, target: V2ScrapeTarget, timeZone: string) ), h.Class( cn( - "flex cursor-pointer items-center gap-3 px-3 py-3 outline-none transition-colors hover:bg-muted/50 focus-visible:bg-muted/50", - isSelected && "bg-muted/60", + "flex cursor-pointer items-center gap-3 px-3 py-3 outline-none transition-colors hover:bg-surface-sunken focus-visible:bg-surface-sunken", + isSelected && "bg-surface-strong", ), ), ], diff --git a/apps/web/src/page/integrations/view-railway.ts b/apps/web/src/page/integrations/view-railway.ts index 3abb558c77..04b483eb3a 100644 --- a/apps/web/src/page/integrations/view-railway.ts +++ b/apps/web/src/page/integrations/view-railway.ts @@ -44,7 +44,7 @@ const environmentsTable = (h: H, model: Model, status: RailwayIntegrationStatus, h.div( [ h.Class( - "flex items-center gap-4 border-b border-border/60 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border-subtle px-4 py-2.5 text-sm last:border-0", ), ], [ diff --git a/apps/web/src/page/integrations/view-supabase.ts b/apps/web/src/page/integrations/view-supabase.ts index c0f500fd7e..dedaa6aefe 100644 --- a/apps/web/src/page/integrations/view-supabase.ts +++ b/apps/web/src/page/integrations/view-supabase.ts @@ -194,7 +194,7 @@ const projectRow = (h: H, model: Model, project: Project): Html => { h.Key(project.ref), h.Class( cn( - "flex items-center gap-4 border-b border-border/60 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border-subtle px-4 py-2.5 text-sm last:border-0", isPaused && "opacity-60", ), ), diff --git a/apps/web/src/page/investigations/conversation/kit/view-approval.ts b/apps/web/src/page/investigations/conversation/kit/view-approval.ts index 122a32e982..95e7427558 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-approval.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-approval.ts @@ -67,7 +67,7 @@ const parsedArray = (value: unknown): ReadonlyArray | undefined => { const widgetRow = (h: HtmlBuilder, widget: Widget): Html => h.div( - [h.Class("flex items-center gap-2 rounded-md border border-border/60 bg-background/60 px-2 py-1.5")], + [h.Class("flex items-center gap-2 rounded-md border border-border-subtle bg-background/60 px-2 py-1.5")], [ icon(h, vizIcon(widget.visualization), { className: "size-3.5 shrink-0 text-muted-foreground" }), h.span([h.Class("truncate text-xs font-medium")], [widget.title]), @@ -198,7 +198,7 @@ const createDashboard = (h: HtmlBuilder, obj: Input): Html => { h.div( [ h.Class( - "rounded-md border border-dashed border-border/60 px-2 py-1.5 text-2xs text-muted-foreground", + "rounded-md border border-dashed border-border-subtle px-2 py-1.5 text-2xs text-muted-foreground", ), ], ["Template will generate widgets automatically."], @@ -288,7 +288,7 @@ const addWidget = (h: HtmlBuilder, obj: Input): Html => { [h.Class("space-y-3")], [ heading(h, "PlusIcon", ["Add widget"], asString(obj.dashboard_id) ?? EMPTY_VALUE), - panel(h, { tone: "background", className: "border-border/60 bg-background/60 p-2" }, [ + panel(h, { tone: "background", className: "border-border-subtle bg-background/60 p-2" }, [ h.div( [h.Class("flex items-center gap-2")], [ diff --git a/apps/web/src/page/investigations/conversation/kit/view-cards.ts b/apps/web/src/page/investigations/conversation/kit/view-cards.ts index e544ef31a7..99509446f3 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-cards.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-cards.ts @@ -54,7 +54,7 @@ const formatValue = (value: unknown, timeZone: string): Formatted => { } const RAW_CLASS = - "max-h-48 overflow-auto whitespace-pre-wrap break-words rounded bg-muted/40 p-2 font-mono text-2xs leading-snug" + "max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-sm bg-surface-sunken p-2 font-mono text-2xs leading-snug" /** `KeyValueFallback`: the proposal's arguments, one row each. */ const approvalSummary = (h: HtmlBuilder, input: unknown, timeZone: string): Html => diff --git a/apps/web/src/page/investigations/conversation/kit/view-inline.ts b/apps/web/src/page/investigations/conversation/kit/view-inline.ts index 8b8a461b9c..1d40caa666 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-inline.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-inline.ts @@ -32,7 +32,7 @@ const cardClass = (interactive: boolean): string => cn(SHELL, interactive && LIN const chevron = (h: HtmlBuilder): Html => icon(h, "ChevronRightIcon", { className: - "size-3.5 shrink-0 text-muted-foreground/50 transition-colors group-hover/inline:text-muted-foreground", + "size-3.5 shrink-0 text-foreground-faint transition-colors group-hover/inline:text-muted-foreground", }) const metric = ( @@ -66,7 +66,7 @@ const serviceChips = (h: HtmlBuilder, services: ReadonlyArray): Re h.span( [ h.Class( - "min-w-0 truncate rounded-sm border border-border/60 bg-background/60 px-1.5 py-0.5 text-2xs text-muted-foreground", + "min-w-0 truncate rounded-sm border border-border-subtle bg-background/60 px-1.5 py-0.5 text-2xs text-muted-foreground", ), h.Title(service), ], @@ -76,7 +76,7 @@ const serviceChips = (h: HtmlBuilder, services: ReadonlyArray): Re ...(services.length > shown.length ? [ h.span( - [h.Class("shrink-0 text-2xs text-muted-foreground/70")], + [h.Class("shrink-0 text-2xs text-foreground-subtle")], ["+", String(services.length - shown.length)], ), ] @@ -218,7 +218,7 @@ const inlineTrace = (h: HtmlBuilder, data: InlineTraceData): Html => value: data.id, kind: "trace", length: 12, - className: "shrink-0 text-2xs text-muted-foreground/70", + className: "shrink-0 text-2xs text-foreground-subtle", }), ...serviceChips(h, data.services ?? []), ], diff --git a/apps/web/src/page/investigations/conversation/kit/view-markdown.ts b/apps/web/src/page/investigations/conversation/kit/view-markdown.ts index 7c33e48700..accb82f614 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-markdown.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-markdown.ts @@ -126,7 +126,7 @@ const tableView = ), ), ], - { className: "bg-muted/40" }, + { className: "bg-surface-sunken" }, ), tableBody( h, diff --git a/apps/web/src/page/investigations/conversation/kit/view-task.ts b/apps/web/src/page/investigations/conversation/kit/view-task.ts index 9d5192eab7..56d1750823 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-task.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-task.ts @@ -62,7 +62,7 @@ const taskLine = (h: HtmlBuilder, host: TaskHost, part: TaskPart): Html traceIcon(h, [taskGlyph(h, part.status)], running ? "size-5" : undefined), ...(running ? [] - : [traceIcon(h, [icon(h, agent.icon, { className: "size-3.5 text-muted-foreground/70" })])]), + : [traceIcon(h, [icon(h, agent.icon, { className: "size-3.5 text-foreground-subtle" })])]), h.span( [ h.Class( @@ -74,12 +74,12 @@ const taskLine = (h: HtmlBuilder, host: TaskHost, part: TaskPart): Html ), traceDescription( h, - [h.span([h.Class("mr-1 text-muted-foreground/40")], ["·"]), part.prompt], + [h.span([h.Class("mr-1 text-foreground-faint")], ["·"]), part.prompt], "min-w-0 shrink truncate text-2xs", ), ...outcomeTag(h, part), ...(running ? runningClock(h, host.clockMount) : []), - traceIcon(h, [icon(h, "ChevronRightIcon", { className: "size-3 text-muted-foreground/60" })]), + traceIcon(h, [icon(h, "ChevronRightIcon", { className: "size-3 text-foreground-subtle" })]), ], ) } @@ -118,7 +118,7 @@ const sheetContent = ( icon(h, agent.icon, { className: "size-3 shrink-0" }), agent.label, " sub-agent", - h.span([h.Class("text-muted-foreground/40")], ["·"]), + h.span([h.Class("text-foreground-faint")], ["·"]), part.status === "running" ? "running" : (OUTCOME.get(part.status) ?? ""), ], ) diff --git a/apps/web/src/page/investigations/conversation/kit/view-tool.ts b/apps/web/src/page/investigations/conversation/kit/view-tool.ts index 153c93ee4d..54d6947000 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-tool.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-tool.ts @@ -69,7 +69,7 @@ export const runningClock = (h: HtmlBuilder, mount: PanelHost["clockMou : [ h.span( [ - h.Class("shrink-0 tabular-nums text-2xs text-muted-foreground/60"), + h.Class("shrink-0 tabular-nums text-2xs text-foreground-subtle"), h.Attribute("hidden", ""), h.OnMount(mount), ], @@ -194,7 +194,7 @@ export const toolRow = (h: HtmlBuilder, part: ToolPart, host: PanelHost traceDescription( h, [summary], - "min-w-0 shrink truncate font-mono text-2xs text-muted-foreground/60", + "min-w-0 shrink truncate font-mono text-2xs text-foreground-subtle", ), ]), ...(status === "running" && live ? runningClock(h, host.clockMount) : []), @@ -258,7 +258,7 @@ export const toolGroup = ( [], [ ...(index > 0 - ? [h.span([h.Class("text-muted-foreground/40")], [" · "])] + ? [h.span([h.Class("text-foreground-faint")], [" · "])] : []), tool.label, ...(tool.count > 1 @@ -266,7 +266,7 @@ export const toolGroup = ( h.span( [ h.Class( - "font-normal tabular-nums text-muted-foreground/60", + "font-normal tabular-nums text-foreground-subtle", ), ], [" ", `×${tool.count}`], @@ -279,7 +279,7 @@ export const toolGroup = ( ...(hidden > 0 ? [ h.span( - [h.Class("font-normal text-muted-foreground/60")], + [h.Class("font-normal text-foreground-subtle")], [` +${hidden} more`], ), ] diff --git a/apps/web/src/page/investigations/conversation/view.ts b/apps/web/src/page/investigations/conversation/view.ts index 21b6218dc1..0db12aedfa 100644 --- a/apps/web/src/page/investigations/conversation/view.ts +++ b/apps/web/src/page/investigations/conversation/view.ts @@ -136,7 +136,7 @@ export const emptyNotice = (h: HtmlBuilder, title: string, body: string): { as: "p", variant: "label", - className: "flex items-center gap-1.5 text-muted-foreground/70", + className: "flex items-center gap-1.5 text-foreground-subtle", }, [h.span([], [title])], ), diff --git a/apps/web/src/page/investigations/detail/view-action-sheet.ts b/apps/web/src/page/investigations/detail/view-action-sheet.ts index d9fd2e5b9c..52936037c6 100644 --- a/apps/web/src/page/investigations/detail/view-action-sheet.ts +++ b/apps/web/src/page/investigations/detail/view-action-sheet.ts @@ -45,7 +45,7 @@ export const actionSheetContent = ( icon(h, glyph.icon, { size: 12, className: "shrink-0" }), "Proposed action ", String(action.index + 1).padStart(2, "0"), - h.span([h.Class("text-muted-foreground/40")], ["·"]), + h.span([h.Class("text-foreground-faint")], ["·"]), glyph.label, ], ), @@ -74,7 +74,7 @@ export const actionSheetContent = ( h.span( [ h.Class( - "rounded border border-dashed px-2 py-1 text-3xs tracking-wider text-muted-foreground/70", + "rounded-sm border border-dashed px-2 py-1 text-3xs tracking-wider text-foreground-subtle", ), ], [action.promise], @@ -112,7 +112,7 @@ export const actionSheetContent = ( ), ...(report.affectedScope ? [ - h.span([h.Class("text-muted-foreground/40")], ["·"]), + h.span([h.Class("text-foreground-faint")], ["·"]), h.span([], [report.affectedScope]), ] : []), @@ -132,7 +132,7 @@ export const actionSheetContent = ( const chips = evidenceChips(h, item, "sheet", trigger) return h.keyed("div")( String(index), - [h.Class("flex flex-col gap-1.5 rounded-md bg-muted/40 p-3")], + [h.Class("flex flex-col gap-1.5 rounded-md bg-surface-sunken p-3")], [ ...(item.note ? [ diff --git a/apps/web/src/page/investigations/detail/view-canvas.ts b/apps/web/src/page/investigations/detail/view-canvas.ts index 82f58b6922..c2601c3413 100644 --- a/apps/web/src/page/investigations/detail/view-canvas.ts +++ b/apps/web/src/page/investigations/detail/view-canvas.ts @@ -215,13 +215,13 @@ const spineNode = (h: H, id: string, data: SpineNodeData, clock: Clock): Readonl variant: "orDate", tooltip: "title", mono: true, - className: "mt-auto pt-0.5 text-4xs leading-3 text-muted-foreground/70", + className: "mt-auto pt-0.5 text-4xs leading-3 text-foreground-subtle", }), ] : []), ] const shell = cn( - "flex size-full flex-col gap-1.5 overflow-hidden rounded-md border px-3 py-2.5", + "flex size-full flex-col gap-1.5 overflow-hidden rounded-md border p-3", data.at ? "justify-start" : "justify-center", isCurrent ? "border-primary bg-card" @@ -251,7 +251,7 @@ const pendingVerdictNode = (h: H, id: string, data: PendingVerdictNodeData): Rea h.div( [ h.Class( - "relative flex size-full flex-col justify-center gap-1.5 overflow-hidden rounded-md border border-dashed bg-background px-3 py-2.5", + "relative flex size-full flex-col justify-center gap-1.5 overflow-hidden rounded-md border border-dashed bg-background p-3", ), ], [ @@ -370,7 +370,7 @@ const actionNode = (h: H, id: string, data: ActionNodeData): ReadonlyArray h.span( [ h.Class( - "min-w-0 flex-1 truncate text-right text-4xs tracking-wider text-muted-foreground/60", + "min-w-0 flex-1 truncate text-right text-4xs tracking-wider text-foreground-subtle", ), ], [data.promise], diff --git a/apps/web/src/page/investigations/detail/view-diagnosis-card.ts b/apps/web/src/page/investigations/detail/view-diagnosis-card.ts index d420cb1a9d..df4372b921 100644 --- a/apps/web/src/page/investigations/detail/view-diagnosis-card.ts +++ b/apps/web/src/page/investigations/detail/view-diagnosis-card.ts @@ -89,7 +89,7 @@ export const diagnosisReportCard = (h: H, model: Model, report: Report, trigger: [ icon(h, "PulseIcon", { className: "size-3.5 text-muted-foreground" }), eyebrow(h, { variant: "label" }, ["AI Diagnosis"]), - h.span([h.Class("text-muted-foreground/40")], ["·"]), + h.span([h.Class("text-foreground-faint")], ["·"]), h.span( [h.Class(`text-2xs font-medium capitalize ${CONFIDENCE_TONE[report.confidence] ?? ""}`)], [report.confidence, " confidence"], @@ -120,7 +120,7 @@ export const diagnosisReportCard = (h: H, model: Model, report: Report, trigger: eyebrow(h, { variant: "label", as: "h4" }, ["Evidence"]), ...evidence.map((item, index) => { const chips = evidenceChips(h, item, "card", trigger) - return h.keyed("div")(String(index), [h.Class("space-y-1.5 rounded-md bg-muted/40 p-3")], [ + return h.keyed("div")(String(index), [h.Class("space-y-1.5 rounded-md bg-surface-sunken p-3")], [ ...(item.note ? [h.p([h.Class("text-sm leading-relaxed text-foreground")], [item.note])] : []), ...(chips === null ? [] : [chips]), ]) @@ -154,7 +154,7 @@ const actionRow = (h: H, action: ActionNodeData): Html => { h.button( [ h.Class( - "-mx-2 flex w-[calc(100%+1rem)] items-start gap-2.5 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-muted/50", + "-mx-2 flex w-[calc(100%+1rem)] items-start gap-2.5 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-surface-sunken", ), h.Type("button"), h.OnClick(Message.ClickedReportAction({ index: action.index })), @@ -174,7 +174,7 @@ const actionRow = (h: H, action: ActionNodeData): Html => { attributes: [h.AriaLabel(glyph.label)], }), h.span([h.Class("min-w-0 flex-1 text-sm leading-relaxed text-foreground")], [action.text]), - icon(h, "ChevronRightIcon", { size: 14, className: "mt-1 shrink-0 text-muted-foreground/50" }), + icon(h, "ChevronRightIcon", { size: 14, className: "mt-1 shrink-0 text-foreground-faint" }), ], ), ], diff --git a/apps/web/src/page/investigations/detail/view-sections.ts b/apps/web/src/page/investigations/detail/view-sections.ts index 1a547c5d0c..2424373d77 100644 --- a/apps/web/src/page/investigations/detail/view-sections.ts +++ b/apps/web/src/page/investigations/detail/view-sections.ts @@ -439,7 +439,7 @@ export const followUpComposer = (h: H): Html => h.Type("button"), h.OnClick(Message.ClickedFollowUp()), h.Class( - "flex h-10.5 w-full items-center gap-3 rounded-md border border-input bg-card px-3.5 text-left transition-colors hover:border-ring hover:bg-accent/40", + "flex h-10.5 w-full items-center gap-3 rounded-md border border-input bg-card px-3.5 text-left transition-colors hover:border-ring hover:bg-accent/50", ), ], [ @@ -480,7 +480,7 @@ export const evidenceChips = ( traceId, [ h.Href(`/traces/${traceId}`), - h.Class("rounded"), + h.Class("rounded-sm"), ...trigger(traceTipId(place, traceId)), ], [ @@ -488,7 +488,7 @@ export const evidenceChips = ( h, { className: - "px-1.5 py-0.5 text-2xs text-primary transition-colors hover:bg-muted/70", + "px-1.5 py-0.5 text-2xs text-primary transition-colors hover:bg-surface-strong", }, [shortId(traceId, "generic", { ellipsis: true })], ), @@ -498,7 +498,7 @@ export const evidenceChips = ( ...item.logPatterns.map((pattern) => inlineCode( h, - { className: "bg-muted/60 px-1.5 py-0.5 text-2xs text-muted-foreground" }, + { className: "bg-surface-strong px-1.5 py-0.5 text-2xs text-muted-foreground" }, [pattern], ), ), diff --git a/apps/web/src/page/investigations/detail/view-verdict.ts b/apps/web/src/page/investigations/detail/view-verdict.ts index 76bcc60f67..d4890f9a04 100644 --- a/apps/web/src/page/investigations/detail/view-verdict.ts +++ b/apps/web/src/page/investigations/detail/view-verdict.ts @@ -270,7 +270,7 @@ const runProgress = ( h.span([], [countLabel(progress?.stepCount ?? 0, "step")]), ...(isStalled ? [ - h.span([h.AriaHidden(true), h.Class("text-muted-foreground/40")], ["·"]), + h.span([h.AriaHidden(true), h.Class("text-foreground-faint")], ["·"]), h.span( [h.Class("text-severity-warn normal-case tracking-normal")], [`no step for ${silenceLabel(silentFor)}`], @@ -366,7 +366,7 @@ const failed = (h: HtmlBuilder, investigation: V2Investigation, nowMs: num ? h.div( [ h.Class( - "flex items-start gap-3 rounded-md border border-severity-error/25 bg-severity-error/6 px-3 py-2.5", + "flex items-start gap-3 rounded-md border border-severity-error/25 bg-severity-error/6 p-3", ), ], [ @@ -419,7 +419,7 @@ const partialList = ( [ icon(h, iconName, { size: 14, - className: "mt-0.5 shrink-0 text-muted-foreground/70", + className: "mt-0.5 shrink-0 text-foreground-subtle", }), h.span([h.Class("min-w-0")], [item]), ], @@ -449,7 +449,7 @@ const inconclusive = (h: HtmlBuilder, investigation: V2Investigation): Htm [ eyebrow(h, { as: "div", className: "flex flex-wrap items-center gap-2 text-severity-warn" }, [ "Partial result", - h.span([h.AriaHidden(true), h.Class("text-muted-foreground/40")], ["·"]), + h.span([h.AriaHidden(true), h.Class("text-foreground-faint")], ["·"]), h.span([], ["No cause established"]), ]), h.h2([h.Class(HEADING)], [headline]), diff --git a/apps/web/src/page/investigations/kit.ts b/apps/web/src/page/investigations/kit.ts index a2650fe890..7c897de62c 100644 --- a/apps/web/src/page/investigations/kit.ts +++ b/apps/web/src/page/investigations/kit.ts @@ -90,7 +90,7 @@ export const confidenceMeter = ( ): Html => { if (confidence === null) return h.span( - [h.Class(cn("text-xs text-muted-foreground/60", className)), h.Title("No diagnosis yet")], + [h.Class(cn("text-xs text-foreground-subtle", className)), h.Title("No diagnosis yet")], [EMPTY_VALUE], ) const filled = FILLED[confidence] diff --git a/apps/web/src/page/investigations/list/view.ts b/apps/web/src/page/investigations/list/view.ts index 4315fe1eee..e899706821 100644 --- a/apps/web/src/page/investigations/list/view.ts +++ b/apps/web/src/page/investigations/list/view.ts @@ -114,7 +114,7 @@ const toolbar = ( h.span( [ h.Class( - "text-muted-foreground/70 tabular-nums group-data-active/tab:text-muted-foreground", + "text-foreground-subtle tabular-nums group-data-active/tab:text-muted-foreground", ), ], [String(counts.get(value) ?? 0)], @@ -159,7 +159,7 @@ const toolbar = ( view: SelectView.view, viewInputs: { entries: KIND_ENTRIES, - className: "w-[140px]", + className: "w-36", renderValue: (value) => [kindLabel(value)], toView: (parts) => h.div([h.Class("contents")], parts), }, @@ -171,7 +171,7 @@ const toolbar = ( view: SelectView.view, viewInputs: { entries: SORT_ENTRIES, - className: "w-[168px]", + className: "w-44", renderValue: (value) => [sortLabel(value)], toView: (parts) => h.div([h.Class("contents")], parts), }, @@ -205,7 +205,7 @@ const rowFinding = (h: H, investigation: V2Investigation): Html => { [h.Class("flex min-w-0 items-center gap-1.5 text-xs text-muted-foreground")], [statusDot(h, { tone: "live" }), truncatedText(h, { text: finding.text })], ) - if (finding.kind === "none") return h.span([h.Class("text-xs text-muted-foreground/60")], [EMPTY_VALUE]) + if (finding.kind === "none") return h.span([h.Class("text-xs text-foreground-subtle")], [EMPTY_VALUE]) return h.span( [ h.Class( @@ -406,7 +406,7 @@ const hubHero = (h: H, model: Model): Html => { ...(model.isCreating ? [h.Disabled(true)] : []), h.OnClick(Message.ClickedSuggestion({ title: suggestion })), h.Class( - "flex w-full items-center gap-3 rounded-md border bg-card px-3.5 py-2.5 text-left text-sm text-foreground transition-colors hover:border-ring hover:bg-accent/40 disabled:opacity-60", + "flex w-full items-center gap-3 rounded-md border bg-card px-3.5 py-2.5 text-left text-sm text-foreground transition-colors hover:border-ring hover:bg-accent/50 disabled:opacity-60", ), ], [ diff --git a/apps/web/src/page/kit/commit-card.ts b/apps/web/src/page/kit/commit-card.ts index 05849e24f2..376a90b09e 100644 --- a/apps/web/src/page/kit/commit-card.ts +++ b/apps/web/src/page/kit/commit-card.ts @@ -223,7 +223,7 @@ const commitCard = ( h.Target("_blank"), h.Rel("noreferrer noopener"), h.Class( - "flex items-center justify-center gap-1 font-medium text-primary transition-colors hover:bg-muted/50 px-3.5 py-2.5", + "flex items-center justify-center gap-1 font-medium text-primary transition-colors hover:bg-surface-sunken px-3.5 py-2.5", ), ], ["View on ", providerLabel, h.span([h.AriaHidden(true)], ["↗"])], diff --git a/apps/web/src/page/kit/connect-flow.ts b/apps/web/src/page/kit/connect-flow.ts index b0f0aa624c..ff9fe24a30 100644 --- a/apps/web/src/page/kit/connect-flow.ts +++ b/apps/web/src/page/kit/connect-flow.ts @@ -1,6 +1,6 @@ import { cn } from "@maple/ui/lib/utils" import type { Html, HtmlBuilder } from "foldkit/html" -import { eyebrow } from "../../ui/eyebrow" +import { eyebrow, eyebrowVariants } from "../../ui/eyebrow" import { icon, type IconName } from "../../ui/icon" import { spinner } from "../../ui/spinner" @@ -81,7 +81,7 @@ export const choiceTiles = (h: HtmlBuilder, tiles: ReadonlyArray, { name: IconName; className: string }> @@ -138,7 +138,7 @@ export const statusRow = (h: HtmlBuilder, options: StatusRowOptions, child [ h.Class( cn( - "flex items-start gap-3 rounded-md border bg-card px-4 py-3", + "flex items-start gap-3 rounded-md border bg-card p-4", options.tone === "error" ? "border-severity-error/40" : "border-border", ), ), @@ -166,7 +166,7 @@ export const foundChips = ( [h.Class("flex flex-wrap gap-1.5")], chips.map((chip) => h.li( - [h.Class("rounded border border-border/60 bg-muted/40 px-1.5 py-0.5 font-mono text-2xs")], + [h.Class("rounded-sm border border-border-subtle bg-surface-sunken px-1.5 py-0.5 font-mono text-2xs")], [ chip.label, ...(chip.detail === undefined @@ -232,7 +232,7 @@ export const flowRail = (h: HtmlBuilder, options: RailOptions): Html => [ icon(h, "ShieldCheckIcon", { size: 14, - className: "mt-px shrink-0 text-success", + className: "mt-px shrink-0 text-severity-info", }), options.trust, ], @@ -273,9 +273,9 @@ export const flowRail = (h: HtmlBuilder, options: RailOptions): Html => /** On Go live: the source exists, so leaving the page is safe. */ export const savedBanner = (h: HtmlBuilder, text: string, meta?: string): Html => h.div( - [h.Class("flex items-center gap-3 rounded-md border border-border bg-card px-4 py-3 text-sm")], + [h.Class("flex items-center gap-3 rounded-md border border-border bg-card p-4 text-sm")], [ - icon(h, "ShieldCheckIcon", { size: 14, className: "shrink-0 text-success" }), + icon(h, "ShieldCheckIcon", { size: 14, className: "shrink-0 text-severity-info" }), h.span([h.Class("flex-1")], [text]), ...(meta === undefined ? [] : [h.span([h.Class("text-xs text-muted-foreground")], [meta])]), ], @@ -293,7 +293,7 @@ export type CheckRow = Readonly<{ }> const CHECK_ICON = { - done: { name: "CircleCheckIcon", className: "text-success" }, + done: { name: "CircleCheckIcon", className: "text-severity-info" }, waiting: { name: "ClockIcon", className: "text-muted-foreground" }, failed: { name: "CircleWarningIcon", className: "text-severity-error" }, } satisfies Record, { name: IconName; className: string }> @@ -339,7 +339,7 @@ export const liveChecklist = ( options.rows.map((row) => h.li( [ - h.Class("flex gap-3 border-t border-border/60 px-5 py-3 first:border-t-0"), + h.Class("flex gap-3 border-t border-border-subtle px-5 py-3 first:border-t-0"), h.DataAttribute("state", row.state), ], [ diff --git a/apps/web/src/page/kit/detail-header.ts b/apps/web/src/page/kit/detail-header.ts index 2fe851d924..6b2161e3f4 100644 --- a/apps/web/src/page/kit/detail-header.ts +++ b/apps/web/src/page/kit/detail-header.ts @@ -22,7 +22,7 @@ export const detailEyebrow = ( h, { as: "div", className: cn("flex flex-wrap items-center gap-x-2 gap-y-1", className) }, shown.flatMap((segment, index) => [ - ...(index > 0 ? [h.span([h.AriaHidden(true), h.Class("text-muted-foreground/40")], ["·"])] : []), + ...(index > 0 ? [h.span([h.AriaHidden(true), h.Class("text-foreground-faint")], ["·"])] : []), h.span([h.Class("truncate")], [segment]), ]), ) diff --git a/apps/web/src/page/kit/guided-setup.ts b/apps/web/src/page/kit/guided-setup.ts index c48e33f1bc..26645bcae4 100644 --- a/apps/web/src/page/kit/guided-setup.ts +++ b/apps/web/src/page/kit/guided-setup.ts @@ -335,7 +335,7 @@ export const connectInstructions = (h: HtmlBuilder, parts: InstructionsPar h.a( [ h.Class( - "mt-3 flex items-center justify-between gap-3 rounded-md border border-border px-3 py-2.5 text-xs text-muted-foreground transition-colors hover:border-foreground/30 hover:text-foreground", + "mt-3 flex items-center justify-between gap-3 rounded-md border border-border p-3 text-xs text-muted-foreground transition-colors hover:border-foreground/30 hover:text-foreground", ), h.Href(docsUrl(docs.page)), h.Target("_blank"), diff --git a/apps/web/src/page/kit/list-toolbar.ts b/apps/web/src/page/kit/list-toolbar.ts index 1ede2dc7ae..eb92f60f09 100644 --- a/apps/web/src/page/kit/list-toolbar.ts +++ b/apps/web/src/page/kit/list-toolbar.ts @@ -22,7 +22,7 @@ export const listToolbar = (h: HtmlBuilder, options: ListToolbarOptions): h.Class( cn( "flex flex-wrap items-center gap-2 gap-y-1.5", - options.framed === true ? "border-b border-border/60 px-2 py-1.5" : "pb-3", + options.framed === true ? "border-b border-border-subtle px-2 py-1.5" : "pb-3", options.className, ), ), diff --git a/apps/web/src/page/kit/message-response.ts b/apps/web/src/page/kit/message-response.ts index e5169a4bf7..c290b7ca18 100644 --- a/apps/web/src/page/kit/message-response.ts +++ b/apps/web/src/page/kit/message-response.ts @@ -81,7 +81,7 @@ const codeAction = ( ) export const LINE_CLASS = - "block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-ui before:text-right before:text-muted-foreground/50 before:font-mono before:select-none" + "block before:content-[counter(line)] before:inline-block before:[counter-increment:line] before:w-6 before:mr-4 before:text-ui before:text-right before:text-foreground-faint before:font-mono before:select-none" const TOKEN_CLASS = "text-[var(--sdm-c,inherit)] dark:text-[var(--shiki-dark,var(--sdm-c,inherit))] bg-[var(--sdm-tbg)] dark:bg-[var(--shiki-dark-bg,var(--sdm-tbg))]" @@ -219,7 +219,7 @@ const viewsFor = ( const views: Markdown.Views = { ...Markdown.defaultViews, InlineCode: ({ value }) => - h.code(streamdown("inline-code", "rounded bg-muted px-1.5 py-0.5 font-mono text-sm")(h), [value]), + h.code(streamdown("inline-code", "rounded-sm bg-muted px-1.5 py-0.5 font-mono text-sm")(h), [value]), Strong: (_strong, content) => h.span(streamdown("strong", "font-semibold")(h), content), // Link text is re-rendered with images as plain labels, at any nesting depth // (`[**![a](u)**](d)`), so a linked image never puts an anchor inside an anchor. @@ -300,7 +300,7 @@ const viewsFor = ( [h.DataAttribute("streamdown", "table-wrapper")], [ h.table(streamdown("table", "w-full border-collapse border border-border")(h), [ - h.thead(streamdown("table-header", "bg-muted/80")(h), [headerRow]), + h.thead(streamdown("table-header", "bg-surface-strong")(h), [headerRow]), h.tbody(streamdown("table-body", "divide-y divide-border")(h), bodyRows), ]), ], diff --git a/apps/web/src/page/kit/query-builder-legend.ts b/apps/web/src/page/kit/query-builder-legend.ts index b9d0510486..a1db3e386e 100644 --- a/apps/web/src/page/kit/query-builder-legend.ts +++ b/apps/web/src/page/kit/query-builder-legend.ts @@ -39,7 +39,7 @@ const compactStrip = (h: HtmlBuilder, options: QueryBuilderLegendOptions(h: HtmlBuilder, stats: SeriesStats | null, unit: string [ h.Class( cn( - "px-2 text-right font-mono tabular-nums text-muted-foreground/60 last:pr-0", + "px-2 text-right font-mono tabular-nums text-foreground-subtle last:pr-0", column.className, ), ), @@ -113,7 +113,7 @@ const statsTable = (h: HtmlBuilder, options: QueryBuilderLegendOptions) h.OnClick(options.onToggle(entry.key)), h.Class( cn( - "hover:bg-muted/50 cursor-pointer select-none", + "hover:bg-surface-sunken cursor-pointer select-none", options.hidden.includes(entry.key) && "opacity-40", ), ), diff --git a/apps/web/src/page/kit/query-builder/metrics-body.ts b/apps/web/src/page/kit/query-builder/metrics-body.ts index 7db541ad0e..d38c9b9015 100644 --- a/apps/web/src/page/kit/query-builder/metrics-body.ts +++ b/apps/web/src/page/kit/query-builder/metrics-body.ts @@ -99,7 +99,7 @@ const breakdown = (h: H, model: Model, query: MetricsQuery, keys: ReadonlyArray< anchorsInput: true, renderItem: (item) => [item === NONE ? "Everything (no breakdown)" : item], isUnfiltered: true, - className: "h-8 w-[220px] text-xs", + className: "h-8 w-56 text-xs", toView: ({ field, rest }) => h.div([h.Class("contents")], [field, ...rest]), }, }) diff --git a/apps/web/src/page/kit/query-builder/view.ts b/apps/web/src/page/kit/query-builder/view.ts index 2c48642209..c529c8815f 100644 --- a/apps/web/src/page/kit/query-builder/view.ts +++ b/apps/web/src/page/kit/query-builder/view.ts @@ -118,7 +118,7 @@ const header = (h: H, model: Model, inputs: QueryPanelInputs): Html => { className: "w-36 border-none bg-transparent shadow-none px-1", ariaLabel: "Query source", toView: (parts) => - h.div([h.Class("flex items-center gap-2 px-3 py-2 bg-muted/30")], [...leading, ...parts, ...trailing]), + h.div([h.Class("flex items-center gap-2 px-3 py-2 bg-surface-sunken")], [...leading, ...parts, ...trailing]), }, ) } @@ -152,12 +152,12 @@ const body = (h: H, model: Model, inputs: QueryPanelInputs): ReadonlyArray `spans:${query.id}`, query.whereClause.includes("root_only = true") ? "root" : "all", SPAN_OPTIONS, - { size: "sm", className: "w-[120px] shrink-0", toView: whereRow }, + { size: "sm", className: "w-32 shrink-0", toView: whereRow }, ) : whereRow([]), panelSelect(h, model, `aggregation:${query.id}`, query.aggregation, aggregationOptions(query), { size: "sm", - className: "w-[160px]", + className: "w-40", toView: (parts) => h.div( [h.Class("flex items-center gap-2 flex-wrap")], diff --git a/apps/web/src/page/kit/series-legend.ts b/apps/web/src/page/kit/series-legend.ts index 89b27c1f2b..632af111ed 100644 --- a/apps/web/src/page/kit/series-legend.ts +++ b/apps/web/src/page/kit/series-legend.ts @@ -19,13 +19,13 @@ const VARIANTS = { item: "inline-flex min-w-0 items-baseline gap-1.5", dot: "size-1.5 translate-y-[-1px]", label: "max-w-[24ch] truncate text-2xs text-muted-foreground", - value: "font-mono text-2xs text-foreground/80 tabular-nums", + value: "font-mono text-2xs text-foreground-soft tabular-nums", }, chip: { root: "flex flex-wrap items-center gap-2", item: "inline-flex items-center gap-1.5 rounded-full border bg-background px-2 py-0.5 text-2xs", dot: "size-2", - label: "font-medium text-foreground/80", + label: "font-medium text-foreground-soft", value: "font-mono text-muted-foreground tabular-nums", }, } as const @@ -105,7 +105,7 @@ export const seriesLegend = ( ), ), ...(overflow > 0 - ? [h.span([h.Class("text-2xs text-muted-foreground/70")], ["+", String(overflow)])] + ? [h.span([h.Class("text-2xs text-foreground-subtle")], ["+", String(overflow)])] : []), ], ) diff --git a/apps/web/src/page/kit/stat-rail.ts b/apps/web/src/page/kit/stat-rail.ts index 2dbf03e667..66b008e970 100644 --- a/apps/web/src/page/kit/stat-rail.ts +++ b/apps/web/src/page/kit/stat-rail.ts @@ -71,7 +71,7 @@ export const statRailItem = (h: HtmlBuilder, options: StatRailItemOptions< (options.delta === undefined || options.delta === "" ? undefined : h.span( - [h.Class("shrink-0 font-mono text-3xs tabular-nums text-muted-foreground/80")], + [h.Class("shrink-0 font-mono text-3xs tabular-nums text-foreground-subtle")], [options.delta], )) const body = [ @@ -144,7 +144,7 @@ export const statRailItem = (h: HtmlBuilder, options: StatRailItemOptions< shell, "w-full text-left", rowSelectedClass(isSelected), - isDisabled ? "cursor-default" : "cursor-pointer hover:bg-muted/25", + isDisabled ? "cursor-default" : "cursor-pointer hover:bg-surface-faint", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", ), ), diff --git a/apps/web/src/page/kit/time-range-picker.ts b/apps/web/src/page/kit/time-range-picker.ts index 300c3008b5..9effa4f5a9 100644 --- a/apps/web/src/page/kit/time-range-picker.ts +++ b/apps/web/src/page/kit/time-range-picker.ts @@ -331,10 +331,10 @@ const presetList = (h: HtmlBuilder, inputs: ViewInputs): Html => h.Class( cn( "relative flex h-7 items-center pl-3 pr-2 text-left text-xs transition-colors", - "before:absolute before:inset-y-1 before:left-0 before:w-[2px] before:rounded-r before:bg-transparent before:transition-colors", - "hover:bg-muted/50", + "before:absolute before:inset-y-1 before:left-0 before:w-[2px] before:rounded-r-sm before:bg-transparent before:transition-colors", + "hover:bg-surface-sunken", isActive && "text-foreground before:bg-primary", - !isActive && "text-foreground/80", + !isActive && "text-foreground-soft", ), ), ], @@ -353,7 +353,7 @@ const presetList = (h: HtmlBuilder, inputs: ViewInputs): Html => h.Type("button"), h.OnClick(Message.ClickedCustomRange(customSeed(inputs))), h.Class( - "mt-1 flex h-7 items-center gap-2 pl-3 pr-2 text-left text-xs text-foreground/80 transition-colors hover:bg-muted/50 hover:text-foreground", + "mt-1 flex h-7 items-center gap-2 pl-3 pr-2 text-left text-xs text-foreground-soft transition-colors hover:bg-surface-sunken hover:text-foreground", ), ], [ @@ -378,7 +378,7 @@ const quickSelect = (h: HtmlBuilder, inputs: ViewInputs): Html => h.Type("button"), h.OnClick(Message.ClickedPreset({ value, ...withMax(inputs) })), h.Class( - "flex h-7 items-center justify-center rounded-md border border-border/60 bg-background/30 font-mono text-2xs tracking-wide text-foreground/90 transition-colors hover:border-border hover:bg-muted/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", + "flex h-7 items-center justify-center rounded-md border border-border-subtle bg-background/30 font-mono text-2xs tracking-wide text-foreground-soft transition-colors hover:border-border hover:bg-surface-strong hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", ), ], [value], @@ -416,12 +416,12 @@ const shorthandInput = (h: HtmlBuilder, model: Model, inputs: ViewInput "focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/20", model.isShorthandInvalid ? "border-destructive/70" - : "border-border/60 hover:border-border", + : "border-border-subtle hover:border-border", ), ), ], [ - h.span([h.Class("font-mono text-2xs text-muted-foreground/70 select-none")], ["›"]), + h.span([h.Class("font-mono text-2xs text-foreground-subtle select-none")], ["›"]), h.input([ h.Value(model.shorthand), h.OnInput((value) => Message.ChangedShorthand({ value })), @@ -432,7 +432,7 @@ const shorthandInput = (h: HtmlBuilder, model: Model, inputs: ViewInput ), h.Placeholder("Any duration, e.g. 90m"), h.Class( - "flex-1 bg-transparent font-mono text-sm tracking-tight text-foreground placeholder:text-muted-foreground/50 focus:outline-none", + "flex-1 bg-transparent font-mono text-sm tracking-tight text-foreground placeholder:text-foreground-faint focus:outline-none", ), h.Spellcheck(false), h.Autocomplete("off"), @@ -549,7 +549,7 @@ const timezoneFooter = (h: HtmlBuilder, model: Model, fallbackZone: str [ h.Id(anchorId), h.Class( - "flex items-center justify-between gap-3 border-t border-border/60 bg-muted/20 px-4 py-2", + "flex items-center justify-between gap-3 border-t border-border-subtle bg-surface-faint px-4 py-2", ), ], [ @@ -567,7 +567,7 @@ const timezoneFooter = (h: HtmlBuilder, model: Model, fallbackZone: str cn( "-mr-1.5 inline-flex h-6 min-w-0 cursor-pointer items-center gap-2 rounded-md px-1.5", "text-2xs tracking-tight outline-none transition-colors", - "hover:bg-muted/60 focus-visible:ring-[3px] focus-visible:ring-ring/24 data-popup-open:bg-muted/60", + "hover:bg-surface-strong focus-visible:ring-[3px] focus-visible:ring-ring/24 data-popup-open:bg-surface-strong", ), ), h.DataAttribute("slot", "combobox-trigger"), @@ -576,12 +576,12 @@ const timezoneFooter = (h: HtmlBuilder, model: Model, fallbackZone: str h.Type("button"), ], [ - icon(h, "GlobeIcon", { className: "size-3 shrink-0 text-muted-foreground/70" }), - h.span([h.Class("truncate font-mono text-foreground/90")], [timeZone]), + icon(h, "GlobeIcon", { className: "size-3 shrink-0 text-foreground-subtle" }), + h.span([h.Class("truncate font-mono text-foreground-soft")], [timeZone]), h.keyed("span")( `utc-offset-${fallbackZone}`, [ - h.Class("shrink-0 font-mono text-muted-foreground/70"), + h.Class("shrink-0 font-mono text-foreground-subtle"), h.OnMount(MountUtcOffset({ timeZone: fallbackZone })), ], [model.utcOffset?.label ?? ""], @@ -672,7 +672,7 @@ export const view = Submodel.defineView((model, inpu h.div( [ h.Class( - "w-full shrink-0 border-b border-border/60 sm:w-[168px] sm:border-r sm:border-b-0", + "w-full shrink-0 border-b border-border-subtle sm:w-44 sm:border-r sm:border-b-0", ), ], [presetList(h, inputs)], diff --git a/apps/web/src/page/kit/timezone-select-view.ts b/apps/web/src/page/kit/timezone-select-view.ts index 46a52018e6..4e8593ada8 100644 --- a/apps/web/src/page/kit/timezone-select-view.ts +++ b/apps/web/src/page/kit/timezone-select-view.ts @@ -29,14 +29,14 @@ const itemText = (h: H, row: ZoneRow): ReadonlyArray => [ h.span( [h.Class("min-w-0 flex-1 truncate")], row.value === SYSTEM_VALUE - ? [h.span([], ["System"]), h.span([h.Class("text-muted-foreground/70")], [` · ${row.zone}`])] + ? [h.span([], ["System"]), h.span([h.Class("text-foreground-subtle")], [` · ${row.zone}`])] : row.isPinned ? [h.span([], [row.zone])] - : [h.span([], [row.city]), h.span([h.Class("text-muted-foreground/50")], [` · ${row.region}`])], + : [h.span([], [row.city]), h.span([h.Class("text-foreground-faint")], [` · ${row.region}`])], ), - h.span([h.Class("shrink-0 font-mono text-2xs tabular-nums text-foreground/70")], [row.clock]), + h.span([h.Class("shrink-0 font-mono text-2xs tabular-nums text-foreground-soft")], [row.clock]), h.span( - [h.Class("w-14 shrink-0 text-right font-mono text-3xs tabular-nums text-muted-foreground/70")], + [h.Class("w-14 shrink-0 text-right font-mono text-3xs tabular-nums text-foreground-subtle")], [row.offset], ), ], @@ -60,14 +60,14 @@ export const zoneListView = Submodel.defineView - cn("min-h-7 text-xs", byValue.get(value)?.startsGroup === true && "mt-1 border-t border-border/60 pt-1"), + cn("min-h-7 text-xs", byValue.get(value)?.startsGroup === true && "mt-1 border-t border-border-subtle pt-1"), renderItem: (value) => rowText(byValue, value, h), trigger: { returnFocusId: inputs.triggerId, header: h.div( - [h.Class("flex items-center gap-2 border-b border-border/60 px-3")], + [h.Class("flex items-center gap-2 border-b border-border-subtle px-3")], [ - icon(h, "GlobeIcon", { className: "size-3.5 shrink-0 text-muted-foreground/60" }), + icon(h, "GlobeIcon", { className: "size-3.5 shrink-0 text-foreground-subtle" }), h.input([ h.Class(cn(C.comboboxChipsInputStyles, C.comboboxChipsInputSmStyles, "h-9 w-full ps-0 text-xs")), h.DataAttribute("size", "sm"), diff --git a/apps/web/src/page/logs/detail/view-hero.ts b/apps/web/src/page/logs/detail/view-hero.ts index 07bbcbd213..7809d67936 100644 --- a/apps/web/src/page/logs/detail/view-hero.ts +++ b/apps/web/src/page/logs/detail/view-hero.ts @@ -41,8 +41,8 @@ export const copyable = ( h.AriaLabel("Copy value"), h.Class( cn( - "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors", - status === "idle" && "hover:bg-muted/50", + "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors", + status === "idle" && "hover:bg-surface-sunken", status === "copied" && "bg-severity-info/20", status === "error" && "bg-severity-error/20", ), diff --git a/apps/web/src/page/logs/detail/view-meta.ts b/apps/web/src/page/logs/detail/view-meta.ts index 0451032444..42a569f5ee 100644 --- a/apps/web/src/page/logs/detail/view-meta.ts +++ b/apps/web/src/page/logs/detail/view-meta.ts @@ -55,7 +55,7 @@ export const metaStrip = ( h.a( [ h.Class( - "inline-flex shrink-0 items-center gap-1 rounded border border-primary/20 bg-primary/5 px-1.5 py-0.5 font-mono text-2xs text-primary hover:bg-primary/10 transition-colors", + "inline-flex shrink-0 items-center gap-1 rounded-sm border border-primary/20 bg-primary/5 px-1.5 py-0.5 font-mono text-2xs text-primary hover:bg-primary/10 transition-colors", ), h.Href( hrefOf( diff --git a/apps/web/src/page/logs/detail/view-panels.ts b/apps/web/src/page/logs/detail/view-panels.ts index cdcbcd7b69..e44c7a1aca 100644 --- a/apps/web/src/page/logs/detail/view-panels.ts +++ b/apps/web/src/page/logs/detail/view-panels.ts @@ -109,7 +109,7 @@ const logTime = (h: H, timestamp: string, timeZone: string): ReadonlyArray { ...cappedCode( h, payload, - "rounded-md border bg-muted/30 p-2 font-mono text-2xs leading-relaxed whitespace-pre-wrap break-all", + "rounded-md border bg-surface-sunken p-2 font-mono text-2xs leading-relaxed whitespace-pre-wrap break-all", ), ], ) diff --git a/apps/web/src/page/logs/list/view-search-help.ts b/apps/web/src/page/logs/list/view-search-help.ts index 5d2757c089..b8bd783bd3 100644 --- a/apps/web/src/page/logs/list/view-search-help.ts +++ b/apps/web/src/page/logs/list/view-search-help.ts @@ -14,7 +14,7 @@ type Mode = "text" | "trace" | "header" // The search mode badge's label and colours. const MODE = new Map>([ ["text", { label: "Text", className: "bg-primary/15 text-primary" }], - ["trace", { label: "Trace", className: "bg-info/15 text-info" }], + ["trace", { label: "Trace", className: "bg-severity-debug/15 text-severity-debug" }], ["header", { label: "Header", className: "bg-chart-throughput/15 text-chart-throughput" }], ]) @@ -61,7 +61,7 @@ const lookupRow = (h: HtmlBuilder, lookup: (typeof LOOKUPS)[number]): H h.dd([h.Class("min-w-0 truncate font-mono text-2xs text-foreground")], [lookup.example]), h.dd( [h.Class("col-start-2 text-2xs text-muted-foreground leading-relaxed")], - [lookup.does, " ", h.span([h.Class("text-muted-foreground/60")], ["(", lookup.note, ")"])], + [lookup.does, " ", h.span([h.Class("text-foreground-subtle")], ["(", lookup.note, ")"])], ), ], ) @@ -80,7 +80,7 @@ const content = (h: HtmlBuilder): ReadonlyArray => [ h.div( [ h.Class( - "mt-3 break-words rounded-md border bg-muted/40 px-2 py-1.5 font-mono text-2xs text-foreground leading-relaxed", + "mt-3 break-words rounded-md border bg-surface-sunken px-2 py-1.5 font-mono text-2xs text-foreground leading-relaxed", ), ], highlightedText(h, TEXT_EXAMPLE, "conn reset"), @@ -113,7 +113,7 @@ export const searchHelp = (h: HtmlBuilder, model: Popover.Model): Html h.Type("button"), h.AriaLabel("What you can search for"), h.Class( - "cursor-pointer rounded-sm text-muted-foreground/60 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring data-[popup-open]:text-foreground", + "cursor-pointer rounded-sm text-foreground-subtle transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring data-[popup-open]:text-foreground", ), ...trigger, ], diff --git a/apps/web/src/page/logs/list/view-volume.ts b/apps/web/src/page/logs/list/view-volume.ts index b3c9c77c03..978177bb48 100644 --- a/apps/web/src/page/logs/list/view-volume.ts +++ b/apps/web/src/page/logs/list/view-volume.ts @@ -112,7 +112,7 @@ const emptyStrip = ( left: (i / (EMPTY_STRIP_TICKS - 1)) * 100, })) const dashed = (className: string) => - h.div([h.Class(`absolute inset-x-0 ${className} border-t border-dashed border-border/60`)]) + h.div([h.Class(`absolute inset-x-0 ${className} border-t border-dashed border-border-subtle`)]) return h.div( [ h.Style({ height: `${LOGS_VOLUME_CHART_HEIGHT}px` }), diff --git a/apps/web/src/page/logs/list/view.ts b/apps/web/src/page/logs/list/view.ts index da2d34f07c..97671aef0d 100644 --- a/apps/web/src/page/logs/list/view.ts +++ b/apps/web/src/page/logs/list/view.ts @@ -41,7 +41,7 @@ const loadingState = (h: HtmlBuilder): Html => [ skeleton(h, "size-1.5 shrink-0 rounded-full"), skeleton(h, "h-3 w-16 shrink-0"), - skeleton(h, "h-3 w-[72px] shrink-0"), + skeleton(h, "h-3 w-20 shrink-0"), skeleton(h, "h-3 flex-1"), ], ), diff --git a/apps/web/src/page/metrics/browse/view-grid.ts b/apps/web/src/page/metrics/browse/view-grid.ts index 5261e63b75..2c9b26b931 100644 --- a/apps/web/src/page/metrics/browse/view-grid.ts +++ b/apps/web/src/page/metrics/browse/view-grid.ts @@ -124,7 +124,7 @@ const previewCard = (h: H, theme: ThemeColors, entry: PreviewEntry, sparklines: h.Key(entryKey(entry.metricName, entry.metricType)), h.Type("button"), h.Class( - "group flex flex-col gap-2 rounded-md border bg-card p-3 text-left transition-colors hover:border-primary/40 hover:bg-accent/40", + "group flex flex-col gap-2 rounded-md border bg-card p-3 text-left transition-colors hover:border-primary/40 hover:bg-accent/50", ), h.OnClick( Message.ClickedMetricCard({ metricName: entry.metricName, metricType: entry.metricType }), diff --git a/apps/web/src/page/metrics/browse/view-table.ts b/apps/web/src/page/metrics/browse/view-table.ts index bcc1fd76cc..3e8827bb84 100644 --- a/apps/web/src/page/metrics/browse/view-table.ts +++ b/apps/web/src/page/metrics/browse/view-table.ts @@ -33,25 +33,25 @@ export const loadingTable = (h: H): Html => { header: "Metric name", headClassName: "w-[40%]", skeleton: "w-48" }, { header: "Type", - headClassName: `${MD_CELL} w-[100px]`, + headClassName: `${MD_CELL} w-24`, cellClassName: MD_CELL, skeleton: "w-16", }, { header: "Service", - headClassName: `${MD_CELL} w-[120px]`, + headClassName: `${MD_CELL} w-32`, cellClassName: MD_CELL, skeleton: "w-20", }, { header: "Points", - headClassName: `${MD_CELL} w-[100px]`, + headClassName: `${MD_CELL} w-24`, cellClassName: MD_CELL, skeleton: "w-12", }, { header: "Last seen", - headClassName: `${MD_CELL} w-[100px]`, + headClassName: `${MD_CELL} w-24`, cellClassName: MD_CELL, skeleton: "w-16", }, @@ -123,7 +123,7 @@ const metricRow = (h: H, model: Model, metric: MetricRow, timeZone: string): Htm `${MD_CELL} text-xs text-muted-foreground`, ), ], - "hover:bg-muted/50", + "hover:bg-surface-sunken", ) /** The loaded table: rows up to `tableLimit`, dimmed while the next page loads. */ @@ -146,10 +146,10 @@ export const metricsTable = ( tableHeader(h, [ tableRow(h, [ tableHead(h, ["Metric name"], "w-[40%]"), - tableHead(h, ["Type"], "w-[100px]"), - tableHead(h, ["Service"], "w-[120px]"), - tableHead(h, ["Points"], "w-[100px]"), - tableHead(h, ["Last seen"], "w-[100px]"), + tableHead(h, ["Type"], "w-24"), + tableHead(h, ["Service"], "w-32"), + tableHead(h, ["Points"], "w-24"), + tableHead(h, ["Last seen"], "w-24"), ]), ]), tableBody( diff --git a/apps/web/src/page/onboarding/cli-login-view.ts b/apps/web/src/page/onboarding/cli-login-view.ts index dcf4d4e9b1..ec1899bcca 100644 --- a/apps/web/src/page/onboarding/cli-login-view.ts +++ b/apps/web/src/page/onboarding/cli-login-view.ts @@ -53,7 +53,7 @@ const ready = (h: H, info: DeviceInfo, workspace: Html): Html => [h.Class("space-y-4")], [ h.div( - [h.Class("space-y-1 border border-border bg-muted/30 p-3")], + [h.Class("space-y-1 border border-border bg-surface-sunken p-3")], [ h.p([h.Class("text-xs text-muted-foreground")], ["Requesting device"]), h.p( diff --git a/apps/web/src/page/onboarding/create-org-view.ts b/apps/web/src/page/onboarding/create-org-view.ts index 0d8f7efd0a..1e7a7adc3b 100644 --- a/apps/web/src/page/onboarding/create-org-view.ts +++ b/apps/web/src/page/onboarding/create-org-view.ts @@ -145,7 +145,7 @@ type OrgRowOptions = Readonly<{ /** An org the user can go to instead of creating one: an invitation, or one they already belong to. */ const orgRow = (h: H, options: OrgRowOptions): Html => h.div( - [h.Class("flex items-center gap-3 rounded-md border border-dashed border-input px-3.5 py-3")], + [h.Class("flex items-center gap-3 rounded-md border border-dashed border-input p-3")], [ options.imageUrl === "" ? h.span( @@ -285,7 +285,7 @@ const workspacePreview = (h: H, model: Model): Html => h.div( [ h.Class( - "flex w-[200px] shrink-0 flex-col gap-4 border-r border-sidebar-border bg-sidebar p-3", + "flex w-52 shrink-0 flex-col gap-4 border-r border-sidebar-border bg-sidebar p-3", ), ], [ diff --git a/apps/web/src/page/onboarding/mcp-authorize-view.ts b/apps/web/src/page/onboarding/mcp-authorize-view.ts index 04352688d6..44a0a4f879 100644 --- a/apps/web/src/page/onboarding/mcp-authorize-view.ts +++ b/apps/web/src/page/onboarding/mcp-authorize-view.ts @@ -34,7 +34,7 @@ const ready = (h: H, info: AuthorizationInfo, workspace: Html): Html => [h.Class("space-y-4")], [ h.div( - [h.Class("space-y-1 border border-border bg-muted/30 p-3")], + [h.Class("space-y-1 border border-border bg-surface-sunken p-3")], [ muted(h, "text-xs", ["Requesting client"]), h.p( diff --git a/apps/web/src/page/onboarding/option-card.ts b/apps/web/src/page/onboarding/option-card.ts index bc4a0cf152..fe5816ae2b 100644 --- a/apps/web/src/page/onboarding/option-card.ts +++ b/apps/web/src/page/onboarding/option-card.ts @@ -135,7 +135,7 @@ export const optionCard = (h: HtmlBuilder, options: OptionCardOptions): ]), h.div( [ - ...(isAccented ? [h.Style({ "border-color": options.accent ?? "", "background-color": `${options.accent ?? ""}0F` })] : []), + ...(isAccented ? [h.Style({ "border-color": options.accent ?? "", "background-color": `color-mix(in oklab, ${options.accent ?? ""} 6%, transparent)` })] : []), h.Class( cn( "flex h-full rounded-md border transition-colors duration-150 motion-reduce:transition-none peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2 peer-focus-visible:ring-offset-background", @@ -159,7 +159,7 @@ export const pixelGlyph = (h: HtmlBuilder, name: PixelGlyphName, isSelecte h.Class( cn( "flex size-10 shrink-0 items-center justify-center rounded-lg transition-colors duration-200 motion-reduce:transition-none", - isSelected ? "bg-primary/10" : "bg-muted/60 group-hover:bg-muted", + isSelected ? "bg-primary/10" : "bg-surface-strong group-hover:bg-muted", ), ), ], diff --git a/apps/web/src/page/onboarding/pricing-cards-view.ts b/apps/web/src/page/onboarding/pricing-cards-view.ts index d7eeecdcb7..9af3c388a1 100644 --- a/apps/web/src/page/onboarding/pricing-cards-view.ts +++ b/apps/web/src/page/onboarding/pricing-cards-view.ts @@ -70,7 +70,7 @@ const dataRow = (h: H, feature: FeatureRow, isDetailed: boolean): Html => { ? [] : [ h.p( - [h.Class("text-muted-foreground/70 text-3xs mt-0.5 font-medium")], + [h.Class("text-foreground-subtle text-3xs mt-0.5 font-medium")], [feature.detail], ), ]), @@ -200,8 +200,8 @@ const planCard = (h: H, plan: CatalogPlan, loadingPlanId: string | null): Html = ], cn( "flex flex-col transition-colors", - isActive && "bg-muted/60", - isUpgrade && "bg-muted/30 ring-1 ring-primary/30", + isActive && "bg-surface-strong", + isUpgrade && "bg-surface-sunken ring-1 ring-primary/30", ), ) } diff --git a/apps/web/src/page/onboarding/quick-start-region-view.ts b/apps/web/src/page/onboarding/quick-start-region-view.ts index ac3bcd39ea..55ebe9b473 100644 --- a/apps/web/src/page/onboarding/quick-start-region-view.ts +++ b/apps/web/src/page/onboarding/quick-start-region-view.ts @@ -19,15 +19,15 @@ export const REGION_CARDS = { name: "United States", place: "North America", residency: "Data stays in the US", - accent: "#E5485B", - check: "border-[#E5485B] bg-[#E5485B] text-white", + accent: "var(--color-region-us)", + check: "border-region-us bg-region-us text-white", }, eu: { name: "European Union", place: "Frankfurt, Germany", residency: "Data stays in the EU", - accent: "#5B7CFF", - check: "border-[#5B7CFF] bg-[#5B7CFF] text-white", + accent: "var(--color-region-eu)", + check: "border-region-eu bg-region-eu text-white", }, } as const satisfies Record @@ -39,7 +39,11 @@ const residency = (h: H, region: Region, isActive: boolean): Html => { "inline-flex items-center gap-1.5 rounded-full border border-border px-2 py-0.5 text-2xs font-medium text-muted-foreground", ), ...(isActive - ? [h.Style({ color: card.accent, "border-color": `${card.accent}66`, "background-color": `${card.accent}14` })] + ? [h.Style({ + color: card.accent, + "border-color": `color-mix(in oklab, ${card.accent} 40%, transparent)`, + "background-color": `color-mix(in oklab, ${card.accent} 8%, transparent)`, + })] : []), ], [ diff --git a/apps/web/src/page/onboarding/quick-start-view.ts b/apps/web/src/page/onboarding/quick-start-view.ts index 0e0b539d7e..4b7eab7fa9 100644 --- a/apps/web/src/page/onboarding/quick-start-view.ts +++ b/apps/web/src/page/onboarding/quick-start-view.ts @@ -100,7 +100,7 @@ const trail = (h: H, items: ReadonlyArray): Html => : h.span( [h.Class("flex items-center gap-1.5 text-muted-foreground")], [ - icon(h, "CheckIcon", { size: 12, className: "text-success" }), + icon(h, "CheckIcon", { size: 12, className: "text-severity-info" }), item.answer, ], ), @@ -257,7 +257,7 @@ const stackCard = (h: H, item: StackItem, isChecked: boolean, onChange: Message) [ h.Class( cn( - "flex items-center gap-3 rounded-md border px-3 py-2.5 transition-colors duration-150 motion-reduce:transition-none peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2 peer-focus-visible:ring-offset-background", + "flex items-center gap-3 rounded-md border p-3 transition-colors duration-150 motion-reduce:transition-none peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2 peer-focus-visible:ring-offset-background", isChecked ? "border-primary bg-primary/5" : "border-border group-hover:border-foreground/30", diff --git a/apps/web/src/page/onboarding/workspace.ts b/apps/web/src/page/onboarding/workspace.ts index 0a13dd3181..c11038e33b 100644 --- a/apps/web/src/page/onboarding/workspace.ts +++ b/apps/web/src/page/onboarding/workspace.ts @@ -4,7 +4,7 @@ import type { Html, HtmlBuilder } from "foldkit/html" /** The workspace card of `/cli-login` and `/mcp-authorize`; `trailing` is the Clerk switcher. */ export const workspaceCard = (h: HtmlBuilder, name: string, trailing: ReadonlyArray): Html => h.div( - [h.Class("flex items-center justify-between gap-3 border border-border bg-muted/30 px-3 py-2")], + [h.Class("flex items-center justify-between gap-3 border border-border bg-surface-sunken px-3 py-2")], [ h.div( [h.Class("min-w-0")], diff --git a/apps/web/src/page/overview/setup-checklist-view.ts b/apps/web/src/page/overview/setup-checklist-view.ts index 35b1bd0023..3c576dae23 100644 --- a/apps/web/src/page/overview/setup-checklist-view.ts +++ b/apps/web/src/page/overview/setup-checklist-view.ts @@ -23,7 +23,7 @@ const keysUnavailable = (h: H): Html => h.p( [ h.Class( - "rounded-md border border-dashed bg-muted/40 px-3 py-2 font-prose text-xs text-muted-foreground", + "rounded-md border border-dashed bg-surface-sunken px-3 py-2 font-prose text-xs text-muted-foreground", ), ], [ @@ -114,7 +114,7 @@ const watchingStrip = (h: H): Html => h.div( [ h.Class( - "flex items-center gap-2.5 rounded-md border border-dashed border-primary/30 bg-primary/5 px-4 py-3", + "flex items-center gap-2.5 rounded-md border border-dashed border-primary/30 bg-primary/5 p-4", ), ], [ @@ -201,7 +201,7 @@ const waitingCard = ( [ listRow(h, { onClick: Message.ClickedToggleExpanded(), - className: "flex-1 px-5 py-4 hover:bg-muted/50", + className: "flex-1 px-5 py-4 hover:bg-surface-sunken", leading: h.span( [ h.Class( diff --git a/apps/web/src/page/overview/view-health.ts b/apps/web/src/page/overview/view-health.ts index e0b7dbf281..462d6ae5fc 100644 --- a/apps/web/src/page/overview/view-health.ts +++ b/apps/web/src/page/overview/view-health.ts @@ -73,7 +73,7 @@ const railAction = (h: HtmlBuilder, slice: SliceSearch, health?: ServiceHe [ h.Href(servicesHref(slice, health)), h.AriaLabel(health === undefined ? "View all services" : `View ${health} services`), - h.Class("text-muted-foreground/40 transition-colors hover:text-foreground"), + h.Class("text-foreground-faint transition-colors hover:text-foreground"), ], [icon(h, "ArrowRightIcon", { className: "size-3" })], ) @@ -177,7 +177,7 @@ const listHeader = (h: HtmlBuilder, slice: SliceSearch): Html => [ eyebrow(h, { variant: "label", as: "h2" }, ["Services"]), h.p( - [h.Class("mt-0.5 font-prose text-2xs text-muted-foreground/70")], + [h.Class("mt-0.5 font-prose text-2xs text-foreground-subtle")], ["Status reflects active alerts and baseline anomalies."], ), ], diff --git a/apps/web/src/page/overview/view-hero.ts b/apps/web/src/page/overview/view-hero.ts index c4f79e7504..7f6bb5e575 100644 --- a/apps/web/src/page/overview/view-hero.ts +++ b/apps/web/src/page/overview/view-hero.ts @@ -36,7 +36,7 @@ const allClear = (h: HtmlBuilder, counts: HeroCounts): Html => [h.Class("text-foreground font-medium tabular-nums")], [String(counts.rulesEnabled)], ), - h.span([h.Class("text-muted-foreground/70")], [" / "]), + h.span([h.Class("text-foreground-subtle")], [" / "]), h.span([h.Class("tabular-nums")], [String(counts.rulesTotal)]), h.span([h.Class("ml-1")], ["rules watching"]), ], @@ -55,7 +55,7 @@ const rulesSummary = (h: HtmlBuilder, counts: HeroCounts): Html => [h.Class("tabular-nums")], [ h.span([h.Class("text-foreground font-medium")], [String(counts.rulesEnabled)]), - h.span([h.Class("text-muted-foreground/70")], ["/"]), + h.span([h.Class("text-foreground-subtle")], ["/"]), h.span([], [String(counts.rulesTotal)]), h.span([h.Class("ml-1")], ["rules"]), ], @@ -102,7 +102,7 @@ const firing = (h: HtmlBuilder, counts: HeroCounts): Html => { ), ], ), - h.span([h.Class("text-muted-foreground/40")], ["·"]), + h.span([h.Class("text-foreground-faint")], ["·"]), h.span([h.Class("text-muted-foreground text-sm")], [label]), ], ), diff --git a/apps/web/src/page/overview/view-metrics.ts b/apps/web/src/page/overview/view-metrics.ts index 8558088cf2..0bb9cb68c8 100644 --- a/apps/web/src/page/overview/view-metrics.ts +++ b/apps/web/src/page/overview/view-metrics.ts @@ -319,7 +319,7 @@ const cardContent = ( h.span( [ h.Class( - "flex flex-1 items-center justify-center font-prose text-xs text-muted-foreground/70", + "flex flex-1 items-center justify-center font-prose text-xs text-foreground-subtle", ), ], [STRIPPED_CAPTION[failureKind(cardFailure)]], diff --git a/apps/web/src/page/overview/view-widget.ts b/apps/web/src/page/overview/view-widget.ts index 49ab9195fa..5c029772a2 100644 --- a/apps/web/src/page/overview/view-widget.ts +++ b/apps/web/src/page/overview/view-widget.ts @@ -85,7 +85,7 @@ const titleHint = ( ? h.span( [ h.AriaLabel(`About ${title}`), - h.Class("shrink-0 text-muted-foreground/60"), + h.Class("shrink-0 text-foreground-subtle"), h.DataAttribute("base-ui-tooltip-trigger", ""), h.DataAttribute("slot", "tooltip-trigger"), ], @@ -94,7 +94,7 @@ const titleHint = ( : h.a( [ h.AriaLabel(`About ${title}`), - h.Class("shrink-0 text-muted-foreground/60 hover:text-foreground"), + h.Class("shrink-0 text-foreground-subtle hover:text-foreground"), h.DataAttribute("base-ui-tooltip-trigger", ""), h.DataAttribute("slot", "tooltip-trigger"), h.Href(hint.href), diff --git a/apps/web/src/page/recommendations/view-body.ts b/apps/web/src/page/recommendations/view-body.ts index ae2ebaba65..d4949a3101 100644 --- a/apps/web/src/page/recommendations/view-body.ts +++ b/apps/web/src/page/recommendations/view-body.ts @@ -21,7 +21,7 @@ export const isLive = (issue: V2Recommendation) => issue.status === "applied" || const summary = (h: H, issue: V2Recommendation): Html => h.p( - [h.Class("text-base leading-relaxed text-foreground/90")], + [h.Class("text-base leading-relaxed text-foreground-soft")], issue.kind === "double-emission" ? [ "Your spans emit both ", @@ -99,7 +99,7 @@ const changeBreakdown = (h: H, issue: V2Recommendation): Html => { ...(issue.canonical_key ? [ h.div( - [h.Class("flex items-start gap-3 border-t border-border/60 px-4 py-3")], + [h.Class("flex items-start gap-3 border-t border-border-subtle px-4 py-3")], [ icon(h, "CircleCheckIcon", { size: 16, @@ -132,7 +132,7 @@ const cautionCallout = (h: H, issue: V2Recommendation): Html => [h.Class("rounded-r-md border-l-2 border-severity-warn bg-severity-warn/8 px-4 py-3")], [ h.p( - [h.Class("text-sm leading-relaxed text-foreground/90")], + [h.Class("text-sm leading-relaxed text-foreground-soft")], [ h.span([h.Class("font-medium text-severity-warn")], ["Please note:"]), " ", @@ -166,7 +166,7 @@ const mappingBlock = (h: H, model: Model, issue: V2Recommendation): Html => { }), panel(h, { tone: "muted" }, [ h.div( - [h.Class("flex items-center justify-between border-b border-border/60 px-3 py-2")], + [h.Class("flex items-center justify-between border-b border-border-subtle px-3 py-2")], [ h.span( [h.Class("text-xs text-muted-foreground")], diff --git a/apps/web/src/page/recommendations/view.ts b/apps/web/src/page/recommendations/view.ts index 2e6e24e2cd..15b3f2ed9b 100644 --- a/apps/web/src/page/recommendations/view.ts +++ b/apps/web/src/page/recommendations/view.ts @@ -181,7 +181,7 @@ const sidebar = (h: H, model: Model, issue: V2Recommendation, timeZone: string): RESOLVES.map((line) => h.li( [h.Class("flex gap-2")], - [h.span([h.AriaHidden(true), h.Class("select-none text-muted-foreground/50")], ["·"]), h.span([], [line])], + [h.span([h.AriaHidden(true), h.Class("select-none text-foreground-faint")], ["·"]), h.span([], [line])], ), ), ), diff --git a/apps/web/src/page/releases/detail/view-comparison.ts b/apps/web/src/page/releases/detail/view-comparison.ts index 1f8fc950e0..c17f98f15c 100644 --- a/apps/web/src/page/releases/detail/view-comparison.ts +++ b/apps/web/src/page/releases/detail/view-comparison.ts @@ -139,7 +139,7 @@ const comparisonTable = (h: HtmlBuilder, impact: ReleaseServiceImpact, bas cn("pr-4 text-right font-mono tabular-nums", changeTone(row)), ), ], - "border-border/60", + "border-border-subtle", [h.Key(row.label)], ), ), @@ -158,7 +158,7 @@ export const releaseComparison = (h: HtmlBuilder, impact: ReleaseServiceIm baseline.spanCount >= MIN_COMPARE_SPANS const action = baseline === undefined - ? h.span([h.Class("text-2xs text-muted-foreground/70")], ["no previous version"]) + ? h.span([h.Class("text-2xs text-foreground-subtle")], ["no previous version"]) : commitTrigger(h, overlays, "release-replaced", baseline.commitSha, "font-mono text-2xs text-muted-foreground", [ "replaced ", shortReleaseLabel(baseline.commitSha), @@ -170,7 +170,7 @@ export const releaseComparison = (h: HtmlBuilder, impact: ReleaseServiceIm ...(baseline !== undefined && !isComparable ? [ h.div( - [h.Class("border-t px-4 py-2 text-2xs text-muted-foreground/70")], + [h.Class("border-t px-4 py-2 text-2xs text-foreground-subtle")], [`Changes are withheld below ${MIN_COMPARE_SPANS} requests on either side.`], ), ] @@ -200,7 +200,7 @@ export const releaseVersionsRail = (h: HtmlBuilder, input: RailInput): { title: "Versions in window", action: h.span( - [h.Class("text-2xs text-muted-foreground/70")], + [h.Class("text-2xs text-foreground-subtle")], [countLabel(sorted.length, "version")], ), }, @@ -227,8 +227,8 @@ const versionLink = (h: HtmlBuilder, input: RailInput, version: Release ), h.Class( cn( - "flex items-center gap-2.5 rounded-sm px-2 py-1.5 text-xs transition-colors hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", - version.commitSha === input.currentSha && "bg-muted/60", + "flex items-center gap-2.5 rounded-sm px-2 py-1.5 text-xs transition-colors hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", + version.commitSha === input.currentSha && "bg-surface-strong", ), ), ], @@ -257,7 +257,7 @@ const versionLink = (h: HtmlBuilder, input: RailInput, version: Release timeZone: input.timeZone, variant: "orDate", tooltip: "title", - className: "w-16 shrink-0 text-right font-mono tabular-nums text-muted-foreground/70", + className: "w-16 shrink-0 text-right font-mono tabular-nums text-foreground-subtle", }), ], ) diff --git a/apps/web/src/page/releases/detail/view-sections.ts b/apps/web/src/page/releases/detail/view-sections.ts index d131044605..013d5c3a2f 100644 --- a/apps/web/src/page/releases/detail/view-sections.ts +++ b/apps/web/src/page/releases/detail/view-sections.ts @@ -106,7 +106,7 @@ const beforeAfter = ( [ ...(before === undefined ? [] - : [h.span([h.Class("text-3xs text-muted-foreground/70")], [format(before), " →"])]), + : [h.span([h.Class("text-3xs text-foreground-subtle")], [format(before), " →"])]), h.span( [ h.Class( @@ -151,7 +151,7 @@ const serviceRow = ( serviceDot(h, { serviceName: impact.serviceName }), impact.serviceName, ...(impact.environment && !environments?.length - ? [h.span([h.Class("text-muted-foreground/70")], [impact.environment])] + ? [h.span([h.Class("text-foreground-subtle")], [impact.environment])] : []), ...(impact.health === "healthy" ? [] @@ -204,7 +204,7 @@ const serviceRow = ( ), ), ], - "border-border/60", + "border-border-subtle", [h.Key(`${impact.serviceName}:${impact.environment}`)], ) @@ -224,7 +224,7 @@ export const deployServices = ( { title: "Services", action: h.span( - [h.Class("text-2xs text-muted-foreground/70")], + [h.Class("text-2xs text-foreground-subtle")], ["against the version each replaced"], ), }, @@ -281,7 +281,7 @@ export const releaseChangeset = (h: HtmlBuilder, state: ChangesetState, cl ]), ]) const action = h.span( - [h.Class("text-2xs text-muted-foreground/70")], + [h.Class("text-2xs text-foreground-subtle")], ["since ", h.span([h.Class("font-mono")], [shortReleaseLabel(state.base)])], ) if (state._tag === "Loading") @@ -314,7 +314,7 @@ export const releaseChangeset = (h: HtmlBuilder, state: ChangesetState, cl [ h.Key(commit.sha), h.Class( - "flex items-start gap-2.5 border-t border-border/60 px-4 py-2 text-xs first:border-t-0", + "flex items-start gap-2.5 border-t border-border-subtle px-4 py-2 text-xs first:border-t-0", ), ], [ @@ -354,7 +354,7 @@ export const releaseChangeset = (h: HtmlBuilder, state: ChangesetState, cl h.span( [ h.Class( - "shrink-0 font-mono text-2xs tabular-nums text-muted-foreground/70", + "shrink-0 font-mono text-2xs tabular-nums text-foreground-subtle", ), ], [ @@ -373,7 +373,7 @@ export const releaseChangeset = (h: HtmlBuilder, state: ChangesetState, cl h.div( [ h.Class( - "border-t border-border/60 px-4 py-2 text-2xs text-muted-foreground/70", + "border-t border-border-subtle px-4 py-2 text-2xs text-foreground-subtle", ), ], [String(hidden), " older ", pluralize(hidden, "commit"), " not shown"], @@ -428,7 +428,7 @@ const issueLine = ( variant: "orDate", mono: true, tooltip: "title", - className: "w-14 text-right text-xs text-muted-foreground/70", + className: "w-14 text-right text-xs text-foreground-subtle", }), ], ), @@ -457,7 +457,7 @@ export const issueList = ( [ h.Class( options.issues.length === 0 - ? "text-2xs text-muted-foreground/70" + ? "text-2xs text-foreground-subtle" : options.tone === "error" ? "text-2xs font-medium text-severity-error" : options.tone === "warn" diff --git a/apps/web/src/page/releases/detail/view-service.ts b/apps/web/src/page/releases/detail/view-service.ts index d4b8d2f097..e2f6a0ab3e 100644 --- a/apps/web/src/page/releases/detail/view-service.ts +++ b/apps/web/src/page/releases/detail/view-service.ts @@ -119,7 +119,7 @@ const releaseMeta = (h: H, model: Model, clock: Clock): ReadonlyArray => { ], onSome: (commit) => [ h.span([h.Class("truncate")], [commit.authorLogin ?? commit.authorName ?? "Unknown author"]), - h.span([h.Class("truncate text-muted-foreground/70")], [commit.repoFullName]), + h.span([h.Class("truncate text-foreground-subtle")], [commit.repoFullName]), h.a( [ h.Href(commit.htmlUrl), @@ -312,7 +312,7 @@ const seriesBar = (h: H, model: Model, serviceName: string): Html => { }, ], }), - h.span([h.Class("text-2xs text-muted-foreground/70")], [caption]), + h.span([h.Class("text-2xs text-foreground-subtle")], [caption]), ], ) } diff --git a/apps/web/src/page/releases/list/view-overview.ts b/apps/web/src/page/releases/list/view-overview.ts index 2b97710fc5..66694bc8d9 100644 --- a/apps/web/src/page/releases/list/view-overview.ts +++ b/apps/web/src/page/releases/list/view-overview.ts @@ -41,7 +41,7 @@ export const liveNow = (h: H, live: ReadonlyArray, timeSearch: Time eyebrow(h, {}, ["Live now"]), behind > 0 ? h.span([h.Class("text-2xs text-severity-warn")], [`${countLabel(behind, "service")} not on the latest release`]) - : h.span([h.Class("text-2xs text-muted-foreground/70")], ["Every service is on its latest release"]), + : h.span([h.Class("text-2xs text-foreground-subtle")], ["Every service is on its latest release"]), ], ), h.div( @@ -79,7 +79,7 @@ export const liveNow = (h: H, live: ReadonlyArray, timeSearch: Time ], ), ), - ...(hidden > 0 ? [h.span([h.Class("self-center px-1 text-2xs text-muted-foreground/70")], [`+${hidden}`])] : []), + ...(hidden > 0 ? [h.span([h.Class("self-center px-1 text-2xs text-foreground-subtle")], [`+${hidden}`])] : []), ], ), ]) @@ -207,7 +207,7 @@ export const releasesTimeline = (h: H, input: TimelineInput): Html => { ), h.div( [ - h.Class("relative h-full border-b border-dashed border-border/60"), + h.Class("relative h-full border-b border-dashed border-border-subtle"), ...(laneIndex === 0 ? [h.OnMount(MeasureReleasesTrack())] : []), ], lane.markers.flatMap((marker) => { @@ -264,7 +264,7 @@ export const releasesTimeline = (h: H, input: TimelineInput): Html => { ...(hidden > 0 ? [ h.div( - [h.Class(`grid ${twoColumns} gap-3 py-1 text-3xs text-muted-foreground/70`)], + [h.Class(`grid ${twoColumns} gap-3 py-1 text-3xs text-foreground-subtle`)], [h.span([], [`+${hidden} more ${pluralize(hidden, "service")}`])], ), ] @@ -275,7 +275,7 @@ export const releasesTimeline = (h: H, input: TimelineInput): Html => { h.span([]), h.div( [ - h.Class("flex justify-between font-mono text-3xs tabular-nums text-muted-foreground/70"), + h.Class("flex justify-between font-mono text-3xs tabular-nums text-foreground-subtle"), h.Style({ "padding-left": `${TRACK_INSET_PX}px`, "padding-right": `${TRACK_INSET_PX}px` }), ], axisLabels(startMs, endMs, input.timeZone).map((label) => h.span([], [label])), diff --git a/apps/web/src/page/releases/list/view-table.ts b/apps/web/src/page/releases/list/view-table.ts index 108089b176..b25e72d220 100644 --- a/apps/web/src/page/releases/list/view-table.ts +++ b/apps/web/src/page/releases/list/view-table.ts @@ -36,7 +36,7 @@ const baselineShift = (h: H, value: number, baseline: number | undefined, format [ ...(baseline === undefined ? [] - : [h.span([h.Class("text-3xs text-muted-foreground/70"), h.Title("The version this one replaced")], [format(baseline), " →"])]), + : [h.span([h.Class("text-3xs text-foreground-subtle"), h.Title("The version this one replaced")], [format(baseline), " →"])]), h.span([h.Class(cn(tone === "error" && "text-severity-error", tone === "warn" && "text-severity-warn"))], [format(value)]), ], ) @@ -44,7 +44,7 @@ const baselineShift = (h: H, value: number, baseline: number | undefined, format const issueCounts = (h: H, counts: ReleaseIssueCounts | undefined | null): Html | null => { if (counts === null) return null if (counts === undefined || (counts.fresh === 0 && counts.regressed === 0)) - return h.span([h.Class("font-mono text-xs text-muted-foreground/50")], [EMPTY_VALUE]) + return h.span([h.Class("font-mono text-xs text-foreground-faint")], [EMPTY_VALUE]) return h.span( [h.Class("inline-flex items-baseline gap-2 whitespace-nowrap font-mono text-xs tabular-nums")], [ @@ -71,7 +71,7 @@ const serviceChips = (h: H, services: ReadonlyArray): Html [ h.span([h.Class("tabular-nums")], [String(names.length), " services"]), ...flagged.slice(0, 2).map((name) => serviceChip(h, name, "inline-flex min-w-0 max-w-56 items-center gap-1")), - ...(flagged.length > 2 ? [h.span([h.Class("text-2xs text-muted-foreground/70")], [`+${flagged.length - 2}`])] : []), + ...(flagged.length > 2 ? [h.span([h.Class("text-2xs text-foreground-subtle")], [`+${flagged.length - 2}`])] : []), ], ) } @@ -187,7 +187,7 @@ export const releasesTable = (h: H, input: TableInput): Html => { tableRow(h, [ h.td( [ - h.Attribute("class", cn(tableCellStyles, cn(eyebrowVariants({}), "bg-muted/40 py-1"))), + h.Attribute("class", cn(tableCellStyles, cn(eyebrowVariants({}), "bg-surface-sunken py-1"))), h.Attribute("colspan", "6"), h.DataAttribute("slot", "eyebrow"), ], @@ -212,7 +212,7 @@ export const releasesTable = (h: H, input: TableInput): Html => { label: isOpen ? "Hide services" : "Show services", hasTooltip: false, className: cn( - "mt-1 text-muted-foreground/60 transition-transform hover:text-foreground", + "mt-1 text-foreground-subtle transition-transform hover:text-foreground", isOpen && "rotate-90", group.services.length <= 1 && "invisible", ), @@ -285,7 +285,7 @@ export const releasesTable = (h: H, input: TableInput): Html => { serviceDot(h, { serviceName: service.serviceName }), h.span([h.Class("min-w-0 truncate"), h.Title(service.serviceName)], [service.serviceName]), ...(service.environment && !input.environments?.length - ? [h.span([h.Class("min-w-0 truncate text-muted-foreground/70")], [service.environment])] + ? [h.span([h.Class("min-w-0 truncate text-foreground-subtle")], [service.environment])] : []), ...(service.health === "healthy" ? [] @@ -318,7 +318,7 @@ export const releasesTable = (h: H, input: TableInput): Html => { ), tableCell(h, [], "py-1.5"), ], - "bg-muted/20", + "bg-surface-faint", [h.Key(`${group.commitSha}:${service.serviceName}:${service.environment}`)], ), ) diff --git a/apps/web/src/page/releases/list/view.ts b/apps/web/src/page/releases/list/view.ts index 989e4fd4bf..61fc754faa 100644 --- a/apps/web/src/page/releases/list/view.ts +++ b/apps/web/src/page/releases/list/view.ts @@ -87,7 +87,7 @@ const loaded = (h: H, model: Model, data: ReleasesData, isWaiting: boolean, time emptyMessage(h, { className: "flex flex-col items-center gap-1 py-12 text-sm" }, [ h.span([], ["No releases detected in this window."]), h.span( - [h.Class("text-xs text-muted-foreground/70")], + [h.Class("text-xs text-foreground-subtle")], [ "Releases compare errors and latency before and after each deploy. Release tracking needs spans to carry the ", inlineCode(h, {}, ["vcs.ref.head.revision"]), @@ -111,9 +111,9 @@ const loaded = (h: H, model: Model, data: ReleasesData, isWaiting: boolean, time ...(flagged > 0 ? [stat(h, formatNumber(flagged), [pluralize(flagged, "release"), " with errors up"], "text-severity-error")] : []), - h.span([h.Class("text-muted-foreground/70")], ["Each release is compared with the version it replaced"]), + h.span([h.Class("text-foreground-subtle")], ["Each release is compared with the version it replaced"]), ...(response.truncated - ? [h.span([h.Class("text-muted-foreground/70")], ["Showing the newest ", formatNumber(response.releases.length), " rows"])] + ? [h.span([h.Class("text-foreground-subtle")], ["Showing the newest ", formatNumber(response.releases.length), " rows"])] : []), ], ), @@ -160,7 +160,7 @@ const loaded = (h: H, model: Model, data: ReleasesData, isWaiting: boolean, time ...(issues?.hasMore === true ? [ h.span( - [h.Class("px-0.5 text-2xs text-muted-foreground/70")], + [h.Class("px-0.5 text-2xs text-foreground-subtle")], ["Issue counts cover the 100 most recently active issues introduced in this window."], ), ] diff --git a/apps/web/src/page/replays/detail/view-player.ts b/apps/web/src/page/replays/detail/view-player.ts index 4a2042fcb8..b37bb76363 100644 --- a/apps/web/src/page/replays/detail/view-player.ts +++ b/apps/web/src/page/replays/detail/view-player.ts @@ -236,7 +236,7 @@ const statusOverlay = ( "This session wasn’t recorded. Replay is off or unsampled for this app. Its traces and events are still below.", h.span([h.Class("mt-2 flex justify-center")], [docsLink(h, "sessionReplay")]), ]) - return h.div([h.Class("absolute inset-0 bg-muted/30")], [body]) + return h.div([h.Class("absolute inset-0 bg-surface-sunken")], [body]) } /** What the stage reads: everything but the playhead, so a tick reuses it. */ @@ -326,7 +326,7 @@ const playOverlay = (h: H, stage: Stage): Html => const urlBar = (h: H, urlInitial: string): Html => h.div( - [h.Class("flex items-center gap-3 border-b border-border bg-muted/40 px-3.5 py-2.5")], + [h.Class("flex items-center gap-3 border-b border-border bg-surface-sunken px-3.5 py-2.5")], [ h.div( [h.Class("flex items-center gap-1.5"), h.AriaHidden(true)], diff --git a/apps/web/src/page/replays/detail/view-rail.ts b/apps/web/src/page/replays/detail/view-rail.ts index 043640b206..51cbf65293 100644 --- a/apps/web/src/page/replays/detail/view-rail.ts +++ b/apps/web/src/page/replays/detail/view-rail.ts @@ -165,7 +165,7 @@ const filterButton = ( h.Class( cn( "flex h-6 cursor-pointer items-center gap-1 rounded-md px-1.5 transition-colors", - config.isActive ? config.selected : cn(config.tone, "hover:bg-muted/50"), + config.isActive ? config.selected : cn(config.tone, "hover:bg-surface-sunken"), config.count === 0 && !config.isActive && "text-muted-foreground opacity-45", ), ), @@ -254,7 +254,7 @@ const eventDetail = (h: H, ev: EventRow): Html => { h.span( [ h.Class( - "whitespace-pre-wrap break-words text-2xs leading-4 text-foreground/80", + "whitespace-pre-wrap break-words text-2xs leading-4 text-foreground-soft", ), ], [ev.message], @@ -276,7 +276,7 @@ const eventDetail = (h: H, ev: EventRow): Html => { props.map(([key, value]) => h.span( [h.Key(key)], - [key, "=", h.span([h.Class("text-foreground/80")], [value])], + [key, "=", h.span([h.Class("text-foreground-soft")], [value])], ), ), ), @@ -326,7 +326,7 @@ const eventLine = (h: H, model: RailView, ev: EventRow, index: number, showNetwo h.Type("button"), h.OnClick(Message.ClickedEvent({ index, timestamp: ev.timestamp })), h.AriaExpanded(isOpen), - h.Class("flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-muted/50"), + h.Class("flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-surface-sunken"), h.Title("Seek replay to this moment"), ], [ @@ -362,7 +362,7 @@ const eventLine = (h: H, model: RailView, ev: EventRow, index: number, showNetwo h.span( [ h.Class( - "flex w-[72px] shrink-0 items-center justify-end gap-1.5 text-3xs tabular-nums", + "flex w-20 shrink-0 items-center justify-end gap-1.5 text-3xs tabular-nums", ), ], [ @@ -464,7 +464,7 @@ const traceListRow = (h: H, model: RailView, summary: TraceSummary): Html => { h.Key(summary.traceId), h.Class( cn( - "relative flex flex-col gap-0.5 px-3 py-2.5 hover:bg-muted/50", + "relative flex flex-col gap-0.5 px-3 py-2.5 hover:bg-surface-sunken", isError && "bg-severity-error/5", ), ), @@ -542,7 +542,7 @@ const traceListRow = (h: H, model: RailView, summary: TraceSummary): Html => { h.Target("_blank"), h.Rel("noreferrer"), h.Class( - "inline-flex shrink-0 items-center gap-1 text-2xs text-info-foreground underline-offset-2 hover:underline", + "inline-flex shrink-0 items-center gap-1 text-2xs text-severity-debug underline-offset-2 hover:underline", ), ], ["open", icon(h, "ExternalLinkIcon", { className: "size-3" })], diff --git a/apps/web/src/page/replays/detail/view-session.ts b/apps/web/src/page/replays/detail/view-session.ts index 743988ee42..fa7684651c 100644 --- a/apps/web/src/page/replays/detail/view-session.ts +++ b/apps/web/src/page/replays/detail/view-session.ts @@ -72,7 +72,7 @@ const stat = (h: H, iconName: IconName, label: string, count: number, isDanger = [ h.Class( cn( - "flex flex-col gap-0.5 rounded-md border border-border/60 bg-muted/30 px-2 py-1.5", + "flex flex-col gap-0.5 rounded-md border border-border-subtle bg-surface-sunken px-2 py-1.5", isDanger && "border-severity-error/30 bg-severity-error/5", ), ), @@ -125,7 +125,7 @@ const summary = (h: H, session: ReplayDetail): Html => { : null const isErrored = session.errorCount > 0 return h.section( - [h.Class("border-b border-border/60 px-4 py-3.5")], + [h.Class("border-b border-border-subtle px-4 py-3.5")], [ statFigure(h, { value: formatSessionDuration(total), unit: "on the page" }), ...(share === null @@ -242,7 +242,7 @@ const identity = (h: H, model: SessionView, session: ReplayDetail): Html | null truncatedText(h, { text: `${key}: ${text}`, className: "max-w-full" }, [ key, "=", - h.span([h.Class("text-foreground/80")], [text]), + h.span([h.Class("text-foreground-soft")], [text]), ]), ), ), diff --git a/apps/web/src/page/replays/detail/view-timeline.ts b/apps/web/src/page/replays/detail/view-timeline.ts index 781c80f6ce..de38f8f41a 100644 --- a/apps/web/src/page/replays/detail/view-timeline.ts +++ b/apps/web/src/page/replays/detail/view-timeline.ts @@ -65,9 +65,9 @@ export const markerLegend = (h: H): Html => const timeRuler = (h: H, totalMs: number): Html => { const ticks = Array.from({ length: 7 }, (_, i) => (totalMs * i) / 6) return h.div( - [h.Class("flex items-stretch border-b border-border/60 bg-muted/10")], + [h.Class("flex items-stretch border-b border-border-subtle bg-surface-faint")], [ - h.div([h.Class(cn(LANE_GUTTER, "shrink-0 border-r border-border/60"))], []), + h.div([h.Class(cn(LANE_GUTTER, "shrink-0 border-r border-border-subtle"))], []), h.div( [h.Class("relative h-5 flex-1")], ticks.map((ms, i) => @@ -93,7 +93,7 @@ const timeRuler = (h: H, totalMs: number): Html => { const activityTrack = (h: H, model: Model, playhead: Playhead): Html => h.div( - [h.Class("flex items-stretch border-b border-border/60")], + [h.Class("flex items-stretch border-b border-border-subtle")], [ activityGutterSlot(activityGutter, [h]), h.div( @@ -128,7 +128,7 @@ const activityGutter = (h: H): Html => h.Class( cn( LANE_GUTTER, - "flex shrink-0 items-center gap-1.5 border-r border-border/60 px-3 py-2 text-xs font-medium text-muted-foreground", + "flex shrink-0 items-center gap-1.5 border-r border-border-subtle px-3 py-2 text-xs font-medium text-muted-foreground", ), ), ], @@ -167,7 +167,7 @@ const tracesHeader = (h: H, count: number | null): Html => { as: "div", variant: "label", - className: "flex items-center gap-2 border-b border-border/60 bg-muted/20 px-3 py-1.5", + className: "flex items-center gap-2 border-b border-border-subtle bg-surface-faint px-3 py-1.5", }, [ icon(h, "PulseIcon", { className: "size-3.5" }), @@ -221,7 +221,7 @@ const spanRowItem = (h: H, frame: SeekFrame, span: SpanRow): Html => { [ h.div( [ - h.Class(cn(LANE_GUTTER, "shrink-0 truncate border-r border-border/60 px-2 py-1 pl-6")), + h.Class(cn(LANE_GUTTER, "shrink-0 truncate border-r border-border-subtle px-2 py-1 pl-6")), h.Title(`${span.serviceName} · ${span.spanName}`), ], [ @@ -263,21 +263,21 @@ const spanRowItem = (h: H, frame: SeekFrame, span: SpanRow): Html => { const spanLane = (h: H, frame: SeekFrame, traceId: string): Html => { const data = frame.view.spans[traceId] ?? AsyncData.Loading() return AsyncData.matchData(data, { - onEmpty: () => h.div([h.Class("bg-muted/10 px-3 py-2")], [skeleton(h, "h-3 w-1/2")]), + onEmpty: () => h.div([h.Class("bg-surface-faint px-3 py-2")], [skeleton(h, "h-3 w-1/2")]), onFailure: (failure) => errorState(h, { failure, variant: "inline", title: "Couldn't load spans for this trace", - className: "bg-muted/10 px-3 py-2", + className: "bg-surface-faint px-3 py-2", }), onData: (spans) => spans.length === 0 - ? emptyMessage(h, { className: "bg-muted/10 py-2 text-2xs" }, [ + ? emptyMessage(h, { className: "bg-surface-faint py-2 text-2xs" }, [ "No spans found for this trace.", ]) : h.div( - [h.Class("max-h-56 space-y-px overflow-y-auto bg-muted/10 py-1")], + [h.Class("max-h-56 space-y-px overflow-y-auto bg-surface-faint py-1")], [...spans] .sort((a, b) => parseChTimestampMs(a.startTime) - parseChTimestampMs(b.startTime)) .map((span) => spanRowItem(h, frame, span)), @@ -292,7 +292,7 @@ const traceRow = (h: H, frame: SeekFrame, summary: TraceSummary): Html => { const leftPct = pct(range.displayStartMs, frame.timeline.activeTotalMs) const widthPct = Math.max(0.6, pct(range.displayEndMs, frame.timeline.activeTotalMs) - leftPct) return h.li( - [h.Key(summary.traceId), h.Class("border-b border-border/60 last:border-b-0")], + [h.Key(summary.traceId), h.Class("border-b border-border-subtle last:border-b-0")], [ h.div( [h.Class("flex items-stretch")], @@ -302,7 +302,7 @@ const traceRow = (h: H, frame: SeekFrame, summary: TraceSummary): Html => { h.Class( cn( LANE_GUTTER, - "flex shrink-0 items-center gap-1.5 border-r border-border/60 pr-2 pl-2 text-xs", + "flex shrink-0 items-center gap-1.5 border-r border-border-subtle pr-2 pl-2 text-xs", ), ), ], @@ -338,7 +338,7 @@ const traceRow = (h: H, frame: SeekFrame, summary: TraceSummary): Html => { h.Target("_blank"), h.Rel("noreferrer"), h.Class( - "group/trace flex min-w-0 flex-1 items-center rounded px-1 py-1.5 text-left transition-colors hover:bg-muted/50", + "group/trace flex min-w-0 flex-1 items-center rounded-sm px-1 py-1.5 text-left transition-colors hover:bg-surface-sunken", ), ], [ @@ -392,7 +392,7 @@ const traceRow = (h: H, frame: SeekFrame, summary: TraceSummary): Html => { [ h.Class( cn( - "absolute top-1/2 flex h-5 -translate-y-1/2 items-center overflow-hidden rounded px-1.5 text-3xs font-medium text-white ring-1 ring-inset transition-[filter] hover:brightness-110", + "absolute top-1/2 flex h-5 -translate-y-1/2 items-center overflow-hidden rounded-sm px-1.5 text-3xs font-medium text-white ring-1 ring-inset transition-[filter] hover:brightness-110", isError ? "bg-severity-error ring-severity-error/40" : "bg-primary ring-primary/40", @@ -469,7 +469,7 @@ const tracesSlot = createLazy() const timelineHeader = (h: H): Html => h.div( - [h.Class("flex items-center justify-between gap-3 border-b border-border bg-muted/30 px-3 py-2")], + [h.Class("flex items-center justify-between gap-3 border-b border-border bg-surface-sunken px-3 py-2")], [eyebrow(h, { variant: "label" }, ["Timeline"]), markerLegend(h)], ) diff --git a/apps/web/src/page/replays/detail/view.ts b/apps/web/src/page/replays/detail/view.ts index 9f3acad1f3..06e88c8b37 100644 --- a/apps/web/src/page/replays/detail/view.ts +++ b/apps/web/src/page/replays/detail/view.ts @@ -1,6 +1,6 @@ import { shortId } from "@maple/ui/lib/ids" import { initialsFrom } from "@maple/ui/lib/initials" -import { gradientFor, hostFromUrl } from "@maple/ui/lib/replay" +import { hostFromUrl } from "@maple/ui/lib/replay" import { formatSessionDuration } from "@maple/ui/lib/replay-format" import { parseChTimestampMs } from "../../../components/replays/replay-timeline" import { Struct } from "effect" @@ -28,6 +28,7 @@ import { replaySurface, replayTransport } from "./view-player" import { sessionRail } from "./view-rail" import { copy } from "./view-session" import { replayTimeline } from "./view-timeline" +import { warmAvatarTone } from "../../../ui/avatar-tone" // The replay detail page on `ResultPage`, with the replay studio. @@ -78,7 +79,7 @@ const identityBar = (h: H, model: IdentityView, session: ReplayDetail, timeZone: h.div( [ h.Class( - `grid size-8 shrink-0 place-items-center rounded-full bg-gradient-to-br ${gradientFor(model.sessionId)} text-xs font-semibold text-white shadow-sm`, + `grid size-8 shrink-0 place-items-center rounded-full ${warmAvatarTone(model.sessionId)} text-xs font-semibold`, ), ], [initialsFrom(label)], diff --git a/apps/web/src/page/replays/kit/session-list-row.ts b/apps/web/src/page/replays/kit/session-list-row.ts index aef9cf9d3c..af191c5a7e 100644 --- a/apps/web/src/page/replays/kit/session-list-row.ts +++ b/apps/web/src/page/replays/kit/session-list-row.ts @@ -40,7 +40,7 @@ const orgButton = ( return h.button( [ h.Type("button"), - h.Class(cn(className, "rounded hover:underline")), + h.Class(cn(className, "rounded-sm hover:underline")), h.OnClick(onFilter(name), { propagation: "Stop" }), ], [name], @@ -176,7 +176,7 @@ export const sessionListRow = ( h.OnClick(open), h.Class( cn( - "group relative flex w-full cursor-pointer items-center gap-3 border-b border-border px-3 transition-colors hover:bg-accent/40 @2xl:gap-4", + "group relative flex w-full cursor-pointer items-center gap-3 border-b border-border px-3 transition-colors hover:bg-accent/50 @2xl:gap-4", lowSignal ? "py-1.5" : "py-2.5", ), ), @@ -210,7 +210,7 @@ export const sessionListRow = ( [ session.groupName ? orgButton(h, session.groupName, options.onFilterGroup) - : h.span([h.Class("text-xs text-muted-foreground/50")], [EMPTY_VALUE]), + : h.span([h.Class("text-xs text-foreground-faint")], [EMPTY_VALUE]), ], ), h.div( diff --git a/apps/web/src/page/replays/kit/sessions-list.ts b/apps/web/src/page/replays/kit/sessions-list.ts index 02e69fb2fa..a8ffc1a837 100644 --- a/apps/web/src/page/replays/kit/sessions-list.ts +++ b/apps/web/src/page/replays/kit/sessions-list.ts @@ -33,7 +33,7 @@ const quietRunRow = ( h.OnClick(onToggle), h.AriaExpanded(item.expanded), h.Class( - "flex w-full items-center gap-3 border-b border-border bg-muted/30 px-3 py-1.5 text-left text-xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring @2xl:gap-4", + "flex w-full items-center gap-3 border-b border-border bg-surface-sunken px-3 py-1.5 text-left text-xs text-muted-foreground transition-colors hover:bg-surface-strong hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring @2xl:gap-4", ), ], [ diff --git a/apps/web/src/page/replays/list/view.ts b/apps/web/src/page/replays/list/view.ts index fd162f4194..2a0e321a2d 100644 --- a/apps/web/src/page/replays/list/view.ts +++ b/apps/web/src/page/replays/list/view.ts @@ -1,6 +1,5 @@ import { countLabel, formatNumber } from "@maple/ui/lib/format" import { initialsFrom } from "@maple/ui/lib/initials" -import { gradientFor } from "@maple/ui/lib/replay" import { Submodel } from "foldkit" import { AsyncData } from "foldkit" import type { Html, HtmlBuilder } from "foldkit/html" @@ -38,6 +37,7 @@ import { Message } from "./message" import type { Model } from "./model" import { DEFAULT_PRESET } from "./update" import { filtersRail } from "./view-filters" +import { warmAvatarTone } from "../../../ui/avatar-tone" type H = HtmlBuilder @@ -104,7 +104,7 @@ const activeUserFilter = ( h.div( [ h.Class( - `grid size-8 shrink-0 place-items-center rounded-full bg-gradient-to-br ${gradientFor(config.userId)} text-xs font-semibold text-white shadow-sm`, + `grid size-8 shrink-0 place-items-center rounded-full ${warmAvatarTone(config.userId)} text-xs font-semibold`, ), ], [initialsFrom(config.userId)], diff --git a/apps/web/src/page/security/kit/finding-body.ts b/apps/web/src/page/security/kit/finding-body.ts index eed5779daf..691b501b79 100644 --- a/apps/web/src/page/security/kit/finding-body.ts +++ b/apps/web/src/page/security/kit/finding-body.ts @@ -33,13 +33,13 @@ const prose = (h: HtmlBuilder, text: string, className?: string): Html => const labelled = (h: HtmlBuilder, label: string, text: string): Html => h.div( - [h.Class("flex flex-col gap-1.5 rounded-md border px-3 py-2.5")], + [h.Class("flex flex-col gap-1.5 rounded-md border p-3")], [eyebrow(h, { as: "div" }, [label]), h.p([h.Class("text-sm")], [text])], ) const codeBlock = (h: HtmlBuilder, text: string, label?: string): Html => h.div( - [h.Class("overflow-hidden rounded-md border bg-muted/40")], + [h.Class("overflow-hidden rounded-md border bg-surface-sunken")], [ ...(label === undefined ? [] diff --git a/apps/web/src/page/security/kit/findings-view.ts b/apps/web/src/page/security/kit/findings-view.ts index a6bf7b1e03..62b8104d99 100644 --- a/apps/web/src/page/security/kit/findings-view.ts +++ b/apps/web/src/page/security/kit/findings-view.ts @@ -123,7 +123,7 @@ const tabButton = ( "flex h-7 shrink-0 items-center gap-1.5 rounded-md border px-2.5 text-xs transition-colors", isActive ? "border-border bg-muted font-medium text-foreground" - : "border-transparent text-muted-foreground hover:bg-muted/50 hover:text-foreground", + : "border-transparent text-muted-foreground hover:bg-surface-sunken hover:text-foreground", ), ), ], @@ -186,7 +186,7 @@ const findingRow = (h: HtmlBuilder, options: FindingRowOptions): Html = const note = noteOf(finding) const attributes: ReadonlyArray> = [ h.Class( - "flex h-10 w-full min-w-0 items-center gap-3 pr-3 pl-8 text-left outline-none hover:bg-muted/50 focus-visible:bg-muted/60 focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", + "flex h-10 w-full min-w-0 items-center gap-3 pr-3 pl-8 text-left outline-none hover:bg-surface-sunken focus-visible:bg-surface-strong focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", ), ] const children = [ @@ -235,7 +235,7 @@ const findingRow = (h: HtmlBuilder, options: FindingRowOptions): Html = ), ] return h.li( - [h.Key(`${finding.targetId}/${finding.fingerprint}`), h.Class("border-b border-border/60")], + [h.Key(`${finding.targetId}/${finding.fingerprint}`), h.Class("border-b border-border-subtle")], [ "href" in options.open ? h.a([h.Href(options.open.href), ...attributes], children) @@ -277,7 +277,7 @@ export const findingGroups = (h: HtmlBuilder, options: FindingGroupsOption h.AriaExpanded(!isCollapsed), h.OnClick(options.onToggle(bucket)), h.Class( - "sticky top-0 z-[1] flex h-9 w-full items-center gap-2 border-b border-border/60 bg-muted/60 px-3 text-left backdrop-blur hover:bg-muted", + "sticky top-0 z-[1] flex h-9 w-full items-center gap-2 border-b border-border-subtle bg-surface-strong px-3 text-left backdrop-blur hover:bg-muted", ), ], [ diff --git a/apps/web/src/page/security/run/view.ts b/apps/web/src/page/security/run/view.ts index f991a323df..e21d3eae0e 100644 --- a/apps/web/src/page/security/run/view.ts +++ b/apps/web/src/page/security/run/view.ts @@ -115,7 +115,7 @@ const runDetails = (h: H, model: Model, run: SecurityAuditRunDetail, timeZone: s h.AriaExpanded(isOpen), h.OnClick(Message.ToggledDetails()), h.Class( - "flex w-full items-center gap-2.5 rounded-md border bg-card px-4 py-3 text-left hover:bg-muted/50", + "flex w-full items-center gap-2.5 rounded-md border bg-card p-4 text-left hover:bg-surface-sunken", ), ], [ diff --git a/apps/web/src/page/security/tabs/view-overview.ts b/apps/web/src/page/security/tabs/view-overview.ts index 25b59636c0..153f30999a 100644 --- a/apps/web/src/page/security/tabs/view-overview.ts +++ b/apps/web/src/page/security/tabs/view-overview.ts @@ -468,7 +468,7 @@ const listLink = (h: HtmlBuilder, href: string, children: ReadonlyArray { [ h.span([h.Class("truncate font-mono")], [config.originDatabase]), config.originHost - ? h.span([h.Class("truncate text-3xs text-muted-foreground/60")], [config.originHost]) - : h.span([h.Class("shrink-0 text-3xs text-muted-foreground/60")], ["private origin"]), + ? h.span([h.Class("truncate text-3xs text-foreground-subtle")], [config.originHost]) + : h.span([h.Class("shrink-0 text-3xs text-foreground-subtle")], ["private origin"]), ], ) } @@ -131,7 +131,7 @@ export const hyperdriveSection = (h: H, configs: ReadonlyArray ], ), keyValueList(h, { className: "grid grid-cols-2 gap-2 text-3xs" }, [ - keyValue(h, { label: "CPU", mono: true, className: "rounded bg-muted/30 px-2 py-1" }, [ + keyValue(h, { label: "CPU", mono: true, className: "rounded-sm bg-surface-sunken px-2 py-1" }, [ utilization(workload.avgCpuLimitUtilization), ]), - keyValue(h, { label: "Memory", mono: true, className: "rounded bg-muted/30 px-2 py-1" }, [ + keyValue(h, { label: "Memory", mono: true, className: "rounded-sm bg-surface-sunken px-2 py-1" }, [ utilization(workload.avgMemoryLimitUtilization), ]), ]), @@ -122,7 +122,7 @@ const runtimeRow = (h: H, link: RuntimeLink): Html => ), ], [ - panel(h, { padded: "sm", className: "space-y-1 transition-colors group-hover:bg-muted/50" }, [ + panel(h, { padded: "sm", className: "space-y-1 transition-colors group-hover:bg-surface-sunken" }, [ eyebrow(h, { as: "div", className: "flex items-center gap-1.5" }, [ icon(h, link.icon, { size: 12 }), h.span([], [link.label]), @@ -155,12 +155,12 @@ const runtimeRow = (h: H, link: RuntimeLink): Html => /** No platform resource and no Kubernetes workload matched: how each one gets linked. */ const infraEmptyState = (h: H): Html => h.div( - [h.Class("rounded-md border border-dashed bg-muted/20 p-4 space-y-3")], + [h.Class("rounded-md border border-dashed bg-surface-faint p-4 space-y-3")], [ h.div( [h.Class("flex items-center gap-2")], [ - icon(h, "CubeIcon", { size: 14, className: "text-muted-foreground/50" }), + icon(h, "CubeIcon", { size: 14, className: "text-foreground-faint" }), h.p( [h.Class("text-xs font-medium text-foreground")], ["Not linked to any infrastructure"], @@ -184,7 +184,7 @@ const infraEmptyState = (h: H): Html => ], ), h.pre( - [h.Class("text-3xs bg-muted px-2 py-1.5 rounded font-mono text-foreground overflow-x-auto")], + [h.Class("text-3xs bg-muted px-2 py-1.5 rounded-sm font-mono text-foreground overflow-x-auto")], ["kubectl label namespace maple.io/instrument=true"], ), docsLink(h, "kubernetes"), diff --git a/apps/web/src/page/service-map/view-service-panel.ts b/apps/web/src/page/service-map/view-service-panel.ts index 34863a2e92..72a1ea700f 100644 --- a/apps/web/src/page/service-map/view-service-panel.ts +++ b/apps/web/src/page/service-map/view-service-panel.ts @@ -322,7 +322,7 @@ export const servicePanel = (h: H, model: Model, inputs: ServicePanelInputs): Ht h.span( [ h.Class( - "ml-1 text-4xs tabular-nums text-muted-foreground/70", + "ml-1 text-4xs tabular-nums text-foreground-subtle", ), ], [String(infraCount)], diff --git a/apps/web/src/page/services/detail/endpoint-peek/view.ts b/apps/web/src/page/services/detail/endpoint-peek/view.ts index 7d8311e4d3..5924beaa9a 100644 --- a/apps/web/src/page/services/detail/endpoint-peek/view.ts +++ b/apps/web/src/page/services/detail/endpoint-peek/view.ts @@ -267,7 +267,7 @@ const statusCard = (h: H, rows: ReadonlyArray, spanName: string): Htm [h.Class("mt-auto truncate text-3xs text-muted-foreground")], [ `error.type `, - h.span([h.Class("text-foreground/80")], [errorType.errorType]), + h.span([h.Class("text-foreground-soft")], [errorType.errorType]), ` on most ${errorType.httpStatusCode}s`, ], ), @@ -362,7 +362,7 @@ const bodyCard = (h: H, detail: EndpointDetail): Html => [h.Class("text-2xs text-muted-foreground")], [ "No request carried ", - h.span([h.Class("text-foreground/80")], ["http.request.body.size"]), + h.span([h.Class("text-foreground-soft")], ["http.request.body.size"]), ".", ], ) @@ -437,14 +437,14 @@ const slowestCard = (h: H, detail: EndpointDetail, inputs: ViewInputs): Html => h.Key(`${request.traceId}-${request.timestamp}`), h.Href(hrefOf(AppRoute.Trace({ traceId: request.traceId, search: {} }))), h.Class( - "flex h-9 items-center gap-2 border-b px-3 text-2xs tabular-nums sm:gap-3 last:border-b-0 hover:bg-muted/50", + "flex h-9 items-center gap-2 border-b px-3 text-2xs tabular-nums sm:gap-3 last:border-b-0 hover:bg-surface-sunken", ), ], [ truncatedId(h, { value: request.traceId, kind: "trace", - className: "w-16 shrink-0 text-info-foreground sm:w-20", + className: "w-16 shrink-0 text-severity-debug sm:w-20", }), h.span( [h.Class("w-14 shrink-0 text-right")], diff --git a/apps/web/src/page/services/detail/view-api-tab.ts b/apps/web/src/page/services/detail/view-api-tab.ts index c111264d92..c0422cc596 100644 --- a/apps/web/src/page/services/detail/view-api-tab.ts +++ b/apps/web/src/page/services/detail/view-api-tab.ts @@ -362,7 +362,7 @@ const codeRow = (h: H, summary: StatusCodeSummary): Html => { [ ...(errorType === undefined ? [] - : [h.span([h.Class("text-foreground/80")], [errorType.name]), " · "]), + : [h.span([h.Class("text-foreground-soft")], [errorType.name]), " · "]), routeList(summary.routes), ], ), @@ -435,7 +435,7 @@ const toolbar = (h: H, model: Model, count: number): Html => ...(AsyncData.isFailure(model.endpointSeries.data) ? [ h.span( - [h.Class("text-2xs text-destructive-foreground")], + [h.Class("text-2xs text-severity-error")], ["Trends failed to load; Reload to retry."], ), ] @@ -459,7 +459,7 @@ const toolbar = (h: H, model: Model, count: number): Html => ariaLabel: "Filter routes", onInput: (value) => Message.ChangedEndpointQuery({ value }), onClear: Message.ChangedEndpointQuery({ value: "" }), - className: "ml-auto w-[240px]", + className: "ml-auto w-60", }), ], ) @@ -603,7 +603,7 @@ const loadingState = (h: H): Html => skeleton(h, "h-2.5 w-9"), skeleton(h, "h-2.5 w-40"), h.span([h.Class("flex-1")]), - skeleton(h, "h-2.5 w-[88px]"), + skeleton(h, "h-2.5 w-24"), skeleton(h, "h-2.5 w-24"), skeleton(h, "h-2.5 w-12"), ], @@ -616,9 +616,9 @@ const loadingState = (h: H): Html => /** `ApiEmptyState`: names the two conditions an endpoint needs. */ const emptyState = (h: H, serviceName: string): Html => { - const mono = (text: string) => h.span([h.Class("text-foreground/80")], [text]) + const mono = (text: string) => h.span([h.Class("text-foreground-soft")], [text]) return panel(h, { className: "items-center gap-3.5 px-[18px] py-11 text-center" }, [ - h.span([h.Class("text-title font-medium text-foreground/90")], ["No HTTP endpoints in this window"]), + h.span([h.Class("text-title font-medium text-foreground-soft")], ["No HTTP endpoints in this window"]), h.span( [h.Class("max-w-[620px] text-ui leading-[21px] text-muted-foreground")], [ diff --git a/apps/web/src/page/services/detail/view-api.ts b/apps/web/src/page/services/detail/view-api.ts index f6701b4d6c..e2672753f9 100644 --- a/apps/web/src/page/services/detail/view-api.ts +++ b/apps/web/src/page/services/detail/view-api.ts @@ -33,13 +33,13 @@ type H = HtmlBuilder /** Below `md` the table keeps the endpoint, its rate, 4xx share and p95; the rest hide. */ export const COLUMN = { - rate: "w-14 md:w-[176px]", - mix: "w-12 md:w-[176px]", - err: "hidden w-[72px] md:table-cell", - p50: "hidden w-[84px] md:table-cell", - p95: "w-16 md:w-[84px]", - p99: "hidden w-[84px] md:table-cell", - body: "hidden w-[88px] md:table-cell", + rate: "w-14 md:w-44", + mix: "w-12 md:w-44", + err: "hidden w-20 md:table-cell", + p50: "hidden w-20 md:table-cell", + p95: "w-16 md:w-20", + p99: "hidden w-20 md:table-cell", + body: "hidden w-24 md:table-cell", chevron: "w-6 md:w-10", } as const @@ -217,7 +217,7 @@ const endpointRow = ( [ // The wrapper hides it on narrow screens; the chart keeps its own flex layout. h.div( - [h.Class("hidden h-5 w-[88px] md:block")], + [h.Class("hidden h-5 w-24 md:block")], context.theme === null ? [] : [ @@ -226,7 +226,7 @@ const endpointRow = ( values: context.sparks.get(endpoint.spanName) ?? [], token: SPARK_TOKENS.requests, theme: context.theme, - className: cn("h-5 w-[88px]", isQuiet && "opacity-60"), + className: cn("h-5 w-24", isQuiet && "opacity-60"), toMessage: (message) => Message.GotChartMessage({ chartId: "sparkline", @@ -301,7 +301,7 @@ const endpointRow = ( ], cn( "group/row h-12 cursor-pointer border-b text-ui last:border-b-0 has-[button:focus-visible]:ring-1 has-[button:focus-visible]:ring-ring has-[button:focus-visible]:ring-inset", - isSelected ? "bg-accent hover:bg-accent" : "hover:bg-muted/50", + isSelected ? "bg-accent hover:bg-accent" : "hover:bg-surface-sunken", ), [h.Key(endpoint.spanName), h.OnClick(Message.ClickedEndpoint({ spanName: endpoint.spanName }))], ) @@ -376,7 +376,7 @@ const groupHeaderRow = ( cell("—", COLUMN.body), tableCell(h, [], COLUMN.chevron), ], - "h-10 border-b bg-muted/30 hover:bg-muted/30", + "h-10 border-b bg-surface-sunken hover:bg-surface-strong", ) } @@ -422,7 +422,7 @@ export const groupRows = ( [copy.explainer], ), h.span( - [h.Class("truncate text-2xs text-muted-foreground/50")], + [h.Class("truncate text-2xs text-foreground-faint")], [ sample.join(" · "), remaining > 0 diff --git a/apps/web/src/page/services/detail/view-dependencies.ts b/apps/web/src/page/services/detail/view-dependencies.ts index 39b64a7ae5..b0c1634bc2 100644 --- a/apps/web/src/page/services/detail/view-dependencies.ts +++ b/apps/web/src/page/services/detail/view-dependencies.ts @@ -87,7 +87,7 @@ const dependencyRow = (h: H, row: DependencyRow, maxima: Readonly<{ calls: numbe ? [] : [ h.span( - [h.Class("truncate text-3xs text-muted-foreground/60")], + [h.Class("truncate text-3xs text-foreground-subtle")], [row.subtitle], ), ]), @@ -115,7 +115,7 @@ const dependencyRow = (h: H, row: DependencyRow, maxima: Readonly<{ calls: numbe latencyValue(h, { ms: row.p95DurationMs, scale: "p95", className: "text-xs" }), ), ], - "cursor-pointer group/row border-b last:border-b-0 hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", + "cursor-pointer group/row border-b last:border-b-0 hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", [ h.Key(row.id), h.Attribute("tabindex", "0"), @@ -163,7 +163,7 @@ const dependencyTable = (h: H, model: Model, rows: ReadonlyArray) emptyMessage(h, {}, [ "No downstream dependencies in this window.", h.span( - [h.Class("mt-1 block text-muted-foreground/70")], + [h.Class("mt-1 block text-foreground-subtle")], [ "Outgoing calls show up when client spans carry peer.service or server.address.", ], @@ -228,7 +228,7 @@ const summaryStrip = (h: H, count: number, summary: DependencySummary): Html => h.span([h.Class("text-muted-foreground")], ["downstream"]), ], ), - h.span([h.Class("text-muted-foreground/60")], [summary.breakdown]), + h.span([h.Class("text-foreground-subtle")], [summary.breakdown]), ], ), h.span([h.Class("hidden grow sm:block")]), diff --git a/apps/web/src/page/services/detail/view-deploys.ts b/apps/web/src/page/services/detail/view-deploys.ts index 082dc5e039..6156812675 100644 --- a/apps/web/src/page/services/detail/view-deploys.ts +++ b/apps/web/src/page/services/detail/view-deploys.ts @@ -59,7 +59,7 @@ const issueLine = (h: H, issue: Issue, clock: Clock): Html => variant: "orDate", mono: true, tooltip: "title", - className: "w-14 text-right text-xs text-muted-foreground/70", + className: "w-14 text-right text-xs text-foreground-subtle", }), ], ), @@ -116,7 +116,7 @@ const errorRateChip = (h: H, deploy: DeployEntry): Html => { mono: true, className: cn( "cursor-default", - level === "neutral" ? "bg-transparent text-muted-foreground/60" : TONE_SOFT[level], + level === "neutral" ? "bg-transparent text-foreground-subtle" : TONE_SOFT[level], ), attributes: [ h.Title( @@ -161,7 +161,7 @@ const rowMeta = ( variant: "orDate", mono: true, tooltip: "title", - className: "ml-auto shrink-0 cursor-default text-muted-foreground/70", + className: "ml-auto shrink-0 cursor-default text-foreground-subtle", }), ] @@ -171,7 +171,7 @@ const deploysEmpty = (h: H): Html => emptyMessage(h, { className: "flex flex-col items-center gap-1" }, [ h.span([], ["No deploys detected in this window."]), h.span( - [h.Class("text-muted-foreground/70")], + [h.Class("text-foreground-subtle")], [ "Deploy tracking needs spans to carry the", " ", @@ -240,7 +240,7 @@ export const deploysPanel = (h: H, model: Model, clock: Clock, isLoading: boolea deploys.length === 0 ? undefined : h.span( - [h.Class("text-xs text-muted-foreground/70")], + [h.Class("text-xs text-foreground-subtle")], [countLabel(deploys.length, "version"), " in window"], ), }, @@ -256,7 +256,7 @@ export const deploysPanel = (h: H, model: Model, clock: Clock, isLoading: boolea h.div( [ h.Class( - "px-2 py-1.5 text-center text-2xs text-muted-foreground/70", + "px-2 py-1.5 text-center text-2xs text-foreground-subtle", ), ], [ diff --git a/apps/web/src/page/services/detail/view-footprint.ts b/apps/web/src/page/services/detail/view-footprint.ts index e4df5a2b2a..5aacb7a643 100644 --- a/apps/web/src/page/services/detail/view-footprint.ts +++ b/apps/web/src/page/services/detail/view-footprint.ts @@ -31,7 +31,7 @@ import { sectionCard, viewAllButton } from "./view-panels" type H = HtmlBuilder const allEnvironments = (h: H): Html => - h.span([h.Class("text-3xs text-muted-foreground/60")], ["all environments"]) + h.span([h.Class("text-3xs text-foreground-subtle")], ["all environments"]) const USAGE_STATS: ReadonlyArray<{ readonly key: keyof UsageTotals @@ -97,7 +97,7 @@ const meterRow = (h: H, label: string, fraction: number): Html => { [h.Key(label), h.Class("flex items-center gap-2 leading-none")], [ h.span( - [h.Class(cn("w-8", "shrink-0 font-mono text-3xs tracking-wider text-muted-foreground/70"))], + [h.Class(cn("w-8", "shrink-0 font-mono text-3xs tracking-wider text-foreground-subtle"))], [label], ), meter(h, { @@ -147,7 +147,7 @@ const runsOnRow = ( itemDescription( h, [[link.label, ...link.location].join(" · ")], - "truncate text-3xs text-muted-foreground/60", + "truncate text-3xs text-foreground-subtle", ), ], "gap-0 leading-tight", @@ -233,7 +233,7 @@ const KIND_ICON = new Map([ const STRIP_LIMIT = 8 const CHIP = - "inline-flex max-w-[220px] items-center gap-1.5 rounded-md border bg-card px-2 py-0.5 text-xs hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" + "inline-flex max-w-[220px] items-center gap-1.5 rounded-md border bg-card px-2 py-0.5 text-xs hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" const stripChip = (h: H, target: StripTarget, onClick: Message): Html => target.kind === "service" @@ -281,7 +281,7 @@ export const dependencyStrip = (h: H, model: Model): Html => { h.Type("button"), h.OnClick(onViewAll), h.Class( - "inline-flex items-center rounded-md border border-dashed px-2 py-0.5 text-xs text-muted-foreground hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", + "inline-flex items-center rounded-md border border-dashed px-2 py-0.5 text-xs text-muted-foreground hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", ), ], [`+${hiddenCount} more`], diff --git a/apps/web/src/page/services/detail/view-markers.ts b/apps/web/src/page/services/detail/view-markers.ts index b3d4fe192d..e1ebe20483 100644 --- a/apps/web/src/page/services/detail/view-markers.ts +++ b/apps/web/src/page/services/detail/view-markers.ts @@ -86,7 +86,7 @@ export const markersOverlay = ( h.Class( cn( "pointer-events-auto flex cursor-pointer items-center justify-center gap-1 rounded-[5px] border px-1.5 font-mono text-2xs leading-none backdrop-blur-sm transition-colors", - "border-border/60 bg-popover/85 text-muted-foreground hover:text-popover-foreground", + "border-border-subtle bg-popover/85 text-muted-foreground hover:text-popover-foreground", ), ), ], @@ -99,7 +99,7 @@ export const markersOverlay = ( h.Class( cn( "shrink-0 rounded-[3px] px-1 text-3xs tabular-nums", - "bg-muted/70 text-muted-foreground", + "bg-surface-strong text-muted-foreground", ), ), ], diff --git a/apps/web/src/page/services/detail/view-operations.ts b/apps/web/src/page/services/detail/view-operations.ts index f7748fd1b1..91c5af3648 100644 --- a/apps/web/src/page/services/detail/view-operations.ts +++ b/apps/web/src/page/services/detail/view-operations.ts @@ -47,7 +47,7 @@ const loadingState = (h: H): Html => skeleton(h, "h-3 w-12"), skeleton(h, "h-3 w-10"), skeleton(h, "h-3 w-12"), - skeleton(h, "hidden h-5 w-[120px] md:block"), + skeleton(h, "hidden h-5 w-32 md:block"), ], ), ), @@ -109,7 +109,7 @@ const operationRow = ( chartId: `ops-${op.spanName}`, values: op.sparkline.map((point) => point.count), color: context.color, - className: "ml-auto h-6 w-[120px]", + className: "ml-auto h-6 w-32", revision: 0, fillOpacity: [0.5, 0.1], }, @@ -119,7 +119,7 @@ const operationRow = ( "py-1.5 pr-3 align-middle", ), ], - "cursor-pointer group/row border-b last:border-b-0 hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", + "cursor-pointer group/row border-b last:border-b-0 hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", [ h.Key(op.spanName), h.Attribute("tabindex", "0"), @@ -163,7 +163,7 @@ const operationsTable = ( column("errorRate", "Errors"), column("p50DurationMs", "p50"), column("p95DurationMs", "p95"), - headLabel(h, ["Activity"], "w-[140px] pr-3 text-right"), + headLabel(h, ["Activity"], "w-36 pr-3 text-right"), ], "border-b", ), diff --git a/apps/web/src/page/services/detail/view-panels.ts b/apps/web/src/page/services/detail/view-panels.ts index d17476e8a1..58b22af559 100644 --- a/apps/web/src/page/services/detail/view-panels.ts +++ b/apps/web/src/page/services/detail/view-panels.ts @@ -74,7 +74,7 @@ export const topOperationsPanel = (h: H, model: Model, theme: ThemeColors | null h.Type("button"), h.OnClick(onViewAll), h.Class( - "relative flex w-full items-center gap-3 px-4 py-2 text-left hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", + "relative flex w-full items-center gap-3 px-4 py-2 text-left hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", ), ], [ @@ -120,7 +120,7 @@ export const topOperationsPanel = (h: H, model: Model, theme: ThemeColors | null chartId: `op-${op.spanName}`, values: op.sparkline.map((point) => point.count), color, - className: "h-5 w-[88px]", + className: "h-5 w-24", revision: 0, fillOpacity: [0.5, 0.1], }, diff --git a/apps/web/src/page/services/list/view-table.ts b/apps/web/src/page/services/list/view-table.ts index 4c83762e88..b3fcc13eaf 100644 --- a/apps/web/src/page/services/list/view-table.ts +++ b/apps/web/src/page/services/list/view-table.ts @@ -213,7 +213,7 @@ const serviceRow = ( "class", cn( tableRowStyles, - "cursor-pointer border-l-2 border-l-transparent hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", + "cursor-pointer border-l-2 border-l-transparent hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", health === "unhealthy" && "border-l-severity-error", ), ), @@ -430,7 +430,7 @@ const desktopTable = ( : groupServices(services, mode).flatMap(([namespace, envGroups]) => [ ...(mode === "namespace" ? [ - groupHeaderRow(h, `ns-${namespace}`, "bg-muted/50 hover:bg-muted/50", [ + groupHeaderRow(h, `ns-${namespace}`, "bg-surface-sunken hover:bg-surface-strong", [ namespaceLabel(h, namespace), h.span( [h.Class("text-xs text-muted-foreground")], @@ -448,7 +448,7 @@ const desktopTable = ( groupHeaderRow( h, `env-${namespace}-${environment}`, - "bg-muted/30 hover:bg-muted/30", + "bg-surface-sunken hover:bg-surface-strong", [ environmentBadge(h, environment), h.span( @@ -506,7 +506,7 @@ const mobileList = ( h.div( [ h.Class( - "flex items-center gap-2 border-b bg-muted/50 px-3 py-2", + "flex items-center gap-2 border-b bg-surface-sunken px-3 py-2", ), ], [ @@ -535,7 +535,7 @@ const mobileList = ( [ h.Class( cn( - "flex items-center gap-2 border-b bg-muted/30 px-3 py-2", + "flex items-center gap-2 border-b bg-surface-sunken px-3 py-2", mode === "namespace" && "pl-6", ), ), @@ -556,7 +556,7 @@ const mobileList = ( ), h.Href(serviceHref(ctx.model, service)), h.Class( - "flex min-h-11 items-center justify-between gap-3 border-b px-3 py-2.5 last:border-b-0 hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", + "flex min-h-11 items-center justify-between gap-3 border-b px-3 py-2.5 last:border-b-0 hover:bg-surface-sunken focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", ), ], [ @@ -619,7 +619,7 @@ const mobileList = ( h.span( [ h.Class( - "text-muted-foreground/60", + "text-foreground-subtle", ), ], ["P99", " "], @@ -636,7 +636,7 @@ const mobileList = ( h.span( [ h.Class( - "text-muted-foreground/60", + "text-foreground-subtle", ), ], ["Thru", " "], diff --git a/apps/web/src/page/settings/account/two-factor/view.ts b/apps/web/src/page/settings/account/two-factor/view.ts index 45ae176eaa..aceee7cc77 100644 --- a/apps/web/src/page/settings/account/two-factor/view.ts +++ b/apps/web/src/page/settings/account/two-factor/view.ts @@ -201,7 +201,7 @@ const stepContent = (h: H, model: Model, step: EnrollStep): ReadonlyArray h.div( [ h.Class( - "grid grid-cols-2 gap-1.5 rounded-md border border-border bg-muted/30 p-3 font-mono text-xs", + "grid grid-cols-2 gap-1.5 rounded-md border border-border bg-surface-sunken p-3 font-mono text-xs", ), ], step.codes.map((code) => h.span([h.Key(code)], [code])), diff --git a/apps/web/src/page/settings/audit-log/view-detail.ts b/apps/web/src/page/settings/audit-log/view-detail.ts index 2f34b4fe13..dac25d4f21 100644 --- a/apps/web/src/page/settings/audit-log/view-detail.ts +++ b/apps/web/src/page/settings/audit-log/view-detail.ts @@ -60,8 +60,8 @@ const metadataBlock = (value: unknown): string | null => { } const changeValue = (h: H, value: unknown): Html => { - if (isPlaceholder(value)) return h.span([h.Class("text-muted-foreground/70 italic")], [value.slice(1, -1)]) - if (value === undefined || value === null || value === "") return h.span([h.Class("text-muted-foreground/60")], [EMPTY_VALUE]) + if (isPlaceholder(value)) return h.span([h.Class("text-foreground-subtle italic")], [value.slice(1, -1)]) + if (value === undefined || value === null || value === "") return h.span([h.Class("text-foreground-subtle")], [EMPTY_VALUE]) return h.span([h.Class("break-all")], [formatScalar(value)]) } @@ -87,7 +87,7 @@ const changesTable = (h: H, changes: V2AuditChanges): Html => table(h, { size: "sm", className: "font-mono" }, [ tableHeader(h, [ tableRow(h, [ - tableHead(h, ["Field"], "w-[160px] font-normal"), + tableHead(h, ["Field"], "w-40 font-normal"), tableHead(h, ["Before"], "font-normal"), tableHead(h, ["After"], "font-normal"), ]), @@ -142,7 +142,7 @@ export const auditDetail = (h: H, model: Model, entry: V2AuditLogEntry, timeZone const changes = entry.changes const metadata = entry.metadata return h.div( - [h.Class("border-border/60 space-y-4 border-t px-4 py-3 @md:pl-[44px]")], + [h.Class("border-border-subtle space-y-4 border-t px-4 py-3 @md:pl-[44px]")], [ keyValueList( h, @@ -194,7 +194,7 @@ export const auditDetail = (h: H, model: Model, entry: V2AuditLogEntry, timeZone ]), keyValue(h, { wrap: true, label: "Resource" }, [ entry.resource_type === null && entry.resource_id === null - ? h.span([h.Class("text-muted-foreground/60")], [EMPTY_VALUE]) + ? h.span([h.Class("text-foreground-subtle")], [EMPTY_VALUE]) : h.span( [h.Class("flex min-w-0 flex-wrap items-center gap-1.5")], [ diff --git a/apps/web/src/page/settings/audit-log/view.ts b/apps/web/src/page/settings/audit-log/view.ts index 28bbbd0be1..3ed34c64f1 100644 --- a/apps/web/src/page/settings/audit-log/view.ts +++ b/apps/web/src/page/settings/audit-log/view.ts @@ -154,10 +154,10 @@ const dateRange = (h: H, model: Model, range: AuditDateRange, timeZone: string): h.OnClick(Message.ClickedRangePreset({ value: option.key })), h.Class( cn( - "flex h-7 items-center px-3 text-left text-xs transition-colors hover:bg-muted/50", + "flex h-7 items-center px-3 text-left text-xs transition-colors hover:bg-surface-sunken", option.key === activeKey ? "font-medium text-foreground" - : "text-foreground/80", + : "text-foreground-soft", ), ), ], @@ -170,7 +170,7 @@ const dateRange = (h: H, model: Model, range: AuditDateRange, timeZone: string): h.Type("button"), h.Class( cn( - "flex h-7 items-center px-3 text-left text-xs transition-colors hover:bg-muted/50 hover:text-foreground", + "flex h-7 items-center px-3 text-left text-xs transition-colors hover:bg-surface-sunken hover:text-foreground", range.kind === "custom" ? "font-medium text-foreground" : "text-muted-foreground", @@ -295,12 +295,12 @@ const auditRow = (h: H, model: Model, entry: V2AuditLogEntry, inputs: ViewInputs const isDenied = entry.outcome === "denied" const label = auditActionLabel(entry.action) ?? entry.action return h.div( - [h.Key(entry.id), ...(isExpanded ? [h.Class("bg-muted/10")] : [])], + [h.Key(entry.id), ...(isExpanded ? [h.Class("bg-surface-faint")] : [])], [ h.div( [ h.Class( - "hover:bg-muted/50 relative flex w-full flex-wrap items-center gap-x-3 gap-y-1 px-4 py-2.5 transition-colors @md:flex-nowrap", + "hover:bg-surface-sunken relative flex w-full flex-wrap items-center gap-x-3 gap-y-1 px-4 py-2.5 transition-colors @md:flex-nowrap", ), ], [ @@ -323,7 +323,7 @@ const auditRow = (h: H, model: Model, entry: V2AuditLogEntry, inputs: ViewInputs icon(h, "ChevronRightIcon", { size: 12, className: cn( - "text-muted-foreground/60 shrink-0 transition-transform", + "text-foreground-subtle shrink-0 transition-transform", isExpanded && "rotate-90", ), }), diff --git a/apps/web/src/page/settings/automation/view.ts b/apps/web/src/page/settings/automation/view.ts index 8a5da35abd..f1f7466327 100644 --- a/apps/web/src/page/settings/automation/view.ts +++ b/apps/web/src/page/settings/automation/view.ts @@ -68,7 +68,7 @@ const severityRule = ( const isLocked = !model.isAdmin || model.isSaving const select = model.confidenceSelects[severity] return h.div( - [h.Key(severity), h.Class("space-y-2 border-t border-border/60 pt-3")], + [h.Key(severity), h.Class("space-y-2 border-t border-border-subtle pt-3")], [ h.div( [h.Class("flex items-center justify-between gap-3")], @@ -92,7 +92,7 @@ const severityRule = ( item, })), size: "sm", - className: "w-[100px]", + className: "w-24", // `` without a renderer prints the raw value. renderValue: (value) => [value], toView: (parts) => h.div([h.Class("contents")], parts), @@ -177,7 +177,7 @@ const policyForm = (h: H, model: Model, draft: PolicyDraft, isKnownMember: boole }), destinationsBlock(h, model, draft), h.div( - [h.Class("flex justify-end border-t border-border/60 pt-3")], + [h.Class("flex justify-end border-t border-border-subtle pt-3")], [ button( h, diff --git a/apps/web/src/page/settings/billing/details/view.ts b/apps/web/src/page/settings/billing/details/view.ts index 0c4f557445..1ac0e55246 100644 --- a/apps/web/src/page/settings/billing/details/view.ts +++ b/apps/web/src/page/settings/billing/details/view.ts @@ -118,7 +118,7 @@ const taxIdsEditor = (h: H, model: Model, profile: BillingProfile): Html => ? [] : [ h.ul( - [h.Class("divide-y divide-border/60 text-sm")], + [h.Class("divide-y divide-border-subtle text-sm")], profile.taxIds.map((taxId) => h.li( [h.Key(taxId.id), h.Class("flex items-center gap-3 py-1.5")], diff --git a/apps/web/src/page/settings/billing/view-account.ts b/apps/web/src/page/settings/billing/view-account.ts index 1e5b7b5a2d..1a86433898 100644 --- a/apps/web/src/page/settings/billing/view-account.ts +++ b/apps/web/src/page/settings/billing/view-account.ts @@ -172,7 +172,7 @@ export const billedOrgsSection = (h: H, model: Model, account: BillingAccount, t [ panel( h, - { className: "divide-y divide-border/60" }, + { className: "divide-y divide-border-subtle" }, account.members.map((member) => memberRow(h, model, member, timeZone)), ), ...(AsyncData.isFailure(model.accountUsage) diff --git a/apps/web/src/page/settings/billing/view-cycle.ts b/apps/web/src/page/settings/billing/view-cycle.ts index bfa46a07ba..e0d631ae58 100644 --- a/apps/web/src/page/settings/billing/view-cycle.ts +++ b/apps/web/src/page/settings/billing/view-cycle.ts @@ -227,7 +227,7 @@ const costBreakdownView = (h: H, model: Model, spend: SpendModel): Html => { h.AriaDisabled(false), h.AriaExpanded(isOpen), h.Class( - "group flex w-full items-center gap-2 px-4 py-2.5 text-left outline-none focus-visible:bg-muted/40", + "group flex w-full items-center gap-2 px-4 py-2.5 text-left outline-none focus-visible:bg-surface-sunken", ), ...(isOpen ? [h.DataAttribute("panel-open", "")] : []), h.DataAttribute("slot", "collapsible-trigger"), @@ -264,7 +264,7 @@ const costBreakdownView = (h: H, model: Model, spend: SpendModel): Html => { ], [ h.div( - [h.Class("divide-y divide-border/60")], + [h.Class("divide-y divide-border-subtle")], costBreakdown(spend).map((line) => h.div( [ diff --git a/apps/web/src/page/settings/billing/view-plan.ts b/apps/web/src/page/settings/billing/view-plan.ts index 1aa837451d..8b0da4f92a 100644 --- a/apps/web/src/page/settings/billing/view-plan.ts +++ b/apps/web/src/page/settings/billing/view-plan.ts @@ -102,7 +102,7 @@ const planRow = (h: H, spend: SpendModel, plans: ReadonlyArray, can const activeIds = new Set(spend.addOns.map((addOn) => addOn.id)) const available = plans.filter((plan) => plan.addOn === true && !activeIds.has(plan.id)) const activeCharges = spend.charges.filter((charge) => charge.kind === "addOn") - return panel(h, { className: "divide-y divide-border/60" }, [ + return panel(h, { className: "divide-y divide-border-subtle" }, [ planLine(h, { key: "plan", name: sentenceCasePlanName(spend.planName), @@ -243,7 +243,7 @@ const customPlanPlate = (h: H, spend: SpendModel): Html => { [ eyebrow(h, {}, ["Included every cycle"]), h.p( - [h.Class("mt-2 font-mono text-2xs leading-relaxed text-foreground/80")], + [h.Class("mt-2 font-mono text-2xs leading-relaxed text-foreground-soft")], [included.length > 0 ? included : "Allotments are set on your contract."], ), ], @@ -312,7 +312,7 @@ const offerPanel = ( [ eyebrow(h, {}, ["Included every cycle"]), h.p( - [h.Class("mt-2 font-mono text-2xs leading-relaxed text-foreground/80")], + [h.Class("mt-2 font-mono text-2xs leading-relaxed text-foreground-soft")], [ includedRun(plan), ...(retention === undefined diff --git a/apps/web/src/page/settings/billing/view-records.ts b/apps/web/src/page/settings/billing/view-records.ts index 2ef4ee9a70..491b6e3fcf 100644 --- a/apps/web/src/page/settings/billing/view-records.ts +++ b/apps/web/src/page/settings/billing/view-records.ts @@ -120,7 +120,7 @@ const invoiceRow = ( const invoicesSkeleton = (h: H): Html => skeletonList(h, { rows: 3, - className: "gap-0 divide-y divide-border/60", + className: "gap-0 divide-y divide-border-subtle", renderRow: () => h.div( [h.Class("flex items-center gap-4 py-2.5")], @@ -244,7 +244,7 @@ export const invoicesSection = (h: H, model: Model, timeZone: string): Html => { const ROW = "py-2.5 px-4 text-sm" -const muted = (h: H, text: string): Html => h.span([h.Class("text-muted-foreground/70")], [text]) +const muted = (h: H, text: string): Html => h.span([h.Class("text-foreground-subtle")], [text]) const detailsSkeleton = (h: H): Html => panel( @@ -286,7 +286,7 @@ export const detailsSection = (h: H, model: Model): Html => { return panel(h, {}, [ keyValueList( h, - { layout: "grid", className: "gap-x-8 gap-y-0 divide-y divide-border/60 text-sm" }, + { layout: "grid", className: "gap-x-8 gap-y-0 divide-y divide-border-subtle text-sm" }, [ keyValue(h, { label: "Bill to", className: ROW }, [ details.name !== undefined && details.name !== null && details.name !== "" diff --git a/apps/web/src/page/settings/billing/view-usage.ts b/apps/web/src/page/settings/billing/view-usage.ts index 19cfcaab1c..6638befd7a 100644 --- a/apps/web/src/page/settings/billing/view-usage.ts +++ b/apps/web/src/page/settings/billing/view-usage.ts @@ -282,7 +282,7 @@ const featureRow = ( ), ]), ], - cn(isEditing && "bg-muted/40"), + cn(isEditing && "bg-surface-sunken"), [h.Key(feature.featureId)], ) } diff --git a/apps/web/src/page/settings/data-platform/view.ts b/apps/web/src/page/settings/data-platform/view.ts index c92485ebcf..e675055b9f 100644 --- a/apps/web/src/page/settings/data-platform/view.ts +++ b/apps/web/src/page/settings/data-platform/view.ts @@ -188,7 +188,7 @@ const connectionPanel = ( h.div( [ h.Class( - "bg-muted/30 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t px-4 py-3", + "bg-surface-sunken flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t px-4 py-3", ), ], [ @@ -298,7 +298,7 @@ const diffRow = (h: H, model: Model, entry: ClickHouseTableDiffEntry): Html => { h.AriaExpanded(isExpanded), h.OnClick(Message.ToggledDrift({ name: entry.name })), h.Class( - "hover:bg-muted/50 flex w-full items-center gap-2 px-3 py-2 text-left text-xs transition-colors", + "hover:bg-surface-sunken flex w-full items-center gap-2 px-3 py-2 text-left text-xs transition-colors", ), ], [ @@ -415,7 +415,7 @@ const schemaDiff = (h: H, model: Model, diff: OrgClickHouseSchemaDiffResponse): h.AriaExpanded(model.showUpToDate), h.OnClick(Message.ToggledUpToDate()), h.Class( - "hover:bg-muted/50 flex w-full items-center gap-2 border-b px-3 py-2 text-left text-xs transition-colors", + "hover:bg-surface-sunken flex w-full items-center gap-2 border-b px-3 py-2 text-left text-xs transition-colors", ), ], [ @@ -611,7 +611,7 @@ const schemaSection = (h: H, model: Model, settings: OrgClickHouseSettingsRespon h.div( [ h.Class( - "bg-muted/30 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t px-4 py-3", + "bg-surface-sunken flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t px-4 py-3", ), ], [ diff --git a/apps/web/src/page/settings/ingestion/view-ingest-rules.ts b/apps/web/src/page/settings/ingestion/view-ingest-rules.ts index 7f4b4b5387..e0e5c0ce44 100644 --- a/apps/web/src/page/settings/ingestion/view-ingest-rules.ts +++ b/apps/web/src/page/settings/ingestion/view-ingest-rules.ts @@ -112,7 +112,7 @@ const ruleRow = ( h.Key(rule.id), h.Class( cn( - "hover:bg-muted/50 flex items-center gap-3 border-t px-4 py-2.5 transition-colors", + "hover:bg-surface-sunken flex items-center gap-3 border-t px-4 py-2.5 transition-colors", !rule.enabled && "text-muted-foreground", ), ), diff --git a/apps/web/src/page/settings/ingestion/view-keys.ts b/apps/web/src/page/settings/ingestion/view-keys.ts index accf0990a7..8c75103b29 100644 --- a/apps/web/src/page/settings/ingestion/view-keys.ts +++ b/apps/web/src/page/settings/ingestion/view-keys.ts @@ -83,7 +83,7 @@ export const credentialRow = (h: H, options: CredentialRowOptions): Html => { return h.div( [h.Class("flex flex-wrap items-center gap-x-3 gap-y-1.5 px-4 py-3 sm:flex-nowrap")], [ - h.span([h.Class("w-full shrink-0 text-sm sm:w-[120px]")], [label]), + h.span([h.Class("w-full shrink-0 text-sm sm:w-32")], [label]), eyebrow( h, { variant: "mono", className: cn("hidden w-14 shrink-0 sm:block", options.badgeClass) }, @@ -96,7 +96,7 @@ export const credentialRow = (h: H, options: CredentialRowOptions): Html => { ...(options.description ? [ h.span( - [h.Class("font-prose text-muted-foreground/70 text-2xs leading-3.5")], + [h.Class("font-prose text-foreground-subtle text-2xs leading-3.5")], [options.description], ), ] @@ -203,12 +203,12 @@ export const ingestKeyRows = (h: H, model: Model): ReadonlyArray => { }), ] return [ - row("public", "Public key", "Client", "text-info", "For browser and client-side telemetry SDKs"), + row("public", "Public key", "Client", "text-severity-debug", "For browser and client-side telemetry SDKs"), row( "private", "Private key", "Server", - "text-warning", + "text-severity-warn", "For server-side ingestion and backend services", ), ] diff --git a/apps/web/src/page/settings/ingestion/view-rules.ts b/apps/web/src/page/settings/ingestion/view-rules.ts index cc07e81e34..c1ac9a365d 100644 --- a/apps/web/src/page/settings/ingestion/view-rules.ts +++ b/apps/web/src/page/settings/ingestion/view-rules.ts @@ -119,7 +119,7 @@ const recommendationActions = (h: H, model: Model, issue: V2Recommendation): Rea const recommendationRow = (h: H, model: Model, issue: V2Recommendation): Html => { const kind = KIND_TAG[issue.kind] return h.div( - [h.Key(issue.id), h.Class("hover:bg-muted/50 flex items-start gap-3 px-4 py-3 transition-colors")], + [h.Key(issue.id), h.Class("hover:bg-surface-sunken flex items-start gap-3 px-4 py-3 transition-colors")], [ eyebrow(h, { variant: "mono", className: cn("w-20 shrink-0 pt-0.5", kind.className) }, [ kind.label, @@ -245,7 +245,7 @@ const mappingRow = (h: H, model: Model, mapping: V2AttributeMapping): Html => { h.Key(mapping.id), h.Class( cn( - "hover:bg-muted/50 flex items-center gap-3 border-t px-4 py-2.5 transition-colors", + "hover:bg-surface-sunken flex items-center gap-3 border-t px-4 py-2.5 transition-colors", !mapping.enabled && "text-muted-foreground", ), ), diff --git a/apps/web/src/page/settings/keys/view-reference.ts b/apps/web/src/page/settings/keys/view-reference.ts index 162437ecce..88c5909aa2 100644 --- a/apps/web/src/page/settings/keys/view-reference.ts +++ b/apps/web/src/page/settings/keys/view-reference.ts @@ -107,7 +107,7 @@ const scopes = (h: H, isOpen: boolean): Html => h.AriaDisabled(false), h.AriaExpanded(isOpen), h.Class( - "group/scopes hover:bg-muted/50 flex w-full items-center gap-2 px-4 py-3 text-left", + "group/scopes hover:bg-surface-sunken flex w-full items-center gap-2 px-4 py-3 text-left", ), ...(isOpen ? [h.DataAttribute("panel-open", "")] : []), h.DataAttribute("slot", "collapsible-trigger"), @@ -215,7 +215,7 @@ export const oauthPointer = (h: H): Html => h.p( [ h.Class( - "w-full rounded-md border border-dashed px-4 py-3 font-prose text-sm text-muted-foreground", + "w-full rounded-md border border-dashed p-4 font-prose text-sm text-muted-foreground", ), ], [ diff --git a/apps/web/src/page/settings/keys/view-table.ts b/apps/web/src/page/settings/keys/view-table.ts index fa44baa268..58e7c996e0 100644 --- a/apps/web/src/page/settings/keys/view-table.ts +++ b/apps/web/src/page/settings/keys/view-table.ts @@ -37,15 +37,15 @@ const TYPE_BADGE = { const COL = { name: "w-0 min-w-[180px] flex-1", - access: "hidden w-[150px] shrink-0 @xl:block", - createdBy: "hidden w-[140px] shrink-0 @min-[820px]:block", - lastUsed: "hidden w-[80px] shrink-0 @2xl:block", - expires: "w-[100px] shrink-0", + access: "hidden w-36 shrink-0 @xl:block", + createdBy: "hidden w-36 shrink-0 @min-[820px]:block", + lastUsed: "hidden w-20 shrink-0 @2xl:block", + expires: "w-24 shrink-0", menu: "w-7 shrink-0", } const ROW_CLASS = - "flex items-center gap-4 border-b border-border/60 px-4 py-3 transition-colors last:border-0" + "flex items-center gap-4 border-b border-border-subtle px-4 py-3 transition-colors last:border-0" const typeBadge = (h: H, type: KeyType): Html => badge(h, { variant: TYPE_BADGE[type], size: "sm", mono: true }, [KEY_TYPE_LABELS[type]]) @@ -111,7 +111,7 @@ const apiRow = ( : []), ] return h.div( - [h.Key(row.id), h.Class(cn(ROW_CLASS, isDead ? "opacity-60" : "hover:bg-muted/50"))], + [h.Key(row.id), h.Class(cn(ROW_CLASS, isDead ? "opacity-60" : "hover:bg-surface-sunken"))], [ h.div( [h.Class(cn(COL.name, "flex flex-col gap-1"))], @@ -142,7 +142,7 @@ const apiRow = ( ), truncatedText(h, { text: keyAccessSummary(row), - className: cn(COL.access, "text-foreground/80 text-2xs"), + className: cn(COL.access, "text-foreground-soft text-2xs"), }), h.div( [h.Class(COL.createdBy)], @@ -152,7 +152,7 @@ const apiRow = ( [ truncatedText(h, { text: key.created_by_email ?? EMPTY_VALUE, - className: "text-foreground/80", + className: "text-foreground-soft", }), h.span([h.Class("text-muted-foreground truncate")], [formatDate(key.created_at)]), ], @@ -211,10 +211,10 @@ export const keysTable = (h: H, model: Model, rows: ReadonlyArray, input const DEVICE_COL = { name: "w-0 min-w-[180px] flex-1", - owner: "hidden w-[180px] shrink-0 @xl:block", - created: "hidden w-[110px] shrink-0 @2xl:block", - lastUsed: "hidden w-[80px] shrink-0 @lg:block", - expires: "w-[100px] shrink-0", + owner: "hidden w-44 shrink-0 @xl:block", + created: "hidden w-28 shrink-0 @2xl:block", + lastUsed: "hidden w-20 shrink-0 @lg:block", + expires: "w-24 shrink-0", menu: "w-7 shrink-0", } @@ -239,7 +239,7 @@ const deviceRow = ( ] : [] return h.div( - [h.Key(row.id), h.Class(cn(ROW_CLASS, "hover:bg-muted/50"))], + [h.Key(row.id), h.Class(cn(ROW_CLASS, "hover:bg-surface-sunken"))], [ h.div( [h.Class(cn(DEVICE_COL.name, "flex min-w-0 items-center gap-2"))], @@ -250,7 +250,7 @@ const deviceRow = ( ), truncatedText(h, { text: key.created_by_email ?? EMPTY_VALUE, - className: cn(DEVICE_COL.owner, "text-foreground/80 text-2xs"), + className: cn(DEVICE_COL.owner, "text-foreground-soft text-2xs"), }), h.span( [h.Class(cn(DEVICE_COL.created, "text-muted-foreground truncate text-2xs"))], diff --git a/apps/web/src/page/settings/mcp/view-tools.ts b/apps/web/src/page/settings/mcp/view-tools.ts index ecff413426..9f9b4c7f2d 100644 --- a/apps/web/src/page/settings/mcp/view-tools.ts +++ b/apps/web/src/page/settings/mcp/view-tools.ts @@ -57,7 +57,7 @@ const toolGroup = (h: H, group: McpToolGroup, isOpen: boolean, isShowingAll: boo ...(isOpen ? [h.AriaControls(panelId)] : []), h.AriaDisabled(false), h.AriaExpanded(isOpen), - h.Class("flex w-full items-center gap-2 px-4 py-2.5 text-left text-sm hover:bg-muted/50"), + h.Class("flex w-full items-center gap-2 px-4 py-2.5 text-left text-sm hover:bg-surface-sunken"), ...(isOpen ? [h.DataAttribute("panel-open", "")] : []), h.DataAttribute("slot", "collapsible-trigger"), h.Tabindex(0), diff --git a/apps/web/src/page/settings/members/view.ts b/apps/web/src/page/settings/members/view.ts index 38c83ef51c..2256a9b35e 100644 --- a/apps/web/src/page/settings/members/view.ts +++ b/apps/web/src/page/settings/members/view.ts @@ -236,7 +236,7 @@ const memberRows = (h: H, model: Model, member: MemberRow, inputs: Inputs): Read [h.Colspan(columnCount)], ), ], - "border-l-2 border-l-primary bg-muted/40 hover:bg-muted/40", + "border-l-2 border-l-primary bg-surface-sunken hover:bg-surface-strong", [h.Key(`${member.id}-confirm`)], ), ] diff --git a/apps/web/src/page/settings/setup-health/view.ts b/apps/web/src/page/settings/setup-health/view.ts index 657a39c82a..790d30155b 100644 --- a/apps/web/src/page/settings/setup-health/view.ts +++ b/apps/web/src/page/settings/setup-health/view.ts @@ -131,7 +131,7 @@ const findingRow = (h: H, check: V2SetupAuditCheck): Html => { [ h.span([h.Class("text-sm font-medium")], [check.title]), h.span( - [h.Class("text-muted-foreground/70 text-2xs")], + [h.Class("text-foreground-subtle text-2xs")], [CATEGORY_LABEL[check.category]], ), ], @@ -145,7 +145,7 @@ const findingRow = (h: H, check: V2SetupAuditCheck): Html => { ), ]), h.p( - [h.Class("text-muted-foreground/80 text-xs leading-relaxed")], + [h.Class("text-foreground-subtle text-xs leading-relaxed")], [check.fix_hint], ), ...(check.affected.length === 0 @@ -162,7 +162,7 @@ const findingRow = (h: H, check: V2SetupAuditCheck): Html => { h.span( [ h.Class( - "text-muted-foreground/70 text-2xs", + "text-foreground-subtle text-2xs", ), ], [ @@ -205,7 +205,7 @@ const summaryPanel = (h: H, audit: V2SetupAudit, isRefreshing: boolean, inputs: ), h.div([h.Class("grow")], []), h.span( - [h.Class("text-muted-foreground/70 text-2xs")], + [h.Class("text-foreground-subtle text-2xs")], [ "Last run ", relativeTime(h, { @@ -326,7 +326,7 @@ const passingDisclosure = ( h.AriaDisabled(false), h.AriaExpanded(isOpen), h.Class( - "group hover:bg-muted/50 flex w-full items-center gap-3 px-4 py-3 text-left transition-colors", + "group hover:bg-surface-sunken flex w-full items-center gap-3 px-4 py-3 text-left transition-colors", ), ...(isOpen ? [h.DataAttribute("panel-open", "")] : []), h.DataAttribute("slot", "collapsible-trigger"), @@ -393,7 +393,7 @@ const passingDisclosure = ( : icon(h, "CircleInfoIcon", { size: 14, className: - "text-muted-foreground/60 shrink-0", + "text-foreground-subtle shrink-0", }), h.span( [h.Class("min-w-0 flex-1 text-xs")], @@ -414,7 +414,7 @@ const passingDisclosure = ( h.span( [ h.Class( - "text-muted-foreground/70 text-2xs", + "text-foreground-subtle text-2xs", ), ], [CATEGORY_LABEL[check.category]], diff --git a/apps/web/src/page/sign-in/view.ts b/apps/web/src/page/sign-in/view.ts index 5d255354e7..3273701e44 100644 --- a/apps/web/src/page/sign-in/view.ts +++ b/apps/web/src/page/sign-in/view.ts @@ -78,7 +78,7 @@ export const view = Submodel.defineView((model, h) => [h.Class("space-y-2")], [ h.h1( - [h.Class("font-display font-[650] text-[30px] leading-[1.1] tracking-tight")], + [h.Class("font-display font-semibold text-3xl leading-[1.1] tracking-tight")], ["Sign in to Maple"], ), h.p( diff --git a/apps/web/src/page/sources/kit/rules-view.ts b/apps/web/src/page/sources/kit/rules-view.ts index 0746c3d9e0..3f1328dac2 100644 --- a/apps/web/src/page/sources/kit/rules-view.ts +++ b/apps/web/src/page/sources/kit/rules-view.ts @@ -62,8 +62,8 @@ const signalCard =

( h.Id(Checkbox.labelId(inputId)), h.Class( cn( - "flex cursor-pointer items-start gap-2.5 rounded-md border px-3 py-2.5 transition-colors", - isChecked ? "border-primary/60 bg-primary/[0.06]" : "hover:bg-muted/50", + "flex cursor-pointer items-start gap-2.5 rounded-md border p-3 transition-colors", + isChecked ? "border-primary/60 bg-primary/[0.06]" : "hover:bg-surface-sunken", ), ), ], diff --git a/apps/web/src/page/sources/kit/setup.ts b/apps/web/src/page/sources/kit/setup.ts index 0ed8d68bf5..3b3c137727 100644 --- a/apps/web/src/page/sources/kit/setup.ts +++ b/apps/web/src/page/sources/kit/setup.ts @@ -115,7 +115,7 @@ export const view =

(h: HtmlBuilder

, config: SetupViewConfig

): Html => eyebrow(h, {}, ["Header"]), token === null ? h.div( - [h.Class("bg-muted/40 text-muted-foreground rounded-md border px-3 py-2 font-mono text-xs")], + [h.Class("bg-surface-sunken text-muted-foreground rounded-md border px-3 py-2 font-mono text-xs")], ["Authorization: Bearer ", shown], ) : copyableField(h, { diff --git a/apps/web/src/page/sources/list/view.ts b/apps/web/src/page/sources/list/view.ts index ffbdc2a774..35331b22b2 100644 --- a/apps/web/src/page/sources/list/view.ts +++ b/apps/web/src/page/sources/list/view.ts @@ -206,7 +206,7 @@ const availableStrip = (h: H, sources: ReadonlyArray): Html | null => const missing = PULL_SOURCE_PLATFORMS.filter((platform: PullSourcePlatform) => !present.has(platform)) if (missing.length === 0) return null return h.div( - [h.Class("flex flex-wrap items-center gap-2 rounded-md border border-dashed px-4 py-3")], + [h.Class("flex flex-wrap items-center gap-2 rounded-md border border-dashed p-4")], [ h.span([h.Class("text-muted-foreground mr-auto text-xs")], ["Pull more data in without an SDK"]), ...missing.map((platform) => diff --git a/apps/web/src/page/sources/new/view-picker.ts b/apps/web/src/page/sources/new/view-picker.ts index 7c5d9c9fbd..851530941f 100644 --- a/apps/web/src/page/sources/new/view-picker.ts +++ b/apps/web/src/page/sources/new/view-picker.ts @@ -49,7 +49,7 @@ const card = ( h.Class( cn( "group bg-card flex items-center gap-3 rounded-md border px-3 py-3 text-left transition-colors", - "hover:bg-muted/50 focus-visible:ring-ring outline-none focus-visible:ring-2", + "hover:bg-surface-sunken focus-visible:ring-ring outline-none focus-visible:ring-2", ), ), ], diff --git a/apps/web/src/page/sources/new/view-trail.ts b/apps/web/src/page/sources/new/view-trail.ts index 09e59b7dc1..a44a9dbf9f 100644 --- a/apps/web/src/page/sources/new/view-trail.ts +++ b/apps/web/src/page/sources/new/view-trail.ts @@ -66,7 +66,7 @@ const ITEM_CLASS = { done: "text-muted-foreground", current: "text-foreground border-primary border-b pb-0.5 font-medium", next: "text-muted-foreground", - blocked: "text-warning border-warning border-b pb-0.5 font-medium", + blocked: "text-severity-warn border-severity-warn border-b pb-0.5 font-medium", } satisfies Record const item = (h: H, entry: TrailItem): Html => @@ -77,9 +77,9 @@ const item = (h: H, entry: TrailItem): Html => ], [ ...(entry.state === "done" - ? [icon(h, "CheckIcon", { size: 12, className: "text-success" })] + ? [icon(h, "CheckIcon", { size: 12, className: "text-severity-info" })] : entry.state === "blocked" - ? [icon(h, "AlertWarningIcon", { size: 12, className: "text-warning" })] + ? [icon(h, "AlertWarningIcon", { size: 12, className: "text-severity-warn" })] : []), entry.label, ], @@ -94,7 +94,7 @@ export const trail = (h: H, model: Model): Html => : [ // An arrow, not a slash: the steps are a flow, not a path back up. h.li( - [h.AriaHidden(true), h.Class("inline-flex text-muted-foreground/60")], + [h.AriaHidden(true), h.Class("inline-flex text-foreground-subtle")], [icon(h, "ArrowRightIcon", { size: 12 })], ), item(h, entry), diff --git a/apps/web/src/page/traces/detail/span-panel/attributes.ts b/apps/web/src/page/traces/detail/span-panel/attributes.ts index 29c55abb53..4f929a28f3 100644 --- a/apps/web/src/page/traces/detail/span-panel/attributes.ts +++ b/apps/web/src/page/traces/detail/span-panel/attributes.ts @@ -26,7 +26,7 @@ const filterAction = (h: H, label: string, onClick: Message, text: string): Html const commitShaValue = (h: H, id: string, value: string): Html => { const className = cn( "cursor-pointer", - "-mx-0.5 cursor-pointer break-all rounded px-0.5 transition-colors hover:bg-muted/50", + "-mx-0.5 cursor-pointer break-all rounded-sm px-0.5 transition-colors hover:bg-surface-sunken", ) const onClick = h.OnClick(Message.ClickedCopy({ id, text: value })) return FULL_SHA.test(value) @@ -53,7 +53,7 @@ const jsonValue = (h: H, model: Model, id: string, value: string): Html => { h.button( [ h.Class( - "flex items-start gap-1 w-full text-left font-mono text-xs break-all cursor-pointer hover:bg-muted/50 rounded px-0.5 -mx-0.5 transition-colors", + "flex items-start gap-1 w-full text-left font-mono text-xs break-all cursor-pointer hover:bg-surface-sunken rounded-sm px-0.5 -mx-0.5 transition-colors", ), h.Title(isOpen ? "Collapse" : "Expand JSON"), h.Type("button"), @@ -74,7 +74,7 @@ const jsonValue = (h: H, model: Model, id: string, value: string): Html => { h.div( [ h.Class( - "group/json relative mt-1 overflow-hidden rounded-md border bg-muted/30", + "group/json relative mt-1 overflow-hidden rounded-md border bg-surface-sunken", ), ], [ @@ -94,7 +94,7 @@ const jsonValue = (h: H, model: Model, id: string, value: string): Html => { iconSize: 10, tooltipId: `${id}:json-tooltip`, className: - "absolute top-1 right-1 border-border/60 bg-background/80 opacity-0 backdrop-blur-sm transition-opacity focus-visible:opacity-100 group-hover/json:opacity-100 pointer-coarse:opacity-100", + "absolute top-1 right-1 border-border-subtle bg-background/80 opacity-0 backdrop-blur-sm transition-opacity focus-visible:opacity-100 group-hover/json:opacity-100 pointer-coarse:opacity-100", }), ], ), @@ -144,7 +144,7 @@ const attributeRow = (h: H, model: Model, row: RowInput): Html => { return h.div( [ h.Class( - "group/attr grid grid-cols-[minmax(7rem,38%)_1fr] items-start gap-x-3 px-2 py-1 transition-colors hover:bg-muted/50", + "group/attr grid grid-cols-[minmax(7rem,38%)_1fr] items-start gap-x-3 px-2 py-1 transition-colors hover:bg-surface-sunken", ), ], [ @@ -203,7 +203,7 @@ const attributeRow = (h: H, model: Model, row: RowInput): Html => { const pick = (row: RowInput) => ({ scope: row.scope, key: row.attrKey, value: row.value }) const heading = (h: H, title: string): Html => - h.h4([h.Class("text-xs font-medium tracking-wide text-foreground/70")], [title]) + h.h4([h.Class("text-xs font-medium tracking-wide text-foreground-soft")], [title]) /** `AttributesTable` without search or namespace grouping (the span panel uses neither). */ const attributesTable = ( @@ -221,7 +221,7 @@ const attributesTable = ( [ heading(h, title), h.div( - [h.Class("divide-y divide-border/60 overflow-hidden rounded-md border")], + [h.Class("divide-y divide-border-subtle overflow-hidden rounded-md border")], entries.map(([attrKey, value]) => attributeRow(h, model, { scope, attrKey, value, isFilterable }), ), @@ -244,7 +244,7 @@ const genAiSection = ( [ heading(h, "AI attributes"), h.div( - [h.Class("divide-y divide-border/60 overflow-hidden rounded-md border")], + [h.Class("divide-y divide-border-subtle overflow-hidden rounded-md border")], groups.map((group) => h.div( [], @@ -252,7 +252,7 @@ const genAiSection = ( h.div( [ h.Class( - "px-1.5 py-1.5 text-2xs font-semibold tracking-wide text-foreground/80", + "px-1.5 py-1.5 text-2xs font-semibold tracking-wide text-foreground-soft", ), ], [group.label], @@ -260,7 +260,7 @@ const genAiSection = ( h.div( [ h.Class( - "divide-y divide-border/60 border-t border-border/60 bg-muted/15", + "divide-y divide-border-subtle border-t border-border-subtle bg-surface-faint", ), ], group.fields.map((field) => diff --git a/apps/web/src/page/traces/detail/span-panel/copy.ts b/apps/web/src/page/traces/detail/span-panel/copy.ts index e6eb0b7fc9..ba68e21f59 100644 --- a/apps/web/src/page/traces/detail/span-panel/copy.ts +++ b/apps/web/src/page/traces/detail/span-panel/copy.ts @@ -55,8 +55,8 @@ export const copyableValue = ( h.AriaLabel(`Copy ${options.label ?? "value"}`), h.Class( cn( - "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors", - status === "idle" && "hover:bg-muted/50", + "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors", + status === "idle" && "hover:bg-surface-sunken", status === "copied" && "bg-severity-info/20", status === "error" && "bg-severity-error/20", options.className, diff --git a/apps/web/src/page/traces/detail/span-panel/error-section.ts b/apps/web/src/page/traces/detail/span-panel/error-section.ts index 9d967d7d9b..58dd0b56af 100644 --- a/apps/web/src/page/traces/detail/span-panel/error-section.ts +++ b/apps/web/src/page/traces/detail/span-panel/error-section.ts @@ -35,7 +35,7 @@ export const errorSection = (h: H, model: Model, input: ErrorSectionInput): Html [ h.Class( cn( - "mx-3 my-2 rounded-md border border-severity-error/25 bg-severity-error/4 px-3 py-2.5", + "mx-3 my-2 rounded-md border border-severity-error/25 bg-severity-error/4 p-3", input.className, ), ), @@ -51,7 +51,7 @@ export const errorSection = (h: H, model: Model, input: ErrorSectionInput): Html : [ h.span( [ - h.Class("min-w-0 truncate font-mono text-2xs text-foreground/80"), + h.Class("min-w-0 truncate font-mono text-2xs text-foreground-soft"), h.Title(input.badge), ], [input.badge], @@ -62,7 +62,7 @@ export const errorSection = (h: H, model: Model, input: ErrorSectionInput): Html h.span( [ h.Class( - "flex shrink-0 items-center gap-1 rounded border border-severity-error/25 px-1 py-px font-mono text-4xs text-severity-error/70 uppercase", + "flex shrink-0 items-center gap-1 rounded-sm border border-severity-error/25 px-1 py-px font-mono text-4xs text-severity-error/70 uppercase", ), h.Title("JSON payload"), ], @@ -83,7 +83,7 @@ export const errorSection = (h: H, model: Model, input: ErrorSectionInput): Html iconSize: 12, tooltipId: "span-panel-error-prompt", className: - "ml-auto size-5 shrink-0 rounded text-severity-error/70 hover:bg-severity-error/10 hover:text-severity-error sm:size-5", + "ml-auto size-5 shrink-0 rounded-sm text-severity-error/70 hover:bg-severity-error/10 hover:text-severity-error sm:size-5", }), ], ), @@ -92,7 +92,7 @@ export const errorSection = (h: H, model: Model, input: ErrorSectionInput): Html h.AriaLabel("Copy error message"), h.Class( cn( - "mt-1.5 block w-full cursor-copy rounded text-left font-mono text-2xs text-foreground/90 leading-relaxed", + "mt-1.5 block w-full cursor-copy rounded-sm text-left font-mono text-2xs text-foreground-soft leading-relaxed", "transition-colors duration-150 hover:text-foreground motion-reduce:transition-none", "data-[copy-status=copied]:text-severity-info", ), @@ -135,7 +135,7 @@ export const errorSection = (h: H, model: Model, input: ErrorSectionInput): Html [ h.AriaExpanded(model.isErrorExpanded), h.Class( - "mt-1 rounded text-2xs text-severity-error/70 hover:text-severity-error", + "mt-1 rounded-sm text-2xs text-severity-error/70 hover:text-severity-error", ), h.Type("button"), h.OnClick(Message.ToggledErrorExpanded()), diff --git a/apps/web/src/page/traces/detail/span-panel/events.ts b/apps/web/src/page/traces/detail/span-panel/events.ts index 85d2ff9e0e..4ee6f04f17 100644 --- a/apps/web/src/page/traces/detail/span-panel/events.ts +++ b/apps/web/src/page/traces/detail/span-panel/events.ts @@ -86,7 +86,7 @@ const stackTrace = (h: H, model: Model, eventId: string, stacktrace: string): Ht h.pre( [ h.Class( - "mt-1 max-h-80 overflow-auto rounded-sm bg-muted/40 p-2 font-mono text-3xs leading-relaxed", + "mt-1 max-h-80 overflow-auto rounded-sm bg-surface-sunken p-2 font-mono text-3xs leading-relaxed", ), ], [stacktrace], diff --git a/apps/web/src/page/traces/detail/span-panel/view-tabs.ts b/apps/web/src/page/traces/detail/span-panel/view-tabs.ts index 1b400361f2..2d77c26b14 100644 --- a/apps/web/src/page/traces/detail/span-panel/view-tabs.ts +++ b/apps/web/src/page/traces/detail/span-panel/view-tabs.ts @@ -133,7 +133,7 @@ export const tabList = (h: H, model: Model, values: ReadonlyArray): Ht const logEntry = (h: H, log: LogEntry, timeZone: string): Html => h.button( - [h.Class("block w-full p-2 text-left hover:bg-muted/50 cursor-pointer"), h.Type("button")], + [h.Class("block w-full p-2 text-left hover:bg-surface-sunken cursor-pointer"), h.Type("button")], [ h.div( [h.Class("flex items-center gap-2 text-3xs text-muted-foreground mb-1")], diff --git a/apps/web/src/page/traces/detail/timeline/view-chrome.ts b/apps/web/src/page/traces/detail/timeline/view-chrome.ts index 1827441c54..b8cc7fd3b3 100644 --- a/apps/web/src/page/traces/detail/timeline/view-chrome.ts +++ b/apps/web/src/page/traces/detail/timeline/view-chrome.ts @@ -20,12 +20,12 @@ type H = HtmlBuilder export const searchBar = (h: H, model: Model, matchCount: number, totalCount: number): Html => h.div( - [h.Class("flex items-center gap-2 border-b border-border bg-muted/20 px-3 py-1.5")], + [h.Class("flex items-center gap-2 border-b border-border bg-surface-faint px-3 py-1.5")], [ icon(h, "MagnifierIcon", { size: 14, className: "text-muted-foreground shrink-0" }), h.input([ h.Class( - "min-w-0 flex-1 bg-transparent font-mono text-xs text-foreground outline-none placeholder:text-muted-foreground/50 pointer-coarse:text-base", + "min-w-0 flex-1 bg-transparent font-mono text-xs text-foreground outline-none placeholder:text-foreground-faint pointer-coarse:text-base", ), h.Placeholder("Search spans…"), h.Type("text"), @@ -168,7 +168,7 @@ export type ToolbarIds = Readonly<{ export const toolbar = (h: H, model: Model, visibleSpanCount: number, ids: ToolbarIds): Html => h.div( - [h.Class("flex items-center gap-2 border-b border-border bg-muted/30 px-3 py-1.5 shrink-0")], + [h.Class("flex items-center gap-2 border-b border-border bg-surface-sunken px-3 py-1.5 shrink-0")], [ depthControls(h, { onCollapseOneLevel: Message.ClickedCollapseOneLevel(), @@ -255,7 +255,7 @@ export const minimap = (h: H, model: Model): Html => { return h.div( [ h.Class( - "relative overflow-hidden border-b border-border bg-muted/10 cursor-crosshair select-none touch-none", + "relative overflow-hidden border-b border-border bg-surface-faint cursor-crosshair select-none touch-none", ), h.Style({ height: `${MINIMAP_HEIGHT}px` }), h.Title( diff --git a/apps/web/src/page/traces/detail/timeline/view-footer.ts b/apps/web/src/page/traces/detail/timeline/view-footer.ts index e382483922..01dee50333 100644 --- a/apps/web/src/page/traces/detail/timeline/view-footer.ts +++ b/apps/web/src/page/traces/detail/timeline/view-footer.ts @@ -17,19 +17,19 @@ export const footer = (h: H, model: Model): Html => h.div( [ h.Class( - "flex shrink-0 items-center gap-3 border-t border-border bg-muted/30 px-2 py-1.5 text-3xs text-muted-foreground @min-[560px]/timeline:px-3", + "flex shrink-0 items-center gap-3 border-t border-border bg-surface-sunken px-2 py-1.5 text-3xs text-muted-foreground @min-[560px]/timeline:px-3", ), ], [ h.div( - [h.Class("hidden shrink-0 items-center gap-3 text-foreground/30 @min-[560px]/timeline:flex")], + [h.Class("hidden shrink-0 items-center gap-3 text-foreground-faint @min-[560px]/timeline:flex")], [ hint(h, "Drag", "zoom"), hint(h, "W A S D", "navigate"), hint(h, "/", "search"), h.button( [ - h.Class("hover:text-foreground/70"), + h.Class("hover:text-foreground-soft"), h.Type("button"), h.OnClick(Message.ClickedShortcuts()), ], diff --git a/apps/web/src/page/traces/detail/timeline/view-row.ts b/apps/web/src/page/traces/detail/timeline/view-row.ts index ea5a0b7d06..33df86ec3f 100644 --- a/apps/web/src/page/traces/detail/timeline/view-row.ts +++ b/apps/web/src/page/traces/detail/timeline/view-row.ts @@ -148,7 +148,7 @@ const labelCell = (h: H, bar: Bar, state: RowState, durationLabel: string): Html attr( h, cn( - "truncate font-mono font-medium text-foreground/90", + "truncate font-mono font-medium text-foreground-soft", bar.isError && TONE_TEXT.crit, bar.span.isMissing === true && "italic text-muted-foreground", ), @@ -189,7 +189,7 @@ const labelCell = (h: H, bar: Bar, state: RowState, durationLabel: string): Html [ attr( h, - "flex items-center gap-0.5 shrink-0 text-4xs text-muted-foreground/70", + "flex items-center gap-0.5 shrink-0 text-4xs text-foreground-subtle", ), h.Title(countLabel(bar.childCount, "hidden span")), ], @@ -298,14 +298,14 @@ const timelineCell = (h: H, bar: Bar, state: RowState, durationLabel: string): H [attr(h, "flex min-w-0 flex-1 items-center overflow-hidden")], [ h.span( - [attr(h, cn("hidden truncate px-1.5 text-foreground/90", fit.inside))], + [attr(h, cn("hidden truncate px-1.5 text-foreground-soft", fit.inside))], [bar.span.spanName], ), h.span( [ attr( h, - "ml-auto hidden shrink-0 px-1.5 text-foreground/50 tabular-nums @min-[140px]/bar:inline", + "ml-auto hidden shrink-0 px-1.5 text-foreground-subtle tabular-nums @min-[140px]/bar:inline", ), ], [durationLabel], @@ -325,7 +325,7 @@ const timelineCell = (h: H, bar: Bar, state: RowState, durationLabel: string): H ...(isLabelLeft ? [h.DataAttribute("side", "left")] : []), ...(isOffscreen ? [h.Style({ visibility: "hidden" })] : []), ], - [h.span([attr(h, "text-foreground/90")], [bar.span.spanName]), " · ", durationLabel], + [h.span([attr(h, "text-foreground-soft")], [bar.span.spanName]), " · ", durationLabel], ), ], ), @@ -347,8 +347,8 @@ export const timelineRow = (h: H, bar: Bar, state: RowState): Html => { h, cn( "absolute left-0 right-0 flex items-stretch cursor-pointer select-none", - "hover:bg-muted/50", - state.isHovered && "bg-muted/50", + "hover:bg-surface-sunken", + state.isHovered && "bg-surface-sunken", state.isSelected && "bg-primary/10", state.isFocused && "ring-1 ring-inset ring-primary/60", state.isMatched && "ring-1 ring-inset ring-primary/40", diff --git a/apps/web/src/page/traces/detail/timeline/view.ts b/apps/web/src/page/traces/detail/timeline/view.ts index 6294c842db..a5e2b92fba 100644 --- a/apps/web/src/page/traces/detail/timeline/view.ts +++ b/apps/web/src/page/traces/detail/timeline/view.ts @@ -191,7 +191,7 @@ export const view = Submodel.defineView((model, inpu toolbar(h, model, bars.length, toolbarIds(inputs.idPrefix)), alignedStrip( h, - "shrink-0 border-b border-r border-border bg-muted/10", + "shrink-0 border-b border-r border-border bg-surface-faint", "flex shrink-0", "flex-1 min-w-0", minimap(h, model), diff --git a/apps/web/src/page/traces/detail/waterfall/row.ts b/apps/web/src/page/traces/detail/waterfall/row.ts index 5ae72e15e7..50c5f166a3 100644 --- a/apps/web/src/page/traces/detail/waterfall/row.ts +++ b/apps/web/src/page/traces/detail/waterfall/row.ts @@ -170,7 +170,7 @@ const missingRow = (h: HtmlBuilder, row: TreeRow, ctx: RowContext): Htm [ h.Class( cn( - "@container/row group flex items-stretch px-2 bg-muted/30", + "@container/row group flex items-stretch px-2 bg-surface-sunken", ctx.isSelected && "bg-primary/5 shadow-[inset_2px_0_0_var(--color-primary)]", ), ), @@ -207,7 +207,7 @@ const missingRow = (h: HtmlBuilder, row: TreeRow, ctx: RowContext): Htm truncatedId(h, { value: span.spanId, kind: "span", - className: "w-16 text-right text-3xs text-muted-foreground/50 truncate", + className: "w-16 text-right text-3xs text-foreground-faint truncate", }), h.div([h.Class("w-14")], []), ], @@ -247,7 +247,7 @@ const serviceLabel = (h: HtmlBuilder, row: TreeRow): ReadonlyArray, span: SpanNodeData, httpInfo: HttpIn [ h.Class( cn( - "px-1 py-0.5 rounded text-3xs font-bold text-white shrink-0 leading-none hidden @min-[500px]:inline-flex", + "px-1 py-0.5 rounded-sm text-3xs font-bold text-white shrink-0 leading-none hidden @min-[500px]:inline-flex", HTTP_METHOD_COLORS[httpInfo.method] ?? "bg-muted-foreground", ), ), @@ -337,7 +337,7 @@ const locationLabel = (h: HtmlBuilder, row: TreeRow): ReadonlyArray, row: TreeRow, ctx: RowContext): [ h.Class( cn( - "@container/row group flex items-stretch hover:bg-muted/50 cursor-pointer px-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", + "@container/row group flex items-stretch hover:bg-surface-sunken cursor-pointer px-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", span.statusCode === "Error" && "bg-severity-error/5", ctx.isSelected && "bg-primary/5 shadow-[inset_2px_0_0_var(--color-primary)]", ), diff --git a/apps/web/src/page/traces/detail/waterfall/view.ts b/apps/web/src/page/traces/detail/waterfall/view.ts index bde5bc4fed..397b154f43 100644 --- a/apps/web/src/page/traces/detail/waterfall/view.ts +++ b/apps/web/src/page/traces/detail/waterfall/view.ts @@ -16,7 +16,7 @@ const header = (h: HtmlBuilder, shown: number, total: number): Html => h.div( [ h.Class( - "@container/row flex shrink-0 items-center border-b bg-muted/30 px-2 py-1.5 text-xs font-medium text-muted-foreground", + "@container/row flex shrink-0 items-center border-b bg-surface-sunken px-2 py-1.5 text-xs font-medium text-muted-foreground", ), ], [ diff --git a/apps/web/src/page/traces/list/view-row.ts b/apps/web/src/page/traces/list/view-row.ts index f18fefdf89..74093337d6 100644 --- a/apps/web/src/page/traces/list/view-row.ts +++ b/apps/web/src/page/traces/list/view-row.ts @@ -91,7 +91,7 @@ const rootSpanCell = ( truncatedText(h, { text: stamp, className: "text-3xs text-muted-foreground" }, [ h.span([h.Class("hidden @min-[480px]/page:inline")], [stamp, " "]), h.span( - [h.Class("text-muted-foreground/60")], + [h.Class("text-foreground-subtle")], [ "(", h.time( @@ -130,8 +130,8 @@ export const traceRow = ( "class", cn( tableRowStyles, - state.isActive && "bg-muted/60", - "hover:bg-muted/50 data-[focused]:bg-muted/70 data-[focused]:ring-1 data-[focused]:ring-ring data-[focused]:ring-inset cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", + state.isActive && "bg-surface-strong", + "hover:bg-surface-sunken data-[focused]:bg-surface-strong data-[focused]:ring-1 data-[focused]:ring-ring data-[focused]:ring-inset cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", ), ), // Keyed by index so a scrolled-in row is a new node the virtualizer measures. diff --git a/apps/web/src/service-map/map/edge.ts b/apps/web/src/service-map/map/edge.ts index 4f32ede57e..b1bfb2efb5 100644 --- a/apps/web/src/service-map/map/edge.ts +++ b/apps/web/src/service-map/map/edge.ts @@ -132,7 +132,7 @@ const edgeLabel = (h: HtmlBuilder, data: ServiceEdgeData | undefined, x: n h.span( [ h.Class( - "rounded bg-card/90 px-1.5 py-0.5 text-3xs font-mono font-medium text-muted-foreground border border-border/60 whitespace-nowrap tabular-nums", + "rounded-sm bg-card/90 px-1.5 py-0.5 text-3xs font-mono font-medium text-muted-foreground border border-border-subtle whitespace-nowrap tabular-nums", ), ], [ diff --git a/apps/web/src/service-map/map/legend.ts b/apps/web/src/service-map/map/legend.ts index 4f18637f97..ff1363b227 100644 --- a/apps/web/src/service-map/map/legend.ts +++ b/apps/web/src/service-map/map/legend.ts @@ -93,16 +93,16 @@ export const serviceMapLegend = ( h.div( [ h.Class( - "flex flex-wrap items-center gap-x-4 gap-y-2 border-t bg-muted/30 px-3 py-2.5 text-2xs text-muted-foreground shrink-0", + "flex flex-wrap items-center gap-x-4 gap-y-2 border-t bg-surface-sunken px-3 py-2.5 text-2xs text-muted-foreground shrink-0", ), ], [ h.span([h.Class("font-medium max-sm:hidden")], ["Drag nodes to arrange"]), - h.span([h.Class("text-foreground/30 max-sm:hidden")], ["·"]), + h.span([h.Class("text-foreground-faint max-sm:hidden")], ["·"]), h.span([h.Class("font-medium max-sm:hidden")], ["Scroll to zoom"]), ...(colorMode === "service" && services.length > 0 ? [ - h.span([h.Class("text-foreground/30 max-sm:hidden")], ["·"]), + h.span([h.Class("text-foreground-faint max-sm:hidden")], ["·"]), ...services .slice(0, 3) .map((service) => swatch(h, serviceSwatchColor(service), service)), @@ -111,7 +111,7 @@ export const serviceMapLegend = ( : []), ...(colorMode === "platform" ? [ - h.span([h.Class("text-foreground/30")], ["·"]), + h.span([h.Class("text-foreground-faint")], ["·"]), ...LEGEND_PLATFORMS.map(([platform, label]) => swatch(h, getPlatformColor(platform === "unknown" ? undefined : platform), label), ), diff --git a/apps/web/src/service-map/map/node-card.ts b/apps/web/src/service-map/map/node-card.ts index 1e973c6f02..e106164df7 100644 --- a/apps/web/src/service-map/map/node-card.ts +++ b/apps/web/src/service-map/map/node-card.ts @@ -89,7 +89,7 @@ export const metricCell = ( h.div( [h.Class("flex flex-col gap-px")], [ - eyebrow(h, { className: "text-4xs text-muted-foreground/60" }, [label]), + eyebrow(h, { className: "text-4xs text-foreground-subtle" }, [label]), h.span( [ h.Class( diff --git a/apps/web/src/service-map/map/nodes.ts b/apps/web/src/service-map/map/nodes.ts index c2c727f12e..81f89e256d 100644 --- a/apps/web/src/service-map/map/nodes.ts +++ b/apps/web/src/service-map/map/nodes.ts @@ -54,7 +54,7 @@ const podsCell = (h: HtmlBuilder, data: ServiceNodeData): Html => h.div( [h.Class("ml-auto flex flex-col items-end gap-px")], [ - eyebrow(h, { className: "text-4xs text-muted-foreground/60" }, ["pods"]), + eyebrow(h, { className: "text-4xs text-foreground-subtle" }, ["pods"]), data.infra ? tooltipTrigger(h, [ h.span( @@ -64,13 +64,13 @@ const podsCell = (h: HtmlBuilder, data: ServiceNodeData): Html => ), ], [ - icon(h, "CubeIcon", { size: 10, className: "text-muted-foreground/70" }), + icon(h, "CubeIcon", { size: 10, className: "text-foreground-subtle" }), String(data.infra.podCount), ], ), ]) : h.span( - [h.Class("font-mono text-2xs tabular-nums text-muted-foreground/30")], + [h.Class("font-mono text-2xs tabular-nums text-foreground-faint")], [EMPTY_VALUE], ), ], @@ -100,7 +100,7 @@ const serviceNode = (h: HtmlBuilder, id: string, data: ServiceNodeData): R [ h.Class( cn( - "flex w-[220px] cursor-pointer overflow-hidden rounded-r-lg border bg-card transition-[border-color,box-shadow] duration-150", + "flex w-56 cursor-pointer overflow-hidden rounded-r-lg border bg-card transition-[border-color,box-shadow] duration-150", selected ? selectedBorderClass(errorRate) : "border-border hover:border-foreground/30", @@ -121,7 +121,7 @@ const serviceNode = (h: HtmlBuilder, id: string, data: ServiceNodeData): R size: 12, className: cn( "shrink-0", - !platformIcon.branded && "text-muted-foreground/80", + !platformIcon.branded && "text-foreground-subtle", ), }), ]), @@ -138,14 +138,14 @@ const serviceNode = (h: HtmlBuilder, id: string, data: ServiceNodeData): R h, { className: - "shrink-0 text-4xs text-muted-foreground/60", + "shrink-0 text-4xs text-foreground-subtle", }, [runtimeInfo.short], ) : tooltipTrigger(h, [ icon(h, runtimeInfo.icon, { size: 12, - className: "shrink-0 text-muted-foreground/70", + className: "shrink-0 text-foreground-subtle", }), ]), ]), @@ -222,7 +222,7 @@ const databaseNode = (h: HtmlBuilder, id: string, data: ServiceNodeData): h.div( [ h.Class( - "flex w-[220px] cursor-pointer overflow-hidden rounded-r-lg border bg-card transition-[border-color,box-shadow] duration-150", + "flex w-56 cursor-pointer overflow-hidden rounded-r-lg border bg-card transition-[border-color,box-shadow] duration-150", ), h.Style(tintedCard(color, 0.12, 0.4, selected)), ], @@ -291,7 +291,7 @@ const namespaceAggregateNode = ( h.div( [ h.Class( - "flex w-[220px] cursor-pointer overflow-hidden rounded-r-lg border border-dashed bg-card transition-[border-color,box-shadow] duration-150", + "flex w-56 cursor-pointer overflow-hidden rounded-r-lg border border-dashed bg-card transition-[border-color,box-shadow] duration-150", ), h.Style(tintedCard(color, 0.1, 0.55, selected)), h.Title("Collapsed namespace. Click to expand"), diff --git a/apps/web/src/service-map/map/panels.ts b/apps/web/src/service-map/map/panels.ts index 402deaa733..3a232ddcbe 100644 --- a/apps/web/src/service-map/map/panels.ts +++ b/apps/web/src/service-map/map/panels.ts @@ -181,7 +181,7 @@ export const serviceMapMiniMap = ( return h.div( [ h.Class( - "react-flow__panel bottom right react-flow__minimap pointer-events-none !bg-muted/50 !border-border max-sm:hidden", + "react-flow__panel bottom right react-flow__minimap pointer-events-none !bg-surface-sunken !border-border max-sm:hidden", ), // The stylesheet's mask rule beats a `fill` attribute, so the dark mask goes through its variable. h.Style({ "--xy-minimap-mask-background-color-props": MINIMAP_MASK }), diff --git a/apps/web/src/service-map/map/toolbar.ts b/apps/web/src/service-map/map/toolbar.ts index dc53b760c0..3e8bad1be0 100644 --- a/apps/web/src/service-map/map/toolbar.ts +++ b/apps/web/src/service-map/map/toolbar.ts @@ -236,7 +236,7 @@ const presentationControls = (h: HtmlBuilder, inputs: ToolbarInputs, tr const bar = (h: HtmlBuilder, inputs: ToolbarInputs, trigger: Trigger, portal: Html | null): Html => h.div( - [h.Class("flex shrink-0 flex-wrap items-center gap-2 border-b bg-muted/30 px-3 py-2")], + [h.Class("flex shrink-0 flex-wrap items-center gap-2 border-b bg-surface-sunken px-3 py-2")], [ ...Option.match(inputs.focus, { onNone: () => [focusCombobox(h, inputs)], diff --git a/apps/web/src/service-map/trace-flow/edge.ts b/apps/web/src/service-map/trace-flow/edge.ts index 8a245714c7..0d1e7599d3 100644 --- a/apps/web/src/service-map/trace-flow/edge.ts +++ b/apps/web/src/service-map/trace-flow/edge.ts @@ -23,7 +23,7 @@ const labelContent = ( ): ReadonlyArray | null => { const { isError, isMissing, share, count } = data if (!(hovered || isError || count > 1 || share >= LABEL_SHARE_THRESHOLD)) return null - if (isMissing) return hovered ? [h.span([h.Class("italic text-muted-foreground/60")], ["no data"])] : null + if (isMissing) return hovered ? [h.span([h.Class("italic text-foreground-subtle")], ["no data"])] : null if (hovered) { const sharePct = formatShare(share) // Text runs stay split, so the DOM holds the same text nodes as the packages/ui flow edge. @@ -114,7 +114,7 @@ export const traceFlowEdge = ( h.span( [ h.Class( - "whitespace-nowrap rounded border border-border/60 bg-card/90 px-1.5 py-0.5 font-mono text-3xs tabular-nums text-muted-foreground backdrop-blur-sm", + "whitespace-nowrap rounded-sm border border-border-subtle bg-card/90 px-1.5 py-0.5 font-mono text-3xs tabular-nums text-muted-foreground backdrop-blur-sm", ), ], label, diff --git a/apps/web/src/service-map/trace-flow/legend.ts b/apps/web/src/service-map/trace-flow/legend.ts index 0e8b102e03..4982a43f3a 100644 --- a/apps/web/src/service-map/trace-flow/legend.ts +++ b/apps/web/src/service-map/trace-flow/legend.ts @@ -6,11 +6,11 @@ import type { SpanCategory } from "./span-category" // The hint, service and category legend under `TraceFlowView`. -const separator = (h: HtmlBuilder): Html => h.span([h.Class("text-foreground/30")], ["·"]) +const separator = (h: HtmlBuilder): Html => h.span([h.Class("text-foreground-faint")], ["·"]) // Hints are instructions, not legend entries: lighter weight and tone so they read as their own group. const hint = (h: HtmlBuilder, text: string): Html => - h.span([h.Class("text-muted-foreground/70")], [text]) + h.span([h.Class("text-foreground-subtle")], [text]) export const flowLegend = ( h: HtmlBuilder, @@ -20,7 +20,7 @@ export const flowLegend = ( h.div( [ h.Class( - "flex flex-wrap items-center gap-x-10 gap-y-2 border-t bg-muted/30 px-3 py-2.5 text-2xs text-muted-foreground shrink-0", + "flex flex-wrap items-center gap-x-10 gap-y-2 border-t bg-surface-sunken px-3 py-2.5 text-2xs text-muted-foreground shrink-0", ), ], [ diff --git a/apps/web/src/service-map/trace-flow/node-card.ts b/apps/web/src/service-map/trace-flow/node-card.ts index 680f227db6..8f8149dfd3 100644 --- a/apps/web/src/service-map/trace-flow/node-card.ts +++ b/apps/web/src/service-map/trace-flow/node-card.ts @@ -102,7 +102,7 @@ const statusBadge = ( statusCode: string, ): Html | null => { const { platform, cacheInfo, httpInfo } = desc - const base = "shrink-0 rounded px-1.5 py-0.5 text-3xs font-semibold" + const base = "shrink-0 rounded-sm px-1.5 py-0.5 text-3xs font-semibold" if (platform?.outcome?.bad) { return h.span( [h.Class(cn(base, outcomeBadgeStyle(true))), h.Title(`${platform.label} outcome`)], @@ -165,14 +165,14 @@ const missingCard = ( h.span([h.Class("flex-1")]), h.span( [ - h.Class(cn("font-mono tabular-nums", "text-muted-foreground/60 truncate")), + h.Class(cn("font-mono tabular-nums", "text-foreground-subtle truncate")), h.Title(data.span.spanId), ], [shortId(data.span.spanId, "span")], ), ], ), - h.div([h.Class("text-3xs italic text-muted-foreground/50")], ["Not ingested or dropped"]), + h.div([h.Class("text-3xs italic text-foreground-faint")], ["Not ingested or dropped"]), ], ), flowHandle(h, nodeId, "source", "bottom", HANDLE_CLASSES), @@ -280,7 +280,7 @@ export const flowSpanNode = ( [ serviceDot(h, span.serviceName, "size-1.5"), h.span([h.Class("truncate")], [span.serviceName]), - h.span([h.Class("shrink-0 text-muted-foreground/50")], ["·"]), + h.span([h.Class("shrink-0 text-foreground-faint")], ["·"]), h.span([h.Class("shrink-0")], [category.label]), h.span([h.Class("flex-1")]), h.span([h.Class("shrink-0 tabular-nums"), h.Title(tooltip)], [main]), @@ -293,7 +293,7 @@ export const flowSpanNode = ( h.div( [ h.Class( - "absolute inset-x-0 bottom-0 h-[3px] overflow-hidden rounded-b-[7px] bg-muted/40", + "absolute inset-x-0 bottom-0 h-[3px] overflow-hidden rounded-b-[7px] bg-surface-sunken", ), ], [ diff --git a/apps/web/src/service-map/trace-flow/view.ts b/apps/web/src/service-map/trace-flow/view.ts index d225acaf89..36d1a6d548 100644 --- a/apps/web/src/service-map/trace-flow/view.ts +++ b/apps/web/src/service-map/trace-flow/view.ts @@ -125,7 +125,7 @@ const minimapColor = (graph: FlowGraph) => { const header = (h: HtmlBuilder, onFit: M): Html => h.div( - [h.Class("flex items-center justify-between border-b bg-muted/30 px-3 py-2 shrink-0")], + [h.Class("flex items-center justify-between border-b bg-surface-sunken px-3 py-2 shrink-0")], [ h.span([h.Class("text-xs font-medium text-muted-foreground")], ["Flow View"]), button( @@ -178,7 +178,7 @@ export const view = ( panels: [ controls(h, model.canvas, toCanvas), miniMap(h, model.canvas, placed, { - className: "!bg-muted/50 !border-border", + className: "!bg-surface-sunken !border-border", maskColor: "oklch(0.15 0 0 / 0.8)", nodeColor: minimapColor(graph), }), diff --git a/apps/web/src/shell/clerk-org-switcher-view.ts b/apps/web/src/shell/clerk-org-switcher-view.ts index 3ad382c936..8e98ed9ac1 100644 --- a/apps/web/src/shell/clerk-org-switcher-view.ts +++ b/apps/web/src/shell/clerk-org-switcher-view.ts @@ -274,7 +274,7 @@ const createFields = (h: H, model: Model): ReadonlyArray => [ ? [] : [ h.div( - [h.Class("text-destructive text-xs text-sm"), h.DataAttribute("slot", "field-error")], + [h.Class("text-destructive text-xs"), h.DataAttribute("slot", "field-error")], [model.errorMessage], ), ]), @@ -318,7 +318,7 @@ const regionField = (h: H, model: Model): Html => { [ h.Id(RadioGroup.labelId(`${regionIdOf(model, region)}-input`)), h.Class( - "flex cursor-pointer items-center gap-3 px-3.5 py-2.5 transition-colors hover:bg-accent/40 has-[[data-checked]]:bg-accent/64", + "flex cursor-pointer items-center gap-3 px-3.5 py-2.5 transition-colors hover:bg-accent/50 has-[[data-checked]]:bg-accent/64", ), ], [ diff --git a/apps/web/src/shell/connect-panel-view.ts b/apps/web/src/shell/connect-panel-view.ts index b99b20c3b0..ba334aaaa2 100644 --- a/apps/web/src/shell/connect-panel-view.ts +++ b/apps/web/src/shell/connect-panel-view.ts @@ -75,7 +75,7 @@ const keysUnavailable = (h: H): Html => h.p( [ h.Class( - "rounded-md border border-dashed bg-muted/40 px-3 py-2 font-prose text-xs text-muted-foreground", + "rounded-md border border-dashed bg-surface-sunken px-3 py-2 font-prose text-xs text-muted-foreground", ), ], [ diff --git a/apps/web/src/shell/onboarding-checklist-view.ts b/apps/web/src/shell/onboarding-checklist-view.ts index 808dd39a69..cdd64c420f 100644 --- a/apps/web/src/shell/onboarding-checklist-view.ts +++ b/apps/web/src/shell/onboarding-checklist-view.ts @@ -62,7 +62,7 @@ const rewardCallout = (h: H, checklist: V2OnboardingChecklist): Html => h.Type("button"), h.OnClick(Message.ClickedPointer()), h.Class( - "min-w-0 flex-1 rounded text-left outline-none focus-visible:ring-2 focus-visible:ring-ring", + "min-w-0 flex-1 rounded-sm text-left outline-none focus-visible:ring-2 focus-visible:ring-ring", ), ], [ @@ -111,7 +111,7 @@ const stepRow = (h: H, step: V2OnboardingChecklistStep, index: number): Html => h.Href(step.href), h.OnClick(Message.ClickedStep()), h.Class( - "group flex items-center gap-3 rounded-md px-2 py-2 text-sm text-foreground outline-none transition-colors hover:bg-muted/50 focus-visible:ring-2 focus-visible:ring-ring", + "group flex items-center gap-3 rounded-md px-2 py-2 text-sm text-foreground outline-none transition-colors hover:bg-surface-sunken focus-visible:ring-2 focus-visible:ring-ring", ), ], [ diff --git a/apps/web/src/shell/palette/shortcuts-view.ts b/apps/web/src/shell/palette/shortcuts-view.ts index 17740dc8b2..6ab9ac1eb1 100644 --- a/apps/web/src/shell/palette/shortcuts-view.ts +++ b/apps/web/src/shell/palette/shortcuts-view.ts @@ -47,7 +47,7 @@ const groups = (h: HtmlBuilder, platform: Platform): ReadonlyArray = [ eyebrow(h, { variant: "label", className: "mb-1", as: "h3" }, [group]), h.div( - [h.Class("divide-y divide-border/60")], + [h.Class("divide-y divide-border-subtle")], defs.map((def) => row(h, def, platform)), ), ], diff --git a/apps/web/src/ui/alert.ts b/apps/web/src/ui/alert.ts index 346b414866..6827a55361 100644 --- a/apps/web/src/ui/alert.ts +++ b/apps/web/src/ui/alert.ts @@ -13,7 +13,7 @@ import type { Html, HtmlBuilder } from "foldkit/html" // The shared `info` variant reuses the green severity hue of `ok`; info reads blue here. `done` // keeps its shared tinted variant; its glyph is what sets it apart from info. const variantOverride = (variant: AlertOptions["variant"]): string | undefined => - variant === "info" ? "border-info/32 bg-info/4 [&>svg]:text-info" : undefined + variant === "info" ? "border-severity-debug/32 bg-severity-debug/4 [&>svg]:text-severity-debug" : undefined type Children = ReadonlyArray diff --git a/apps/web/src/ui/attributes/attribute-row.ts b/apps/web/src/ui/attributes/attribute-row.ts index 9348be1c49..6a64f63d14 100644 --- a/apps/web/src/ui/attributes/attribute-row.ts +++ b/apps/web/src/ui/attributes/attribute-row.ts @@ -29,8 +29,8 @@ export const copyableValue = ( h.AriaLabel(`Copy ${options.label ?? "value"}`), h.Class( cn( - "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors", - status === "idle" && "hover:bg-muted/50", + "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors", + status === "idle" && "hover:bg-surface-sunken", status === "copied" && "bg-severity-info/20", status === "error" && "bg-severity-error/20", options.className, @@ -78,7 +78,7 @@ const jsonValue = (h: H, model: Model, id: string, value: string): Html => { [ h.Type("button"), h.Class( - "flex items-start gap-1 w-full text-left font-mono text-xs break-all cursor-pointer hover:bg-muted/50 rounded px-0.5 -mx-0.5 transition-colors", + "flex items-start gap-1 w-full text-left font-mono text-xs break-all cursor-pointer hover:bg-surface-sunken rounded-sm px-0.5 -mx-0.5 transition-colors", ), h.OnClick(Message.ToggledCollapsible({ key: `json:${id}`, defaultOpen: false }), stop), h.Title(isExpanded ? "Collapse" : "Expand JSON"), @@ -96,7 +96,7 @@ const jsonValue = (h: H, model: Model, id: string, value: string): Html => { h.div( [ h.Class( - "group/json relative mt-1 overflow-hidden rounded-md border bg-muted/30", + "group/json relative mt-1 overflow-hidden rounded-md border bg-surface-sunken", ), ], [ @@ -117,7 +117,7 @@ const jsonValue = (h: H, model: Model, id: string, value: string): Html => { label: "JSON", iconSize: 10, className: - "absolute top-1 right-1 border-border/60 bg-background/80 opacity-0 backdrop-blur-sm transition-opacity focus-visible:opacity-100 group-hover/json:opacity-100 pointer-coarse:opacity-100", + "absolute top-1 right-1 border-border-subtle bg-background/80 opacity-0 backdrop-blur-sm transition-opacity focus-visible:opacity-100 group-hover/json:opacity-100 pointer-coarse:opacity-100", attributes: [ h.OnClick( Message.ClickedCopy({ copyId: `json:${id}`, text: value }), @@ -135,7 +135,7 @@ const jsonValue = (h: H, model: Model, id: string, value: string): Html => { const COMMIT_SHA_KEYS = new Set(["vcs.ref.head.revision"]) const FULL_SHA = /^[0-9a-f]{40}$/i -const COMMIT_SHA_CLASS = "-mx-0.5 cursor-pointer break-all rounded px-0.5 transition-colors hover:bg-muted/50" +const COMMIT_SHA_CLASS = "-mx-0.5 cursor-pointer break-all rounded-sm px-0.5 transition-colors hover:bg-surface-sunken" /** A commit SHA value as a commit link. TODO(commit-card): the hover card itself. */ const commitShaValue = (h: H, id: string, value: string): Html => @@ -224,7 +224,7 @@ export const attributeRow = ( [ h.Key(attrKey), h.Class( - "group/attr grid grid-cols-[minmax(7rem,38%)_1fr] items-start gap-x-3 px-2 py-1 transition-colors hover:bg-muted/50", + "group/attr grid grid-cols-[minmax(7rem,38%)_1fr] items-start gap-x-3 px-2 py-1 transition-colors hover:bg-surface-sunken", ), ], [ diff --git a/apps/web/src/ui/attributes/attributes-view.ts b/apps/web/src/ui/attributes/attributes-view.ts index caa3ed2a80..0fc253b999 100644 --- a/apps/web/src/ui/attributes/attributes-view.ts +++ b/apps/web/src/ui/attributes/attributes-view.ts @@ -102,7 +102,7 @@ const filterEntries = ( } const title4 = (h: H, title: string) => - h.h4([h.Class("text-xs font-medium tracking-wide text-foreground/70")], [title]) + h.h4([h.Class("text-xs font-medium tracking-wide text-foreground-soft")], [title]) const noMatches = (h: H, title: string, query: string) => h.div( @@ -145,20 +145,20 @@ const attributesTable = (h: H, context: RowContext, options: TableOptions): Html [ title4(h, options.title), h.div( - [h.Class("divide-y divide-border/60 overflow-hidden rounded-md border")], + [h.Class("divide-y divide-border-subtle overflow-hidden rounded-md border")], groups.map((group) => collapsible(h, model, { key: `${options.section}:${group.namespace}`, defaultOpen: group.entries.length <= 8 || query !== "", triggerClassName: - "group flex w-full items-center gap-1.5 px-1.5 py-1.5 text-2xs text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground", + "group flex w-full items-center gap-1.5 px-1.5 py-1.5 text-2xs text-muted-foreground transition-colors hover:bg-surface-sunken hover:text-foreground", trigger: [ icon(h, "ChevronRightIcon", { size: 12, className: "transition-transform group-data-[panel-open]:rotate-90", }), h.span( - [h.Class("font-mono font-semibold text-foreground/80")], + [h.Class("font-mono font-semibold text-foreground-soft")], [group.namespace], ), badge(h, { variant: "muted", size: "xs", mono: true, className: "ml-auto" }, [ @@ -169,7 +169,7 @@ const attributesTable = (h: H, context: RowContext, options: TableOptions): Html h.div( [ h.Class( - "divide-y divide-border/60 border-t border-border/60 bg-muted/15", + "divide-y divide-border-subtle border-t border-border-subtle bg-surface-faint", ), ], group.entries.map(([key, value]) => @@ -196,7 +196,7 @@ const attributesTable = (h: H, context: RowContext, options: TableOptions): Html [ title4(h, options.title), h.div( - [h.Class("divide-y divide-border/60 overflow-hidden rounded-md border")], + [h.Class("divide-y divide-border-subtle overflow-hidden rounded-md border")], filtered.map(([key, value]) => attributeRow(h, rowContext, key, value)), ), ], diff --git a/apps/web/src/ui/avatar-tone.ts b/apps/web/src/ui/avatar-tone.ts index f92616b155..13c9e6d359 100644 --- a/apps/web/src/ui/avatar-tone.ts +++ b/apps/web/src/ui/avatar-tone.ts @@ -1,11 +1,11 @@ // Warm tiles for initials avatars, near the primary orange, so an org or a user without an image // gets the same colour wherever their avatar is drawn. const WARM_TONES: readonly [string, ...string[]] = [ - "bg-[oklch(0.7_0.15_59)] text-primary-foreground", - "bg-[oklch(0.76_0.13_80)] text-primary-foreground", - "bg-[oklch(0.66_0.14_40)] text-primary-foreground", - "bg-[oklch(0.68_0.1_25)] text-primary-foreground", - "bg-[oklch(0.72_0.07_65)] text-primary-foreground", + "bg-avatar-1 text-primary-foreground", + "bg-avatar-2 text-primary-foreground", + "bg-avatar-3 text-primary-foreground", + "bg-avatar-4 text-primary-foreground", + "bg-avatar-5 text-primary-foreground", ] /** The tile classes for a seed (an org or user name): stable across renders and pages. */ diff --git a/apps/web/src/ui/chart-skeleton-shapes.ts b/apps/web/src/ui/chart-skeleton-shapes.ts index 608f45c2d4..5dd9ce9119 100644 --- a/apps/web/src/ui/chart-skeleton-shapes.ts +++ b/apps/web/src/ui/chart-skeleton-shapes.ts @@ -247,7 +247,7 @@ export const statGhost = (h: HtmlBuilder): Html => [h.Class("flex h-full w-full flex-col items-center justify-center gap-2.5")], [ stub(h, "h-8 w-24 rounded-md bg-foreground/10 animate-pulse"), - stub(h, "h-3 w-14 rounded bg-foreground/10 animate-pulse", { "animation-delay": "0.2s" }), + stub(h, "h-3 w-14 rounded-sm bg-foreground/10 animate-pulse", { "animation-delay": "0.2s" }), ], ) diff --git a/apps/web/src/ui/chart-state.ts b/apps/web/src/ui/chart-state.ts index 53a7d92c6d..f81b81d368 100644 --- a/apps/web/src/ui/chart-state.ts +++ b/apps/web/src/ui/chart-state.ts @@ -81,10 +81,10 @@ export const chartEmpty = ( h.div( [h.Class("relative flex flex-col items-center gap-1")], [ - h.span([h.Class("text-foreground/70")], children), + h.span([h.Class("text-foreground-soft")], children), ...(options.hint === undefined ? [] - : [h.span([h.Class("text-3xs text-muted-foreground/80")], [options.hint])]), + : [h.span([h.Class("text-3xs text-foreground-subtle")], [options.hint])]), ], ), ], diff --git a/apps/web/src/ui/detail-rail.ts b/apps/web/src/ui/detail-rail.ts index 93c698f4aa..8789ca5628 100644 --- a/apps/web/src/ui/detail-rail.ts +++ b/apps/web/src/ui/detail-rail.ts @@ -20,7 +20,7 @@ export const detailRailGroup = ( [ h.DataAttribute("slot", "detail-rail-group"), h.Class( - cn("flex flex-col gap-1.5 border-b border-border/60 px-4 py-3.5 last:border-b-0", className), + cn("flex flex-col gap-1.5 border-b border-border-subtle px-4 py-3.5 last:border-b-0", className), ), ], [eyebrow(h, { as: "h3" }, [label]), h.div([h.Class("flex flex-col gap-1")], children)], @@ -57,7 +57,7 @@ export const detailRailRow = ( ? [] : [ icon(h, options.icon, { - className: "size-3.5 shrink-0 text-muted-foreground/70", + className: "size-3.5 shrink-0 text-foreground-subtle", attributes: [h.AriaHidden(true)], }), ]), @@ -68,7 +68,7 @@ export const detailRailRow = ( ...(options.hint ? [ h.span( - [h.Class("truncate text-3xs text-muted-foreground/70")], + [h.Class("truncate text-3xs text-foreground-subtle")], [options.hint], ), ] @@ -99,7 +99,7 @@ export const detailRailField = ( [ h.span([], [options.label]), ...(options.hint - ? [h.span([h.Class("text-3xs text-muted-foreground/70")], [options.hint])] + ? [h.span([h.Class("text-3xs text-foreground-subtle")], [options.hint])] : []), ], ), @@ -140,7 +140,7 @@ export const detailRailMetaRow = ( [ h.DataAttribute("slot", "detail-rail-meta-row"), h.Class( - "group flex items-baseline justify-between gap-3 border-b border-border/60 py-1.5 last:border-0", + "group flex items-baseline justify-between gap-3 border-b border-border-subtle py-1.5 last:border-0", ), ], [ @@ -156,7 +156,7 @@ export const detailRailMetaRow = ( : [ icon(h, options.icon, { className: - "size-3.5 shrink-0 self-center text-muted-foreground/70", + "size-3.5 shrink-0 self-center text-foreground-subtle", }), ]), options.label, @@ -172,7 +172,7 @@ export const detailRailMetaRow = ( [ h.Class( cn( - "break-all text-right font-mono text-2xs tabular-nums text-foreground/80", + "break-all text-right font-mono text-2xs tabular-nums text-foreground-soft", options.valueClassName, ), ), diff --git a/apps/web/src/ui/error-section.ts b/apps/web/src/ui/error-section.ts index d6a726a63d..7ce2385f48 100644 --- a/apps/web/src/ui/error-section.ts +++ b/apps/web/src/ui/error-section.ts @@ -47,7 +47,7 @@ export const errorSectionView = (h: HtmlBuilder, options: ErrorSectionOpti : capForDisplay(body.full) const { prompt } = options return h.div( - [h.Class("mx-3 my-2 rounded-md border border-severity-error/25 bg-severity-error/4 px-3 py-2.5")], + [h.Class("mx-3 my-2 rounded-md border border-severity-error/25 bg-severity-error/4 p-3")], [ h.div( [h.Class("flex min-w-0 items-center gap-2")], @@ -60,7 +60,7 @@ export const errorSectionView = (h: HtmlBuilder, options: ErrorSectionOpti ? [ h.span( [ - h.Class("min-w-0 truncate font-mono text-2xs text-foreground/80"), + h.Class("min-w-0 truncate font-mono text-2xs text-foreground-soft"), h.Title(options.badge), ], [options.badge], @@ -72,7 +72,7 @@ export const errorSectionView = (h: HtmlBuilder, options: ErrorSectionOpti h.span( [ h.Class( - "flex shrink-0 items-center gap-1 rounded border border-severity-error/25 px-1 py-px font-mono text-4xs text-severity-error/70 uppercase", + "flex shrink-0 items-center gap-1 rounded-sm border border-severity-error/25 px-1 py-px font-mono text-4xs text-severity-error/70 uppercase", ), h.Title("JSON payload"), ], @@ -89,7 +89,7 @@ export const errorSectionView = (h: HtmlBuilder, options: ErrorSectionOpti iconSize: 12, idleIcon: "SparkleIcon", className: - "ml-auto size-5 shrink-0 rounded text-severity-error/70 hover:bg-severity-error/10 hover:text-severity-error sm:size-5", + "ml-auto size-5 shrink-0 rounded-sm text-severity-error/70 hover:bg-severity-error/10 hover:text-severity-error sm:size-5", slot: prompt.tooltipId === undefined && prompt.trigger === undefined ? undefined @@ -113,7 +113,7 @@ export const errorSectionView = (h: HtmlBuilder, options: ErrorSectionOpti h.AriaLabel("Copy error message"), h.Class( cn( - "mt-1.5 block w-full cursor-copy rounded text-left font-mono text-2xs text-foreground/90 leading-relaxed", + "mt-1.5 block w-full cursor-copy rounded-sm text-left font-mono text-2xs text-foreground-soft leading-relaxed", "transition-colors duration-150 hover:text-foreground motion-reduce:transition-none", "data-[copy-status=copied]:text-severity-info", ), @@ -163,7 +163,7 @@ export const errorSectionView = (h: HtmlBuilder, options: ErrorSectionOpti [ h.AriaExpanded(options.isExpanded), h.Class( - "mt-1 rounded text-2xs text-severity-error/70 hover:text-severity-error", + "mt-1 rounded-sm text-2xs text-severity-error/70 hover:text-severity-error", ), h.Type("button"), h.OnClick(options.onToggle), diff --git a/apps/web/src/ui/error-state.ts b/apps/web/src/ui/error-state.ts index 1275af7e9a..9f7aec6426 100644 --- a/apps/web/src/ui/error-state.ts +++ b/apps/web/src/ui/error-state.ts @@ -122,15 +122,15 @@ const droppedSignalGlyph = (h: HtmlBuilder): Html => y1: "30", x2: "194", y2: "30", - class: "stroke-destructive", + class: "stroke-severity-error", "stroke-width": "1.5", "stroke-dasharray": "3 5", "stroke-linecap": "round", opacity: "0.45", }), ), - h.circle(attr(h, { cx: "118", cy: "30", r: "5.5", class: "fill-destructive", opacity: "0.35" })), - h.circle(attr(h, { cx: "118", cy: "30", r: "2.5", class: "fill-destructive" })), + h.circle(attr(h, { cx: "118", cy: "30", r: "5.5", class: "fill-severity-error", opacity: "0.35" })), + h.circle(attr(h, { cx: "118", cy: "30", r: "2.5", class: "fill-severity-error" })), ]) /** `NarrowedSignalGlyph`: scattered lines funnelled into one, the request needs narrowing. */ @@ -173,8 +173,8 @@ const narrowedSignalGlyph = (h: HtmlBuilder): Html => opacity: "0.7", }), ), - h.circle(attr(h, { cx: "116", cy: "28", r: "5.5", class: "fill-warning", opacity: "0.35" })), - h.circle(attr(h, { cx: "116", cy: "28", r: "2.5", class: "fill-warning" })), + h.circle(attr(h, { cx: "116", cy: "28", r: "5.5", class: "fill-severity-warn", opacity: "0.35" })), + h.circle(attr(h, { cx: "116", cy: "28", r: "2.5", class: "fill-severity-warn" })), ]) /** `LockedSignalGlyph`: a signal line that stops at a lock, with no trail past it. */ @@ -210,7 +210,7 @@ const lockedSignalGlyph = (h: HtmlBuilder): Html => "stroke-width": "2", }), ), - h.circle(attr(h, { cx: "100", cy: "32.5", r: "2.25", class: "fill-destructive" })), + h.circle(attr(h, { cx: "100", cy: "32.5", r: "2.25", class: "fill-severity-error" })), h.line( attr(h, { x1: "124", @@ -271,8 +271,8 @@ const lockTick = (h: HtmlBuilder, size: number): Html => ]) const INLINE_TINT = { - outage: "bg-destructive/10 text-destructive", - fixable: "bg-warning/10 text-warning-foreground", + outage: "bg-severity-error/10 text-severity-error", + fixable: "bg-severity-warn/10 text-severity-warn", access: "bg-muted text-muted-foreground", } satisfies Record @@ -554,7 +554,7 @@ export const errorState = (h: HtmlBuilder, options: ErrorStateOptions): ...autoRetry, ], [ - h.div([h.Class("rounded-md border bg-card/50 px-3 py-2.5")], [glyphFor(h, kind)]), + h.div([h.Class("rounded-md border bg-card/50 p-3")], [glyphFor(h, kind)]), h.div( [h.Class("max-w-md space-y-1")], [ diff --git a/apps/web/src/ui/filters/active-filter-chips.ts b/apps/web/src/ui/filters/active-filter-chips.ts index b01f74b24a..170e3b7d8a 100644 --- a/apps/web/src/ui/filters/active-filter-chips.ts +++ b/apps/web/src/ui/filters/active-filter-chips.ts @@ -46,7 +46,7 @@ export const activeFilterChips = ( "inline-flex max-w-full items-center gap-1.5 rounded-md border py-1 pr-1 pl-2 text-xs", isNegated ? "border-dashed border-destructive/40 bg-destructive/5 text-destructive" - : "border-border/60 bg-muted/40 text-foreground", + : "border-border-subtle bg-surface-sunken text-foreground", ), ), ], diff --git a/apps/web/src/ui/filters/filter-section.ts b/apps/web/src/ui/filters/filter-section.ts index 284373ccce..a845b7c7dd 100644 --- a/apps/web/src/ui/filters/filter-section.ts +++ b/apps/web/src/ui/filters/filter-section.ts @@ -141,7 +141,7 @@ export const filterDescriptionMark = (h: HtmlBuilder, title: string): Html h.span( [ h.AriaLabel(`About ${title}`), - h.Class("inline-flex shrink-0 text-muted-foreground/50 hover:text-muted-foreground"), + h.Class("inline-flex shrink-0 text-foreground-faint hover:text-muted-foreground"), h.DataAttribute("base-ui-tooltip-trigger", ""), h.DataAttribute("slot", "tooltip-trigger"), h.Tabindex(0), @@ -219,7 +219,7 @@ const optionRow = (h: HtmlBuilder, config: FilterSectionConfig, option: className: cn( "flex-1 min-w-0 flex items-center gap-1.5 cursor-pointer text-xs font-normal", isExcluded - ? "text-muted-foreground/70 line-through decoration-1 decoration-muted-foreground/50" + ? "text-foreground-subtle line-through decoration-1 decoration-muted-foreground/50" : "text-foreground", ), attributes: [ @@ -349,7 +349,7 @@ export const filterSection = (h: HtmlBuilder, config: FilterSectionConfig< : collapsedBadges(h, config.selected.length, excluded.length)), icon(h, "ChevronDownIcon", { className: cn( - "size-3.5 shrink-0 text-muted-foreground/40 transition-[transform,color] duration-200 ease-out group-hover:text-muted-foreground", + "size-3.5 shrink-0 text-foreground-faint transition-[transform,color] duration-200 ease-out group-hover:text-muted-foreground", state.isOpen && "rotate-180", ), }), diff --git a/apps/web/src/ui/filters/range-filter-section.ts b/apps/web/src/ui/filters/range-filter-section.ts index 596c41444a..4ca6fc8a79 100644 --- a/apps/web/src/ui/filters/range-filter-section.ts +++ b/apps/web/src/ui/filters/range-filter-section.ts @@ -97,7 +97,7 @@ const panelBody = (h: HtmlBuilder, config: RangeFilterSectionConfig): H [ ...(config.hint === undefined || config.hint === "" ? [] - : [h.p([h.Class("text-xs text-muted-foreground/70")], [config.hint])]), + : [h.p([h.Class("text-xs text-foreground-subtle")], [config.hint])]), ...(histogram === null ? [] : [histogram]), h.div( [h.Class("flex items-center gap-1.5")], @@ -242,7 +242,7 @@ const trigger = (h: HtmlBuilder, config: RangeFilterSectionConfig, isOp : []), icon(h, "ChevronDownIcon", { className: cn( - "size-3.5 shrink-0 text-muted-foreground/40 transition-[transform,color] duration-200 ease-out group-hover:text-muted-foreground", + "size-3.5 shrink-0 text-foreground-faint transition-[transform,color] duration-200 ease-out group-hover:text-muted-foreground", isOpen && "rotate-180", ), }), diff --git a/apps/web/src/ui/filters/range-histogram.ts b/apps/web/src/ui/filters/range-histogram.ts index 2f91eb800c..b6c1431582 100644 --- a/apps/web/src/ui/filters/range-histogram.ts +++ b/apps/web/src/ui/filters/range-histogram.ts @@ -199,7 +199,7 @@ export const rangeHistogram = (h: HtmlBuilder, config: RangeHistogramConfi ), ), h.div( - [h.Class("mt-1 flex justify-between text-3xs tabular-nums text-muted-foreground/60")], + [h.Class("mt-1 flex justify-between text-3xs tabular-nums text-foreground-subtle")], [ h.span([], [formatValue(first.from, unit)]), h.span([], [formatValue(middle.from, unit)]), diff --git a/apps/web/src/ui/http-span-label.ts b/apps/web/src/ui/http-span-label.ts index 324f91a48b..1c51304f81 100644 --- a/apps/web/src/ui/http-span-label.ts +++ b/apps/web/src/ui/http-span-label.ts @@ -55,7 +55,7 @@ export const httpSpanLabel = (h: HtmlBuilder, options: HttpSpanLabelOption [ h.Class( cn( - "shrink-0 inline-flex items-center gap-0.5 rounded px-1 py-0.5 text-3xs font-bold leading-none text-white", + "shrink-0 inline-flex items-center gap-0.5 rounded-sm px-1 py-0.5 text-3xs font-bold leading-none text-white", HTTP_METHOD_COLORS[info.method] ?? "bg-[#5A5248]", ), ), diff --git a/apps/web/src/ui/logs/chip-card.ts b/apps/web/src/ui/logs/chip-card.ts index da5472c97c..39809a3651 100644 --- a/apps/web/src/ui/logs/chip-card.ts +++ b/apps/web/src/ui/logs/chip-card.ts @@ -156,7 +156,7 @@ const cardView = (h: HtmlBuilder, index: number, chip: LogChip, canFilt h.Type("button"), h.AriaLabel("Copy value"), h.Class( - "-mx-0.5 cursor-pointer rounded px-0.5 text-left transition-colors hover:bg-muted/50", + "-mx-0.5 cursor-pointer rounded-sm px-0.5 text-left transition-colors hover:bg-surface-sunken", ), h.Title("Click to copy"), h.OnClick(Message.ClickedCardCopy({ part: "key" }), { diff --git a/apps/web/src/ui/logs/log-row-expanded.ts b/apps/web/src/ui/logs/log-row-expanded.ts index 9d22671b63..b6ee7aa82d 100644 --- a/apps/web/src/ui/logs/log-row-expanded.ts +++ b/apps/web/src/ui/logs/log-row-expanded.ts @@ -57,7 +57,7 @@ export const logRowExpanded = ( const { shown, omitted } = capForDisplay(formatted) const lines = shown.split("\n") return h.div( - [h.Class("border-t border-border/60 bg-muted/20 px-3 py-3 pl-9 font-mono")], + [h.Class("border-t border-border-subtle bg-surface-faint px-3 py-3 pl-9 font-mono")], [ h.div( [h.Class("max-h-[60vh] space-y-3 overflow-auto")], @@ -65,7 +65,7 @@ export const logRowExpanded = ( h.div( [ h.Class( - "relative rounded-md border border-border/60 bg-background/60 py-2 pl-3 pr-24", + "relative rounded-md border border-border-subtle bg-background/60 py-2 pl-3 pr-24", ), ], [ diff --git a/apps/web/src/ui/logs/log-row.ts b/apps/web/src/ui/logs/log-row.ts index ae123854ba..09ebef5e13 100644 --- a/apps/web/src/ui/logs/log-row.ts +++ b/apps/web/src/ui/logs/log-row.ts @@ -63,11 +63,11 @@ const ROW_CHIP_LIMIT = 2 // Row and row action classes const ROW_CLASS = - "hover:bg-muted/50 data-[expanded]:bg-muted/40 data-[focused]:bg-muted/70 data-[focused]:ring-1 data-[focused]:ring-ring data-[focused]:ring-inset focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset" + "hover:bg-surface-sunken data-[expanded]:bg-surface-sunken data-[focused]:bg-surface-strong data-[focused]:ring-1 data-[focused]:ring-ring data-[focused]:ring-inset focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset" const EXPAND_BUTTON_CLASS = - "-mr-1.5 shrink-0 flex h-4 items-center justify-center w-4 text-muted-foreground/40 group-hover/row:text-muted-foreground hover:text-foreground transition-colors cursor-pointer focus-visible:outline-none focus-visible:text-foreground" + "-mr-1.5 shrink-0 flex h-4 items-center justify-center w-4 text-foreground-faint group-hover/row:text-muted-foreground hover:text-foreground transition-colors cursor-pointer focus-visible:outline-none focus-visible:text-foreground" const ROW_ACTION_CLASS = - "inline-flex size-5 items-center justify-center rounded text-3xs text-muted-foreground hover:bg-muted hover:text-foreground cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" + "inline-flex size-5 items-center justify-center rounded-sm text-3xs text-muted-foreground hover:bg-muted hover:text-foreground cursor-pointer focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" const ACTIONS_CLASS = "absolute right-0 hidden items-center gap-0.5 rounded-md border border-border bg-background p-0.5 group-hover/row:flex group-data-[focused]/row:flex group-focus-within/row:flex" const ICON_BUTTON_CLASS = cn( @@ -103,8 +103,8 @@ const pinnedCell = (h: HtmlBuilder, cell: PinnedCell): Html => cn( "block min-w-0 truncate", cn( - "shrink-0 text-foreground/80 hidden md:block", - cell.isEmpty && "text-muted-foreground/40", + "shrink-0 text-foreground-soft hidden md:block", + cell.isEmpty && "text-foreground-faint", cell.isNumeric && "tabular-nums", ), ), @@ -167,7 +167,7 @@ export const logRow = ( width: "100%", transform: `translateY(${start}px)`, }), - rowClass(h, "border-b border-border/60"), + rowClass(h, "border-b border-border-subtle"), ], [ h.div( @@ -213,14 +213,14 @@ export const logRow = ( ), h.span( [ - rowClass(h, "shrink-0 w-[92px] text-foreground/70 tabular-nums"), + rowClass(h, "shrink-0 w-24 text-foreground-soft tabular-nums"), h.Title(row.timeTitle), ], row.timeFraction === "" ? [row.timeMain] : [ row.timeMain, - h.span([rowClass(h, "text-muted-foreground/50")], [row.timeFraction]), + h.span([rowClass(h, "text-foreground-faint")], [row.timeFraction]), ], ), h.span( diff --git a/apps/web/src/ui/logs/logs-stream-view.ts b/apps/web/src/ui/logs/logs-stream-view.ts index 1853c83fd5..f679f13503 100644 --- a/apps/web/src/ui/logs/logs-stream-view.ts +++ b/apps/web/src/ui/logs/logs-stream-view.ts @@ -86,7 +86,7 @@ const columnHeader = ( }, [ h.span([h.AriaHidden(true), h.Class("-mr-1.5 shrink-0 w-4")]), - h.span([h.Class("shrink-0 w-[92px]"), h.Title(`Times in ${timeZone}`)], ["Time"]), + h.span([h.Class("shrink-0 w-24"), h.Title(`Times in ${timeZone}`)], ["Time"]), h.span([h.Class("shrink-0 w-11")], ["Level"]), h.span([h.Class("shrink-0 w-40 hidden md:inline-block")], ["Service"]), ...pinnedColumns.map((key) => { @@ -94,7 +94,7 @@ const columnHeader = ( const parts = pinnedColumnParts(key) return h.span( [ - h.Class("shrink-0 min-w-0 hidden md:flex text-foreground/60 whitespace-nowrap"), + h.Class("shrink-0 min-w-0 hidden md:flex text-foreground-subtle whitespace-nowrap"), h.Style({ width: PINNED_COL_WIDTH }), h.Title(key), ], diff --git a/apps/web/src/ui/logs/styles.ts b/apps/web/src/ui/logs/styles.ts index fa6da4657b..217a4986ad 100644 --- a/apps/web/src/ui/logs/styles.ts +++ b/apps/web/src/ui/logs/styles.ts @@ -13,8 +13,8 @@ export const rowClass = (h: HtmlBuilder, value: string): Attri export const CHIP_TONE_CLASSES = { crit: "bg-severity-error/10 text-severity-error border-severity-error/20 hover:bg-severity-error/15", warn: "bg-severity-warn/10 text-severity-warn border-severity-warn/20 hover:bg-severity-warn/15", - emphasis: "bg-muted text-foreground/80 border-border hover:bg-muted/80", - muted: "bg-muted/40 text-muted-foreground border-border/60 hover:bg-muted/70", + emphasis: "bg-muted text-foreground-soft border-border hover:bg-surface-strong", + muted: "bg-surface-sunken text-muted-foreground border-border-subtle hover:bg-surface-strong", } satisfies Record /** The chip's key steps back from its value; error and warning keys keep their tone colour. */ export const CHIP_KEY_TONE_CLASSES = { @@ -25,6 +25,6 @@ export const CHIP_KEY_TONE_CLASSES = { muted: "opacity-70", } satisfies Record export const CHIP_CLASS = - "inline-flex items-center gap-1 h-[18px] min-w-0 px-1.5 rounded border text-3xs font-mono leading-none whitespace-nowrap shrink-0 cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" + "inline-flex items-center gap-1 h-[18px] min-w-0 px-1.5 rounded-sm border text-3xs font-mono leading-none whitespace-nowrap shrink-0 cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" export const CHIP_FILTER_ACTION_CLASS = - "inline-flex h-6 items-center gap-1 rounded px-1.5 text-2xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" + "inline-flex h-6 items-center gap-1 rounded-sm px-1.5 text-2xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" diff --git a/apps/web/src/ui/segmented-select.ts b/apps/web/src/ui/segmented-select.ts index 72a9639a11..ab4d5a81dd 100644 --- a/apps/web/src/ui/segmented-select.ts +++ b/apps/web/src/ui/segmented-select.ts @@ -183,7 +183,7 @@ export const segmentedSelect = ( [ h.AriaHidden(true), h.Class( - "-z-10 absolute inset-0 rounded-md bg-background shadow-sm ring-1 ring-border/70 dark:bg-input dark:ring-white/10", + "-z-10 absolute inset-0 rounded-md bg-background shadow-sm ring-1 ring-border-subtle dark:bg-input dark:ring-white/10", ), h.Style({ opacity: "1" }), ], diff --git a/packages/ui/src/components/charts/_shared/query-builder-legend.tsx b/packages/ui/src/components/charts/_shared/query-builder-legend.tsx index a288fbc70d..adda712130 100644 --- a/packages/ui/src/components/charts/_shared/query-builder-legend.tsx +++ b/packages/ui/src/components/charts/_shared/query-builder-legend.tsx @@ -148,7 +148,7 @@ function CompactStrip({ layout, maxHeight }: { layout: "bottom" | "right"; maxHe type="button" onClick={() => actions.toggle?.(entry.key)} className={cn( - "hover:bg-muted/50 flex min-w-0 max-w-full items-center gap-1.5 rounded px-1 py-0.5 select-none", + "hover:bg-surface-sunken flex min-w-0 max-w-full items-center gap-1.5 rounded-sm px-1 py-0.5 select-none", isHidden && "opacity-40", )} title={entry.label} @@ -212,7 +212,7 @@ function StatsTable({ key={entry.key} onClick={() => actions.toggle?.(entry.key)} className={cn( - "hover:bg-muted/50 cursor-pointer select-none", + "hover:bg-surface-sunken cursor-pointer select-none", isHidden && "opacity-40", )} > @@ -237,7 +237,7 @@ function StatsTable({ diff --git a/packages/ui/src/components/plot/floating-tooltip.tsx b/packages/ui/src/components/plot/floating-tooltip.tsx index 57bd7a09e9..4cc8442611 100644 --- a/packages/ui/src/components/plot/floating-tooltip.tsx +++ b/packages/ui/src/components/plot/floating-tooltip.tsx @@ -78,7 +78,7 @@ export function useChartTooltipSuppressed(): boolean { * tooltip. Module-local: charts get it via `ChartFloatingTooltip`, never directly. */ export const chartTooltipCardClassName = - "border-border/50 bg-popover/90 text-popover-foreground rounded-xl border px-3 py-2 text-xs shadow-xl backdrop-blur-md" + "border-border-subtle bg-popover/90 text-popover-foreground rounded-xl border px-3 py-2 text-xs shadow-xl backdrop-blur-md" /** * Gates the position transition so a tooltip snaps to its anchor on first diff --git a/packages/ui/src/components/plot/plot-legend.tsx b/packages/ui/src/components/plot/plot-legend.tsx index 790a951a47..fac36c6e15 100644 --- a/packages/ui/src/components/plot/plot-legend.tsx +++ b/packages/ui/src/components/plot/plot-legend.tsx @@ -279,7 +279,7 @@ function PlotLegendItem({ seriesKey }: { seriesKey: string }) { onPointerEnter={() => actions.setActive(entry.key)} onFocus={() => actions.setActive(entry.key)} className={cn( - "flex items-center gap-1.5 rounded px-1 py-0.5 hover:bg-muted/50", + "flex items-center gap-1.5 rounded-sm px-1 py-0.5 hover:bg-surface-sunken", isMuted && "opacity-40", // Struck through as well as dimmed: opacity alone reads as "muted by // someone else's highlight", and the two states have to be told apart @@ -288,7 +288,7 @@ function PlotLegendItem({ seriesKey }: { seriesKey: string }) { // Emphasis is carried by the OTHERS fading, as it is in the chart — // brightening the picked row as well would double the contrast step and // make a two-series legend look broken. - !isHidden && (isActive || (!hovering && isHighlighted)) && "bg-muted/50", + !isHidden && (isActive || (!hovering && isHighlighted)) && "bg-surface-sunken", )} > diff --git a/packages/ui/src/components/plot/plot-tooltip.tsx b/packages/ui/src/components/plot/plot-tooltip.tsx index 04b7ef8fe8..77c2bc86e5 100644 --- a/packages/ui/src/components/plot/plot-tooltip.tsx +++ b/packages/ui/src/components/plot/plot-tooltip.tsx @@ -284,7 +284,7 @@ export function PlotTooltipBody({ return (

-
+
{heading(datum)}
diff --git a/packages/ui/src/components/traces/flamegraph-minimap.tsx b/packages/ui/src/components/traces/flamegraph-minimap.tsx index 8350320257..76dade09e7 100644 --- a/packages/ui/src/components/traces/flamegraph-minimap.tsx +++ b/packages/ui/src/components/traces/flamegraph-minimap.tsx @@ -111,7 +111,7 @@ export function FlamegraphMinimap({ return (
)} -
+
Minimap
diff --git a/packages/ui/src/components/traces/flamegraph.tsx b/packages/ui/src/components/traces/flamegraph.tsx index 4a38ca4d87..8e0a9b376f 100644 --- a/packages/ui/src/components/traces/flamegraph.tsx +++ b/packages/ui/src/components/traces/flamegraph.tsx @@ -157,14 +157,14 @@ export function Flamegraph({ return (
-
+
Flamegraph {focusedSpan && ( <> - / + / {focusedSpan.spanName} - + ({formatDuration(focusedSpan.durationMs)}) @@ -275,8 +275,8 @@ export function Flamegraph({
-
-
+
+
Click diff --git a/packages/ui/src/components/traces/flow-edge.tsx b/packages/ui/src/components/traces/flow-edge.tsx index ff50bbd9ea..641ea412c0 100644 --- a/packages/ui/src/components/traces/flow-edge.tsx +++ b/packages/ui/src/components/traces/flow-edge.tsx @@ -54,7 +54,7 @@ export const TraceFlowEdge = memo(function TraceFlowEdge({ let label: React.ReactNode = null if (showLabel && data) { if (isMissing) { - label = hovered ? no data : null + label = hovered ? no data : null } else if (hovered) { const sharePct = formatShare(share) label = ( @@ -116,7 +116,7 @@ export const TraceFlowEdge = memo(function TraceFlowEdge({ className="pointer-events-none overflow-visible" >
- + {label}
diff --git a/packages/ui/src/components/traces/flow-node.tsx b/packages/ui/src/components/traces/flow-node.tsx index 5a6ea40e53..a359e33c68 100644 --- a/packages/ui/src/components/traces/flow-node.tsx +++ b/packages/ui/src/components/traces/flow-node.tsx @@ -101,7 +101,7 @@ function StatusBadge({ statusCode: string }) { const { platform, cacheInfo, httpInfo } = desc - const base = "shrink-0 rounded px-1.5 py-0.5 text-3xs font-semibold" + const base = "shrink-0 rounded-sm px-1.5 py-0.5 text-3xs font-semibold" if (platform?.outcome?.bad) { return ( @@ -170,9 +170,9 @@ export const FlowSpanNode = memo(function FlowSpanNode({ data }: FlowSpanNodePro
Missing span - +
-
Not ingested or dropped
+
Not ingested or dropped
{span.serviceName} - · + · {category.label} @@ -275,7 +275,7 @@ export const FlowSpanNode = memo(function FlowSpanNode({ data }: FlowSpanNodePro
{/* Cost rail: span duration as share of the trace */} -
+
-
+
Flow View
-
+
Click to select - | + | Scroll to zoom - | + | Drag to pan - | + |
{services.map((service) => (
@@ -244,7 +244,7 @@ export function TraceFlowView({
{presentCategories.length > 0 && ( <> - | + |
{presentCategories.map((category) => (
diff --git a/packages/ui/src/components/ui/alert-dialog.styles.ts b/packages/ui/src/components/ui/alert-dialog.styles.ts index 5414753c89..efba1bf8a4 100644 --- a/packages/ui/src/components/ui/alert-dialog.styles.ts +++ b/packages/ui/src/components/ui/alert-dialog.styles.ts @@ -17,7 +17,7 @@ export const alertDialogHeaderStyles = "flex flex-col gap-2 p-6 text-center max- export const alertDialogFooterStyles = "flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]" -export const alertDialogFooterDefaultStyles = "border-t bg-muted/72 py-4" +export const alertDialogFooterDefaultStyles = "border-t bg-surface-strong py-4" export const alertDialogFooterBareStyles = "pb-6" diff --git a/packages/ui/src/components/ui/badge.styles.ts b/packages/ui/src/components/ui/badge.styles.ts index 687eb9b775..a94024b4fa 100644 --- a/packages/ui/src/components/ui/badge.styles.ts +++ b/packages/ui/src/components/ui/badge.styles.ts @@ -38,9 +38,9 @@ export const badgeVariants = cva( info: TONE_SOFT.info, done: TONE_SOFT.done, // Neutral tinted chip: counts, kinds, quiet metadata. - muted: "bg-muted text-muted-foreground [button&,a&]:hover:bg-muted/80", + muted: "bg-muted text-muted-foreground [button&,a&]:hover:bg-surface-strong", // Bordered meta chip on the page surface: services, environments, reopen markers. - meta: "border-border/70 bg-background text-muted-foreground [button&,a&]:hover:bg-muted/50", + meta: "border-border-subtle bg-background text-muted-foreground [button&,a&]:hover:bg-surface-sunken", outline: "border-input bg-background text-foreground dark:bg-input/32 [button&,a&]:hover:bg-accent/50 dark:[button&,a&]:hover:bg-input/48", secondary: "bg-secondary text-secondary-foreground [button&,a&]:hover:bg-secondary/90", @@ -48,7 +48,7 @@ export const badgeVariants = cva( warn: TONE_SOFT.warn, // Tiny uppercase label chip (System, Current, Pinned). Sizes itself, so it // resets the size variant; recolour with className. - tag: "h-auto min-w-0 rounded-xs bg-muted px-1 py-px text-3xs text-muted-foreground uppercase tracking-wide sm:h-auto sm:min-w-0 sm:text-3xs [button&,a&]:hover:bg-muted/80 [button&,a&]:hover:text-foreground", + tag: "h-auto min-w-0 rounded-xs bg-muted px-1 py-px text-3xs text-muted-foreground uppercase tracking-wide sm:h-auto sm:min-w-0 sm:text-3xs [button&,a&]:hover:bg-surface-strong [button&,a&]:hover:text-foreground", }, }, }, diff --git a/packages/ui/src/components/ui/bubble.styles.ts b/packages/ui/src/components/ui/bubble.styles.ts index 37ba557286..42b7ca1c8e 100644 --- a/packages/ui/src/components/ui/bubble.styles.ts +++ b/packages/ui/src/components/ui/bubble.styles.ts @@ -13,7 +13,7 @@ export const bubbleVariants = cva( tinted: "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]", outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30", - ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50", + ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-surface-sunken", destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30", }, diff --git a/packages/ui/src/components/ui/calendar.styles.ts b/packages/ui/src/components/ui/calendar.styles.ts index 75be0d9fb1..0e4ada8917 100644 --- a/packages/ui/src/components/ui/calendar.styles.ts +++ b/packages/ui/src/components/ui/calendar.styles.ts @@ -10,7 +10,7 @@ export const calendarClassNames = { day: "size-(--cell-size) text-sm py-px", day_button: cn( calendarButtonStyles, - "in-data-disabled:pointer-events-none in-[.range-middle]:rounded-none in-[.range-end:not(.range-start)]:rounded-s-none in-[.range-start:not(.range-end)]:rounded-e-none in-[.range-middle]:in-data-selected:bg-accent in-data-selected:bg-primary in-[.range-middle]:in-data-selected:text-foreground in-data-disabled:text-muted-foreground/72 in-data-outside:text-muted-foreground/72 in-data-selected:in-data-outside:text-primary-foreground in-data-selected:text-primary-foreground in-data-disabled:line-through outline-none in-[[data-selected]:not(.range-middle)]:transition-[color,background-color,border-radius,box-shadow] focus-visible:z-1 focus-visible:ring-[3px] focus-visible:ring-ring/50", + "in-data-disabled:pointer-events-none in-[.range-middle]:rounded-none in-[.range-end:not(.range-start)]:rounded-s-none in-[.range-start:not(.range-end)]:rounded-e-none in-[.range-middle]:in-data-selected:bg-accent in-data-selected:bg-primary in-[.range-middle]:in-data-selected:text-foreground in-data-disabled:text-foreground-subtle in-data-outside:text-foreground-subtle in-data-selected:in-data-outside:text-primary-foreground in-data-selected:text-primary-foreground in-data-disabled:line-through outline-none in-[[data-selected]:not(.range-middle)]:transition-[color,background-color,border-radius,box-shadow] focus-visible:z-1 focus-visible:ring-[3px] focus-visible:ring-ring/50", ), dropdown: "absolute bg-popover inset-0 opacity-0", dropdown_root: @@ -27,8 +27,8 @@ export const calendarClassNames = { range_middle: "range-middle", range_start: "range-start", today: "*:after:pointer-events-none *:after:absolute *:after:bottom-1 *:after:start-1/2 *:after:z-1 *:after:size-[3px] *:after:-translate-x-1/2 *:after:rounded-full *:after:bg-primary [&[data-selected]:not(.range-middle)>*]:after:bg-background [&[data-disabled]>*]:after:bg-foreground/30 *:after:transition-colors", - week_number: "size-(--cell-size) p-0 text-xs font-medium text-muted-foreground/72", - weekday: "size-(--cell-size) p-0 text-xs font-medium text-muted-foreground/72", + week_number: "size-(--cell-size) p-0 text-xs font-medium text-foreground-subtle", + weekday: "size-(--cell-size) p-0 text-xs font-medium text-foreground-subtle", } export const calendarChevronStyles = "rtl:rotate-180" diff --git a/packages/ui/src/components/ui/command.styles.ts b/packages/ui/src/components/ui/command.styles.ts index 2e7a969fa7..b789847e92 100644 --- a/packages/ui/src/components/ui/command.styles.ts +++ b/packages/ui/src/components/ui/command.styles.ts @@ -5,7 +5,7 @@ export const commandDialogViewportStyles = "fixed inset-0 z-50 flex flex-col items-center px-4 py-[max(--spacing(4),4vh)] sm:py-[10vh]" export const commandDialogPopupStyles = - "relative row-start-2 flex max-h-105 min-h-0 w-full min-w-0 max-w-xl -translate-y-[calc(1.25rem*var(--nested-dialogs))] scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 outline-none transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:bg-muted/72 before:shadow-[0_1px_--theme(--color-black/4%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=scroll-area-viewport]:data-has-overflow-y:pe-1 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]" + "relative row-start-2 flex max-h-105 min-h-0 w-full min-w-0 max-w-xl -translate-y-[calc(1.25rem*var(--nested-dialogs))] scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border bg-popover not-dark:bg-clip-padding text-popover-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-lg/5 outline-none transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:bg-surface-strong before:shadow-[0_1px_--theme(--color-black/4%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 **:data-[slot=scroll-area-viewport]:data-has-overflow-y:pe-1 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]" export const commandInputWrapperStyles = "px-2.5 py-1.5" @@ -24,7 +24,7 @@ export const commandItemStyles = "py-1.5" export const commandSeparatorStyles = "my-2" export const commandShortcutStyles = - "ms-auto font-medium font-sans text-muted-foreground/72 text-xs tracking-widest" + "ms-auto font-medium font-sans text-foreground-subtle text-xs tracking-widest" export const commandFooterStyles = "flex items-center justify-between gap-2 rounded-b-[calc(var(--radius-2xl)-1px)] border-t px-5 py-3 text-muted-foreground text-xs" diff --git a/packages/ui/src/components/ui/delta.styles.ts b/packages/ui/src/components/ui/delta.styles.ts index 7eb9bc58a9..202b10565f 100644 --- a/packages/ui/src/components/ui/delta.styles.ts +++ b/packages/ui/src/components/ui/delta.styles.ts @@ -1,11 +1,11 @@ -export const deltaEmptyStyles = "tabular-nums text-muted-foreground/60" +export const deltaEmptyStyles = "tabular-nums text-foreground-subtle" export const deltaStyles = "inline-flex items-center gap-1 tabular-nums" -export const deltaMutedStyles = "text-muted-foreground/70" +export const deltaMutedStyles = "text-foreground-subtle" export const deltaGoodStyles = "text-severity-info" export const deltaBadStyles = "text-severity-error" -export const deltaSuffixStyles = "text-muted-foreground/50" +export const deltaSuffixStyles = "text-foreground-faint" diff --git a/packages/ui/src/components/ui/dialog.styles.ts b/packages/ui/src/components/ui/dialog.styles.ts index 3da57a88ab..94d7122f7f 100644 --- a/packages/ui/src/components/ui/dialog.styles.ts +++ b/packages/ui/src/components/ui/dialog.styles.ts @@ -20,7 +20,7 @@ export const dialogHeaderStyles = export const dialogFooterStyles = "flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end sm:rounded-b-[calc(var(--radius-2xl)-1px)]" -export const dialogFooterDefaultStyles = "border-t bg-muted/72 py-4" +export const dialogFooterDefaultStyles = "border-t bg-surface-strong py-4" export const dialogFooterBareStyles = "in-[[data-slot=dialog-popup]:has([data-slot=dialog-panel])]:pt-3 pt-4 pb-6" diff --git a/packages/ui/src/components/ui/eyebrow.styles.ts b/packages/ui/src/components/ui/eyebrow.styles.ts index 934ea9adcd..0910537728 100644 --- a/packages/ui/src/components/ui/eyebrow.styles.ts +++ b/packages/ui/src/components/ui/eyebrow.styles.ts @@ -8,7 +8,7 @@ export const eyebrowVariants = cva("font-medium uppercase text-muted-foreground" variant: { overline: "text-3xs tracking-[0.12em]", label: "text-2xs tracking-[0.08em]", - mono: "font-mono text-3xs tracking-[0.12em] text-muted-foreground/70", + mono: "font-mono text-3xs tracking-[0.12em] text-foreground-subtle", }, }, }) diff --git a/packages/ui/src/components/ui/filter-chip.styles.ts b/packages/ui/src/components/ui/filter-chip.styles.ts index 8cb495132f..58d563e2d7 100644 --- a/packages/ui/src/components/ui/filter-chip.styles.ts +++ b/packages/ui/src/components/ui/filter-chip.styles.ts @@ -3,7 +3,7 @@ import type { Tone } from "../../lib/tone" // One look for every on/off filter chip: muted when off, foreground + border when on. export const filterChipVariants = cva( - "inline-flex shrink-0 cursor-pointer select-none items-center gap-1.5 whitespace-nowrap rounded-md border font-medium text-xs outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 border-transparent bg-muted/40 text-muted-foreground hover:text-foreground data-pressed:bg-background data-pressed:text-foreground [&_svg:not([class*='size-'])]:size-3.5 [&_svg]:shrink-0", + "inline-flex shrink-0 cursor-pointer select-none items-center gap-1.5 whitespace-nowrap rounded-md border font-medium text-xs outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 border-transparent bg-surface-sunken text-muted-foreground hover:text-foreground data-pressed:bg-background data-pressed:text-foreground [&_svg:not([class*='size-'])]:size-3.5 [&_svg]:shrink-0", { defaultVariants: { size: "sm" }, variants: { diff --git a/packages/ui/src/components/ui/inline-code.styles.ts b/packages/ui/src/components/ui/inline-code.styles.ts index 675c7bfbe2..094c24b4f2 100644 --- a/packages/ui/src/components/ui/inline-code.styles.ts +++ b/packages/ui/src/components/ui/inline-code.styles.ts @@ -1,5 +1,5 @@ export const inlineCodeStyles = "font-mono text-[0.9em]" -export const inlineCodeChipStyles = "rounded bg-muted px-1 py-px text-foreground" +export const inlineCodeChipStyles = "rounded-sm bg-muted px-1 py-px text-foreground" export const inlineCodePlainStyles = "text-muted-foreground" diff --git a/packages/ui/src/components/ui/input.styles.ts b/packages/ui/src/components/ui/input.styles.ts index b33c0579e8..b462d2192e 100644 --- a/packages/ui/src/components/ui/input.styles.ts +++ b/packages/ui/src/components/ui/input.styles.ts @@ -10,7 +10,7 @@ export const inputControlChromeStyles = "rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-autofill:bg-foreground/4 has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-autofill:bg-foreground/8 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]" export const inputStyles = - "h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none [transition:background-color_5000000s_ease-in-out_0s] placeholder:text-muted-foreground/72 sm:h-7.5 sm:leading-7.5" + "h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none [transition:background-color_5000000s_ease-in-out_0s] placeholder:text-foreground-subtle sm:h-7.5 sm:leading-7.5" export const inputSmStyles = "h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5" diff --git a/packages/ui/src/components/ui/item.styles.ts b/packages/ui/src/components/ui/item.styles.ts index 80a0d5fcad..b580bd309c 100644 --- a/packages/ui/src/components/ui/item.styles.ts +++ b/packages/ui/src/components/ui/item.styles.ts @@ -7,9 +7,9 @@ export const itemVariants = cva( variant: { default: "border-transparent", outline: "border-border", - muted: "bg-muted/50 border-transparent", + muted: "bg-surface-sunken border-transparent", // Raised panel row on the page surface (integration headers, linked resources). - card: "rounded-lg border-border/60 bg-card", + card: "rounded-lg border-border-subtle bg-card", // Row inside a `divide-y` list: no frame of its own. flush: "rounded-none border-transparent", }, diff --git a/packages/ui/src/components/ui/kbd.styles.ts b/packages/ui/src/components/ui/kbd.styles.ts index 71687c45dd..9ea1fd1e9e 100644 --- a/packages/ui/src/components/ui/kbd.styles.ts +++ b/packages/ui/src/components/ui/kbd.styles.ts @@ -1,4 +1,4 @@ export const kbdStyles = - "pointer-events-none inline-flex h-5 min-w-5 select-none items-center justify-center gap-1 rounded bg-muted px-1 font-medium font-sans text-muted-foreground text-xs [&_svg:not([class*='size-'])]:size-3" + "pointer-events-none inline-flex h-5 min-w-5 select-none items-center justify-center gap-1 rounded-sm bg-muted px-1 font-medium font-sans text-muted-foreground text-xs [&_svg:not([class*='size-'])]:size-3" export const kbdGroupStyles = "inline-flex items-center gap-1" diff --git a/packages/ui/src/components/ui/key-value.styles.ts b/packages/ui/src/components/ui/key-value.styles.ts index bf37cad4d8..86771b6843 100644 --- a/packages/ui/src/components/ui/key-value.styles.ts +++ b/packages/ui/src/components/ui/key-value.styles.ts @@ -8,7 +8,7 @@ export const keyValueListInlineStyles = "flex flex-wrap items-baseline gap-x-4 g export const keyValueListSplitStyles = "flex flex-col gap-1.5" -export const keyValueListDividedStyles = "gap-y-0 divide-y divide-border/60 [&>div]:py-1.5" +export const keyValueListDividedStyles = "gap-y-0 divide-y divide-border-subtle [&>div]:py-1.5" export const keyValueStyles = "min-w-0" diff --git a/packages/ui/src/components/ui/list-row.styles.ts b/packages/ui/src/components/ui/list-row.styles.ts index d918d1feda..959b2f085f 100644 --- a/packages/ui/src/components/ui/list-row.styles.ts +++ b/packages/ui/src/components/ui/list-row.styles.ts @@ -8,11 +8,11 @@ export const ROW_LANE = /** Lane + tint for a selected row, transparent lane otherwise. */ export function rowSelectedClass(selected: boolean | undefined): string { - return cn(ROW_LANE, selected ? "bg-muted/60 before:bg-primary" : "before:bg-transparent") + return cn(ROW_LANE, selected ? "bg-surface-strong before:bg-primary" : "before:bg-transparent") } export const listRowVariants = cva( - "flex w-full min-w-0 items-center gap-3 text-left outline-none transition-colors hover:bg-muted/50 focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", + "flex w-full min-w-0 items-center gap-3 text-left outline-none transition-colors hover:bg-surface-sunken focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", { defaultVariants: { density: "default", divided: false }, variants: { @@ -22,7 +22,7 @@ export const listRowVariants = cva( }, divided: { false: "", - true: "border-b border-border/60 last:border-b-0", + true: "border-b border-border-subtle last:border-b-0", }, }, }, diff --git a/packages/ui/src/components/ui/meter.styles.ts b/packages/ui/src/components/ui/meter.styles.ts index 16572fdd89..edd62cddbd 100644 --- a/packages/ui/src/components/ui/meter.styles.ts +++ b/packages/ui/src/components/ui/meter.styles.ts @@ -1,10 +1,10 @@ -export const meterStyles = "relative h-1 min-w-0 overflow-hidden rounded-full bg-muted/60" +export const meterStyles = "relative h-1 min-w-0 overflow-hidden rounded-full bg-surface-strong" export const meterFillStyles = "absolute inset-y-0 left-0 rounded-[inherit] transition-[width] duration-500" export const meterFillUntonedStyles = "bg-primary/60" -export const segmentedBarStyles = "flex h-1.5 min-w-0 overflow-hidden rounded-full bg-muted/60" +export const segmentedBarStyles = "flex h-1.5 min-w-0 overflow-hidden rounded-full bg-surface-strong" export const segmentedBarSegmentStyles = "h-full transition-[width] duration-500" diff --git a/packages/ui/src/components/ui/navigation-menu.styles.ts b/packages/ui/src/components/ui/navigation-menu.styles.ts index 88e570abf5..60242fef6a 100644 --- a/packages/ui/src/components/ui/navigation-menu.styles.ts +++ b/packages/ui/src/components/ui/navigation-menu.styles.ts @@ -1,7 +1,7 @@ import { cva } from "class-variance-authority" export const navigationMenuTriggerStyle = cva( - "bg-background hover:bg-muted focus:bg-muted data-open:hover:bg-muted data-open:focus:bg-muted data-open:bg-muted/50 focus-visible:ring-ring/50 data-popup-open:bg-muted/50 data-popup-open:hover:bg-muted rounded-lg px-2.5 py-1.5 text-xs font-medium transition-all focus-visible:ring-1 focus-visible:outline-1 disabled:opacity-50 group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center disabled:pointer-events-none outline-none", + "bg-background hover:bg-muted focus:bg-muted data-open:hover:bg-muted data-open:focus:bg-muted data-open:bg-surface-sunken focus-visible:ring-ring/50 data-popup-open:bg-surface-sunken data-popup-open:hover:bg-muted rounded-lg px-2.5 py-1.5 text-xs font-medium transition-all focus-visible:ring-1 focus-visible:outline-1 disabled:opacity-50 group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center disabled:pointer-events-none outline-none", ) export const navigationMenuStyles = @@ -28,7 +28,7 @@ export const navigationMenuPopupStyles = export const navigationMenuViewportStyles = "relative size-full overflow-hidden" export const navigationMenuLinkStyles = - "data-active:focus:bg-muted data-active:hover:bg-muted data-active:bg-muted/50 focus-visible:ring-ring/50 hover:bg-muted focus:bg-muted flex items-center gap-2 rounded-lg p-2 text-xs transition-all outline-none focus-visible:ring-1 focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4 [[data-slot=navigation-menu-content]_&]:rounded-lg" + "data-active:focus:bg-muted data-active:hover:bg-muted data-active:bg-surface-sunken focus-visible:ring-ring/50 hover:bg-muted focus:bg-muted flex items-center gap-2 rounded-lg p-2 text-xs transition-all outline-none focus-visible:ring-1 focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4 [[data-slot=navigation-menu-content]_&]:rounded-lg" export const navigationMenuIndicatorStyles = "data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden" diff --git a/packages/ui/src/components/ui/panel.styles.ts b/packages/ui/src/components/ui/panel.styles.ts index 90fee48e3d..2c42179731 100644 --- a/packages/ui/src/components/ui/panel.styles.ts +++ b/packages/ui/src/components/ui/panel.styles.ts @@ -1,6 +1,6 @@ export const panelToneStyles = { default: "bg-card", - muted: "bg-muted/40", + muted: "bg-surface-sunken", background: "bg-background", } as const diff --git a/packages/ui/src/components/ui/select.styles.ts b/packages/ui/src/components/ui/select.styles.ts index 88dcb498da..efbccb3dc7 100644 --- a/packages/ui/src/components/ui/select.styles.ts +++ b/packages/ui/src/components/ui/select.styles.ts @@ -18,7 +18,7 @@ export const selectTriggerVariants = cva( export const selectTriggerIconClassName = "-me-1 size-4 opacity-80 sm:size-3.5" -export const selectButtonValueStyles = "flex-1 truncate in-data-placeholder:text-muted-foreground/72" +export const selectButtonValueStyles = "flex-1 truncate in-data-placeholder:text-foreground-subtle" export const selectButtonStyles = "min-w-0" diff --git a/packages/ui/src/components/ui/sheet.styles.ts b/packages/ui/src/components/ui/sheet.styles.ts index c258f7f55c..ed6dcca2be 100644 --- a/packages/ui/src/components/ui/sheet.styles.ts +++ b/packages/ui/src/components/ui/sheet.styles.ts @@ -38,7 +38,7 @@ export const sheetHeaderStyles = export const sheetFooterStyles = "flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end" -export const sheetFooterDefaultStyles = "border-t bg-muted/72 py-4" +export const sheetFooterDefaultStyles = "border-t bg-surface-strong py-4" export const sheetFooterBareStyles = "in-[[data-slot=sheet-popup]:has([data-slot=sheet-panel])]:pt-3 pt-4 pb-6" diff --git a/packages/ui/src/components/ui/tabs.styles.ts b/packages/ui/src/components/ui/tabs.styles.ts index 05a1548445..63d02d477c 100644 --- a/packages/ui/src/components/ui/tabs.styles.ts +++ b/packages/ui/src/components/ui/tabs.styles.ts @@ -5,7 +5,7 @@ export const tabsListStyles = export const tabsListVerticalStyles = "data-[orientation=vertical]:flex-col" -export const tabsListDefaultStyles = "rounded-lg bg-muted p-0.5 text-muted-foreground/72" +export const tabsListDefaultStyles = "rounded-lg bg-muted p-0.5 text-foreground-subtle" export const tabsListUnderlineStyles = "data-[orientation=vertical]:px-1 data-[orientation=horizontal]:py-1 *:data-[slot=tabs-tab]:hover:bg-accent" diff --git a/packages/ui/src/components/ui/toggle.styles.ts b/packages/ui/src/components/ui/toggle.styles.ts index 407d8d8464..923c0aea2e 100644 --- a/packages/ui/src/components/ui/toggle.styles.ts +++ b/packages/ui/src/components/ui/toggle.styles.ts @@ -47,7 +47,7 @@ export const toggleVariants = cva( // Hover tints the label, not the surface: a background on hover // competes with the selected pill sitting right next to it. "hover:bg-transparent hover:text-foreground", - "data-pressed:border-border/70 data-pressed:bg-background data-pressed:font-medium data-pressed:text-foreground data-pressed:shadow-sm", + "data-pressed:border-border-subtle data-pressed:bg-background data-pressed:font-medium data-pressed:text-foreground data-pressed:shadow-sm", "dark:data-pressed:border-white/10 dark:data-pressed:bg-input dark:hover:bg-transparent", ), }, diff --git a/packages/ui/src/components/ui/trace.styles.ts b/packages/ui/src/components/ui/trace.styles.ts index e52a0d2af4..1632e3689b 100644 --- a/packages/ui/src/components/ui/trace.styles.ts +++ b/packages/ui/src/components/ui/trace.styles.ts @@ -9,7 +9,7 @@ export const traceIconStyles = export const traceTitleStyles = "min-w-0 truncate motion-reduce:shimmer-none" -export const traceDescriptionStyles = "shrink-0 text-muted-foreground/70 tabular-nums" +export const traceDescriptionStyles = "shrink-0 text-foreground-subtle tabular-nums" export const traceCollapsibleStyles = "flex w-full min-w-0 flex-col" diff --git a/packages/ui/src/lib/error-rate.ts b/packages/ui/src/lib/error-rate.ts index 460da81a24..0dc49ca573 100644 --- a/packages/ui/src/lib/error-rate.ts +++ b/packages/ui/src/lib/error-rate.ts @@ -20,7 +20,7 @@ export function errorRateLevel(rate: number): ErrorRateLevel { export const ERROR_RATE_TEXT: Record = { crit: TONE_TEXT.crit, warn: TONE_TEXT.warn, - neutral: "text-foreground/80", + neutral: "text-foreground-soft", } satisfies Record export const ERROR_RATE_FILL: Record = { diff --git a/packages/ui/src/lib/latency-tone.ts b/packages/ui/src/lib/latency-tone.ts index 28b706f109..933c81e62a 100644 --- a/packages/ui/src/lib/latency-tone.ts +++ b/packages/ui/src/lib/latency-tone.ts @@ -70,7 +70,7 @@ export function latencyLevel(ms: number, scale: LatencyScale = "p95", budgetMs?: */ export const LATENCY_TEXT_TONE: Record = { quiet: "text-muted-foreground", - nominal: "text-foreground/70", + nominal: "text-foreground-soft", elevated: "text-foreground", slow: "text-severity-warn", critical: "text-severity-error", diff --git a/packages/ui/src/styles/tokens.css b/packages/ui/src/styles/tokens.css index e5f6750924..b5f4bf11a4 100644 --- a/packages/ui/src/styles/tokens.css +++ b/packages/ui/src/styles/tokens.css @@ -81,6 +81,15 @@ the dark-canvas value lives in .dark). */ --service-map-edge-core: oklch(1 0 0); --border-hairline: 1px; + /* Initials avatars: warm tiles near the primary amber, the same in both themes. */ + --avatar-1: oklch(0.7 0.15 59); + --avatar-2: oklch(0.76 0.13 80); + --avatar-3: oklch(0.66 0.14 40); + --avatar-4: oklch(0.68 0.1 25); + --avatar-5: oklch(0.72 0.07 65); + /* Data-residency region identity (onboarding region picker). */ + --region-us: oklch(0.628 0.193 17.9); + --region-eu: oklch(0.631 0.198 269.4); --severity-trace: oklch(0.552 0.016 285.938); /* zinc-500 */ --severity-debug: oklch(0.623 0.214 259.815); /* blue-500 */ --severity-info: oklch(0.696 0.17 162.48); /* emerald-500 */ @@ -414,6 +423,23 @@ --color-info-foreground: var(--info-foreground); --color-info: var(--info); --color-destructive-foreground: var(--destructive-foreground); + /* The opacity ladders, named. Text: soft (body copy a step under foreground), subtle (secondary + meta), faint (separators, placeholders, empty cells). Surfaces: faint wash, sunken (wells, row + hover), strong (selected, pressed). Use these instead of `/NN` modifiers on the base colours. */ + --color-foreground-soft: color-mix(in oklab, var(--foreground) 80%, transparent); + --color-foreground-subtle: color-mix(in oklab, var(--muted-foreground) 70%, transparent); + --color-foreground-faint: color-mix(in oklab, var(--muted-foreground) 45%, transparent); + --color-surface-faint: color-mix(in oklab, var(--muted) 20%, transparent); + --color-surface-sunken: color-mix(in oklab, var(--muted) 50%, transparent); + --color-surface-strong: color-mix(in oklab, var(--muted) 60%, transparent); + --color-border-subtle: color-mix(in oklab, var(--border) 60%, transparent); + --color-avatar-1: var(--avatar-1); + --color-avatar-2: var(--avatar-2); + --color-avatar-3: var(--avatar-3); + --color-avatar-4: var(--avatar-4); + --color-avatar-5: var(--avatar-5); + --color-region-us: var(--region-us); + --color-region-eu: var(--region-eu); @keyframes skeleton { from { transform: translateX(-100%);