Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions apps/web/src/page/agent-sessions/list/view-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { Attribute, Html, HtmlBuilder } from "foldkit/html"
import { AppRoute, hrefOf } from "../../../route"
import { icon, type IconName } from "../../../ui/icon"
import { loadingMoreRow } from "../../../ui/list-footer"
import { table, tableBody, tableCell, tableHead, tableHeader, tableRow } from "../../../ui/table"
import { rowLink, table, tableBody, tableCell, tableHead, tableHeader, tableRow } from "../../../ui/table"
import { tableSkeleton } from "../../../ui/table-skeleton"
import { servicePills } from "../../../ui/trace-badges"
import type { DetectedModel } from "../kit/detected-models"
Expand Down Expand Up @@ -127,9 +127,7 @@ export const listSkeleton = (h: H): Html =>
})),
})

// A row link stretched over its row, and the lift for tooltips above it.
const ROW_STRETCHED_LINK_CLASS =
"after:absolute after:inset-0 after:content-[''] focus-visible:outline-none focus-visible:after:ring-1 focus-visible:after:ring-ring focus-visible:after:ring-inset"
// The lift for tooltips above the row link.
const ROW_LIFT_TOOLTIPS = "[&_[data-slot=tooltip-trigger]]:relative [&_[data-slot=tooltip-trigger]]:z-10"

