From bde4cfc6a82ece017b2a273953da6c31da3daada Mon Sep 17 00:00:00 2001 From: Makisuo Date: Fri, 30 Oct 2026 19:37:49 +0100 Subject: [PATCH 1/2] style(web): one scale for type, icons, radii, hover, borders and timeline colours Pixel text sizes use the type tokens, icons sit on 12/14/16, bordered surfaces are rounded-md, row hovers are muted/50 with selected rows at muted/60, borders are border or border/60. The trace timeline bars and the service-map namespace labels mix their hue into the theme background, so light mode no longer gets near-black bars with unreadable labels. --- apps/web/src/charts/bucket-tooltip.ts | 13 +- apps/web/src/charts/histogram-chart.ts | 2 +- .../src/components/infra/severity-tokens.ts | 2 +- apps/web/src/page/agent-sessions/kit/tabs.ts | 2 +- .../page/agent-sessions/list/view-table.ts | 4 +- .../session/span-popover-details.ts | 205 ++++++++++++------ .../session/span-popover-messages.ts | 4 +- .../session/transcript-calls.ts | 4 +- .../session/transcript-lanes.ts | 4 +- .../session/transcript-messages.ts | 2 +- .../session/transcript-shell.ts | 2 +- .../session/transcript-turns.ts | 6 +- .../agent-sessions/session/view-header.ts | 2 +- .../page/agent-sessions/session/view-rail.ts | 4 +- .../agent-sessions/session/view-toolbar.ts | 2 +- .../agent-sessions/session/view-waterfall.ts | 2 +- .../tool/view-error-modal-payload.ts | 8 +- .../tool/view-error-modal-rail.ts | 6 +- .../tool/view-error-modal-samples.ts | 10 +- .../agent-sessions/tool/view-error-modal.ts | 2 +- .../page/agent-sessions/tool/view-errors.ts | 4 +- .../page/agent-sessions/tool/view-sessions.ts | 4 +- .../page/agent-sessions/tools-kit/table.ts | 4 +- .../page/agent-sessions/tools/view-table.ts | 2 +- apps/web/src/page/alerts/destination/view.ts | 2 +- .../src/page/alerts/editor/view-condition.ts | 2 +- .../web/src/page/alerts/editor/view-notify.ts | 2 +- apps/web/src/page/alerts/editor/view-sql.ts | 2 +- apps/web/src/page/alerts/hub/view-empty.ts | 2 +- apps/web/src/page/alerts/hub/view-inbox.ts | 6 +- apps/web/src/page/alerts/hub/view-rules.ts | 2 +- apps/web/src/page/alerts/shared/providers.ts | 4 +- .../src/page/alerts/uptime-form/view-kinds.ts | 2 +- apps/web/src/page/alerts/uptime-form/view.ts | 2 +- apps/web/src/page/analytics/view-ai-parts.ts | 6 +- apps/web/src/page/analytics/view-breakdown.ts | 140 ++++++++---- apps/web/src/page/analytics/view.ts | 2 +- .../src/page/anomalies/detail/view-body.ts | 4 +- apps/web/src/page/anomalies/kit/row.ts | 2 +- apps/web/src/page/anomalies/list/view-list.ts | 6 +- .../page/code-review/analytics/view-charts.ts | 2 +- .../page/code-review/analytics/view-lists.ts | 2 +- .../src/page/code-review/ci/view-tables.ts | 2 +- .../page/code-review/kit/review-sheet-more.ts | 4 +- .../code-review/pull-requests/view-table.ts | 2 +- .../web/src/page/dashboards/list/view-list.ts | 6 +- .../page/dashboards/templates/view-list.ts | 8 +- .../page/dashboards/templates/view-panel.ts | 4 +- .../src/page/dashboards/view/view-embed.ts | 88 ++++++-- .../src/page/dashboards/view/view-history.ts | 2 +- .../src/page/dashboards/view/view-share.ts | 80 +++++-- apps/web/src/page/errors/hub/view-list.ts | 8 +- apps/web/src/page/errors/hub/view-signal.ts | 4 +- .../src/page/errors/issue/view-activity.ts | 4 +- .../src/page/errors/issue/view-anomalies.ts | 2 +- apps/web/src/page/errors/issue/view-chart.ts | 2 +- .../cloudflare/list/view-accounts.ts | 2 +- .../cloudflare/list/view-tables.ts | 2 +- .../cloudflare/worker/view.ts | 4 +- .../cloudflare/zone/view-breakdown.ts | 6 +- .../cloudflare/zone/view-sections.ts | 2 +- .../gcp/list/view-resources.ts | 2 +- .../page/infra-integrations/gcp/list/view.ts | 4 +- .../infra-integrations/gcp/service-icon.ts | 2 +- .../gcp/workload/view-rail.ts | 2 +- .../gcp/workload/view-sql-peek.ts | 8 +- .../gcp/workload/view-sql.ts | 4 +- .../infra-integrations/gcp/workload/view.ts | 2 +- .../kit/filter-chip-rail.ts | 2 +- .../planetscale/db/view-breakdown.ts | 4 +- .../infra-integrations/planetscale/db/view.ts | 2 +- .../railway/list/view-table.ts | 7 +- .../supabase/list/view-bottom.ts | 6 +- .../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 +- .../supabase/project/view.ts | 5 +- apps/web/src/page/infra/kit/data-table.ts | 8 +- apps/web/src/page/infra/kit/meta-line.ts | 4 +- .../infra/kubernetes/pod-restarts-view.ts | 35 ++- .../src/page/infra/overview/view-findings.ts | 2 +- apps/web/src/page/integrations/view-aws.ts | 8 +- .../integrations/view-cloudflare-board.ts | 8 +- .../integrations/view-cloudflare-connected.ts | 2 +- .../integrations/view-cloudflare-zones.ts | 2 +- .../src/page/integrations/view-flow-github.ts | 2 +- .../page/integrations/view-flow-supabase.ts | 4 +- .../view-gcp-configure-collect.ts | 2 +- .../view-gcp-configure-method-choice.ts | 17 +- .../integrations/view-gcp-configure-script.ts | 30 ++- .../integrations/view-gcp-configure-status.ts | 41 +++- .../page/integrations/view-gcp-connection.ts | 2 +- .../integrations/view-gcp-setup-methods.ts | 2 +- .../page/integrations/view-gcp-workloads.ts | 8 +- .../page/integrations/view-github-repos.ts | 10 +- apps/web/src/page/integrations/view-github.ts | 2 +- apps/web/src/page/integrations/view-hub.ts | 4 +- .../integrations/view-prometheus-details.ts | 2 +- .../web/src/page/integrations/view-railway.ts | 2 +- .../src/page/integrations/view-supabase.ts | 2 +- .../conversation/kit/view-cards.ts | 2 +- .../conversation/kit/view-code.ts | 2 +- .../conversation/kit/view-inline.ts | 2 +- .../page/investigations/detail/view-canvas.ts | 12 +- .../detail/view-diagnosis-card.ts | 4 +- .../investigations/detail/view-verdict.ts | 4 +- apps/web/src/page/kit/commit-card.ts | 2 +- apps/web/src/page/kit/connect-flow.ts | 14 +- apps/web/src/page/kit/guided-setup.ts | 2 +- .../src/page/kit/infra-correlation/view.ts | 2 +- apps/web/src/page/kit/message-response.ts | 4 +- apps/web/src/page/kit/refresh-controls.ts | 2 +- apps/web/src/page/kit/series-legend.ts | 2 +- apps/web/src/page/kit/time-range-picker.ts | 6 +- apps/web/src/page/kit/timezone-select-view.ts | 2 +- apps/web/src/page/logs/detail/view-meta.ts | 2 +- apps/web/src/page/logs/detail/view-panels.ts | 6 +- apps/web/src/page/logs/list/view-toolbar.ts | 2 +- apps/web/src/page/logs/live-controls.ts | 2 +- .../src/page/onboarding/create-org-view.ts | 4 +- .../src/page/onboarding/pricing-cards-view.ts | 2 +- .../page/onboarding/quick-start-team-view.ts | 4 +- .../src/page/onboarding/quick-start-view.ts | 14 +- .../src/page/overview/setup-checklist-view.ts | 4 +- apps/web/src/page/recommendations/view.ts | 2 +- apps/web/src/page/replays/detail/view-rail.ts | 6 +- .../src/page/replays/detail/view-session.ts | 4 +- .../src/page/replays/detail/view-timeline.ts | 4 +- .../web/src/page/replays/kit/sessions-list.ts | 2 +- 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 | 6 +- .../page/service-map/view-service-infra.ts | 13 +- .../services/detail/endpoint-peek/view.ts | 2 +- .../src/page/services/detail/view-api-tab.ts | 6 +- apps/web/src/page/services/detail/view-api.ts | 2 +- .../page/services/detail/view-dependencies.ts | 2 +- .../page/services/detail/view-footprint.ts | 2 +- .../page/services/detail/view-operations.ts | 2 +- .../src/page/services/detail/view-panels.ts | 2 +- apps/web/src/page/settings/audit-log/view.ts | 2 +- .../src/page/settings/billing/details/view.ts | 2 +- .../src/page/settings/billing/view-plan.ts | 6 +- .../src/page/settings/billing/view-records.ts | 2 +- .../src/page/settings/data-platform/view.ts | 6 +- .../settings/ingestion/mapping-dialog-view.ts | 2 +- .../settings/ingestion/view-ingest-rules.ts | 2 +- .../src/page/settings/ingestion/view-rules.ts | 4 +- .../src/page/settings/keys/view-reference.ts | 2 +- apps/web/src/page/settings/keys/view-table.ts | 6 +- apps/web/src/page/settings/mcp/view-tools.ts | 2 +- .../src/page/settings/setup-health/view.ts | 2 +- apps/web/src/page/sources/kit/rules-view.ts | 2 +- apps/web/src/page/sources/list/view.ts | 2 +- apps/web/src/page/sources/new/view-picker.ts | 4 +- .../src/page/traces/detail/depth-controls.ts | 2 +- .../traces/detail/span-panel/attributes.ts | 4 +- .../traces/detail/span-panel/error-section.ts | 2 +- .../traces/detail/span-panel/view-tabs.ts | 2 +- .../src/page/traces/detail/timeline/layout.ts | 22 +- .../traces/detail/timeline/view-chrome.ts | 4 +- .../page/traces/detail/timeline/view-row.ts | 6 +- .../src/page/traces/detail/waterfall/row.ts | 2 +- apps/web/src/page/traces/list/view-row.ts | 2 +- apps/web/src/service-map/map/edge.ts | 2 +- .../src/service-map/map/namespace-group.ts | 5 +- apps/web/src/service-map/trace-flow/edge.ts | 2 +- .../src/service-map/trace-flow/node-card.ts | 4 +- apps/web/src/shell/connect-panel-view.ts | 6 +- .../src/shell/onboarding-checklist-view.ts | 2 +- apps/web/src/shell/palette/shortcuts-view.ts | 2 +- apps/web/src/ui/attributes/attribute-row.ts | 2 +- apps/web/src/ui/attributes/attributes-view.ts | 6 +- apps/web/src/ui/detail-rail.ts | 4 +- apps/web/src/ui/error-section.ts | 2 +- apps/web/src/ui/logs/log-row-expanded.ts | 2 +- apps/web/src/ui/logs/log-row.ts | 10 +- .../ui/src/components/ui/list-row.styles.ts | 2 +- 180 files changed, 794 insertions(+), 491 deletions(-) diff --git a/apps/web/src/charts/bucket-tooltip.ts b/apps/web/src/charts/bucket-tooltip.ts index 4ca459214e..3a8ca13943 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/50 border-b pb-1 font-medium text-muted-foreground tracking-tight")], + [h.Class("border-border/60 border-b pb-1 font-medium text-muted-foreground tracking-tight")], [tooltip.heading], ), h.div( @@ -72,10 +72,17 @@ export const bucketTooltipBody = ( ? [] : [ h.div( - [h.Class("flex items-center justify-between gap-3 border-border/50 border-t pt-1.5 leading-none")], + [ + h.Class( + "flex items-center justify-between gap-3 border-border/60 border-t pt-1.5 leading-none", + ), + ], [ h.span([h.Class("text-muted-foreground")], ["Total"]), - h.span([h.Class("font-mono font-semibold text-foreground tabular-nums")], [tooltip.total]), + h.span( + [h.Class("font-mono font-semibold text-foreground tabular-nums")], + [tooltip.total], + ), ], ), ]), diff --git a/apps/web/src/charts/histogram-chart.ts b/apps/web/src/charts/histogram-chart.ts index d1b7a5d7a1..248d14817c 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/50 border-b pb-1 font-medium text-muted-foreground tracking-tight")], + [h.Class("border-border/60 border-b pb-1 font-medium text-muted-foreground tracking-tight")], [heading], ), h.div( diff --git a/apps/web/src/components/infra/severity-tokens.ts b/apps/web/src/components/infra/severity-tokens.ts index 58ff624abb..2a39562e21 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/75", + ok: "text-foreground/70", warn: TONE_TEXT.warn, crit: TONE_TEXT.crit, } satisfies Record diff --git a/apps/web/src/page/agent-sessions/kit/tabs.ts b/apps/web/src/page/agent-sessions/kit/tabs.ts index 2bea8df74e..60609c3cf3 100644 --- a/apps/web/src/page/agent-sessions/kit/tabs.ts +++ b/apps/web/src/page/agent-sessions/kit/tabs.ts @@ -44,7 +44,7 @@ const tabLink = ( h.Href(options.href), ], [ - icon(h, options.iconName, { size: 13, attributes: [h.AriaHidden(true)] }), + icon(h, options.iconName, { size: 14, attributes: [h.AriaHidden(true)] }), options.label, ...(options.count === undefined ? [] 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 751adc1e53..3da409dc2b 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-[10px] font-normal text-muted-foreground/70", + "ml-0.5 whitespace-nowrap text-3xs font-normal text-muted-foreground/70", ), ], [column.subLabel], @@ -245,7 +245,7 @@ const sessionCell = (h: H, row: DisplayRow, context: RowContext): Html => { ], [ icon(h, vendorIcon(row.vendorId), { - size: 15, + size: 16, style: { color: vendorColor(row.vendorId) }, attributes: [h.AriaHidden(true)], }), 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 61ccbe38bd..5eed4377df 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 @@ -1,5 +1,13 @@ import type { AiSessionSpan } from "@maple/domain/http" -import { classifyAiSpan, formatCost, payload, spanCost, spanFailed, type SpanToolCall, spanTtftMs } from "@maple/agent-sessions" +import { + classifyAiSpan, + formatCost, + payload, + spanCost, + spanFailed, + type SpanToolCall, + spanTtftMs, +} from "@maple/agent-sessions" import { formatTimestampInTimezone } from "@maple/web-data/lib/timezone-format" import { formatDuration, formatNumber } from "@maple/ui/lib/format" import { shortId } from "@maple/ui/lib/ids" @@ -38,7 +46,7 @@ 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/70")], + [h.Class("min-w-0 overflow-hidden rounded-md border border-border/60")], [ h.div( [h.Class("flex items-center gap-2 bg-muted/40 px-2.5 py-1.5")], @@ -47,7 +55,13 @@ const toolCallCard = ( h.span([h.Class("shrink-0 font-medium font-mono text-chart-4 text-xs")], ["tool"]), ...(call.name === undefined ? [] - : [truncatedText(h, { text: call.name, mono: true, className: "text-foreground text-xs" })]), + : [ + truncatedText(h, { + text: call.name, + mono: true, + className: "text-foreground text-xs", + }), + ]), ...(call.id === undefined ? [] : [ @@ -61,7 +75,16 @@ const toolCallCard = ( ), ...(call.description === undefined ? [] - : [h.p([h.Class("border-border/60 border-t px-2.5 py-1.5 text-muted-foreground text-xs")], [call.description])]), + : [ + h.p( + [ + h.Class( + "border-border/60 border-t px-2.5 py-1.5 text-muted-foreground text-xs", + ), + ], + [call.description], + ), + ]), ...toolIo(h, model, { args: payload(call.argumentsText), result: payload(call.resultText), @@ -78,14 +101,19 @@ const failureBanner = (b: HtmlBuilder, span: AiSessionSpan): Html => { const errorType = span.genAi.errorType const responseStatus = span.genAi.responseStatus const hasErrorType = errorType !== undefined && errorType !== "" - const pill = (text: string) => badge(b, { pill: true, size: "xs", mono: true, className: TONE_SOFT.crit }, [text]) + const pill = (text: string) => + badge(b, { pill: true, size: "xs", mono: true, className: TONE_SOFT.crit }, [text]) 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")], + [ + b.Class( + "flex flex-col gap-1.5 rounded-md border border-severity-error/40 bg-severity-error/5 px-3 py-2.5", + ), + ], [ b.div( [b.Class("flex flex-wrap items-center gap-2")], [ - icon(b, "CircleWarningIcon", { size: 13, className: "shrink-0 text-severity-error" }), + icon(b, "CircleWarningIcon", { size: 14, className: "shrink-0 text-severity-error" }), b.span([b.Class("font-medium text-ui text-severity-error")], ["This call failed"]), ...(span.statusCode === "Error" ? [pill("span status Error")] : []), ...(hasErrorType ? [pill(`error.type ${errorType}`)] : []), @@ -96,7 +124,9 @@ const failureBanner = (b: HtmlBuilder, span: AiSessionSpan): Html => { ), b.p( [b.Class("text-muted-foreground text-xs leading-relaxed")], - ["The pills here are the attributes the failure was read from; the span carries no status message."], + [ + "The pills here are the attributes the failure was read from; the span carries no status message.", + ], ), ], ) @@ -130,7 +160,10 @@ const identityRows = (p: P, state: PanelState, span: AiSessionSpan, timeZone: st ["Started", formatTimestampInTimezone(span.timestamp, { timeZone, withMilliseconds: true })], ["Duration", formatDuration(span.durationMs)], ["Time to first token", ttftMs === undefined ? undefined : formatDuration(ttftMs)], - ["Status", span.statusMessage === "" ? span.statusCode : `${span.statusCode} · ${span.statusMessage}`], + [ + "Status", + span.statusMessage === "" ? span.statusCode : `${span.statusCode} · ${span.statusMessage}`, + ], ["Kind", span.spanKind], ["Service", span.serviceName], ["Span ID", span.spanId], @@ -139,23 +172,26 @@ const identityRows = (p: P, state: PanelState, span: AiSessionSpan, timeZone: st ] return keyValueList( p, - { layout: "grid", divided: true, className: "rounded-md border border-border/70 px-2.5" }, + { layout: "grid", divided: true, className: "rounded-md border border-border/60 px-2.5" }, rows.flatMap(([label, value]) => value === undefined ? [] : [ keyValue(p, { label, mono: true }, [ - copyableValue(p, state, { id: `identity:${label}`, value, className: "min-w-0" }, [ - p.span([p.Class("block truncate")], [value]), - ]), + copyableValue( + p, + state, + { id: `identity:${label}`, value, className: "min-w-0" }, + [p.span([p.Class("block truncate")], [value])], + ), ]), ], ), ) } -const identityView = Submodel.defineView((state, { span, timeZone }, p) => - identityRows(p, state, span, timeZone), +const identityView = Submodel.defineView( + (state, { span, timeZone }, p) => identityRows(p, state, span, timeZone), ) /** The span attributes once the lazy `spanDetail` read lands; its skeleton and failure meanwhile. */ @@ -164,74 +200,99 @@ const spanAttributesView = Submodel.defineView p.div( [p.Class("flex flex-col gap-2")], - [skeleton(p, "h-4 w-32"), skeleton(p, "h-24 w-full"), skeleton(p, "h-4 w-32"), skeleton(p, "h-24 w-full")], + [ + skeleton(p, "h-4 w-32"), + skeleton(p, "h-24 w-full"), + skeleton(p, "h-4 w-32"), + skeleton(p, "h-24 w-full"), + ], ), onFailure: () => emptyMessage(p, {}, ["Couldn't load this span's full attributes."]), onData: (detail) => - attributesSection(p, state, "span", detail.spanAttributes, "Span attributes", { isFilterable: false }), - }), -) - -const resourceAttributesView = Submodel.defineView((state, _inputs, p) => - AsyncData.matchData(state.detail.data, { - onEmpty: () => p.empty, - onFailure: () => p.empty, - onData: (detail) => - attributesSection(p, state, "resource", detail.resourceAttributes, "Resource attributes", { + attributesSection(p, state, "span", detail.spanAttributes, "Span attributes", { isFilterable: false, }), }), ) +const resourceAttributesView = Submodel.defineView( + (state, _inputs, p) => + AsyncData.matchData(state.detail.data, { + onEmpty: () => p.empty, + onFailure: () => p.empty, + onData: (detail) => + attributesSection(p, state, "resource", detail.resourceAttributes, "Resource attributes", { + isFilterable: false, + }), + }), +) + /** `LogsSection`: the trace panel's span logs, read once the tab is open. */ const logsView = Submodel.defineView((state, { timeZone }, p) => - p.div([p.Class("overflow-hidden rounded-md border border-border/70")], [spanLogs(p, state, timeZone)]), + p.div([p.Class("overflow-hidden rounded-md border border-border/60")], [spanLogs(p, state, timeZone)]), ) /** The call's own settings and identity, shown only where the span reported them. */ -const metaStripView = Submodel.defineView((state, { span, timeZone }, p) => { - const ttftMs = spanTtftMs(span) - const cost = spanCost(span) - const pairs: ReadonlyArray = [ - ["provider", span.genAi.providerName], - ["started", formatTimestampInTimezone(span.timestamp, { timeZone, withMilliseconds: true })], - ["ttft", ttftMs === undefined ? undefined : formatDuration(ttftMs)], - ["max_tokens", span.genAi.requestMaxTokens === undefined ? undefined : formatNumber(span.genAi.requestMaxTokens)], - ["temperature", span.genAi.requestTemperature], - ["cost", cost === undefined ? undefined : p.span([p.Class("text-primary")], [formatCost(cost)])], - ] - return p.div( - [p.Class("flex flex-wrap items-baseline gap-x-4 gap-y-1 py-2.5")], - [ - ...pairs.flatMap(([label, value]) => - value === undefined - ? [] - : [ - p.span( - [p.Class("flex items-baseline gap-1.5")], - [ - p.span([p.Class("text-2xs text-muted-foreground")], [label]), - p.span([p.Class("font-mono text-foreground text-xs")], [typeof value === "number" ? String(value) : value]), - ], - ), - ], - ), - p.span( - [p.Class("ml-auto flex items-baseline gap-1.5 font-mono text-2xs text-muted-foreground/70")], - [ - copyableValue(p, state, { id: "meta:span", value: span.spanId, label: "Span ID" }, ["span ", span.spanId]), - p.span([p.AriaHidden(true)], ["·"]), - copyableValue(p, state, { id: "meta:trace", value: span.traceId, label: "Trace ID" }, [ - "trace ", - shortId(span.traceId, "trace"), - "…", - span.traceId.slice(-4), - ]), - ], - ), - ], - ) -}) +const metaStripView = Submodel.defineView( + (state, { span, timeZone }, p) => { + const ttftMs = spanTtftMs(span) + const cost = spanCost(span) + const pairs: ReadonlyArray = [ + ["provider", span.genAi.providerName], + ["started", formatTimestampInTimezone(span.timestamp, { timeZone, withMilliseconds: true })], + ["ttft", ttftMs === undefined ? undefined : formatDuration(ttftMs)], + [ + "max_tokens", + span.genAi.requestMaxTokens === undefined + ? undefined + : formatNumber(span.genAi.requestMaxTokens), + ], + ["temperature", span.genAi.requestTemperature], + ["cost", cost === undefined ? undefined : p.span([p.Class("text-primary")], [formatCost(cost)])], + ] + return p.div( + [p.Class("flex flex-wrap items-baseline gap-x-4 gap-y-1 py-2.5")], + [ + ...pairs.flatMap(([label, value]) => + value === undefined + ? [] + : [ + p.span( + [p.Class("flex items-baseline gap-1.5")], + [ + p.span([p.Class("text-2xs text-muted-foreground")], [label]), + p.span( + [p.Class("font-mono text-foreground text-xs")], + [typeof value === "number" ? String(value) : value], + ), + ], + ), + ], + ), + p.span( + [ + p.Class( + "ml-auto flex items-baseline gap-1.5 font-mono text-2xs text-muted-foreground/70", + ), + ], + [ + copyableValue(p, state, { id: "meta:span", value: span.spanId, label: "Span ID" }, [ + "span ", + span.spanId, + ]), + p.span([p.AriaHidden(true)], ["·"]), + copyableValue( + p, + state, + { id: "meta:trace", value: span.traceId, label: "Trace ID" }, + ["trace ", shortId(span.traceId, "trace"), "…", span.traceId.slice(-4)], + ), + ], + ), + ], + ) + }, +) export const metaStrip = (h: H, model: Model, span: AiSessionSpan, timeZone: string): Html => panelPart(h, model, "meta", metaStripView, { span, timeZone }) @@ -265,7 +326,9 @@ export const detailsSection = ( const inputs = { span, timeZone: options.timeZone } const isFailed = spanFailed(span) const failedToolResult = - isFailed && classifyAiSpan(span) === "tool" ? toolCalls.find((call) => call.own)?.resultText : undefined + isFailed && classifyAiSpan(span) === "tool" + ? toolCalls.find((call) => call.own)?.resultText + : undefined return h.div( [h.Class("flex flex-col gap-3 pb-1")], [ 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 5139ec9526..7d1f0751bf 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,7 +72,7 @@ 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/70")], + [h.Class("min-w-0 overflow-hidden rounded-md border border-border/60")], [ h.div( [h.Class("flex items-center gap-2 bg-muted/40 px-2.5 py-1.5")], @@ -275,7 +275,7 @@ const systemMessageRow = (h: H, model: Model, message: SpanMessage, key: string) ], [ icon(h, isOpen ? "ChevronDownIcon" : "ChevronRightIcon", { - size: 11, + size: 12, className: "shrink-0 text-muted-foreground", }), eyebrow(h, { variant: "mono", className: "shrink-0" }, [message.role]), 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 00c8b2bef8..00d64f3efa 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/40", + "-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", rowSelectedClass(isSelected), ), ), @@ -281,7 +281,7 @@ export const structureRow = ( ], [ icon(h, STRUCTURE_ICON[category], { - size: 13, + size: 14, className: cn( "shrink-0", structure.failed ? "text-severity-error" : STRUCTURE_TONE[category], 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 79499f7fde..961452b84a 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-lanes.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-lanes.ts @@ -187,7 +187,7 @@ export const noteBlock = (h: H, note: Extract): h.div( [h.Class("flex items-center gap-2.5")], [ - icon(h, "CircleInfoIcon", { size: 13, className: "shrink-0 text-muted-foreground" }), + icon(h, "CircleInfoIcon", { size: 14, className: "shrink-0 text-muted-foreground" }), h.span([h.Class(cn(LABEL, "text-muted-foreground"))], ["Capture changes here"]), h.span( [h.Class("min-w-0 text-muted-foreground text-xs")], @@ -206,7 +206,7 @@ export const noteBlock = (h: H, note: Extract): 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")], [ - icon(h, "CircleInfoIcon", { size: 15, className: "mt-0.5 shrink-0 text-muted-foreground" }), + icon(h, "CircleInfoIcon", { size: 16, className: "mt-0.5 shrink-0 text-muted-foreground" }), h.div( [h.Class("flex min-w-0 grow flex-col gap-1")], [ 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 1e8cfe6d21..5713a426a3 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-messages.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-messages.ts @@ -106,7 +106,7 @@ export const userBlock = ( ]) const chevron = (h: H, isOpen: boolean, className: string): Html => - icon(h, isOpen ? "ChevronDownIcon" : "ChevronRightIcon", { size: 11, className }) + icon(h, isOpen ? "ChevronDownIcon" : "ChevronRightIcon", { size: 12, className }) const systemCoverage = (calls: number, turnCalls: number): string => calls >= turnCalls diff --git a/apps/web/src/page/agent-sessions/session/transcript-shell.ts b/apps/web/src/page/agent-sessions/session/transcript-shell.ts index 4c2a11f2c0..0f3dd741aa 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-shell.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-shell.ts @@ -82,7 +82,7 @@ export const inlineNote = (h: H, children: ReadonlyArray, classNa ), ], [ - icon(h, "CircleQuestionIcon", { size: 13, className: "mt-0.5 shrink-0 text-muted-foreground" }), + icon(h, "CircleQuestionIcon", { size: 14, className: "mt-0.5 shrink-0 text-muted-foreground" }), h.p([h.Class("min-w-0 text-muted-foreground text-xs leading-relaxed")], children), ], ) diff --git a/apps/web/src/page/agent-sessions/session/transcript-turns.ts b/apps/web/src/page/agent-sessions/session/transcript-turns.ts index 925d5db5f3..6ec24a308d 100644 --- a/apps/web/src/page/agent-sessions/session/transcript-turns.ts +++ b/apps/web/src/page/agent-sessions/session/transcript-turns.ts @@ -57,11 +57,11 @@ export const turnChapter = ( ...(isCollapsed ? [] : [rule(h)]), isCollapsed ? icon(h, "ChevronRightIcon", { - size: 11, + size: 12, className: "shrink-0 text-muted-foreground", }) : icon(h, "ChevronDownIcon", { - size: 11, + size: 12, className: "shrink-0 text-muted-foreground opacity-0 group-hover/turn:opacity-100", }), @@ -115,7 +115,7 @@ export const emptyTurnRow = (h: H, chapter: Extract { [h.Key(band.kind), h.Class("flex items-center gap-2.5")], [ icon(h, AGENT_TIME_ICON[band.kind], { - size: 13, + size: 14, className: cn("shrink-0", AGENT_TIME_TEXT[band.kind]), attributes: [h.AriaHidden(true)], }), @@ -180,7 +180,7 @@ const tokensSection = (h: H, summary: SessionSummary): Html => { [h.Key(bucket.key), h.Class("flex items-center gap-2.5")], [ icon(h, bucket.icon, { - size: 13, + size: 14, className: cn("shrink-0", bucket.text), attributes: [h.AriaHidden(true)], }), diff --git a/apps/web/src/page/agent-sessions/session/view-toolbar.ts b/apps/web/src/page/agent-sessions/session/view-toolbar.ts index 7338106111..e1bfcd2217 100644 --- a/apps/web/src/page/agent-sessions/session/view-toolbar.ts +++ b/apps/web/src/page/agent-sessions/session/view-toolbar.ts @@ -126,7 +126,7 @@ const displayOptions = (h: H, model: Model, view: SessionView): Html => { ], }, [ - icon(h, "SlidersIcon", { size: 13, className: "text-muted-foreground" }), + icon(h, "SlidersIcon", { size: 14, className: "text-muted-foreground" }), "Display", h.span( [h.Class("text-muted-foreground tabular-nums")], 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 102902909b..2d1976ee03 100644 --- a/apps/web/src/page/agent-sessions/session/view-waterfall.ts +++ b/apps/web/src/page/agent-sessions/session/view-waterfall.ts @@ -287,7 +287,7 @@ const spanCell = ( ], [ icon(h, isErrored ? "CircleXmarkIcon" : CATEGORY_ICON[category], { - size: 13, + size: 14, className: cn("shrink-0", isErrored ? "text-severity-error" : CATEGORY_TEXT[category]), attributes: [h.AriaHidden(true)], }), 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 ac07c0c128..0feaaa3b6d 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 @@ -75,7 +75,7 @@ const payloadLineView = (h: H, line: PayloadLine): Html => ? "text-foreground" : line.folded !== undefined ? "text-muted-foreground" - : "text-foreground/85", + : "text-foreground/80", ), ), ], @@ -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/85", + "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", ), ], [args === undefined ? row.arguments : JSON.stringify(args, null, 2)], @@ -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/85", + "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", ), ], [parsed === undefined ? row.result : JSON.stringify(parsed, null, 2)], @@ -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/85")], + [h.Class("text-xs leading-4 text-foreground/80")], [ h.span([h.Class("font-medium text-foreground")], [hint.subject]), " ", 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 d6ed0c1f6d..78d168ca95 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 @@ -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/40", + isSelected ? "bg-primary/10" : "hover:bg-muted/50", ), ), h.Title(unwrapToolErrorText(row.message).text), @@ -187,9 +187,9 @@ export const sessionLink = ( const sessionRowClass = (isSelected: boolean) => cn( - "group flex w-full shrink-0 items-center gap-3 border-b border-border/50 pr-4 pl-4 text-left transition-colors", + "group flex w-full shrink-0 items-center gap-3 border-b border-border/60 pr-4 pl-4 text-left transition-colors", rowSelectedClass(isSelected), - !isSelected && "hover:bg-muted/30", + !isSelected && "hover:bg-muted/50", ) const LAST_CLASS = "w-14 shrink-0 text-right font-mono text-2xs tabular-nums text-muted-foreground/70" 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 2a95dfaced..f1e1d8e5b0 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 @@ -185,14 +185,14 @@ const sampleRow = ( [ h.Key(row.spanId), h.DataAttribute("slot", "tool-error-sample"), - h.Class("border-b border-border/50"), + h.Class("border-b border-border/60"), ], [ h.div( [ h.Class( cn( - "group relative flex w-full items-center gap-3.5 px-6 font-mono transition-colors hover:bg-muted/30", + "group relative flex w-full items-center gap-3.5 px-6 font-mono transition-colors hover:bg-muted/50", options.isOpen ? "h-11" : "h-10", ), ), @@ -253,7 +253,7 @@ const sampleRow = ( "hidden shrink-0 rounded-sm border border-border px-[5px] text-2xs leading-3.5 text-muted-foreground/70 md:block", ), ], - ["variant ", h.span([h.Class("text-foreground/85")], [options.variant])], + ["variant ", h.span([h.Class("text-foreground/80")], [options.variant])], ), ]), h.span([h.Class("grow")], []), @@ -270,7 +270,7 @@ const sampleRow = ( ), ]), h.span( - [h.Class("w-12 shrink-0 text-right text-xs tabular-nums text-foreground/85")], + [h.Class("w-12 shrink-0 text-right text-xs tabular-nums text-foreground/80")], [formatDurationNs(row.durationNs)], ), h.a( @@ -290,7 +290,7 @@ const sampleRow = ( ], [ "Open trace", - icon(h, "ExternalLinkIcon", { size: 11, attributes: [h.AriaHidden(true)] }), + icon(h, "ExternalLinkIcon", { size: 12, attributes: [h.AriaHidden(true)] }), ], ), ], 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 8a1d5de893..8d008ca0c9 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 @@ -349,7 +349,7 @@ const headerActions = (h: H, model: Model, inputs: ModalInputs): Html => { [ "Open in Sessions", icon(h, "ExternalLinkIcon", { - size: 11, + size: 12, className: "text-muted-foreground", attributes: [h.AriaHidden(true)], }), 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 d50d94a5d0..12d3d03ebe 100644 --- a/apps/web/src/page/agent-sessions/tool/view-errors.ts +++ b/apps/web/src/page/agent-sessions/tool/view-errors.ts @@ -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/50 px-2.5 last:border-0"), + h.Class("flex h-[38px] items-center gap-3 border-b border-border/60 px-2.5 last:border-0"), h.Style({ opacity: String(1 - index * 0.2) }), ], [ @@ -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/30", + "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", ), h.Type("button"), h.OnClick(Message.ToggledErrorsExpanded()), 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 b25572daae..13eb17b34c 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/30 focus-visible:bg-muted/30 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-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none", ), // `{ ...sessionLinkWindow(session), tool, view }` in that order. h.Href( @@ -168,7 +168,7 @@ export const sessionsPanel = (h: H, inputs: SessionsPanelInputs): Html => [ "Open in Sessions", icon(h, "ExternalLinkIcon", { - size: 11, + size: 12, className: "text-muted-foreground", attributes: [h.AriaHidden(true)], }), 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 c3d13796b9..b9b226fc6d 100644 --- a/apps/web/src/page/agent-sessions/tools-kit/table.ts +++ b/apps/web/src/page/agent-sessions/tools-kit/table.ts @@ -131,10 +131,10 @@ export const toolTableBody = ( ) const ROW = - "flex h-[38px] w-full shrink-0 items-center gap-3 border-b border-border/50 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/60 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/30 focus-visible:bg-muted/30") + cn(ROW, rowSelectedClass(isSelected), !isSelected && "hover:bg-muted/50 focus-visible:bg-muted/50") export const toolTableFooter = (h: HtmlBuilder, subject: string, detail: string): Html => h.div( diff --git a/apps/web/src/page/agent-sessions/tools/view-table.ts b/apps/web/src/page/agent-sessions/tools/view-table.ts index 86faf9532d..d1959c2ddb 100644 --- a/apps/web/src/page/agent-sessions/tools/view-table.ts +++ b/apps/web/src/page/agent-sessions/tools/view-table.ts @@ -100,7 +100,7 @@ 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/85" : "text-muted-foreground", + isDriving ? "text-foreground/80" : "text-muted-foreground", hidden, ), ), diff --git a/apps/web/src/page/alerts/destination/view.ts b/apps/web/src/page/alerts/destination/view.ts index 2b79287d37..c3997d1ba5 100644 --- a/apps/web/src/page/alerts/destination/view.ts +++ b/apps/web/src/page/alerts/destination/view.ts @@ -115,7 +115,7 @@ const providerTile = ( "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/40", + : "border-border/60 bg-card hover:border-border hover:bg-muted/50", ), ), h.Style({ "--tile-accent": provider.accent }), diff --git a/apps/web/src/page/alerts/editor/view-condition.ts b/apps/web/src/page/alerts/editor/view-condition.ts index 1b8e94c47b..861432851a 100644 --- a/apps/web/src/page/alerts/editor/view-condition.ts +++ b/apps/web/src/page/alerts/editor/view-condition.ts @@ -305,7 +305,7 @@ const intervalPicker = ( ...(isRaw ? [ h.span( - [h.Class("text-[11px] font-normal tabular-nums opacity-80")], + [h.Class("text-2xs font-normal tabular-nums opacity-80")], [`${option.limitSeconds} s limit`], ), ] diff --git a/apps/web/src/page/alerts/editor/view-notify.ts b/apps/web/src/page/alerts/editor/view-notify.ts index bf65ced055..474cc03d99 100644 --- a/apps/web/src/page/alerts/editor/view-notify.ts +++ b/apps/web/src/page/alerts/editor/view-notify.ts @@ -180,7 +180,7 @@ 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/40 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-muted/50 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", ), diff --git a/apps/web/src/page/alerts/editor/view-sql.ts b/apps/web/src/page/alerts/editor/view-sql.ts index 6f3bec48dc..7338a63858 100644 --- a/apps/web/src/page/alerts/editor/view-sql.ts +++ b/apps/web/src/page/alerts/editor/view-sql.ts @@ -207,7 +207,7 @@ const queryTimeMeter = (h: H, form: RuleForm, timing: AlertQueryTiming): Html => [h.div([h.Class(cn("h-full rounded-full", TONE_FILL[tone])), h.Style({ width: `${fill * 100}%` })], [])], ), h.div( - [h.Class("relative h-3 text-[10px] tabular-nums text-muted-foreground"), h.AriaHidden(true)], + [h.Class("relative h-3 text-3xs tabular-nums text-muted-foreground"), h.AriaHidden(true)], METER_TICKS.map((tickMs) => h.span( [ diff --git a/apps/web/src/page/alerts/hub/view-empty.ts b/apps/web/src/page/alerts/hub/view-empty.ts index fb9118c305..c04635f942 100644 --- a/apps/web/src/page/alerts/hub/view-empty.ts +++ b/apps/web/src/page/alerts/hub/view-empty.ts @@ -140,7 +140,7 @@ const templateTile = (h: HtmlBuilder, template: AlertTemplate, serviceName [ h.span( [h.Class(cn("flex size-6 shrink-0 items-center justify-center rounded-md", tone?.glyph))], - [icon(h, template.icon, { size: 13 })], + [icon(h, template.icon, { size: 14 })], ), h.span([h.Class("font-medium text-sm")], [template.title]), ], diff --git a/apps/web/src/page/alerts/hub/view-inbox.ts b/apps/web/src/page/alerts/hub/view-inbox.ts index b9ec236a8d..6ccda6a8b4 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/40"))], + [h.Key(incident.id), h.Class(cn(INCIDENT_GRID, "relative px-4 py-3 hover:bg-muted/50"))], [ h.span([ h.AriaHidden(true), @@ -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/40", + "group relative grid grid-cols-[72px_minmax(0,1fr)_auto] items-center gap-4 py-2.5 hover:bg-muted/50", ), ], [ @@ -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/40"))], + [h.Key(rule.id), h.Class(cn(HEADROOM_GRID, "relative py-2.5 hover:bg-muted/50"))], [ h.div( [h.Class("min-w-0")], diff --git a/apps/web/src/page/alerts/hub/view-rules.ts b/apps/web/src/page/alerts/hub/view-rules.ts index e502f922d3..6e478db639 100644 --- a/apps/web/src/page/alerts/hub/view-rules.ts +++ b/apps/web/src/page/alerts/hub/view-rules.ts @@ -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/40"))], + [h.Key(rule.id), h.Class(cn(ROW_GRID, "relative px-4 py-3 hover:bg-muted/50"))], [ statusDot(h, { tone: BUCKET_TONE.get(row.bucket) ?? "neutral", size: "lg" }), h.div( diff --git a/apps/web/src/page/alerts/shared/providers.ts b/apps/web/src/page/alerts/shared/providers.ts index b83d8ab2df..f351674fb7 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-lg border border-border/60 bg-card", + "relative inline-flex shrink-0 items-center justify-center rounded-md border border-border/60 bg-card", options.className, ), ), @@ -293,7 +293,7 @@ export const providerLogo = (h: HtmlBuilder, options: ProviderLogoOptions< [ h.span([ h.AriaHidden(true), - h.Class("absolute inset-0 rounded-lg opacity-70"), + h.Class("absolute inset-0 rounded-md opacity-70"), h.Style({ background: `radial-gradient(circle at 30% 20%, ${provider.accentBg}, transparent 70%)`, }), 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 9348f33054..ff322578b2 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/40 hover:text-foreground", + "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", ), ...trigger, ], diff --git a/apps/web/src/page/alerts/uptime-form/view.ts b/apps/web/src/page/alerts/uptime-form/view.ts index f88015a958..5ef1632990 100644 --- a/apps/web/src/page/alerts/uptime-form/view.ts +++ b/apps/web/src/page/alerts/uptime-form/view.ts @@ -368,7 +368,7 @@ export const view = Submodel.defineView((model, const isHttp = model.form.kind === "http" const widthClass = isHttp ? "max-w-6xl" : "max-w-3xl" const card = h.div( - [h.Class("divide-y rounded-lg border bg-card")], + [h.Class("divide-y rounded-md border bg-card")], [kindPicker(h, model), ...kindSections(h, model), serviceSection(h, model), notifySection(h, model)], ) return dashboardPage(h, { ...header, fill: true }, [ diff --git a/apps/web/src/page/analytics/view-ai-parts.ts b/apps/web/src/page/analytics/view-ai-parts.ts index 505011e15a..2b4320436a 100644 --- a/apps/web/src/page/analytics/view-ai-parts.ts +++ b/apps/web/src/page/analytics/view-ai-parts.ts @@ -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/40 px-4 py-2 text-2xs text-muted-foreground transition-colors hover:bg-muted/40 hover:text-foreground focus-visible:bg-muted/40 focus-visible:outline-none", + "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", ), ], [ @@ -290,7 +290,7 @@ 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/40 px-4 py-2 last:border-0"), + h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-2 last:border-0"), ], [ h.span( @@ -376,7 +376,7 @@ export const crawlerTable = ( return h.div( [ h.Key(row.crawler), - h.Class("flex items-center gap-4 border-b border-border/40 px-4 py-2 last:border-0"), + h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-2 last:border-0"), ], [ h.span( diff --git a/apps/web/src/page/analytics/view-breakdown.ts b/apps/web/src/page/analytics/view-breakdown.ts index 0152c3a3b3..a153f696ff 100644 --- a/apps/web/src/page/analytics/view-breakdown.ts +++ b/apps/web/src/page/analytics/view-breakdown.ts @@ -49,7 +49,9 @@ const shareBarStyle = (share: number): Readonly> => { const pct = Math.min(100, share * 100) if (!Number.isFinite(pct) || pct < 0.5) return {} const fill = "color-mix(in oklab, var(--primary) 14%, transparent)" - return { "background-image": `linear-gradient(to right, ${fill} 0%, ${fill} ${pct}%, transparent ${pct}%)` } + return { + "background-image": `linear-gradient(to right, ${fill} 0%, ${fill} ${pct}%, transparent ${pct}%)`, + } } const columnLabel = (noun: string): string => noun.charAt(0).toUpperCase() + noun.slice(1) @@ -70,7 +72,8 @@ export const panelView = (state: PanelState, dimensions: ReadonlyArray = dimension.rows .filter((row) => needle - ? label(row.name).toLowerCase().includes(needle) || (row.secondary?.toLowerCase().includes(needle) ?? false) + ? label(row.name).toLowerCase().includes(needle) || + (row.secondary?.toLowerCase().includes(needle) ?? false) : true, ) .map((row) => ({ ...row, share: total > 0 ? (hasViews ? (row.views ?? 0) : row.count) / total : 0 })) @@ -81,12 +84,24 @@ export const panelView = (state: PanelState, dimensions: ReadonlyArray> /** `DimensionTabs`. */ -export const dimensionTabs = (h: H, cardId: string, dimensions: ReadonlyArray, activeTab: number): Html => +export const dimensionTabs = ( + h: H, + cardId: string, + dimensions: ReadonlyArray, + activeTab: number, +): Html => h.div( [ h.Role("group"), h.AriaLabel("Breakdown dimension"), - h.Class(cn(toggleGroupStyles, toggleGroupHorizontalStyles, toggleGroupConnectedStyles, "flex-wrap gap-1")), + h.Class( + cn( + toggleGroupStyles, + toggleGroupHorizontalStyles, + toggleGroupConnectedStyles, + "flex-wrap gap-1", + ), + ), h.DataAttribute("orientation", "horizontal"), h.DataAttribute("size", "sm"), h.DataAttribute("slot", "toggle-group"), @@ -104,7 +119,11 @@ export const dimensionTabs = (h: H, cardId: string, dimensions: ReadonlyArray
, + options: Readonly<{ + maxHeight: string + surfaceClass: string + isRanked: boolean + selected: string | undefined + isWaiting: boolean + }>, ): Html => { const { dimension, hasViews, label } = view const isRanked = options.isRanked @@ -155,8 +180,14 @@ export const breakdownTable = ( ? Message.ClickedExpandedRow({ key: dimension.filterKey, value: name }) : Message.ToggledFilter({ key: dimension.filterKey, value: name }) const head = [ - ...(isRanked ? [columnHead(h, { label: "#", width: "w-6", align: "right", hidden: "max-sm:hidden" })] : []), - columnHead(h, { label: columnLabel(dimension.noun), width: "w-0 flex-1 min-w-0", sort: sortHead(cardId, view, "name") }), + ...(isRanked + ? [columnHead(h, { label: "#", width: "w-6", align: "right", hidden: "max-sm:hidden" })] + : []), + columnHead(h, { + label: columnLabel(dimension.noun), + width: "w-0 flex-1 min-w-0", + sort: sortHead(cardId, view, "name"), + }), ...(hasViews ? [ columnHead(h, { @@ -205,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/40 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/60 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), ), @@ -215,34 +246,54 @@ export const breakdownTable = ( ...(isRanked ? [ h.span( - [h.Class("w-6 text-right font-mono text-2xs tabular-nums text-muted-foreground/60 max-sm:hidden")], + [ + h.Class( + "w-6 text-right font-mono text-2xs tabular-nums text-muted-foreground/60 max-sm:hidden", + ), + ], [String(index + 1)], ), ] : []), - h.span([h.Class("flex w-0 min-w-0 flex-1 items-center gap-2")], [ - ...(rowIcon !== undefined - ? [rowIcon] - : hasIcons - ? [h.span([h.Class("size-4 shrink-0"), h.AriaHidden(true)], [])] - : []), - h.span( - [ - h.Class( - cn( - "min-w-0 truncate text-xs transition-colors", - isSelected ? "font-medium text-foreground" : "text-foreground/90 group-hover:text-foreground", + h.span( + [h.Class("flex w-0 min-w-0 flex-1 items-center gap-2")], + [ + ...(rowIcon !== undefined + ? [rowIcon] + : hasIcons + ? [h.span([h.Class("size-4 shrink-0"), h.AriaHidden(true)], [])] + : []), + h.span( + [ + h.Class( + cn( + "min-w-0 truncate text-xs transition-colors", + isSelected + ? "font-medium text-foreground" + : "text-foreground/90 group-hover:text-foreground", + ), ), - ), - h.Title(row.secondary ? `${row.secondary}${row.name}` : label(row.name)), - ], - [label(row.name)], - ), - ]), + h.Title( + row.secondary + ? `${row.secondary}${row.name}` + : label(row.name), + ), + ], + [label(row.name)], + ), + ], + ), ...(hasViews ? [ h.span( - [h.Class(cn("text-right font-mono text-2xs tabular-nums", isRanked ? "w-16 sm:w-24" : "w-16"))], + [ + h.Class( + cn( + "text-right font-mono text-2xs tabular-nums", + isRanked ? "w-16 sm:w-24" : "w-16", + ), + ), + ], [formatNumber(row.views ?? 0)], ), ] @@ -267,7 +318,9 @@ export const breakdownTable = ( h.Class( cn( "w-16 text-right font-mono text-2xs tabular-nums text-muted-foreground", - isRanked ? "max-sm:hidden" : "hidden @min-[380px]/panel:inline-block", + isRanked + ? "max-sm:hidden" + : "hidden @min-[380px]/panel:inline-block", ), ), ], @@ -303,10 +356,13 @@ export const breakdownPanel = ( if (view === null) return null const { dimension } = view return panel(h, { className: "@container/panel" }, [ - h.div([h.Class("flex flex-wrap items-center justify-between gap-x-3 gap-y-2 px-3 pt-2.5 pb-2")], [ - dimensionTabs(h, card.id, card.dimensions, view.activeTab), - panelFilterInput(h, card.id, state.query, dimension.nounPlural, "min-w-24 max-w-40 flex-1"), - ]), + h.div( + [h.Class("flex flex-wrap items-center justify-between gap-x-3 gap-y-2 px-3 pt-2.5 pb-2")], + [ + dimensionTabs(h, card.id, card.dimensions, view.activeTab), + panelFilterInput(h, card.id, state.query, dimension.nounPlural, "min-w-24 max-w-40 flex-1"), + ], + ), ...(dimension.rows.length === 0 ? [ emptyMessage( @@ -328,16 +384,18 @@ 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/40 hover:text-foreground focus-visible:bg-muted/40 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-muted/50 hover:text-foreground focus-visible:bg-muted/50 focus-visible:outline-none", ), ], [ - h.span([h.Class("flex items-center gap-1.5")], [icon(h, "MaximizeIcon", { size: 12 }), "Expand table"]), - h.span([h.Class("font-mono tabular-nums")], [ - formatNumber(dimension.rows.length), - " ", - dimension.nounPlural, - ]), + h.span( + [h.Class("flex items-center gap-1.5")], + [icon(h, "MaximizeIcon", { size: 12 }), "Expand table"], + ), + h.span( + [h.Class("font-mono tabular-nums")], + [formatNumber(dimension.rows.length), " ", dimension.nounPlural], + ), ], ), ]), diff --git a/apps/web/src/page/analytics/view.ts b/apps/web/src/page/analytics/view.ts index 7653f297d7..958adcdb84 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/70 text-muted-foreground", + : "border-border/60 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 6210881285..cb893e12d2 100644 --- a/apps/web/src/page/anomalies/detail/view-body.ts +++ b/apps/web/src/page/anomalies/detail/view-body.ts @@ -174,7 +174,7 @@ export const signalChart = ( h, { dashed: true, - className: "flex h-64 w-full items-center justify-center border-border/50 py-0 text-xs", + className: "flex h-64 w-full items-center justify-center border-border/60 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/70 p-4")], + [h.Class("rounded-md border border-dashed border-border/60 p-4")], [ h.div( [h.Class("flex flex-wrap items-center justify-between gap-3")], diff --git a/apps/web/src/page/anomalies/kit/row.ts b/apps/web/src/page/anomalies/kit/row.ts index 4f5b26690d..47f7150f69 100644 --- a/apps/web/src/page/anomalies/kit/row.ts +++ b/apps/web/src/page/anomalies/kit/row.ts @@ -204,5 +204,5 @@ const linkedIssueChip = (h: HtmlBuilder, issueId: ErrorIssueId): Html => h.Href(hrefOf(AppRoute.ErrorIssue({ issueId, search: {} }))), h.Title("Open linked issue"), ], - [icon(h, "LinkIcon", { size: 11 }), shortIssueId(issueId)], + [icon(h, "LinkIcon", { size: 12 }), shortIssueId(issueId)], ) diff --git a/apps/web/src/page/anomalies/list/view-list.ts b/apps/web/src/page/anomalies/list/view-list.ts index dcb5eb5fa6..c3084a5848 100644 --- a/apps/web/src/page/anomalies/list/view-list.ts +++ b/apps/web/src/page/anomalies/list/view-list.ts @@ -59,7 +59,7 @@ const group = ( ...(isOpen ? [ h.div( - [h.Id(`anomaly-group-${key}`), h.Role("list"), h.Class("divide-y divide-border/40")], + [h.Id(`anomaly-group-${key}`), h.Role("list"), h.Class("divide-y divide-border/60")], clusterByService(incidents).map((cluster) => h.div( [h.Key(cluster.key + (cluster.incidents[0]?.id ?? ""))], @@ -69,7 +69,7 @@ const group = ( h.div( [ h.Class( - "flex h-7 items-center gap-1.5 border-b border-border/40 bg-muted/20 pl-5 text-2xs text-muted-foreground", + "flex h-7 items-center gap-1.5 border-b border-border/60 bg-muted/20 pl-5 text-2xs text-muted-foreground", ), ], [ @@ -82,7 +82,7 @@ const group = ( ] : []), h.div( - [h.Class("divide-y divide-border/40")], + [h.Class("divide-y divide-border/60")], cluster.incidents.map((incident) => h.div( [h.Key(incident.id), h.Role("listitem")], diff --git a/apps/web/src/page/code-review/analytics/view-charts.ts b/apps/web/src/page/code-review/analytics/view-charts.ts index 0dd660fe68..50405e75dd 100644 --- a/apps/web/src/page/code-review/analytics/view-charts.ts +++ b/apps/web/src/page/code-review/analytics/view-charts.ts @@ -161,7 +161,7 @@ export const issuesCard = ( ), h.Href(href), ], - ["See all issues caught", icon(h, "ArrowRightIcon", { size: 13 })], + ["See all issues caught", icon(h, "ArrowRightIcon", { size: 14 })], ), ], ) 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 a28744f3fd..7624b2d419 100644 --- a/apps/web/src/page/code-review/analytics/view-lists.ts +++ b/apps/web/src/page/code-review/analytics/view-lists.ts @@ -30,7 +30,7 @@ export const repositoryList = (h: HtmlBuilder, title: string, rows: Readon [h.Key(row.key), h.Class("flex items-center gap-2.5 py-1.5 text-sm")], [ icon(h, "GithubIcon", { - size: 15, + size: 16, className: "shrink-0 text-muted-foreground", }), h.span([h.Class("min-w-0 flex-1 truncate")], [row.name]), 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 67c12b6d7e..633e897ff0 100644 --- a/apps/web/src/page/code-review/ci/view-tables.ts +++ b/apps/web/src/page/code-review/ci/view-tables.ts @@ -183,7 +183,7 @@ const workflowRow = ( "hidden px-4 sm:table-cell", ), ], - cn("cursor-pointer transition-colors hover:bg-muted/40", isActive && "bg-muted/40"), + cn("cursor-pointer transition-colors hover:bg-muted/50", isActive && "bg-muted/60"), [h.Key(`${row.owner}/${row.repository}/${row.pipeline}`), h.OnClick(select)], ) } 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 86821d9160..4298b8f7aa 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/60", + "flex items-center gap-3 rounded-md px-2 py-1 text-sm hover:bg-muted/50", ), ], [ @@ -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/60", + isCurrent ? "bg-muted" : "hover:bg-muted/50", ), ), ...(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 3c3e82a3fb..75184af250 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/40", isSelected && "bg-muted/40"), + cn("cursor-pointer transition-colors hover:bg-muted/50", isSelected && "bg-muted/60"), [h.Key(review.id), h.OnClick(open)], ) } diff --git a/apps/web/src/page/dashboards/list/view-list.ts b/apps/web/src/page/dashboards/list/view-list.ts index 9c0a8bf80b..e7c18721dc 100644 --- a/apps/web/src/page/dashboards/list/view-list.ts +++ b/apps/web/src/page/dashboards/list/view-list.ts @@ -370,7 +370,7 @@ const createRow = (h: H, isReadOnly: boolean): Html => ), ], ), - icon(h, "ArrowRightIcon", { size: 13, className: "text-muted-foreground shrink-0" }), + icon(h, "ArrowRightIcon", { size: 14, className: "text-muted-foreground shrink-0" }), ], ) @@ -419,7 +419,7 @@ const nothingMatched = (h: H, model: Model): Html => { h, [ emptyHeader(h, [ - emptyMedia(h, { variant: "icon" }, [icon(h, "MagnifierIcon", { size: 17 })]), + emptyMedia(h, { variant: "icon" }, [icon(h, "MagnifierIcon", { size: 16 })]), emptyTitle(h, [ isSearching ? `No dashboard matches “${query}”` @@ -474,7 +474,7 @@ const nothingStarred = (h: H): Html => h, [ emptyHeader(h, [ - emptyMedia(h, { variant: "icon" }, [icon(h, "StarIcon", { size: 17 })]), + emptyMedia(h, { variant: "icon" }, [icon(h, "StarIcon", { size: 16 })]), emptyTitle(h, ["Nothing starred on this device"]), emptyDescription(h, [ "Favorites are stored in this browser, not shared with your org. Star a dashboard to pin it to the top of the list.", diff --git a/apps/web/src/page/dashboards/templates/view-list.ts b/apps/web/src/page/dashboards/templates/view-list.ts index d3de63b442..abbd352545 100644 --- a/apps/web/src/page/dashboards/templates/view-list.ts +++ b/apps/web/src/page/dashboards/templates/view-list.ts @@ -119,7 +119,7 @@ const filteredEmpty = (h: H, query: string): Html => noun: "templates", title: `No template matches “${query.trim()}”`, description: "Try a shorter term. Or start blank and add the widgets you want.", - icon: icon(h, "MagnifierIcon", { size: 17 }), + icon: icon(h, "MagnifierIcon", { size: 16 }), onClear: Message.ChangedSearchDraft({ value: "" }), clearLabel: "Clear search", className: "py-14", @@ -131,7 +131,7 @@ const filterHidEverything = (h: H, filter: ReadinessFilter, matched: number, isS [ emptyHeader(h, [ emptyMedia(h, { variant: "icon" }, [ - icon(h, filter === "ready" ? "CircleWarningIcon" : "CircleCheckIcon", { size: 17 }), + icon(h, filter === "ready" ? "CircleWarningIcon" : "CircleCheckIcon", { size: 16 }), ]), emptyTitle(h, [ filter === "ready" ? "None of these are ready yet" : "These are all ready to use", @@ -325,7 +325,7 @@ export const templateList = ( "flex size-5.5 shrink-0 items-center justify-center rounded-sm border border-input border-dashed", ), ], - [icon(h, "PlusIcon", { size: 11, className: "text-muted-foreground" })], + [icon(h, "PlusIcon", { size: 12, className: "text-muted-foreground" })], ), h.span( [h.Class("flex min-w-0 grow items-baseline gap-2.25")], @@ -334,7 +334,7 @@ export const templateList = ( h.span([h.Class("text-muted-foreground text-2xs")], ["start from nothing"]), ], ), - icon(h, "ArrowRightIcon", { size: 13, className: "text-muted-foreground shrink-0" }), + icon(h, "ArrowRightIcon", { size: 14, className: "text-muted-foreground shrink-0" }), ], ), ], diff --git a/apps/web/src/page/dashboards/templates/view-panel.ts b/apps/web/src/page/dashboards/templates/view-panel.ts index cfda3ed54a..fdc6b9b238 100644 --- a/apps/web/src/page/dashboards/templates/view-panel.ts +++ b/apps/web/src/page/dashboards/templates/view-panel.ts @@ -478,10 +478,10 @@ export const detailPanel = ( h.span( [ h.Class( - "border-border bg-card flex size-8.5 shrink-0 items-center justify-center rounded-lg border", + "border-border bg-card flex size-8.5 shrink-0 items-center justify-center rounded-md border", ), ], - [icon(h, templateIcon(template.id, template.category), { size: 17 })], + [icon(h, templateIcon(template.id, template.category), { size: 16 })], ), h.div( [h.Class("flex min-w-0 flex-col gap-1")], diff --git a/apps/web/src/page/dashboards/view/view-embed.ts b/apps/web/src/page/dashboards/view/view-embed.ts index c0c49de606..8a5a61f22e 100644 --- a/apps/web/src/page/dashboards/view/view-embed.ts +++ b/apps/web/src/page/dashboards/view/view-embed.ts @@ -31,8 +31,24 @@ const wrap = (message: ShareMessage) => Message.GotShareMessage({ message }) const warehouseDateTime = (ms: number) => new Date(ms).toISOString().slice(0, 19).replace("T", " ") const iframeSnippet = (h: H, model: Model, url: string): Html => { - const html = [""].join("\n") - const jsx = [""].join("\n") + const html = [ + "", + ].join("\n") + const jsx = [ + "", + ].join("\n") const copy = { copy: model.sharing.snippetCopy, toCopyMessage: (message: Parameters[0]["message"]) => @@ -48,7 +64,10 @@ const iframeSnippet = (h: H, model: Model, url: string): Html => { labels: ["HTML", "React"], className: "gap-2", wrapList: (list) => - h.div([h.Class("flex items-center justify-between gap-3")], [h.div([h.Class("font-medium text-xs")], ["Embed in a page"]), list]), + h.div( + [h.Class("flex items-center justify-between gap-3")], + [h.div([h.Class("font-medium text-xs")], ["Embed in a page"]), list], + ), panel: (value) => value === "html" ? [codeBlock(h, { code: html, language: "html", ...copy })] @@ -62,13 +81,17 @@ const notPublicNotice = (h: H, isOrgOnly: boolean, isBusy: boolean): Html => h.div( [h.Class("flex items-start gap-3")], [ - icon(h, "GlobeIcon", { size: 15, className: "mt-0.5 shrink-0 text-muted-foreground" }), + icon(h, "GlobeIcon", { size: 16, className: "mt-0.5 shrink-0 text-muted-foreground" }), h.div( [h.Class("space-y-1")], [ h.div( [h.Class("font-medium text-sm")], - [isOrgOnly ? "This dashboard is shared with your organization only" : "This dashboard isn't shared"], + [ + isOrgOnly + ? "This dashboard is shared with your organization only" + : "This dashboard isn't shared", + ], ), h.p( [h.Class("text-muted-foreground text-xs leading-relaxed")], @@ -93,17 +116,33 @@ const notPublicNotice = (h: H, isOrgOnly: boolean, isBusy: boolean): Html => [ button( h, - { size: "sm", variant: "destructive", isDisabled: isBusy, attributes: [h.OnClick(wrap(ShareMessage.ClickedMakePublic()))] }, + { + size: "sm", + variant: "destructive", + isDisabled: isBusy, + attributes: [h.OnClick(wrap(ShareMessage.ClickedMakePublic()))], + }, [icon(h, "GlobeIcon"), "Make dashboard public"], ), ], ), ]) -type UrlOption = Readonly<{ key: string; icon: IconName; param: string; description: string; example: string; unavailable?: boolean }> +type UrlOption = Readonly<{ + key: string + icon: IconName + param: string + description: string + example: string + unavailable?: boolean +}> /** An example for a variable: its current value, else its first option, else its default. */ -const exampleValue = (variable: Variable, resolved: ResolvedVariable | undefined, options: ReadonlyArray | undefined) => +const exampleValue = ( + variable: Variable, + resolved: ResolvedVariable | undefined, + options: ReadonlyArray | undefined, +) => resolved !== undefined && !resolved.isAll && resolved.value !== "" ? resolved.value : options?.[0] || variable.defaultValue || (variable.type === "textbox" ? "value" : ALL_VALUE) @@ -114,7 +153,13 @@ const urlOptions = (h: H, model: Model, context: PageContext): Html => { const values = variablesOf(model, context).values const optionsByName = optionsByNameOf(model, context) const options: ReadonlyArray = [ - { key: "theme", icon: "SunIcon", param: "theme", description: "light or dark", example: "&theme=light" }, + { + key: "theme", + icon: "SunIcon", + param: "theme", + description: "light or dark", + example: "&theme=light", + }, { key: "range", icon: "ClockIcon", @@ -162,7 +207,10 @@ const urlOptions = (h: H, model: Model, context: PageContext): Html => { [], [ h.div([h.Class("font-medium text-xs")], ["URL options"]), - h.p([h.Class("text-muted-foreground text-xs")], ["Append any of these to the embed link."]), + h.p( + [h.Class("text-muted-foreground text-xs")], + ["Append any of these to the embed link."], + ), ], ), h.ul( @@ -178,12 +226,20 @@ const urlOptions = (h: H, model: Model, context: PageContext): Html => { ), ], [ - h.span([h.Class("flex h-5 items-center text-muted-foreground")], [icon(h, option.icon, { size: 14 })]), + h.span( + [h.Class("flex h-5 items-center text-muted-foreground")], + [icon(h, option.icon, { size: 14 })], + ), truncatedText(h, { text: option.param, className: "font-medium font-mono" }), h.span([h.Class("text-muted-foreground")], [option.description]), - inlineCode(h, { className: "col-start-3 w-fit max-w-full truncate px-1.5 text-2xs text-muted-foreground" }, [ - option.example, - ]), + inlineCode( + h, + { + className: + "col-start-3 w-fit max-w-full truncate px-1.5 text-2xs text-muted-foreground", + }, + [option.example], + ), ], ), ), @@ -245,7 +301,9 @@ export const embedDialog = (h: H, model: Model, context: PageContext): Html => { ), ]), DialogView.dialogPanel(h, "dialog", id, embedContent(h, model, context), "space-y-4"), - DialogView.dialogFooter(h, "dialog", [button(h, { variant: "outline", attributes: close }, ["Done"])]), + DialogView.dialogFooter(h, "dialog", [ + button(h, { variant: "outline", attributes: close }, ["Done"]), + ]), ], }, }) diff --git a/apps/web/src/page/dashboards/view/view-history.ts b/apps/web/src/page/dashboards/view/view-history.ts index c6956364b8..c9da0ba26b 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/40", + "hover:bg-muted/50", rowSelectedClass(isPreviewing), ), ), diff --git a/apps/web/src/page/dashboards/view/view-share.ts b/apps/web/src/page/dashboards/view/view-share.ts index c8f0016a14..d7e1625cd9 100644 --- a/apps/web/src/page/dashboards/view/view-share.ts +++ b/apps/web/src/page/dashboards/view/view-share.ts @@ -20,8 +20,18 @@ type H = HtmlBuilder const wrap = (message: ShareMessage) => Message.GotShareMessage({ message }) const ACCESS: ReadonlyArray> = [ - { value: "off", icon: "LockIcon", title: "Not shared", body: "Only members of this organization with access to Maple can see it." }, - { value: "org", icon: "ShieldIcon", title: "Anyone in this organization", body: "Signed-in members of this organization can open the link." }, + { + value: "off", + icon: "LockIcon", + title: "Not shared", + body: "Only members of this organization with access to Maple can see it.", + }, + { + value: "org", + icon: "ShieldIcon", + title: "Anyone in this organization", + body: "Signed-in members of this organization can open the link.", + }, { value: "public", icon: "GlobeIcon", @@ -33,12 +43,27 @@ const ACCESS: ReadonlyArray): Html => h.div( - [h.Class(cn("flex items-start gap-2 text-xs leading-relaxed", tone === "error" ? TONE_TEXT.crit : "text-muted-foreground"))], - [icon(h, "CircleWarningIcon", { size: 13, className: "mt-0.5 shrink-0" }), h.p([h.Class("min-w-0")], children)], + [ + h.Class( + cn( + "flex items-start gap-2 text-xs leading-relaxed", + tone === "error" ? TONE_TEXT.crit : "text-muted-foreground", + ), + ), + ], + [ + icon(h, "CircleWarningIcon", { size: 14, className: "mt-0.5 shrink-0" }), + h.p([h.Class("min-w-0")], children), + ], ) /** `ShareLinkRow`: the copyable link, and Replace behind a confirmation. */ -export const shareLinkRow = (h: H, model: Model, url: string, replaceWarning: string): ReadonlyArray => [ +export const shareLinkRow = ( + h: H, + model: Model, + url: string, + replaceWarning: string, +): ReadonlyArray => [ h.div( [h.Class("flex items-center gap-2")], [ @@ -54,10 +79,15 @@ export const shareLinkRow = (h: H, model: Model, url: string, replaceWarning: st }), ], ), - button(h, { size: "sm", variant: "outline", attributes: [h.OnClick(wrap(ShareMessage.ClickedReplace()))] }, [ - icon(h, "ArrowRotateClockwiseIcon"), - "Replace", - ]), + button( + h, + { + size: "sm", + variant: "outline", + attributes: [h.OnClick(wrap(ShareMessage.ClickedReplace()))], + }, + [icon(h, "ArrowRotateClockwiseIcon"), "Replace"], + ), ], ), confirmDialog(h, { @@ -72,7 +102,11 @@ export const shareLinkRow = (h: H, model: Model, url: string, replaceWarning: st }), ] -const accessOption = (h: H, config: RadioGroup.RadioGroupViewConfig, option: (typeof ACCESS)[number]): Html => +const accessOption = ( + h: H, + config: RadioGroup.RadioGroupViewConfig, + option: (typeof ACCESS)[number], +): Html => h.label( [ h.For(`share-${option.value}`), @@ -83,8 +117,9 @@ const accessOption = (h: H, config: RadioGroup.RadioGroupViewConfig, op ], [ icon(h, option.icon, { - size: 15, - className: "mt-0.5 shrink-0 text-muted-foreground transition-colors group-has-[[data-checked]]:text-primary", + size: 16, + className: + "mt-0.5 shrink-0 text-muted-foreground transition-colors group-has-[[data-checked]]:text-primary", }), h.div( [h.Class("min-w-0 flex-1 space-y-0.5")], @@ -104,7 +139,11 @@ const panelContent = (h: H, model: Model): ReadonlyArray => { const config: RadioGroup.RadioGroupViewConfig = { model: RadioGroup.init(model.sharing.pendingAccess ?? serverAccess), toParentMessage: (message) => wrap(ShareMessage.GotAccessMessage({ message })), - items: ACCESS.map((option) => ({ value: option.value, id: `share-${option.value}-radio`, inputId: `share-${option.value}` })), + items: ACCESS.map((option) => ({ + value: option.value, + id: `share-${option.value}-radio`, + inputId: `share-${option.value}`, + })), } const unsupported = unsupportedShareWidgets(model.document?.widgets ?? []) return [ @@ -124,7 +163,9 @@ const panelContent = (h: H, model: Model): ReadonlyArray => { ...(unsupported.length > 0 && boardShare !== undefined ? [ noticeRow(h, "muted", [ - unsupported.length === 1 ? "1 widget won't render for viewers" : `${unsupported.length} widgets won't render for viewers`, + unsupported.length === 1 + ? "1 widget won't render for viewers" + : `${unsupported.length} widgets won't render for viewers`, ": ", unsupported.map((widget) => widget.title).join(", "), ". Shared views support", @@ -154,10 +195,17 @@ export const shareDialog = (h: H, model: Model): Html => { toContent: (close) => [ DialogView.dialogHeader(h, "dialog", [ DialogView.dialogTitle(h, "dialog", id, "Share dashboard"), - DialogView.dialogDescription(h, "dialog", id, "Anyone you share with sees this dashboard's data, but cannot edit it."), + DialogView.dialogDescription( + h, + "dialog", + id, + "Anyone you share with sees this dashboard's data, but cannot edit it.", + ), ]), DialogView.dialogPanel(h, "dialog", id, panelContent(h, model), "space-y-4"), - DialogView.dialogFooter(h, "dialog", [button(h, { variant: "outline", attributes: close }, ["Done"])]), + DialogView.dialogFooter(h, "dialog", [ + button(h, { variant: "outline", attributes: close }, ["Done"]), + ]), ], }, }) diff --git a/apps/web/src/page/errors/hub/view-list.ts b/apps/web/src/page/errors/hub/view-list.ts index b9ce3730f1..bb2b49b0db 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/40", + className: "gap-0 divide-y divide-border/60", }), ] @@ -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/40 border-t border-border/40", + className: "gap-0 divide-y divide-border/60 border-t border-border/60", }), ] } return [ h.div( - [h.Class("flex items-center justify-center gap-3 border-t border-border/40 p-4")], + [h.Class("flex items-center justify-center gap-3 border-t border-border/60 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/40"), h.OnMount(MountRowSelect())], + [h.Role("list"), h.Class("divide-y divide-border/60"), 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-signal.ts b/apps/web/src/page/errors/hub/view-signal.ts index 6b1e5186e9..7aecf4b4a8 100644 --- a/apps/web/src/page/errors/hub/view-signal.ts +++ b/apps/web/src/page/errors/hub/view-signal.ts @@ -111,7 +111,7 @@ export const signalActivity = (h: H, signal: ErrorSignal): Html | null => { ), h.Title(`${countLabel(signal.commentCount, "comment")} on the timeline`), ], - [icon(h, "ChatBubbleIcon", { size: 11 }), String(signal.commentCount)], + [icon(h, "ChatBubbleIcon", { size: 12 }), String(signal.commentCount)], ), ] : []), @@ -133,7 +133,7 @@ export const signalActivity = (h: H, signal: ErrorSignal): Html | null => { : countLabel(prCount, "open pull request"), ), ], - [icon(h, "PullRequestIcon", { size: 11 }), String(prCount)], + [icon(h, "PullRequestIcon", { size: 12 }), String(prCount)], ), ] : []), diff --git a/apps/web/src/page/errors/issue/view-activity.ts b/apps/web/src/page/errors/issue/view-activity.ts index 4f02733db8..a15e96d272 100644 --- a/apps/web/src/page/errors/issue/view-activity.ts +++ b/apps/web/src/page/errors/issue/view-activity.ts @@ -202,8 +202,8 @@ const messageRow = ( [ h.Class( cn( - "mt-1.5 max-w-prose overflow-x-auto rounded-xl border px-3 py-2 text-sm", - isAgent ? AGENT_ACCENT.surface : "border-border/70 bg-muted/40", + "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", ), ), ], diff --git a/apps/web/src/page/errors/issue/view-anomalies.ts b/apps/web/src/page/errors/issue/view-anomalies.ts index db15752e65..e5a74e346b 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/40")], + [h.Class("overflow-hidden rounded-md border border-border/60 divide-y divide-border/60")], 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 7ff5d09f85..671801ec3e 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/50 py-0 text-xs", + className: "flex h-44 w-full items-center justify-center border-border/60 py-0 text-xs", }, ["No activity in this window"], ) 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 b9d5dc3ce2..2e47b99df4 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/40 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-muted/50 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 0fdcb00234..82338048e0 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 @@ -485,7 +485,7 @@ export const workerTable = ( // QUEUES const QUEUE_ROW = - "flex items-center gap-4 border-b border-border/40 px-4 py-3 last:border-0 hover:bg-muted/40" + "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50" const numCell = (h: H, value: string, hidden?: boolean): Html => h.div( 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 5aaa00020e..0818d1372d 100644 --- a/apps/web/src/page/infra-integrations/cloudflare/worker/view.ts +++ b/apps/web/src/page/infra-integrations/cloudflare/worker/view.ts @@ -95,7 +95,7 @@ const figure = (h: H, value: string, caption: string, className?: string): Html /** `CloudflareTraceGapCallout`: failures Cloudflare saw that the Worker's spans never recorded. */ const traceGapCallout = (h: H, exceptions: number, tracedErrors: number, tracedService: string): Html => h.div( - [h.Class("@container rounded-lg border border-severity-error/40")], + [h.Class("@container rounded-md border border-severity-error/40")], [ h.div( [h.Class("flex flex-col @2xl:flex-row @2xl:items-center")], @@ -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/40")], + [h.Class("divide-y divide-border/60")], totals.byStatus.map(({ status, count }) => { const success = status === "success" const share = totals.invocations > 0 ? count / totals.invocations : 0 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 47476c8287..a688a32b34 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/40 px-4 py-3 last:border-0 hover:bg-muted/40" + "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50" const MONO_LINK = "font-mono text-3xs text-muted-foreground underline-offset-2 transition-colors hover:text-foreground hover:underline" @@ -52,11 +52,11 @@ 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/70 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/60 bg-background/60 px-2 transition-colors focus-within:border-ring min-w-0 max-w-xs flex-1", ), ], [ - icon(h, "MagnifierIcon", { size: 11, className: "shrink-0 text-muted-foreground" }), + icon(h, "MagnifierIcon", { size: 12, className: "shrink-0 text-muted-foreground" }), h.input([ h.Type("search"), h.Value(value), 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 0e555cd7d2..5b4d9aa4e5 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/40 px-4 py-3 last:border-0 hover:bg-muted/40" + "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50" export const SCOPE_IDS = { dns: "cf-scope-dns", 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 02950f1267..4fc6af84e8 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 @@ -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/40 px-4 py-3 last:border-0 hover:bg-muted/40", + "flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0 hover:bg-muted/50", ), ], cells, 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 ffc5f5585e..7cb4cb6e00 100644 --- a/apps/web/src/page/infra-integrations/gcp/list/view.ts +++ b/apps/web/src/page/infra-integrations/gcp/list/view.ts @@ -210,7 +210,7 @@ const regionChip = (h: H, region: string): Html => { h.span( [ h.Class( - "inline-flex items-center gap-1 rounded-sm border border-border/70 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/60 bg-background/60 py-0.5 pr-0.5 pl-1.5 font-mono text-3xs text-muted-foreground", ), ], [ @@ -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/40 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-muted/50 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 1b1da7cc19..192a29a633 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/75", + "flex shrink-0 items-center justify-center border bg-muted/40 text-foreground/70", tile.box, options.className, ), 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 dfac43e2c2..031ac45d27 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,7 +33,7 @@ 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/85 transition-colors hover:bg-muted/60 hover:text-foreground" + "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" const label = (h: H, text: string): Html => h.span([h.Class("min-w-0 flex-1 truncate")], [text]) 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 c0ab8dc4a3..71a18d971f 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 @@ -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/70")], + [h.Class("border-y border-border/60")], 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/40 px-1 py-2 transition-colors last:border-0 hover:bg-muted/50", + "flex items-center gap-3 border-b border-border/60 px-1 py-2 transition-colors last:border-0 hover:bg-muted/50", ), ], [ @@ -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/40 px-1 py-2 transition-colors last:border-0 hover:bg-muted/50", + "flex items-center gap-3 border-b border-border/60 px-1 py-2 transition-colors last:border-0 hover:bg-muted/50", ), ], [ @@ -286,7 +286,7 @@ const slowestCalls = (h: H, inputs: QueryPeekInputs): Html => { [ h.Class( cn( - "border-y border-border/70", + "border-y border-border/60", 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 38e79b4a28..a7face7dbf 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/40 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/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", rowSelectedClass(isPeeked), ), ), @@ -256,7 +256,7 @@ export const appWaitCallout = ( ? `The gap is waiting for a connection: ${instanceName} sat at ${Math.round(peak.open)} of ${peak.max}${idle > 0 ? `, and ${idle} of them were idle in transaction` : ""}. Fix the pool, not the query.` : "The time is spent outside the database: the network, or waiting on the connection pool." return h.div( - [h.Class("@container rounded-lg border border-severity-error/40")], + [h.Class("@container rounded-md border border-severity-error/40")], [ h.div( [h.Class("flex flex-col @2xl:flex-row @2xl:items-center")], diff --git a/apps/web/src/page/infra-integrations/gcp/workload/view.ts b/apps/web/src/page/infra-integrations/gcp/workload/view.ts index 86f19b63d5..8042fb7680 100644 --- a/apps/web/src/page/infra-integrations/gcp/workload/view.ts +++ b/apps/web/src/page/infra-integrations/gcp/workload/view.ts @@ -159,7 +159,7 @@ const traceGapCallout = ( const time = (ms: number) => new Intl.DateTimeFormat("en-US", { timeZone, hour: "2-digit", minute: "2-digit" }).format(ms) return h.div( - [h.Class("@container rounded-lg border border-severity-error/40")], + [h.Class("@container rounded-md border border-severity-error/40")], [ h.div( [h.Class("flex flex-col @2xl:flex-row @2xl:items-center")], 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 1c57fa9499..f5f08b761d 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/70 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/60 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" 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 cbb5499bb7..ad3203fd86 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 @@ -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/40", - isSelected && "bg-muted/40", + "flex w-full items-center gap-3 px-3 py-1.5 text-left transition-colors hover:bg-muted/50", + isSelected && "bg-muted/60", ), ), ...styleAttrs, 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 0d633349f2..2fa8285133 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/70 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/60 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")], 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 9f51f04efd..1f48305f9b 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 @@ -82,7 +82,10 @@ const syncNote = (h: H, sync: RailwaySync, clock: Clock): Html => { [ "paused", ...(sync.lastSyncedAt !== null - ? [" · last data ", relativeTime(h, { tooltip: "title", value: sync.lastSyncedAt, ...clock })] + ? [ + " · last data ", + relativeTime(h, { tooltip: "title", value: sync.lastSyncedAt, ...clock }), + ] : []), ], ) @@ -203,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/40 bg-muted/30 px-4 py-2 font-mono text-2xs", + "flex items-center gap-2.5 border-b border-border/60 bg-muted/30 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 d1aacad130..442a421a70 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/40 px-4 py-2.5 first:border-t-0 transition-colors" + "flex items-center gap-4 border-t border-border/60 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/40"))], children), + : h.a([h.Href(href), h.Class(cn(className, "hover:bg-muted/50"))], children), ], ) } @@ -159,7 +159,7 @@ const findingsBody = ( h.p( [ h.Key(note), - h.Class("border-t border-border/40 px-4 py-2 text-2xs text-muted-foreground"), + h.Class("border-t border-border/60 px-4 py-2 text-2xs text-muted-foreground"), ], [note], ), 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 35838249e3..49fecd4c2f 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/40 px-4 py-3 first:border-t-0"), + h.Class("flex flex-col gap-1 border-t border-border/60 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 4d82aa8eb3..12021d3250 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/40 px-4 py-2.5 last:border-0"), + h.Class("flex items-center gap-4 border-b border-border/60 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 a1cc7a7f39..50f0e73998 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/40 px-4 py-2 text-xs first:border-t-0"), + h.Class("flex items-center gap-4 border-t border-border/60 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 6c6446e060..0ebe536d3d 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/40 px-4 py-2.5 first:border-t-0", + "flex items-start gap-3 border-t border-border/60 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 2ed2231b1d..41d2131818 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/40 px-4 py-2 text-xs" +const PATH_ROW = "flex items-center gap-4 border-t border-border/60 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-integrations/supabase/project/view.ts b/apps/web/src/page/infra-integrations/supabase/project/view.ts index e948b28548..cdfe0fe77a 100644 --- a/apps/web/src/page/infra-integrations/supabase/project/view.ts +++ b/apps/web/src/page/infra-integrations/supabase/project/view.ts @@ -152,7 +152,7 @@ const heroActions = (h: H, model: Model, project: DiscoveredProject | null): Rea href: supabaseDashboardHref(model.projectRef), attributes: [h.Target("_blank"), h.Rel("noopener noreferrer")], }, - ["Open in Supabase", icon(h, "ExternalLinkIcon", { size: 12 })], + ["Open in Supabase", icon(h, "ExternalLinkIcon", { size: 14 })], ), ] @@ -194,8 +194,7 @@ export const view = Submodel.defineView((model, { scrollClassName: "gap-4", titleContent: hero.title, - actions: - headerActions(h, actions, timeControls), + actions: headerActions(h, actions, timeControls), }, [ hero.body, diff --git a/apps/web/src/page/infra/kit/data-table.ts b/apps/web/src/page/infra/kit/data-table.ts index 43673534c1..92bd96aca5 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/40 px-4 py-3 transition-colors last:border-0 hover:bg-muted/40 focus-visible:bg-muted/40 focus-visible:outline-none" + "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" /** A sortable head's state: `null` sort is the skeleton's inert head (no current key). */ export const headSort = ( @@ -61,7 +61,7 @@ export const columnHead = (h: HtmlBuilder, options: ColumnHeadOptions): [ options.label, icon(h, "ArrowUpDownIcon", { - size: 10, + size: 12, className: cn( "transition-opacity", sort.isActive ? "opacity-100" : "opacity-40", @@ -98,7 +98,7 @@ export const dataTable = ( ) return h.div( [ - h.Class(cn("border-y border-border/70", refreshingClass(isWaiting), options.className)), + h.Class(cn("border-y border-border/60", 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/40 px-4 py-3 last:border-0")], + [h.Class("flex items-center gap-4 border-b border-border/60 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 e41cb30c33..29f4a77289 100644 --- a/apps/web/src/page/infra/kit/meta-line.ts +++ b/apps/web/src/page/infra/kit/meta-line.ts @@ -73,11 +73,11 @@ export const platformLabel = (h: HtmlBuilder, kind: PlatformKind, value: s : [ known.color === undefined ? icon(h, known.icon, { - size: 11, + size: 12, className: cn("shrink-0", "text-foreground/70"), }) : icon(h, known.icon, { - size: 11, + size: 12, className: cn("shrink-0"), style: { color: known.color }, }), 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 5bf8d74c88..f09e99fa27 100644 --- a/apps/web/src/page/infra/kubernetes/pod-restarts-view.ts +++ b/apps/web/src/page/infra/kubernetes/pod-restarts-view.ts @@ -18,11 +18,17 @@ type Restarts = AsyncData.AsyncData, LoadFailure> export const podRestartsStat = (h: HtmlBuilder, restarts: Restarts): Html => AsyncData.matchData(restarts, { onEmpty: () => statRailItemSkeleton(h), - onFailure: () => statRailItem(h, { eyebrow: "Restarts", value: EMPTY_VALUE, hint: "unavailable", compact: true }), + onFailure: () => + statRailItem(h, { eyebrow: "Restarts", value: EMPTY_VALUE, hint: "unavailable", compact: true }), onData: (rows) => { // No rows means the cluster collector isn't reporting this pod, not zero restarts. if (rows.length === 0) - return statRailItem(h, { eyebrow: "Restarts", value: EMPTY_VALUE, hint: "not reported", compact: true }) + return statRailItem(h, { + eyebrow: "Restarts", + value: EMPTY_VALUE, + hint: "not reported", + compact: true, + }) const summary = summarizePodRestarts(rows).values().next().value const count = summary?.restarts ?? 0 const reason = summary?.lastTerminatedReason ?? "" @@ -39,19 +45,34 @@ export const podRestartsStat = (h: HtmlBuilder, restarts: Restarts): Html const containerRow = (h: HtmlBuilder, row: RestartRow): Html => h.div( - [h.Key(row.containerName), h.Class("flex items-center gap-4 border-b border-border/40 px-4 py-3 last:border-0")], [ - h.span([h.Class("w-0 min-w-[200px] flex-1 truncate font-mono text-xs text-foreground")], [row.containerName || EMPTY_VALUE]), + h.Key(row.containerName), + h.Class("flex items-center gap-4 border-b border-border/60 px-4 py-3 last:border-0"), + ], + [ + h.span( + [h.Class("w-0 min-w-[200px] flex-1 truncate font-mono text-xs text-foreground")], + [row.containerName || EMPTY_VALUE], + ), h.span( [ h.Class( - cn("w-[96px] text-right font-mono text-xs tabular-nums", TONE_TEXT[restartTone(row.restarts, row.lastTerminatedReason)]), + cn( + "w-[96px] text-right font-mono text-xs tabular-nums", + TONE_TEXT[restartTone(row.restarts, row.lastTerminatedReason)], + ), ), ], [String(row.restarts)], ), - h.span([h.Class("w-[96px] 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")], [row.lastTerminatedReason || EMPTY_VALUE]), + h.span( + [h.Class("w-[96px] 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")], + [row.lastTerminatedReason || EMPTY_VALUE], + ), ], ) diff --git a/apps/web/src/page/infra/overview/view-findings.ts b/apps/web/src/page/infra/overview/view-findings.ts index 76d443fb7f..a232ecbb3b 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/40 focus-visible:bg-muted/40 focus-visible:outline-none" + "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" 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/integrations/view-aws.ts b/apps/web/src/page/integrations/view-aws.ts index 1f6ac584c5..f33edcd387 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-lg border bg-muted/20 p-3"), + h.Class("flex w-full flex-col gap-4 rounded-md border bg-muted/20 p-3"), h.OnSubmit(Message.SubmittedAwsMetrics({ id: connection.id })), ], [ @@ -121,7 +121,7 @@ const stepGlyph = (h: H, state: StepState, index: number): Html => ? h.span( [ h.Class( - "flex size-4 shrink-0 items-center justify-center rounded-full border text-[10px] tabular-nums text-muted-foreground", + "flex size-4 shrink-0 items-center justify-center rounded-full border text-3xs tabular-nums text-muted-foreground", ), ], [String(index + 1)], @@ -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-lg border bg-muted/20 p-3")], + [h.Class("mt-2 flex w-full flex-col gap-3 rounded-md border bg-muted/20 p-3")], [ h.div( [h.Class("flex flex-wrap items-center gap-2")], @@ -594,7 +594,7 @@ const removedPanel = (h: H, model: Model, focusId: string | null): ReadonlyArray .filter((stack) => focusId === null || stack.connectionId === focusId) .map((stack) => h.div( - [h.Class("flex flex-col gap-3 rounded-lg border p-4")], + [h.Class("flex flex-col gap-3 rounded-md border p-4")], [ 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 6905ecb904..c2a1af2234 100644 --- a/apps/web/src/page/integrations/view-cloudflare-board.ts +++ b/apps/web/src/page/integrations/view-cloudflare-board.ts @@ -136,7 +136,7 @@ const resourceRow = ( ), ] const rowClass = - "group flex items-start gap-3 border-b border-border/40 px-3 py-2 transition-colors last:border-0" + "group flex items-start gap-3 border-b border-border/60 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/40 focus-visible:bg-muted/40 focus-visible:outline-none", + "hover:bg-muted/50 focus-visible:bg-muted/50 focus-visible:outline-none", ), ), ], @@ -322,7 +322,7 @@ export const workersCard = ( ...(aggregate.kind === "issue" || aggregate.kind === "no-data" ? [ h.div( - [h.Class(cn("border-b border-border/40 px-4 py-2 text-2xs", aggregate.detailClass))], + [h.Class(cn("border-b border-border/60 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/40 py-2.5 last:border-0", + "flex items-center justify-between gap-3 border-b border-border/60 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 cdb16b2cf2..aed2b67083 100644 --- a/apps/web/src/page/integrations/view-cloudflare-connected.ts +++ b/apps/web/src/page/integrations/view-cloudflare-connected.ts @@ -141,7 +141,7 @@ const statCards = (h: H, usage: CloudflareUsageResponse | null): Html => { "inline-flex shrink-0 items-center gap-1 text-2xs text-muted-foreground hover:text-foreground", ), ], - ["Open", icon(h, "ArrowRightIcon", { size: 11 })], + ["Open", icon(h, "ArrowRightIcon", { size: 12 })], ), }), ]) diff --git a/apps/web/src/page/integrations/view-cloudflare-zones.ts b/apps/web/src/page/integrations/view-cloudflare-zones.ts index cf8458e6fe..007fafcfb0 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/40"), + h.Class("flex min-w-0 items-center gap-2.5 px-3 py-1.5 text-sm hover:bg-muted/50"), ], [ ...Checkbox.view(h, { diff --git a/apps/web/src/page/integrations/view-flow-github.ts b/apps/web/src/page/integrations/view-flow-github.ts index 3cb9d2d9ff..6538f77de3 100644 --- a/apps/web/src/page/integrations/view-flow-github.ts +++ b/apps/web/src/page/integrations/view-flow-github.ts @@ -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/40 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border/60 px-4 py-2.5 text-sm last:border-0", ), ], [ diff --git a/apps/web/src/page/integrations/view-flow-supabase.ts b/apps/web/src/page/integrations/view-flow-supabase.ts index adc999017b..bb63dfa7b2 100644 --- a/apps/web/src/page/integrations/view-flow-supabase.ts +++ b/apps/web/src/page/integrations/view-flow-supabase.ts @@ -140,7 +140,7 @@ const selfHostedLine = (h: H): Html => const revokedNotice = (h: H, status: SupabaseIntegrationStatus): Html => h.div( - [h.Class("flex gap-3 rounded-lg 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 px-4 py-3"), 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/40 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border/60 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 e46f6831e5..a44a0f5794 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-lg border")], + [h.Class("divide-y divide-border/60 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-method-choice.ts b/apps/web/src/page/integrations/view-gcp-configure-method-choice.ts index 62f07a34d7..80c4b74f11 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-lg border" }, [ + RadioGroup.radioGroup(h, { className: "gap-0 divide-y divide-border/60 rounded-md border" }, [ ...METHODS.map((option) => h.div( [h.Key(option.value), h.Class("flex flex-col gap-3 p-4")], @@ -110,7 +110,16 @@ export const methodChoice = (h: H, configure: ConfigureModel, changing: boolean) option.title, ...(option.badge === null ? [] - : [h.span([h.Class("text-xs font-normal text-muted-foreground")], [option.badge])]), + : [ + h.span( + [ + h.Class( + "text-xs font-normal text-muted-foreground", + ), + ], + [option.badge], + ), + ]), ], ), h.span([h.Class(SMALL)], [option.description]), @@ -118,7 +127,9 @@ export const methodChoice = (h: H, configure: ConfigureModel, changing: boolean) ), ], ), - ...(option.value === "code" && row === "code" ? [flavourToggle(h, configure, flavour)] : []), + ...(option.value === "code" && row === "code" + ? [flavourToggle(h, configure, flavour)] + : []), ], ), ), 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 68e0a12542..e3dcdcf637 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-script.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-script.ts @@ -59,7 +59,10 @@ const promptButton = (h: H, configure: ConfigureModel, prompt: string | null): H isDisabled: prompt === null, attributes: prompt === null ? [] : [h.OnClick(Message.ClickedGcpCopyPrompt({ prompt }))], }, - [...(isCopied ? [icon(h, "CheckIcon", { size: 12 })] : []), isCopied ? "Prompt copied" : "Copy prompt for coding agent"], + [ + ...(isCopied ? [icon(h, "CheckIcon", { size: 12 })] : []), + isCopied ? "Prompt copied" : "Copy prompt for coding agent", + ], ) } @@ -71,7 +74,7 @@ export const fileCard = (h: H, model: Model, configure: ConfigureModel, options: const copyable = promptShown ? (prompt ?? null) : text const shown = promptShown ? (prompt?.trimEnd() ?? null) : (text?.trimEnd() ?? null) return h.div( - [h.Class("overflow-clip rounded-lg border")], + [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")], @@ -80,7 +83,9 @@ export const fileCard = (h: H, model: Model, configure: ConfigureModel, options: [h.Class("font-mono text-xs text-muted-foreground")], [ promptShown ? "Prompt for a coding agent" : name, - ...(shown === null || promptShown ? [] : [` · ${countLabel(shown.split("\n").length, "line")}`]), + ...(shown === null || promptShown + ? [] + : [` · ${countLabel(shown.split("\n").length, "line")}`]), ], ), h.span( @@ -89,13 +94,17 @@ export const fileCard = (h: H, model: Model, configure: ConfigureModel, options: ...(prompt === undefined ? [] : [promptButton(h, configure, prompt)]), CopyButton.view(h, { model: model.gcpCard.copies[COPY_ID] ?? CopyButton.init(), - toParentMessage: (message) => Message.GotGcpCopyMessage({ id: COPY_ID, message }), + toParentMessage: (message) => + Message.GotGcpCopyMessage({ id: COPY_ID, message }), value: copyable ?? "", label: promptShown ? "prompt" : name, idleLabel: secret ? "Copy script" : "Copy", variant: children === undefined ? "default" : "outline", size: "sm", - className: cn(children === undefined && "text-primary-foreground hover:text-primary-foreground"), + className: cn( + children === undefined && + "text-primary-foreground hover:text-primary-foreground", + ), attributes: copyable === null ? [h.Disabled(true)] : [], }), ...(children ?? []), @@ -154,9 +163,16 @@ const fileText = ( const footerText = (configure: ConfigureModel, name: string, secret: boolean): string => { if (!configure.isPromptShown) - return secret ? "Holds this connection's secret. Don't share or commit it." : "No secrets in this file. Safe to commit." + return secret + ? "Holds this connection's secret. Don't share or commit it." + : "No secrets in this file. Safe to commit." const copied = configure.promptCopied - const status = copied === false ? "Couldn't copy: select the prompt and copy it." : copied === true ? "Copied." : "Copying." + const status = + copied === false + ? "Couldn't copy: select the prompt and copy it." + : copied === true + ? "Copied." + : "Copying." return `${status} It ends with the full ${name}.` } 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 7f16aeef11..181e46416f 100644 --- a/apps/web/src/page/integrations/view-gcp-configure-status.ts +++ b/apps/web/src/page/integrations/view-gcp-configure-status.ts @@ -62,7 +62,10 @@ const overdueHelp = (h: H): Html => /** How a setup without the script is confirmed: by the first data, as no run reports it. */ const CONFIRMED_BY = { logs: { done: "Confirmed: logs arrive", waiting: "Confirmed by the first log Maple receives" }, - metrics: { done: "Confirmed: metrics are read", waiting: "Confirmed by the first metrics read, within 5 minutes" }, + metrics: { + done: "Confirmed: metrics are read", + waiting: "Confirmed by the first metrics read, within 5 minutes", + }, } as const /** A row per capability set up or removed, ticked as the script reports or, without it, as data arrives. */ @@ -87,7 +90,10 @@ export const runStatus = ( const state: RowState = confirmed && (reported || !byScript) ? "done" : running || !byScript ? "running" : "pending" // The poller's failure, once past the grant's grace: what a setup without the script can be told. - const error = !byScript && capability === "metrics" && metricsState.kind === "failing" ? metricsState.error : null + const error = + !byScript && capability === "metrics" && metricsState.kind === "failing" + ? metricsState.error + : null const detail = byScript ? wanted ? run.on @@ -117,7 +123,10 @@ export const runStatus = ( overdue ? icon(h, "AlertWarningIcon", { size: 14, className: "shrink-0 text-severity-warn" }) : done === rows.length - ? icon(h, "CircleCheckIcon", { size: 14, className: "shrink-0 text-severity-info" }) + ? icon(h, "CircleCheckIcon", { + size: 14, + className: "shrink-0 text-severity-info", + }) : spinner(h, "size-3.5 shrink-0 text-severity-debug"), h.p( [h.Class(cn("text-sm font-medium", overdue && "text-severity-warn"))], @@ -127,15 +136,19 @@ export const runStatus = ( ? "Confirmed by the first data" : "Waiting for Google Cloud" : overdue - ? "No report from the script yet" - : reporting - ? "The script is reporting back" - : "Waiting for the script to report back", + ? "No report from the script yet" + : reporting + ? "The script is reporting back" + : "Waiting for the script to report back", ], ), h.span( [h.Class("ml-auto shrink-0 font-mono text-xs text-muted-foreground")], - [reporting ? `${done} of ${rows.length} ${byScript ? "done" : "confirmed"}` : "updates on its own"], + [ + reporting + ? `${done} of ${rows.length} ${byScript ? "done" : "confirmed"}` + : "updates on its own", + ], ), ], ), @@ -145,7 +158,11 @@ export const runStatus = ( [h.Class("flex flex-col gap-1.5 pl-6")], rows.map((row) => h.li( - [h.Class("grid grid-cols-[auto_1fr] items-center gap-x-2.5 text-xs/5 sm:grid-cols-[auto_10rem_1fr]")], + [ + h.Class( + "grid grid-cols-[auto_1fr] items-center gap-x-2.5 text-xs/5 sm:grid-cols-[auto_10rem_1fr]", + ), + ], [ rowMarker(h, row.state), h.span([h.Class("text-foreground")], [row.title]), @@ -154,7 +171,9 @@ export const runStatus = ( h.Class( cn( "col-start-2 text-pretty sm:col-start-auto", - row.error === null ? "text-muted-foreground" : "text-severity-error", + row.error === null + ? "text-muted-foreground" + : "text-severity-error", ), ), ], @@ -216,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-lg border text-left")], + [h.Class("w-full divide-y divide-border/60 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 5cec4a49f2..b7c36032b1 100644 --- a/apps/web/src/page/integrations/view-gcp-connection.ts +++ b/apps/web/src/page/integrations/view-gcp-connection.ts @@ -319,7 +319,7 @@ const fact = (h: H, label: string, value: Html | string): Html => ) const signalLink = (h: H, href: string, label: string): Html => - h.a([h.Href(href), h.Class(SIGNAL_LINK)], [label, icon(h, "ArrowRightIcon", { size: 11 })]) + h.a([h.Href(href), h.Class(SIGNAL_LINK)], [label, icon(h, "ArrowRightIcon", { size: 12 })]) const menuEntries: ReadonlyArray = [ ...(IS_ADMIN ? [{ _tag: "Item", value: "configure", label: "Edit data" } as const] : []), 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 24b2441b40..5756aac78e 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-lg border")], + [h.Class("divide-y divide-border/60 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 0c095f070a..0e7a87575a 100644 --- a/apps/web/src/page/integrations/view-gcp-workloads.ts +++ b/apps/web/src/page/integrations/view-gcp-workloads.ts @@ -98,7 +98,7 @@ const workloads = (h: H, model: Model, className: string): Html => { ? [] : [ h.p( - [h.Class("border-b border-border/40 px-4 py-2 text-2xs text-severity-warn")], + [h.Class("border-b border-border/60 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/40 px-4 py-2.5 transition-colors last:border-0 hover:bg-muted/40 focus-visible:bg-muted/40 focus-visible:outline-none", + "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", ), ], [ @@ -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/40 focus-visible:bg-muted/40 focus-visible:outline-none", + "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", ), ], [ @@ -275,7 +275,7 @@ const resources = (h: H, model: Model, className: string): Html => { types.length > TYPES_SHOWN ? `All ${countLabel(types.length, "type")}` : "All resources", - icon(h, "ArrowRightIcon", { size: 11 }), + icon(h, "ArrowRightIcon", { size: 12 }), ], ), ], diff --git a/apps/web/src/page/integrations/view-github-repos.ts b/apps/web/src/page/integrations/view-github-repos.ts index 65124a0981..4694e1eee7 100644 --- a/apps/web/src/page/integrations/view-github-repos.ts +++ b/apps/web/src/page/integrations/view-github-repos.ts @@ -134,7 +134,7 @@ const repoRow = (h: H, model: Model, repo: GithubRepoSummary, timeZone: string): return item(h, { variant: "flush", size: "lg", tag: "li" }, [ itemMedia(h, {}, [ icon(h, presentation.icon, { - size: 17, + size: 16, className: `${presentation.tone} ${presentation.spin === true ? "animate-spin" : ""}`, }), ]), @@ -199,7 +199,7 @@ const syncCount = (h: H, glyph: Html, count: number, label: string): Html => const removedRow = (h: H, model: Model, repo: GithubRepoSummary): Html => item(h, { variant: "flush", size: "lg", tag: "li" }, [ - itemMedia(h, {}, [icon(h, "CircleWarningIcon", { size: 17, className: "text-severity-warn" })]), + itemMedia(h, {}, [icon(h, "CircleWarningIcon", { size: 16, className: "text-severity-warn" })]), itemContent( h, [ @@ -245,7 +245,7 @@ export const repositoriesPanels = ( ? [ syncCount( h, - icon(h, "CircleCheckIcon", { size: 13, className: "text-severity-info" }), + icon(h, "CircleCheckIcon", { size: 14, className: "text-severity-info" }), synced, "synced", ), @@ -256,7 +256,7 @@ export const repositoriesPanels = ( ? [ syncCount( h, - icon(h, "CircleWarningIcon", { size: 13, className: "text-severity-error" }), + icon(h, "CircleWarningIcon", { size: 14, className: "text-severity-error" }), failed, "failed", ), @@ -300,7 +300,7 @@ export const repositoriesPanels = ( [h.Class("flex items-center gap-1.5 text-sm font-medium")], [ icon(h, "CircleWarningIcon", { - size: 15, + size: 16, className: "text-severity-warn", }), "Needs attention", diff --git a/apps/web/src/page/integrations/view-github.ts b/apps/web/src/page/integrations/view-github.ts index 610569b09e..64b4c806f8 100644 --- a/apps/web/src/page/integrations/view-github.ts +++ b/apps/web/src/page/integrations/view-github.ts @@ -232,7 +232,7 @@ export const githubDeactivated = (h: H, model: Model, status: GithubIntegrationS return h.div( [ h.Class( - "flex flex-col items-center gap-5 rounded-lg border border-severity-warn/40 bg-severity-warn/5 px-6 py-10 text-center", + "flex flex-col items-center gap-5 rounded-md border border-severity-warn/40 bg-severity-warn/5 px-6 py-10 text-center", ), ], [ diff --git a/apps/web/src/page/integrations/view-hub.ts b/apps/web/src/page/integrations/view-hub.ts index 62e31d6418..3b9c27be93 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/40 focus-visible:bg-muted/40 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-muted/50 focus-visible:bg-muted/50 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/40", ), ], [ @@ -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-lg border border-border/60 bg-card p-4 text-left outline-none transition-colors hover:border-border hover:bg-muted/40 focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40", + "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", ), ], [ diff --git a/apps/web/src/page/integrations/view-prometheus-details.ts b/apps/web/src/page/integrations/view-prometheus-details.ts index d6ae6d6549..348062a9f6 100644 --- a/apps/web/src/page/integrations/view-prometheus-details.ts +++ b/apps/web/src/page/integrations/view-prometheus-details.ts @@ -375,6 +375,6 @@ export const targetDetails = (h: H, model: Model, target: V2ScrapeTarget, timeZo const sectionTitle = (h: H, iconName: "PulseIcon" | "ExternalLinkIcon" | "HistoryIcon", text: string): Html => eyebrow(h, { variant: "label", className: "flex items-center gap-2", as: "div" }, [ - icon(h, iconName, { size: 13 }), + icon(h, iconName, { size: 14 }), text, ]) diff --git a/apps/web/src/page/integrations/view-railway.ts b/apps/web/src/page/integrations/view-railway.ts index 1e97fd11d1..3abb558c77 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/40 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border/60 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 6b25a8c958..c0f500fd7e 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/40 px-4 py-2.5 text-sm last:border-0", + "flex items-center gap-4 border-b border-border/60 px-4 py-2.5 text-sm last:border-0", isPaused && "opacity-60", ), ), 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 0f434b2249..e544ef31a7 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-cards.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-cards.ts @@ -106,7 +106,7 @@ export type ApprovalCardOptions = Readonly<{ export const approvalCard = (h: HtmlBuilder, options: ApprovalCardOptions): Html => h.div( - [h.Class("overflow-hidden rounded-lg border border-severity-warn/40 bg-severity-warn/5 text-xs")], + [h.Class("overflow-hidden rounded-md border border-severity-warn/40 bg-severity-warn/5 text-xs")], [ item(h, { size: "xs", variant: "flush", className: "gap-2 px-3" }, [ itemMedia(h, { variant: "icon" }, [ diff --git a/apps/web/src/page/investigations/conversation/kit/view-code.ts b/apps/web/src/page/investigations/conversation/kit/view-code.ts index 72fb21d7d2..fe26f35733 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-code.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-code.ts @@ -96,7 +96,7 @@ export const codeBlock = (h: HtmlBuilder, host: CodeHost, value: string return h.div( [ h.Class( - "relative my-4 flex w-full flex-col gap-2 rounded-xl border border-border bg-sidebar p-2", + "relative my-4 flex w-full flex-col gap-2 rounded-md border border-border bg-sidebar p-2", ), h.DataAttribute("language", language), h.DataAttribute("streamdown", "code-block"), 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 a42b0da93b..8b8a461b9c 100644 --- a/apps/web/src/page/investigations/conversation/kit/view-inline.ts +++ b/apps/web/src/page/investigations/conversation/kit/view-inline.ts @@ -66,7 +66,7 @@ const serviceChips = (h: HtmlBuilder, services: ReadonlyArray): Re h.span( [ h.Class( - "min-w-0 truncate rounded-sm border border-border/70 bg-background/60 px-1.5 py-0.5 text-2xs text-muted-foreground", + "min-w-0 truncate rounded-sm border border-border/60 bg-background/60 px-1.5 py-0.5 text-2xs text-muted-foreground", ), h.Title(service), ], diff --git a/apps/web/src/page/investigations/detail/view-canvas.ts b/apps/web/src/page/investigations/detail/view-canvas.ts index e296834d4c..82f58b6922 100644 --- a/apps/web/src/page/investigations/detail/view-canvas.ts +++ b/apps/web/src/page/investigations/detail/view-canvas.ts @@ -122,7 +122,7 @@ const spineNode = (h: H, id: string, data: SpineNodeData, clock: Clock): Readonl ], [ icon(h, GLYPH[data.glyph], { - size: 13, + size: 14, className: cn( "relative", isCurrent ? null : data.glyph === "verdict" ? TONE_TEXT.info : TONE_TEXT.crit, @@ -221,7 +221,7 @@ const spineNode = (h: H, id: string, data: SpineNodeData, clock: Clock): Readonl : []), ] const shell = cn( - "flex size-full flex-col gap-1.5 overflow-hidden rounded-lg border px-3 py-2.5", + "flex size-full flex-col gap-1.5 overflow-hidden rounded-md border px-3 py-2.5", 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-lg 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 px-3 py-2.5", ), ], [ @@ -264,7 +264,7 @@ const pendingVerdictNode = (h: H, id: string, data: PendingVerdictNodeData): Rea "flex size-5.5 shrink-0 items-center justify-center rounded-sm border border-dashed", ), ], - [icon(h, "ClockIcon", { size: 13, className: "text-muted-foreground" })], + [icon(h, "ClockIcon", { size: 14, className: "text-muted-foreground" })], ), eyebrow(h, { className: "min-w-0 flex-1 leading-[1.3] text-muted-foreground" }, [ data.word, @@ -290,7 +290,7 @@ const actionGhostNode = (h: H, id: string): ReadonlyArray => [ [ h.AriaHidden(true), h.Class( - "pointer-events-none flex size-full items-center gap-2.5 rounded-lg border border-dashed bg-card/40 px-3", + "pointer-events-none flex size-full items-center gap-2.5 rounded-md border border-dashed bg-card/40 px-3", ), ], [ @@ -326,7 +326,7 @@ const actionNode = (h: H, id: string, data: ActionNodeData): ReadonlyArray h.OnClick(Message.ClickedAction({ index: data.index })), h.OnKeyDownPreventDefault(openKey(data.index)), h.Class( - "flex size-full cursor-pointer items-center gap-2.5 rounded-lg border bg-card px-3 transition-colors hover:border-primary/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", + "flex size-full cursor-pointer items-center gap-2.5 rounded-md border bg-card px-3 transition-colors hover:border-primary/60 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", ), ], [ 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 d0aa240270..d420cb1a9d 100644 --- a/apps/web/src/page/investigations/detail/view-diagnosis-card.ts +++ b/apps/web/src/page/investigations/detail/view-diagnosis-card.ts @@ -169,12 +169,12 @@ const actionRow = (h: H, action: ActionNodeData): Html => { [String(action.index + 1)], ), icon(h, glyph.icon, { - size: 13, + size: 14, className: "mt-1 shrink-0 text-muted-foreground", 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: 13, className: "mt-1 shrink-0 text-muted-foreground/50" }), + icon(h, "ChevronRightIcon", { size: 14, className: "mt-1 shrink-0 text-muted-foreground/50" }), ], ), ], diff --git a/apps/web/src/page/investigations/detail/view-verdict.ts b/apps/web/src/page/investigations/detail/view-verdict.ts index 6270dbc878..76bcc60f67 100644 --- a/apps/web/src/page/investigations/detail/view-verdict.ts +++ b/apps/web/src/page/investigations/detail/view-verdict.ts @@ -366,7 +366,7 @@ const failed = (h: HtmlBuilder, investigation: V2Investigation, nowMs: num ? h.div( [ h.Class( - "flex items-start gap-3 rounded-lg 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 px-3 py-2.5", ), ], [ @@ -418,7 +418,7 @@ const partialList = ( [h.Class(cn("flex gap-2 text-sm leading-6", tone))], [ icon(h, iconName, { - size: 13, + size: 14, className: "mt-0.5 shrink-0 text-muted-foreground/70", }), h.span([h.Class("min-w-0")], [item]), diff --git a/apps/web/src/page/kit/commit-card.ts b/apps/web/src/page/kit/commit-card.ts index b76ca122e0..05849e24f2 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/60 px-3.5 py-2.5", + "flex items-center justify-center gap-1 font-medium text-primary transition-colors hover:bg-muted/50 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 2cc76275d6..b0f0aa624c 100644 --- a/apps/web/src/page/kit/connect-flow.ts +++ b/apps/web/src/page/kit/connect-flow.ts @@ -26,7 +26,7 @@ export type StepCardOptions = Readonly<{ /** The step's one card: a titled body. */ export const stepCard = (h: HtmlBuilder, options: StepCardOptions, children: Children): Html => h.section( - [h.Class("flex flex-col gap-5 rounded-lg border border-border bg-card p-5")], + [h.Class("flex flex-col gap-5 rounded-md border border-border bg-card p-5")], [ h.header( [h.Class("flex flex-wrap items-center justify-between gap-2")], @@ -81,7 +81,7 @@ export const choiceTiles = (h: HtmlBuilder, tiles: ReadonlyArray(h: HtmlBuilder, options: StatusRowOptions, child [ h.Class( cn( - "flex items-start gap-3 rounded-lg border bg-card px-4 py-3", + "flex items-start gap-3 rounded-md border bg-card px-4 py-3", 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-[11px]")], + [h.Class("rounded border border-border/60 bg-muted/40 px-1.5 py-0.5 font-mono text-2xs")], [ chip.label, ...(chip.detail === undefined @@ -196,7 +196,7 @@ export const flowRail = (h: HtmlBuilder, options: RailOptions): Html => [h.Class("flex flex-col gap-3")], [ h.div( - [h.Class("flex flex-col gap-4 rounded-lg border border-border bg-card p-4")], + [h.Class("flex flex-col gap-4 rounded-md border border-border bg-card p-4")], [ eyebrow(h, { variant: "label" }, [options.eyebrow]), h.ul( @@ -273,7 +273,7 @@ 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-lg 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 px-4 py-3 text-sm")], [ icon(h, "ShieldCheckIcon", { size: 14, className: "shrink-0 text-success" }), h.span([h.Class("flex-1")], [text]), @@ -317,7 +317,7 @@ export const liveChecklist = ( ): Html => h.section( [ - h.Class("flex flex-col rounded-lg border border-border bg-card"), + h.Class("flex flex-col rounded-md border border-border bg-card"), h.AriaLabel(options.title ?? "Going live"), ], [ diff --git a/apps/web/src/page/kit/guided-setup.ts b/apps/web/src/page/kit/guided-setup.ts index 5ba909f5b9..c48e33f1bc 100644 --- a/apps/web/src/page/kit/guided-setup.ts +++ b/apps/web/src/page/kit/guided-setup.ts @@ -167,7 +167,7 @@ export const agentPromptButton = ( ), ), ], - [icon(h, mark.name, { size: 13, className: mark.className })], + [icon(h, mark.name, { size: 14, className: mark.className })], ), ), ), diff --git a/apps/web/src/page/kit/infra-correlation/view.ts b/apps/web/src/page/kit/infra-correlation/view.ts index 7536ba7ada..c475e12599 100644 --- a/apps/web/src/page/kit/infra-correlation/view.ts +++ b/apps/web/src/page/kit/infra-correlation/view.ts @@ -63,7 +63,7 @@ const section = (h: H, model: Model, correlation: InfraCorrelation, timeZone: st h.span([h.Class("text-xs font-medium text-foreground")], [correlation.title]), h.a( [h.Href(correlationHref(correlation)), h.Class(LINK_CLASS)], - ["View in Infrastructure", icon(h, "ExternalLinkIcon", { size: 11 })], + ["View in Infrastructure", icon(h, "ExternalLinkIcon", { size: 12 })], ), ], ), diff --git a/apps/web/src/page/kit/message-response.ts b/apps/web/src/page/kit/message-response.ts index b647a30ebe..e5169a4bf7 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-[13px] 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-muted-foreground/50 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))]" @@ -97,7 +97,7 @@ const codeBlock = ( return h.div( [ h.Class( - "relative my-4 flex w-full flex-col gap-2 rounded-xl border border-border bg-sidebar p-2", + "relative my-4 flex w-full flex-col gap-2 rounded-md border border-border bg-sidebar p-2", ), h.DataAttribute("language", language), h.DataAttribute("streamdown", "code-block"), diff --git a/apps/web/src/page/kit/refresh-controls.ts b/apps/web/src/page/kit/refresh-controls.ts index ba9e60a1fe..5423bcc37f 100644 --- a/apps/web/src/page/kit/refresh-controls.ts +++ b/apps/web/src/page/kit/refresh-controls.ts @@ -82,7 +82,7 @@ export const refreshControls = (h: HtmlBuilder, options: RefreshControlsOp [h.Class(cn("tabular-nums", !isOn && "text-muted-foreground"))], [formatRefreshInterval(seconds)], ), - icon(h, "ChevronDownIcon", { className: "size-3 opacity-60" }), + icon(h, "ChevronDownIcon", { className: "size-3.5 opacity-60" }), ], ), ), diff --git a/apps/web/src/page/kit/series-legend.ts b/apps/web/src/page/kit/series-legend.ts index 7687130fe8..89b27c1f2b 100644 --- a/apps/web/src/page/kit/series-legend.ts +++ b/apps/web/src/page/kit/series-legend.ts @@ -19,7 +19,7 @@ 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/85 tabular-nums", + value: "font-mono text-2xs text-foreground/80 tabular-nums", }, chip: { root: "flex flex-wrap items-center gap-2", diff --git a/apps/web/src/page/kit/time-range-picker.ts b/apps/web/src/page/kit/time-range-picker.ts index 14985a9cae..300c3008b5 100644 --- a/apps/web/src/page/kit/time-range-picker.ts +++ b/apps/web/src/page/kit/time-range-picker.ts @@ -416,7 +416,7 @@ 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/70 hover:border-border", + : "border-border/60 hover:border-border", ), ), ], @@ -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/70 bg-muted/20 px-4 py-2", + "flex items-center justify-between gap-3 border-t border-border/60 bg-muted/20 px-4 py-2", ), ], [ @@ -672,7 +672,7 @@ export const view = Submodel.defineView((model, inpu h.div( [ h.Class( - "w-full shrink-0 border-b border-border/70 sm:w-[168px] sm:border-r sm:border-b-0", + "w-full shrink-0 border-b border-border/60 sm:w-[168px] 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 f91d691827..46a52018e6 100644 --- a/apps/web/src/page/kit/timezone-select-view.ts +++ b/apps/web/src/page/kit/timezone-select-view.ts @@ -65,7 +65,7 @@ export const zoneListView = Submodel.defineView, model: Model, tip: Tip): Html => h.DataAttribute("slot", "tooltip-trigger"), ], [ - icon(h, "ThumbtackIcon", { size: 13, className: "text-muted-foreground" }), + icon(h, "ThumbtackIcon", { size: 14, className: "text-muted-foreground" }), "Columns", ...((model.search.columns?.length ?? 0) > 0 ? [ diff --git a/apps/web/src/page/logs/live-controls.ts b/apps/web/src/page/logs/live-controls.ts index a1215ddd71..5694c0b0c0 100644 --- a/apps/web/src/page/logs/live-controls.ts +++ b/apps/web/src/page/logs/live-controls.ts @@ -33,7 +33,7 @@ export const liveControls = (h: HtmlBuilder, model: LiveControlsInputs) ? [ h.span( [h.Class("flex items-center gap-1.5 text-muted-foreground text-xs")], - [icon(h, "MediaPauseIcon", { size: 10 }), "Paused while you inspect"], + [icon(h, "MediaPauseIcon", { size: 12 }), "Paused while you inspect"], ), ] : []), diff --git a/apps/web/src/page/onboarding/create-org-view.ts b/apps/web/src/page/onboarding/create-org-view.ts index 1f6f4e927a..0d8f7efd0a 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-lg border border-dashed border-input px-3.5 py-3")], + [h.Class("flex items-center gap-3 rounded-md border border-dashed border-input px-3.5 py-3")], [ options.imageUrl === "" ? h.span( @@ -273,7 +273,7 @@ const workspacePreview = (h: H, model: Model): Html => [ h.span([h.Class("text-sm font-medium text-foreground")], ["A peek at your new workspace"]), h.div( - [h.Class("w-full overflow-hidden rounded-xl border border-border bg-background")], + [h.Class("w-full overflow-hidden rounded-md border border-border bg-background")], [ h.div( [h.Class("flex h-9 items-center gap-1.5 border-b border-border bg-sidebar px-3.5")], diff --git a/apps/web/src/page/onboarding/pricing-cards-view.ts b/apps/web/src/page/onboarding/pricing-cards-view.ts index 9a475a9dc9..d7eeecdcb7 100644 --- a/apps/web/src/page/onboarding/pricing-cards-view.ts +++ b/apps/web/src/page/onboarding/pricing-cards-view.ts @@ -200,7 +200,7 @@ const planCard = (h: H, plan: CatalogPlan, loadingPlanId: string | null): Html = ], cn( "flex flex-col transition-colors", - isActive && "bg-muted/40", + isActive && "bg-muted/60", isUpgrade && "bg-muted/30 ring-1 ring-primary/30", ), ) diff --git a/apps/web/src/page/onboarding/quick-start-team-view.ts b/apps/web/src/page/onboarding/quick-start-team-view.ts index 74a27a8125..9b6caf0db5 100644 --- a/apps/web/src/page/onboarding/quick-start-team-view.ts +++ b/apps/web/src/page/onboarding/quick-start-team-view.ts @@ -124,7 +124,7 @@ export const teamStep = (h: H, team: Team): Html => { [ h.AriaLabel("Tools"), h.Class( - "flex flex-col divide-y divide-border overflow-hidden rounded-lg border border-border bg-card", + "flex flex-col divide-y divide-border overflow-hidden rounded-md border border-border bg-card", ), ], TOOLS.map((tool) => toolRow(h, tool)), @@ -226,7 +226,7 @@ export const teamPreview = (h: H): Html => ), ...SURFACES.map((surface) => h.div( - [h.Class("flex flex-col gap-2.5 rounded-xl border border-border bg-background p-3.5")], + [h.Class("flex flex-col gap-2.5 rounded-md border border-border bg-background p-3.5")], [ h.div( [h.Class("flex items-center gap-2 text-xs text-muted-foreground")], diff --git a/apps/web/src/page/onboarding/quick-start-view.ts b/apps/web/src/page/onboarding/quick-start-view.ts index b4c342eb5a..0e0b539d7e 100644 --- a/apps/web/src/page/onboarding/quick-start-view.ts +++ b/apps/web/src/page/onboarding/quick-start-view.ts @@ -223,7 +223,7 @@ const shell = (h: H, options: ShellOptions, children: ReadonlyArray): Html h.Key(options.step), h.Class( cn( - "relative m-auto w-full max-w-[540px] rounded-2xl border border-border bg-sidebar p-5", + "relative m-auto w-full max-w-[540px] rounded-md border border-border bg-sidebar p-5", "onboarding-enter-preview", ), ), @@ -490,7 +490,7 @@ const stackPreview = (h: H, orgName: string, state: QuickStartState): Html => { h.ul( [ h.Class( - "flex flex-col divide-y divide-border overflow-hidden rounded-xl border border-border bg-background", + "flex flex-col divide-y divide-border overflow-hidden rounded-md border border-border bg-background", ), ], surfaces.map((surface) => @@ -651,7 +651,7 @@ export const connectStep = (h: H, model: Model, state: QuickStartState): Html => h.ul( [ h.Class( - "flex flex-col divide-y divide-border overflow-hidden rounded-lg border border-border bg-card", + "flex flex-col divide-y divide-border overflow-hidden rounded-md border border-border bg-card", ), ], platforms.map((platform) => providerRow(h, model, platform)), @@ -688,7 +688,7 @@ export const connectStep = (h: H, model: Model, state: QuickStartState): Html => "flex size-6 items-center justify-center rounded-sm border border-border bg-card", ), ], - [icon(h, name, { size: 13 })], + [icon(h, name, { size: 14 })], ), ), ), @@ -796,7 +796,7 @@ const connectPreview = (h: H, orgName: string, model: Model, state: QuickStartSt h.ul( [ h.Class( - "flex flex-col divide-y divide-border overflow-hidden rounded-xl border border-border bg-background", + "flex flex-col divide-y divide-border overflow-hidden rounded-md border border-border bg-background", ), ], [ @@ -994,7 +994,7 @@ export const liveStep = (h: H, model: Model, state: QuickStartState, orgName: st h.ul( [ h.Class( - "grid gap-px overflow-hidden rounded-xl border border-border bg-border sm:grid-cols-3", + "grid gap-px overflow-hidden rounded-md border border-border bg-border sm:grid-cols-3", ), ], startCards(findings).map((card) => @@ -1041,7 +1041,7 @@ export const liveStep = (h: H, model: Model, state: QuickStartState, orgName: st h.ul( [ h.Class( - "flex flex-col divide-y divide-border overflow-hidden rounded-lg border border-border", + "flex flex-col divide-y divide-border overflow-hidden rounded-md border border-border", ), ], [ diff --git a/apps/web/src/page/overview/setup-checklist-view.ts b/apps/web/src/page/overview/setup-checklist-view.ts index 1f7c543823..35b1bd0023 100644 --- a/apps/web/src/page/overview/setup-checklist-view.ts +++ b/apps/web/src/page/overview/setup-checklist-view.ts @@ -114,7 +114,7 @@ const watchingStrip = (h: H): Html => h.div( [ h.Class( - "flex items-center gap-2.5 rounded-lg 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 px-4 py-3", ), ], [ @@ -201,7 +201,7 @@ const waitingCard = ( [ listRow(h, { onClick: Message.ClickedToggleExpanded(), - className: "flex-1 px-5 py-4 hover:bg-muted/30", + className: "flex-1 px-5 py-4 hover:bg-muted/50", leading: h.span( [ h.Class( diff --git a/apps/web/src/page/recommendations/view.ts b/apps/web/src/page/recommendations/view.ts index abeeca2670..2e6e24e2cd 100644 --- a/apps/web/src/page/recommendations/view.ts +++ b/apps/web/src/page/recommendations/view.ts @@ -159,7 +159,7 @@ const sidebar = (h: H, model: Model, issue: V2Recommendation, timeZone: string): row(h, "Type", [badge(h, { variant: kindBadge.variant }, [kindBadge.label])]), row(h, "Fix", [ badge(h, { variant: "outline", className: cn("gap-1", mode.className), attributes: [h.Title(mode.title)] }, [ - icon(h, mode.icon, { size: 11 }), + icon(h, mode.icon, { size: 12 }), mode.label, ]), ]), diff --git a/apps/web/src/page/replays/detail/view-rail.ts b/apps/web/src/page/replays/detail/view-rail.ts index 26a1813ea2..043640b206 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/60"), + config.isActive ? config.selected : cn(config.tone, "hover:bg-muted/50"), config.count === 0 && !config.isActive && "text-muted-foreground opacity-45", ), ), @@ -206,7 +206,7 @@ const filterBar = (h: H, model: RailView, events: ReadonlyArray): Html }, [ icon(h, EVENT_KIND_VISUALS[filter].icon, { - size: 13, + size: 14, attributes: [h.AriaHidden(true)], }), ], @@ -226,7 +226,7 @@ const filterBar = (h: H, model: RailView, events: ReadonlyArray): Html h.DataAttribute("base-ui-popover-trigger", ""), ], }, - [icon(h, "CircleInfoIcon", { size: 13 })], + [icon(h, "CircleInfoIcon", { size: 14 })], ), ], ) diff --git a/apps/web/src/page/replays/detail/view-session.ts b/apps/web/src/page/replays/detail/view-session.ts index b37effc691..743988ee42 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/50 bg-muted/30 px-2 py-1.5", + "flex flex-col gap-0.5 rounded-md border border-border/60 bg-muted/30 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/40 px-4 py-3.5")], + [h.Class("border-b border-border/60 px-4 py-3.5")], [ statFigure(h, { value: formatSessionDuration(total), unit: "on the page" }), ...(share === null diff --git a/apps/web/src/page/replays/detail/view-timeline.ts b/apps/web/src/page/replays/detail/view-timeline.ts index f792ed49c6..781c80f6ce 100644 --- a/apps/web/src/page/replays/detail/view-timeline.ts +++ b/apps/web/src/page/replays/detail/view-timeline.ts @@ -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/40 px-2 py-1 pl-6")), + h.Class(cn(LANE_GUTTER, "shrink-0 truncate border-r border-border/60 px-2 py-1 pl-6")), h.Title(`${span.serviceName} · ${span.spanName}`), ], [ @@ -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/40 last:border-b-0")], + [h.Key(summary.traceId), h.Class("border-b border-border/60 last:border-b-0")], [ h.div( [h.Class("flex items-stretch")], diff --git a/apps/web/src/page/replays/kit/sessions-list.ts b/apps/web/src/page/replays/kit/sessions-list.ts index 3f47c1b1a7..02e69fb2fa 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/60 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-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", ), ], [ diff --git a/apps/web/src/page/security/run/view.ts b/apps/web/src/page/security/run/view.ts index d1e6b4a3c9..f991a323df 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/40", + "flex w-full items-center gap-2.5 rounded-md border bg-card px-4 py-3 text-left hover:bg-muted/50", ), ], [ diff --git a/apps/web/src/page/security/tabs/view-overview.ts b/apps/web/src/page/security/tabs/view-overview.ts index 31911ea5dd..25b59636c0 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 { ), ], [ - icon(h, "PlanetScaleIcon", { size: 11, className: "shrink-0 text-muted-foreground" }), + icon(h, "PlanetScaleIcon", { size: 12, className: "shrink-0 text-muted-foreground" }), h.span([h.Class("truncate font-mono")], [config.matched.name]), h.span( [h.Class("shrink-0 text-3xs text-muted-foreground")], @@ -83,7 +83,7 @@ const hyperdriveOrigin = (h: H, config: HyperdriveNodeInfo): Html => { return h.span( [h.Class("flex min-w-0 items-center gap-1.5 text-muted-foreground")], [ - icon(h, "PlanetScaleIcon", { size: 11, className: "shrink-0" }), + icon(h, "PlanetScaleIcon", { size: 12, className: "shrink-0" }), h.span([h.Class("truncate font-mono")], [config.originDatabase]), h.span([h.Class("shrink-0 text-3xs")], ["PlanetScale (not in inventory)"]), ], @@ -139,7 +139,7 @@ export const hyperdriveSection = (h: H, configs: ReadonlyArray [h.Class("min-w-0 flex-1")], [ eyebrow(h, { as: "div", className: "flex items-center gap-1.5" }, [ - icon(h, "CubeIcon", { size: 11 }), + icon(h, "CubeIcon", { size: 12 }), h.span([], [workload.workloadKind]), ]), h.p( @@ -98,10 +98,7 @@ const workloadRow = (h: H, workload: ServiceWorkload, time: TimeSearch): Html => ? [] : [ h.a( - [ - h.Class(LINK), - h.Href(workloadLink(workload, time).href), - ], + [h.Class(LINK), h.Href(workloadLink(workload, time).href)], ["View workload ", icon(h, "ArrowRightIcon", { size: 10 })], ), ]), @@ -125,9 +122,9 @@ const runtimeRow = (h: H, link: RuntimeLink): Html => ), ], [ - panel(h, { padded: "sm", className: "space-y-1 transition-colors group-hover:bg-muted/40" }, [ + panel(h, { padded: "sm", className: "space-y-1 transition-colors group-hover:bg-muted/50" }, [ eyebrow(h, { as: "div", className: "flex items-center gap-1.5" }, [ - icon(h, link.icon, { size: 11 }), + icon(h, link.icon, { size: 12 }), h.span([], [link.label]), ]), h.div( @@ -138,7 +135,7 @@ const runtimeRow = (h: H, link: RuntimeLink): Html => [link.name], ), icon(h, "ArrowRightIcon", { - size: 10, + size: 12, className: "shrink-0 text-muted-foreground group-hover:text-primary", }), ], 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 e37e1274a0..091742b288 100644 --- a/apps/web/src/page/services/detail/endpoint-peek/view.ts +++ b/apps/web/src/page/services/detail/endpoint-peek/view.ts @@ -437,7 +437,7 @@ 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/40", + "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", ), ], [ 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 a29ed7662d..c111264d92 100644 --- a/apps/web/src/page/services/detail/view-api-tab.ts +++ b/apps/web/src/page/services/detail/view-api-tab.ts @@ -586,8 +586,8 @@ const loadingState = (h: H): Html => h.div( [h.Class("flex flex-col gap-4 lg:flex-row")], [ - skeleton(h, "h-[262px] flex-1 rounded-lg"), - skeleton(h, "h-[262px] w-full rounded-lg lg:w-[400px]"), + skeleton(h, "h-[262px] flex-1 rounded-md"), + skeleton(h, "h-[262px] w-full rounded-md lg:w-[400px]"), ], ), panel(h, {}, [ @@ -695,7 +695,7 @@ const loaded = ( ], ) : Option.match(overview, { - onNone: () => skeleton(h, "h-[262px] flex-1 rounded-lg"), + onNone: () => skeleton(h, "h-[262px] flex-1 rounded-md"), onSome: (data) => responsesChart(h, model, data, inputs, theme), }), breakdownFailure !== null diff --git a/apps/web/src/page/services/detail/view-api.ts b/apps/web/src/page/services/detail/view-api.ts index aaa879913d..e5c63d9c8b 100644 --- a/apps/web/src/page/services/detail/view-api.ts +++ b/apps/web/src/page/services/detail/view-api.ts @@ -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/40", + isSelected ? "bg-accent hover:bg-accent" : "hover:bg-muted/50", ), [h.Key(endpoint.spanName), h.OnClick(Message.ClickedEndpoint({ spanName: endpoint.spanName }))], ) diff --git a/apps/web/src/page/services/detail/view-dependencies.ts b/apps/web/src/page/services/detail/view-dependencies.ts index a9e99824b3..39b64a7ae5 100644 --- a/apps/web/src/page/services/detail/view-dependencies.ts +++ b/apps/web/src/page/services/detail/view-dependencies.ts @@ -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/40 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-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", [ h.Key(row.id), h.Attribute("tabindex", "0"), diff --git a/apps/web/src/page/services/detail/view-footprint.ts b/apps/web/src/page/services/detail/view-footprint.ts index dbecd19d14..e4df5a2b2a 100644 --- a/apps/web/src/page/services/detail/view-footprint.ts +++ b/apps/web/src/page/services/detail/view-footprint.ts @@ -253,7 +253,7 @@ const stripChip = (h: H, target: StripTarget, onClick: Message): Html => h.Class(cn(CHIP, "text-muted-foreground")), ], [ - icon(h, KIND_ICON.get(target.kind) ?? "GlobeIcon", { size: 11 }), + icon(h, KIND_ICON.get(target.kind) ?? "GlobeIcon", { size: 12 }), truncatedText(h, { text: target.name }), ], ) diff --git a/apps/web/src/page/services/detail/view-operations.ts b/apps/web/src/page/services/detail/view-operations.ts index 000897e54f..f7748fd1b1 100644 --- a/apps/web/src/page/services/detail/view-operations.ts +++ b/apps/web/src/page/services/detail/view-operations.ts @@ -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/40 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-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-inset", [ h.Key(op.spanName), h.Attribute("tabindex", "0"), diff --git a/apps/web/src/page/services/detail/view-panels.ts b/apps/web/src/page/services/detail/view-panels.ts index 222a3128ed..d17476e8a1 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/40 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-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring", ), ], [ diff --git a/apps/web/src/page/settings/audit-log/view.ts b/apps/web/src/page/settings/audit-log/view.ts index 23c8edb817..28bbbd0be1 100644 --- a/apps/web/src/page/settings/audit-log/view.ts +++ b/apps/web/src/page/settings/audit-log/view.ts @@ -300,7 +300,7 @@ const auditRow = (h: H, model: Model, entry: V2AuditLogEntry, inputs: ViewInputs h.div( [ h.Class( - "hover:bg-muted/20 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-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", ), ], [ diff --git a/apps/web/src/page/settings/billing/details/view.ts b/apps/web/src/page/settings/billing/details/view.ts index c88e73a9d7..0c4f557445 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/40 text-sm")], + [h.Class("divide-y divide-border/60 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-plan.ts b/apps/web/src/page/settings/billing/view-plan.ts index 2b047e0333..1aa837451d 100644 --- a/apps/web/src/page/settings/billing/view-plan.ts +++ b/apps/web/src/page/settings/billing/view-plan.ts @@ -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/85")], + [h.Class("mt-2 font-mono text-2xs leading-relaxed text-foreground/80")], [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/85")], + [h.Class("mt-2 font-mono text-2xs leading-relaxed text-foreground/80")], [ includedRun(plan), ...(retention === undefined @@ -484,7 +484,7 @@ export const planSection = ( }, [ "Compare plans", - icon(h, "ArrowRightIcon", { className: "size-3", attributes: [h.AriaHidden(true)] }), + icon(h, "ArrowRightIcon", { className: "size-3.5", attributes: [h.AriaHidden(true)] }), ], ), }), diff --git a/apps/web/src/page/settings/billing/view-records.ts b/apps/web/src/page/settings/billing/view-records.ts index 6f67fb432f..2ef4ee9a70 100644 --- a/apps/web/src/page/settings/billing/view-records.ts +++ b/apps/web/src/page/settings/billing/view-records.ts @@ -231,7 +231,7 @@ export const invoicesSection = (h: H, model: Model, timeZone: string): Html => { [ "View all", icon(h, "ArrowRightIcon", { - className: "size-3", + className: "size-3.5", attributes: [h.AriaHidden(true)], }), ], diff --git a/apps/web/src/page/settings/data-platform/view.ts b/apps/web/src/page/settings/data-platform/view.ts index 23c4d52d53..c92485ebcf 100644 --- a/apps/web/src/page/settings/data-platform/view.ts +++ b/apps/web/src/page/settings/data-platform/view.ts @@ -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/20 flex w-full items-center gap-2 px-3 py-2 text-left text-xs transition-colors", + "hover:bg-muted/50 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/20 flex w-full items-center gap-2 border-b px-3 py-2 text-left text-xs transition-colors", + "hover:bg-muted/50 flex w-full items-center gap-2 border-b px-3 py-2 text-left text-xs transition-colors", ), ], [ @@ -697,7 +697,7 @@ const usageSection = (h: H, model: Model): Html => { eyebrow: stat.label, value, action: icon(h, stat.icon, { - size: 13, + size: 14, className: cn("shrink-0", stat.tone), attributes: [h.AriaHidden(true)], }), diff --git a/apps/web/src/page/settings/ingestion/mapping-dialog-view.ts b/apps/web/src/page/settings/ingestion/mapping-dialog-view.ts index 9c195c7a0c..bccc23096c 100644 --- a/apps/web/src/page/settings/ingestion/mapping-dialog-view.ts +++ b/apps/web/src/page/settings/ingestion/mapping-dialog-view.ts @@ -115,7 +115,7 @@ const preview = (h: H, model: Model): ReadonlyArray => { icon(h, "ArrowRightIcon", { size: 12, className: "text-muted-foreground shrink-0" }), inlineCode(h, { variant: "plain", className: "text-foreground" }, [target]), badge(h, { variant: operation.value === "copy" ? "info" : "warn", className: "ml-1 gap-1" }, [ - icon(h, operation.icon, { size: 11 }), + icon(h, operation.icon, { size: 12 }), operation.label, ]), ], 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 d310875003..7f4b4b5387 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/20 flex items-center gap-3 border-t px-4 py-2.5 transition-colors", + "hover:bg-muted/50 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-rules.ts b/apps/web/src/page/settings/ingestion/view-rules.ts index 9b00c38d51..cc07e81e34 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/20 flex items-start gap-3 px-4 py-3 transition-colors")], + [h.Key(issue.id), h.Class("hover:bg-muted/50 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/20 flex items-center gap-3 border-t px-4 py-2.5 transition-colors", + "hover:bg-muted/50 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 a735eb8cc7..162437ecce 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/20 flex w-full items-center gap-2 px-4 py-3 text-left", + "group/scopes hover:bg-muted/50 flex w-full items-center gap-2 px-4 py-3 text-left", ), ...(isOpen ? [h.DataAttribute("panel-open", "")] : []), h.DataAttribute("slot", "collapsible-trigger"), diff --git a/apps/web/src/page/settings/keys/view-table.ts b/apps/web/src/page/settings/keys/view-table.ts index ac653ab03d..fa44baa268 100644 --- a/apps/web/src/page/settings/keys/view-table.ts +++ b/apps/web/src/page/settings/keys/view-table.ts @@ -45,7 +45,7 @@ const COL = { } const ROW_CLASS = - "flex items-center gap-4 border-b border-border/40 px-4 py-3 transition-colors last:border-0" + "flex items-center gap-4 border-b border-border/60 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/20"))], + [h.Key(row.id), h.Class(cn(ROW_CLASS, isDead ? "opacity-60" : "hover:bg-muted/50"))], [ h.div( [h.Class(cn(COL.name, "flex flex-col gap-1"))], @@ -239,7 +239,7 @@ const deviceRow = ( ] : [] return h.div( - [h.Key(row.id), h.Class(cn(ROW_CLASS, "hover:bg-muted/20"))], + [h.Key(row.id), h.Class(cn(ROW_CLASS, "hover:bg-muted/50"))], [ h.div( [h.Class(cn(DEVICE_COL.name, "flex min-w-0 items-center gap-2"))], diff --git a/apps/web/src/page/settings/mcp/view-tools.ts b/apps/web/src/page/settings/mcp/view-tools.ts index 5a016f15cf..ecff413426 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/40"), + h.Class("flex w-full items-center gap-2 px-4 py-2.5 text-left text-sm hover:bg-muted/50"), ...(isOpen ? [h.DataAttribute("panel-open", "")] : []), h.DataAttribute("slot", "collapsible-trigger"), h.Tabindex(0), diff --git a/apps/web/src/page/settings/setup-health/view.ts b/apps/web/src/page/settings/setup-health/view.ts index 3e42d5c018..657a39c82a 100644 --- a/apps/web/src/page/settings/setup-health/view.ts +++ b/apps/web/src/page/settings/setup-health/view.ts @@ -326,7 +326,7 @@ const passingDisclosure = ( h.AriaDisabled(false), h.AriaExpanded(isOpen), h.Class( - "group hover:bg-muted/20 flex w-full items-center gap-3 px-4 py-3 text-left transition-colors", + "group hover:bg-muted/50 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"), diff --git a/apps/web/src/page/sources/kit/rules-view.ts b/apps/web/src/page/sources/kit/rules-view.ts index bb5c1c0c27..0746c3d9e0 100644 --- a/apps/web/src/page/sources/kit/rules-view.ts +++ b/apps/web/src/page/sources/kit/rules-view.ts @@ -63,7 +63,7 @@ const signalCard =

( 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/30", + isChecked ? "border-primary/60 bg-primary/[0.06]" : "hover:bg-muted/50", ), ), ], diff --git a/apps/web/src/page/sources/list/view.ts b/apps/web/src/page/sources/list/view.ts index 157492052a..ffbdc2a774 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-lg border border-dashed px-4 py-3")], + [h.Class("flex flex-wrap items-center gap-2 rounded-md border border-dashed px-4 py-3")], [ 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 c5a414cadb..7c5d9c9fbd 100644 --- a/apps/web/src/page/sources/new/view-picker.ts +++ b/apps/web/src/page/sources/new/view-picker.ts @@ -48,8 +48,8 @@ const card = ( h.OnClick(onSelect), h.Class( cn( - "group bg-card flex items-center gap-3 rounded-lg border px-3 py-3 text-left transition-colors", - "hover:bg-muted/40 focus-visible:ring-ring outline-none focus-visible:ring-2", + "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", ), ), ], diff --git a/apps/web/src/page/traces/detail/depth-controls.ts b/apps/web/src/page/traces/detail/depth-controls.ts index dd755fb6bc..05f3465b37 100644 --- a/apps/web/src/page/traces/detail/depth-controls.ts +++ b/apps/web/src/page/traces/detail/depth-controls.ts @@ -36,7 +36,7 @@ const depthButton = ( h.OnClick(onClick), ], }, - [icon(h, name, { size: 11 })], + [icon(h, name, { size: 12 })], ) export const depthControls = (h: HtmlBuilder, options: DepthControlsOptions): Html => 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 daf5522bb8..29c55abb53 100644 --- a/apps/web/src/page/traces/detail/span-panel/attributes.ts +++ b/apps/web/src/page/traces/detail/span-panel/attributes.ts @@ -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/40", + "group/attr grid grid-cols-[minmax(7rem,38%)_1fr] items-start gap-x-3 px-2 py-1 transition-colors hover:bg-muted/50", ), ], [ @@ -260,7 +260,7 @@ const genAiSection = ( h.div( [ h.Class( - "divide-y divide-border/40 border-t border-border/60 bg-muted/15", + "divide-y divide-border/60 border-t border-border/60 bg-muted/15", ), ], group.fields.map((field) => 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 ab5ea502c2..9d967d7d9b 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-lg 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 px-3 py-2.5", input.className, ), ), 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 9182f4f040..1b400361f2 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/30 cursor-pointer"), h.Type("button")], + [h.Class("block w-full p-2 text-left hover:bg-muted/50 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/layout.ts b/apps/web/src/page/traces/detail/timeline/layout.ts index 31b47f9bbf..96f0823899 100644 --- a/apps/web/src/page/traces/detail/timeline/layout.ts +++ b/apps/web/src/page/traces/detail/timeline/layout.ts @@ -21,22 +21,24 @@ import type { SpanNodeData } from "../trace-data" export const ROW_PITCH = ROW_HEIGHT + ROW_GAP -const ERROR_HUE = 25 -const NEUTRAL_FILL = "oklch(0.22 0.005 0)" -const NEUTRAL_BORDER = "oklch(0.45 0.02 0)" - -const barFillFromHue = (hue: number | null, isError: boolean, statusPreset: boolean): string => { - if (isError && !statusPreset) return `oklch(0.22 0.06 ${ERROR_HUE})` - if (hue === null) return NEUTRAL_FILL - return `oklch(0.22 0.015 ${hue})` -} +// The border carries the hue; the fill is that colour washed into the page background, so bars +// read in both themes. +const NEUTRAL_BORDER = "var(--muted-foreground)" +const ERROR_BORDER = "var(--severity-error)" +const wash = (color: string, percent: number): string => + `color-mix(in oklch, ${color} ${percent}%, var(--background))` const barBorderFromHue = (hue: number | null, isError: boolean, statusPreset: boolean): string => { - if (isError && !statusPreset) return `oklch(0.62 0.22 ${ERROR_HUE})` + if (isError && !statusPreset) return ERROR_BORDER if (hue === null) return NEUTRAL_BORDER return `oklch(0.55 0.18 ${hue})` } +const barFillFromHue = (hue: number | null, isError: boolean, statusPreset: boolean): string => { + if (isError && !statusPreset) return wash(ERROR_BORDER, 22) + return wash(barBorderFromHue(hue, false, statusPreset), hue === null ? 12 : 16) +} + /** `TimelineBar` over `SpanNodeData`. */ export interface Bar { readonly span: SpanNodeData 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 932e5a1949..1827441c54 100644 --- a/apps/web/src/page/traces/detail/timeline/view-chrome.ts +++ b/apps/web/src/page/traces/detail/timeline/view-chrome.ts @@ -22,7 +22,7 @@ export const searchBar = (h: H, model: Model, matchCount: number, totalCount: nu h.div( [h.Class("flex items-center gap-2 border-b border-border bg-muted/20 px-3 py-1.5")], [ - icon(h, "MagnifierIcon", { size: 13, className: "text-muted-foreground shrink-0" }), + 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", @@ -222,7 +222,7 @@ export const toolbar = (h: H, model: Model, visibleSpanCount: number, ids: Toolb h.Id(ids.skew), ], [ - icon(h, "AlertWarningIcon", { size: 11 }), + icon(h, "AlertWarningIcon", { size: 12 }), h.span([h.Class("hidden @min-[400px]/timeline:inline")], ["skew"]), ], ), 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 baec9701c6..ea5a0b7d06 100644 --- a/apps/web/src/page/traces/detail/timeline/view-row.ts +++ b/apps/web/src/page/traces/detail/timeline/view-row.ts @@ -138,7 +138,7 @@ const labelCell = (h: H, bar: Bar, state: RowState, durationLabel: string): Html [attr(h, "flex shrink-0 items-center"), h.Title(category.label)], [ icon(h, category.icon, { - size: 11, + size: 12, className: bar.isError ? TONE_TEXT.crit : category.accent.text, }), ], @@ -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/30", - state.isHovered && "bg-muted/30", + "hover:bg-muted/50", + state.isHovered && "bg-muted/50", 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/waterfall/row.ts b/apps/web/src/page/traces/detail/waterfall/row.ts index ae29972c28..5ae72e15e7 100644 --- a/apps/web/src/page/traces/detail/waterfall/row.ts +++ b/apps/web/src/page/traces/detail/waterfall/row.ts @@ -227,7 +227,7 @@ const serviceLabel = (h: HtmlBuilder, row: TreeRow): ReadonlyArray(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/50 whitespace-nowrap tabular-nums", + "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", ), ], [ diff --git a/apps/web/src/service-map/map/namespace-group.ts b/apps/web/src/service-map/map/namespace-group.ts index 65b14fb183..1e7c5c309b 100644 --- a/apps/web/src/service-map/map/namespace-group.ts +++ b/apps/web/src/service-map/map/namespace-group.ts @@ -36,8 +36,9 @@ const box = (h: HtmlBuilder, label: string, hue: number, onCollapse: M): H "pointer-events-auto absolute left-2.5 top-2 flex max-w-[calc(100%-1.25rem)] items-center gap-1.5 rounded-md border px-1.5 py-0.5 text-3xs font-semibold uppercase tracking-widest", ), h.Style({ - color: `oklch(0.82 0.12 ${hue})`, - "background-color": `oklch(0.24 0.04 ${hue} / 0.92)`, + // Mixed against the theme so the label reads on the light canvas too. + color: `color-mix(in oklch, oklch(0.62 0.14 ${hue}) 70%, var(--foreground))`, + "background-color": `color-mix(in oklch, oklch(0.62 0.11 ${hue}) 14%, var(--background))`, "border-color": `oklch(0.66 0.12 ${hue} / 0.4)`, }), ], diff --git a/apps/web/src/service-map/trace-flow/edge.ts b/apps/web/src/service-map/trace-flow/edge.ts index 5380f9d308..8a245714c7 100644 --- a/apps/web/src/service-map/trace-flow/edge.ts +++ b/apps/web/src/service-map/trace-flow/edge.ts @@ -114,7 +114,7 @@ export const traceFlowEdge = ( h.span( [ h.Class( - "whitespace-nowrap rounded border border-border/50 bg-card/90 px-1.5 py-0.5 font-mono text-3xs tabular-nums text-muted-foreground backdrop-blur-sm", + "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", ), ], label, 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 07660c0024..680f227db6 100644 --- a/apps/web/src/service-map/trace-flow/node-card.ts +++ b/apps/web/src/service-map/trace-flow/node-card.ts @@ -245,8 +245,8 @@ export const flowSpanNode = ( ], [ category.id === "cache" && cacheInfo?.system - ? cacheSystemIcon(h, cacheInfo.system, 13) - : icon(h, category.icon, { size: 13 }), + ? cacheSystemIcon(h, cacheInfo.system, 14) + : icon(h, category.icon, { size: 14 }), ], ), h.div( diff --git a/apps/web/src/shell/connect-panel-view.ts b/apps/web/src/shell/connect-panel-view.ts index fefa957606..b99b20c3b0 100644 --- a/apps/web/src/shell/connect-panel-view.ts +++ b/apps/web/src/shell/connect-panel-view.ts @@ -59,7 +59,7 @@ const statusPill = (h: H, model: Model): Html => { }, isConnected ? [statusDot(h, { tone: "ok" }), `Connected · ${countLabel(services.length, "service")}`] - : [icon(h, "ClockIcon", { size: 11, className: "size-[11px]" }), "Waiting for telemetry"], + : [icon(h, "ClockIcon", { size: 12, className: "size-3" }), "Waiting for telemetry"], ) } @@ -149,7 +149,7 @@ type ClientMark = Readonly<{ name: IconName; className: string }> const clientMark = (h: H, mark: ClientMark): Html => h.span( [h.Class("flex size-6 shrink-0 items-center justify-center rounded-md border bg-background")], - [icon(h, mark.name, { size: 13, className: mark.className })], + [icon(h, mark.name, { size: 14, className: mark.className })], ) /** `McpClientRow`: a client's mark and name, then its one way in. */ @@ -190,7 +190,7 @@ const copyAction = (h: H, model: Model, value: string, field: CopyField, label: const installAction = (h: H, href: string, label: string): Html => linkButton(h, { size: "xs", variant: "outline", className: "gap-1", href }, [ label, - icon(h, "ExternalLinkIcon", { size: 11, className: "text-muted-foreground" }), + icon(h, "ExternalLinkIcon", { size: 12, className: "text-muted-foreground" }), ]) /** `McpCard`: each client's fastest way to add Maple, the endpoint for any other. */ diff --git a/apps/web/src/shell/onboarding-checklist-view.ts b/apps/web/src/shell/onboarding-checklist-view.ts index 9b389787e0..808dd39a69 100644 --- a/apps/web/src/shell/onboarding-checklist-view.ts +++ b/apps/web/src/shell/onboarding-checklist-view.ts @@ -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/60 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-muted/50 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 38699705fb..17740dc8b2 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/50")], + [h.Class("divide-y divide-border/60")], defs.map((def) => row(h, def, platform)), ), ], diff --git a/apps/web/src/ui/attributes/attribute-row.ts b/apps/web/src/ui/attributes/attribute-row.ts index cecc6816e2..9348be1c49 100644 --- a/apps/web/src/ui/attributes/attribute-row.ts +++ b/apps/web/src/ui/attributes/attribute-row.ts @@ -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/40", + "group/attr grid grid-cols-[minmax(7rem,38%)_1fr] items-start gap-x-3 px-2 py-1 transition-colors hover:bg-muted/50", ), ], [ diff --git a/apps/web/src/ui/attributes/attributes-view.ts b/apps/web/src/ui/attributes/attributes-view.ts index 0ac04ea6b6..caa3ed2a80 100644 --- a/apps/web/src/ui/attributes/attributes-view.ts +++ b/apps/web/src/ui/attributes/attributes-view.ts @@ -151,10 +151,10 @@ const attributesTable = (h: H, context: RowContext, options: TableOptions): Html 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/40 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-muted/50 hover:text-foreground", trigger: [ icon(h, "ChevronRightIcon", { - size: 11, + size: 12, className: "transition-transform group-data-[panel-open]:rotate-90", }), h.span( @@ -169,7 +169,7 @@ const attributesTable = (h: H, context: RowContext, options: TableOptions): Html h.div( [ h.Class( - "divide-y divide-border/40 border-t border-border/60 bg-muted/15", + "divide-y divide-border/60 border-t border-border/60 bg-muted/15", ), ], group.entries.map(([key, value]) => diff --git a/apps/web/src/ui/detail-rail.ts b/apps/web/src/ui/detail-rail.ts index 27420f36d3..93c698f4aa 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/40 px-4 py-3.5 last:border-b-0", className), + cn("flex flex-col gap-1.5 border-b border-border/60 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)], @@ -172,7 +172,7 @@ export const detailRailMetaRow = ( [ h.Class( cn( - "break-all text-right font-mono text-2xs tabular-nums text-foreground/85", + "break-all text-right font-mono text-2xs tabular-nums text-foreground/80", options.valueClassName, ), ), diff --git a/apps/web/src/ui/error-section.ts b/apps/web/src/ui/error-section.ts index 821ade13fb..d6a726a63d 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-lg 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 px-3 py-2.5")], [ h.div( [h.Class("flex min-w-0 items-center gap-2")], diff --git a/apps/web/src/ui/logs/log-row-expanded.ts b/apps/web/src/ui/logs/log-row-expanded.ts index 99ef7a5da5..9d22671b63 100644 --- a/apps/web/src/ui/logs/log-row-expanded.ts +++ b/apps/web/src/ui/logs/log-row-expanded.ts @@ -65,7 +65,7 @@ export const logRowExpanded = ( h.div( [ h.Class( - "relative rounded-md border border-border/70 bg-background/60 py-2 pl-3 pr-24", + "relative rounded-md border border-border/60 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 dd09dad543..ae123854ba 100644 --- a/apps/web/src/ui/logs/log-row.ts +++ b/apps/web/src/ui/logs/log-row.ts @@ -167,7 +167,7 @@ export const logRow = ( width: "100%", transform: `translateY(${start}px)`, }), - rowClass(h, "border-b border-border/70"), + rowClass(h, "border-b border-border/60"), ], [ h.div( @@ -213,7 +213,7 @@ export const logRow = ( ), h.span( [ - rowClass(h, "shrink-0 w-[92px] text-foreground/75 tabular-nums"), + rowClass(h, "shrink-0 w-[92px] text-foreground/70 tabular-nums"), h.Title(row.timeTitle), ], row.timeFraction === "" @@ -296,13 +296,13 @@ const rowActions = ( h, "Copy message", events.clickedCopyMessage(index), - icon(h, "CopyIcon", { size: 13 }), + icon(h, "CopyIcon", { size: 14 }), ), iconButton( h, "Copy link to log", events.clickedCopyLink(index), - icon(h, "LinkIcon", { size: 13 }), + icon(h, "LinkIcon", { size: 14 }), ), ...(row.traceId === "" ? [] @@ -314,7 +314,7 @@ const rowActions = ( h.Title("Open trace"), rowClass(h, ROW_ACTION_CLASS), ], - [icon(h, "PulseIcon", { size: 13 })], + [icon(h, "PulseIcon", { size: 14 })], ), ]), iconButton( diff --git a/packages/ui/src/components/ui/list-row.styles.ts b/packages/ui/src/components/ui/list-row.styles.ts index 304e6d6eb8..d918d1feda 100644 --- a/packages/ui/src/components/ui/list-row.styles.ts +++ b/packages/ui/src/components/ui/list-row.styles.ts @@ -8,7 +8,7 @@ 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/40 before:bg-primary" : "before:bg-transparent") + return cn(ROW_LANE, selected ? "bg-muted/60 before:bg-primary" : "before:bg-transparent") } export const listRowVariants = cva( From 650e71a17e38784ff3bbab897a717f370711a6aa Mon Sep 17 00:00:00 2001 From: Makisuo Date: Fri, 30 Oct 2026 20:04:20 +0100 Subject: [PATCH 2/2] fix(web): timeline and namespace mixes in oklab, 2xx on the healthy token Mixing in oklch against a background with a declared hue rotated every bar toward it, so blue services painted pink. 2xx used chart-3, which is amber in light mode beside the amber 4xx; it now uses severity-info. --- apps/web/src/page/services/detail/endpoint-peek/view.ts | 2 +- apps/web/src/page/services/detail/view-api-charts.ts | 4 ++-- apps/web/src/page/services/detail/view-api.ts | 2 +- apps/web/src/page/traces/detail/timeline/layout.ts | 4 ++-- apps/web/src/service-map/map/namespace-group.ts | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) 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 091742b288..7d8311e4d3 100644 --- a/apps/web/src/page/services/detail/endpoint-peek/view.ts +++ b/apps/web/src/page/services/detail/endpoint-peek/view.ts @@ -226,7 +226,7 @@ const statusCard = (h: H, rows: ReadonlyArray, spanName: string): Htm ? [h.p([h.Class("text-2xs text-muted-foreground")], ["No status codes recorded in this window."])] : codes.slice(0, 4).map((code) => { const tone = code.name.startsWith("2") - ? { text: TONE_TEXT.info, bar: "bg-chart-3" } + ? { text: TONE_TEXT.info, bar: TONE_FILL.ok } : isServerError(code.name) ? { text: TONE_TEXT.crit, bar: TONE_FILL.crit } : { text: TONE_TEXT.warn, bar: TONE_FILL.warn } diff --git a/apps/web/src/page/services/detail/view-api-charts.ts b/apps/web/src/page/services/detail/view-api-charts.ts index b8a154526a..c03a1c7e56 100644 --- a/apps/web/src/page/services/detail/view-api-charts.ts +++ b/apps/web/src/page/services/detail/view-api-charts.ts @@ -18,7 +18,7 @@ import type { ApiBucket } from "./model-tabs" /** The status classes' colours; 2xx stays calm, 4xx is the warning hue, 5xx the error one. */ export const STATUS_COLORS = { - "2xx": "var(--chart-3)", + "2xx": "var(--severity-info)", "4xx": "var(--warning)", "5xx": "var(--severity-error)", unknown: "var(--muted-foreground)", @@ -39,7 +39,7 @@ export const SPARK_TOKENS = { /** Every token the API tab paints on canvas; resolved once by the page's theme Mount. */ export const API_THEME_TOKENS = [ ...Object.values(SPARK_TOKENS), - "--chart-3", + "--severity-info", "--muted-foreground", ...LATENCY_SERIES.map((series) => series.token), "--border", diff --git a/apps/web/src/page/services/detail/view-api.ts b/apps/web/src/page/services/detail/view-api.ts index e5c63d9c8b..f6701b4d6c 100644 --- a/apps/web/src/page/services/detail/view-api.ts +++ b/apps/web/src/page/services/detail/view-api.ts @@ -94,7 +94,7 @@ export const statusMixBar = (h: HtmlBuilder, mix: StatusMix | null, classN mix === null ? [] : [ - h.div([h.Class("h-full bg-chart-3"), h.Style({ width: `${mix.ok * 100}%` })]), + h.div([h.Class(cn("h-full", TONE_FILL.ok)), h.Style({ width: `${mix.ok * 100}%` })]), h.div([ h.Class(cn("h-full", TONE_FILL.warn)), h.Style({ width: `${mix.client * 100}%` }), diff --git a/apps/web/src/page/traces/detail/timeline/layout.ts b/apps/web/src/page/traces/detail/timeline/layout.ts index 96f0823899..9e01550885 100644 --- a/apps/web/src/page/traces/detail/timeline/layout.ts +++ b/apps/web/src/page/traces/detail/timeline/layout.ts @@ -22,11 +22,11 @@ import type { SpanNodeData } from "../trace-data" export const ROW_PITCH = ROW_HEIGHT + ROW_GAP // The border carries the hue; the fill is that colour washed into the page background, so bars -// read in both themes. +// read in both themes. Oklab, not oklch: the backgrounds carry a hue that would rotate the mix. const NEUTRAL_BORDER = "var(--muted-foreground)" const ERROR_BORDER = "var(--severity-error)" const wash = (color: string, percent: number): string => - `color-mix(in oklch, ${color} ${percent}%, var(--background))` + `color-mix(in oklab, ${color} ${percent}%, var(--background))` const barBorderFromHue = (hue: number | null, isError: boolean, statusPreset: boolean): string => { if (isError && !statusPreset) return ERROR_BORDER diff --git a/apps/web/src/service-map/map/namespace-group.ts b/apps/web/src/service-map/map/namespace-group.ts index 1e7c5c309b..759c2312f0 100644 --- a/apps/web/src/service-map/map/namespace-group.ts +++ b/apps/web/src/service-map/map/namespace-group.ts @@ -37,8 +37,8 @@ const box = (h: HtmlBuilder, label: string, hue: number, onCollapse: M): H ), h.Style({ // Mixed against the theme so the label reads on the light canvas too. - color: `color-mix(in oklch, oklch(0.62 0.14 ${hue}) 70%, var(--foreground))`, - "background-color": `color-mix(in oklch, oklch(0.62 0.11 ${hue}) 14%, var(--background))`, + color: `color-mix(in oklab, oklch(0.62 0.14 ${hue}) 70%, var(--foreground))`, + "background-color": `color-mix(in oklab, oklch(0.62 0.11 ${hue}) 14%, var(--background))`, "border-color": `oklch(0.66 0.12 ${hue} / 0.4)`, }), ],