const triggerAttributes = (h: H): ReadonlyArray<Attribute<Message>> => [
Expand Down Expand Up @@ -234,7 +232,7 @@ const sessionCell = (h: H, row: DisplayRow, context: RowContext): Html => {
return h.div(
[h.Class("min-w-0")],
[
h.a([h.AriaHidden(true), h.Class(ROW_STRETCHED_LINK_CLASS), h.Href(href), h.Tabindex(-1)], []),
rowLink(h, { href, attributes: [h.AriaHidden(true), h.Tabindex(-1)] }),
h.div(
[h.Class("flex min-w-0 items-center gap-2")],
[
Expand Down
46 changes: 23 additions & 23 deletions apps/web/src/page/alerts/hub/view-inbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ import type { Html, HtmlBuilder } from "foldkit/html"
import { badge } from "../../../ui/display"
import { eyebrow } from "../../../ui/eyebrow"
import { icon } from "../../../ui/icon"
import { rowLink } from "../../../ui/table"
import { severityBadge } from "../shared/badges"
import { incidentHref, ROW_STRETCHED_LINK_CLASS, ruleHref } from "../shared/links"
import { incidentHref, ruleHref } from "../shared/links"
import { sortIncidents } from "../shared/sort"
import { isoMs, msIso } from "../shared/time"

Expand Down Expand Up @@ -179,12 +180,13 @@ const openIncidentRow = <M>(h: HtmlBuilder<M>, incident: AlertIncidentDocument,
"Held",
])
: severityBadge(h, incident.severity),
h.a(
[
h.Class(cn("min-w-0 truncate font-medium", ROW_STRETCHED_LINK_CLASS)),
h.Href(incidentHref(incident.id)),
h.Title(incidentTitle(incident)),
],
rowLink(
h,
{
href: incidentHref(incident.id),
className: "min-w-0 truncate font-medium",
attributes: [h.Title(incidentTitle(incident))],
},
[isHeld ? `${incident.ruleName}: waiting on data` : incidentTitle(incident)],
),
],
Expand Down Expand Up @@ -396,16 +398,13 @@ const blindSpotRow = <M>(h: HtmlBuilder<M>, spot: BlindSpot): Html => {
),
],
),
h.a(
[
h.Class(
cn(
"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-foreground group-hover:bg-accent",
ROW_STRETCHED_LINK_CLASS,
),
),
h.Href(ruleHref(spot.rule.id)),
],
rowLink(
h,
{
href: ruleHref(spot.rule.id),
className:
"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-foreground group-hover:bg-accent",
},
[meta.action, icon(h, "ArrowRightIcon", { className: "size-3 text-muted-foreground" })],
),
],
Expand Down Expand Up @@ -475,12 +474,13 @@ const headroomRow = <M>(h: HtmlBuilder<M>, row: RuleHeadroom, now: number): Html
h.div(
[h.Class("min-w-0")],
[
h.a(
[
h.Class(cn("block truncate text-sm", ROW_STRETCHED_LINK_CLASS)),
h.Href(ruleHref(rule.id)),
h.Title(rule.name),
],
rowLink(
h,
{
href: ruleHref(rule.id),
className: "block truncate text-sm",
attributes: [h.Title(rule.name)],
},
[rule.name],
),
...(row.groupKey !== null
Expand Down
23 changes: 11 additions & 12 deletions apps/web/src/page/alerts/hub/view-rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import * as Menu from "../../../ui/menu"
import type { MenuEntry } from "../../../ui/menu-view"
import { rowActionsMenu } from "../../../ui/row-actions-menu"
import { statusDot } from "../../../ui/status-dot"
import { ROW_LINK_LIFT, rowLink } from "../../../ui/table"
import { filteredEmpty } from "../../kit/signal-empty-state"
import { ROW_LINK_LIFT, ROW_STRETCHED_LINK_CLASS, ruleHref } from "../shared/links"
import { ruleHref } from "../shared/links"
import { isoMs } from "../shared/time"
import { Message, type RuleBucket } from "./message"
import type { Model } from "./model"
Expand Down Expand Up @@ -307,18 +308,16 @@ const ruleRow = (h: H, model: Model, row: RowInputs): Html => {
h.div(
[h.Class("min-w-0 space-y-0.5")],
[
h.a(
[
h.Class(
cn(
"block truncate text-sm font-medium",
!rule.enabled && "text-muted-foreground",
ROW_STRETCHED_LINK_CLASS,
),
rowLink(
h,
{
href: ruleHref(rule.id),
className: cn(
"block truncate text-sm font-medium",
!rule.enabled && "text-muted-foreground",
),
h.Href(ruleHref(rule.id)),
h.Title(rule.name),
],
attributes: [h.Title(rule.name)],
},
[rule.name],
),
h.p(
Expand Down
18 changes: 7 additions & 11 deletions apps/web/src/page/alerts/hub/view-uptime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import { rowActionsMenu } from "../../../ui/row-actions-menu"
import { searchInput } from "../../../ui/search-input"
import { segmentedSelect } from "../../../ui/segmented-select"
import { skeleton } from "../../../ui/skeleton"
import { ROW_LINK_LIFT, rowLink } from "../../../ui/table"
import { emptyActions, filteredEmpty } from "../../kit/signal-empty-state"
import { statRail, statRailItem, statRailLoading } from "../../kit/stat-rail"
import { ROW_LINK_LIFT, ROW_STRETCHED_LINK_CLASS } from "../shared/links"
import { isoMs } from "../shared/time"
import { monitorHref, newMonitorHref } from "../shared/uptime-commands"
import {
Expand Down Expand Up @@ -263,16 +263,12 @@ const monitorRow = (h: H, model: Model, monitor: UptimeMonitor, nowMs: number):
h.div(
[h.Class("flex min-w-0 items-center gap-2")],
[
h.a(
[
h.Href(monitorHref(monitor.id)),
h.Class(
cn(
"truncate text-sm font-medium",
ROW_STRETCHED_LINK_CLASS,
),
),
],
rowLink(
h,
{
href: monitorHref(monitor.id),
className: "truncate text-sm font-medium",
},
[monitor.name],
),
...(displayStatus(monitor) === "up"
Expand Down
44 changes: 12 additions & 32 deletions apps/web/src/page/alerts/hub/view.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { AlertsOverviewReady } from "@maple/web-data/alerts/overview"
import { cn } from "@maple/ui/lib/utils"
import { makeClientErrorBody } from "@maple/web-data/lib/error-messages"
import { Option } from "effect"
import { AsyncData, Submodel } from "foldkit"
Expand All @@ -13,7 +12,7 @@ import * as MenuView from "../../../ui/menu-view"
import { skeleton, skeletonList } from "../../../ui/skeleton"
import type { PageViewInputs } from "../../contract"
import { dashboardPage } from "../../kit/dashboard-page"
import { underlineTabClass, underlineTabStrip } from "../../kit/underline-tabs"
import { linkTabStrip } from "../../kit/underline-tabs"
import { alertsHref, createHref } from "../shared/links"
import { type AlertsTab, destinationsOf, overviewOf, resolveStatus, resolveTab } from "./derive"
import { Message } from "./message"
Expand Down Expand Up @@ -45,9 +44,9 @@ const tabBar = (
active: AlertsTab,
): Html => {
const monitorCount = Option.map(AsyncData.getData(model.monitors.data), (monitors) => monitors.length)
return underlineTabStrip(
return linkTabStrip(
h,
{ label: "Alerts sections", navigation: true },
"Alerts sections",
ALERTS_TABS.map((tab) => {
const count =
tab.value === "uptime"
Expand All @@ -61,34 +60,15 @@ const tabBar = (
? data.rules.length
: undefined,
})
return h.a(
[
h.Key(tab.value),
h.Href(alertsHref({ ...model.search, tab: tab.value })),
...(tab.value === active ? [h.AriaCurrent("page")] : []),
h.Class(underlineTabClass(tab.value === active)),
],
[
tab.label,
...(count !== undefined && count > 0
? [
h.span(
[
h.Class(
cn(
"font-mono text-xs tabular-nums",
tab.value === "inbox"
? "text-severity-error"
: "text-muted-foreground",
),
),
],
[String(count)],
),
]
: []),
],
)
return {
key: tab.value,
href: alertsHref({ ...model.search, tab: tab.value }),
label: tab.label,
count: count !== undefined && count > 0 ? count : undefined,
countTone: tab.value === "inbox" ? "error" : "muted",
isCurrent: tab.value === active,
isRouteActive: tab.value === active,
}
}),
)
}
Expand Down
27 changes: 11 additions & 16 deletions apps/web/src/page/alerts/rule/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { dashboardPage } from "../../kit/dashboard-page"
import { resourceNotFound } from "../../kit/resource-not-found"
import { timeControls } from "../../kit/time-controls"
import * as TimeRangePicker from "../../kit/time-range-picker"
import { underlineTabClass, underlineTabStrip } from "../../kit/underline-tabs"
import { linkTabStrip } from "../../kit/underline-tabs"
import { alertStatusBadge, severityBadge } from "../shared/badges"
import { alertsHref, createHref, ruleHref } from "../shared/links"
import { RULE_CHART_TOKENS } from "../shared/rule-chart"
Expand Down Expand Up @@ -107,21 +107,17 @@ const header = (h: H, model: Model, rule: AlertRuleDocument) => {

const tabStrip = (h: H, model: Model): Html => {
const active = activeTabOf(model)
return underlineTabStrip(
return linkTabStrip(
h,
{ label: "Rule sections", navigation: true },
TABS.map((tab) =>
h.a(
[
h.Key(tab),
// `search={(prev) => ({ ...prev, tab })}`: the time range rides along.
h.Href(ruleHref(model.ruleId, { ...model.search, tab })),
...(tab === active ? [h.AriaCurrent("page")] : []),
h.Class(underlineTabClass(tab === active)),
],
[tab === "overview" ? "Overview" : "History"],
),
),
"Rule sections",
TABS.map((tab) => ({
key: tab,
// `search={(prev) => ({ ...prev, tab })}`: the time range rides along.
href: ruleHref(model.ruleId, { ...model.search, tab }),
label: tab === "overview" ? "Overview" : "History",
isCurrent: tab === active,
isRouteActive: tab === active,
})),
)
}

Expand Down Expand Up @@ -170,4 +166,3 @@ export const breadcrumbsOf = (model: Model) => {
{ label: model.rules === null ? "Loading…" : rule === null ? "Not found" : rule.name },
]
}

8 changes: 1 addition & 7 deletions apps/web/src/page/alerts/shared/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ import { Option, Schema } from "effect"
import { AppRoute, hrefOf } from "../../../route"
import type { AlertRuleSearch, AlertsCreateSearch, AlertsSearch } from "../../../route/search"

// `ROW_STRETCHED_LINK_CLASS` and `ROW_LINK_LIFT`: a row-wide link and the lift for controls above it.
export const ROW_STRETCHED_LINK_CLASS =
"after:absolute after:inset-0 after:content-[''] focus-visible:outline-none focus-visible:after:ring-1 focus-visible:after:ring-ring focus-visible:after:ring-inset"
export const ROW_LINK_LIFT = "relative z-10"

const decodeRuleId = Schema.decodeUnknownOption(AlertRuleId)

/** A rule's page. Derived rows carry the id as a plain string; one that is not a rule id links home. */
Expand All @@ -20,8 +15,7 @@ export const ruleHref = (rawRuleId: string, search: typeof AlertRuleSearch.Type
export const incidentHref = (incidentId: string): string =>
hrefOf(AppRoute.AlertIncident({ incidentId, search: {} }))

export const alertsHref = (search: typeof AlertsSearch.Type): string =>
hrefOf(AppRoute.Alerts({ search }))
export const alertsHref = (search: typeof AlertsSearch.Type): string => hrefOf(AppRoute.Alerts({ search }))

export const createHref = (search: typeof AlertsCreateSearch.Type): string =>
hrefOf(AppRoute.AlertsCreate({ search }))
Loading
Loading