redesgin
This commit is contained in:
1 parent
21f04d696b
commit
5792e9c037
16 files changed
+2101
-2109
No files matched your search
@@ -0,0 +1,128 @@
|
||||
import React from "react"
|
||||
import {
|
||||
Activity,
|
||||
AlertOctagon,
|
||||
CloudCog,
|
||||
GitBranch,
|
||||
Globe,
|
||||
LineChart,
|
||||
Radar,
|
||||
ScrollText,
|
||||
TrendingUp,
|
||||
Waypoints,
|
||||
Wrench,
|
||||
} from "lucide-react"
|
||||
import type { LucideIcon } from "lucide-react"
|
||||
import { useObservabilityData } from "../../hooks/useObservabilityData"
|
||||
import { useIssues } from "../../hooks/useIssues"
|
||||
import { useStatsAvailability } from "../../hooks/useStats"
|
||||
|
||||
interface RailItem {
|
||||
tab: string
|
||||
label: string
|
||||
Icon: LucideIcon
|
||||
dotTone?: "critical" | "warn"
|
||||
dotVisible?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* The 72px fixed icon rail: primary navigation for every screen. Icon-only
|
||||
* with a real aria-label per control (spec: "72px icon rail, fixed. 46x46
|
||||
* targets, aria-label on every one"). A small status dot only appears when
|
||||
* that view has something real to flag (open issues, error logs) - it is
|
||||
* never decorative.
|
||||
*/
|
||||
export const IconRail: React.FC = () => {
|
||||
const { activeTab, setActiveTab, logs } = useObservabilityData()
|
||||
const { issues } = useIssues()
|
||||
const statsAvailable = useStatsAvailability()
|
||||
|
||||
const openIssuesCount = React.useMemo(
|
||||
() => issues.filter((i) => !i.status || i.status === "open").length,
|
||||
[issues],
|
||||
)
|
||||
|
||||
const errorLogCount = React.useMemo(() => {
|
||||
let errs = 0
|
||||
logs.forEach((log) => {
|
||||
;(log.scopeLogs ?? []).forEach((sl) => {
|
||||
;(sl.logRecords ?? []).forEach((r) => {
|
||||
if ((r.severityNumber ?? 0) >= 17) errs += 1
|
||||
})
|
||||
})
|
||||
})
|
||||
return errs
|
||||
}, [logs])
|
||||
|
||||
const items: RailItem[] = [
|
||||
{ tab: "tab0", label: "Triage overview", Icon: AlertOctagon, dotTone: "critical", dotVisible: openIssuesCount > 0 },
|
||||
{ tab: "tab8", label: "Similarity patterns", Icon: GitBranch },
|
||||
{ tab: "tab9", label: "Cluster rollouts", Icon: CloudCog },
|
||||
{ tab: "tab1", label: "Traces & spans", Icon: Activity },
|
||||
{ tab: "tab3", label: "Live log stream", Icon: ScrollText, dotTone: "warn", dotVisible: errorLogCount > 0 },
|
||||
{ tab: "tab2", label: "Metrics & APM", Icon: LineChart },
|
||||
{ tab: "tab7", label: "RUM sessions", Icon: Globe },
|
||||
...(statsAvailable ? [{ tab: "tab5", label: "Historical trends", Icon: TrendingUp }] : []),
|
||||
{ tab: "tab6", label: "Archive & trap", Icon: Radar },
|
||||
]
|
||||
|
||||
return (
|
||||
<nav
|
||||
aria-label="Primary"
|
||||
className="fixed left-0 top-0 z-50 flex h-full w-[72px] flex-col items-center gap-1.5 border-r border-ds-line bg-ds-chrome py-4"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveTab("tab0")}
|
||||
aria-label="Stackship — go to triage overview"
|
||||
className="mb-2 flex h-[34px] w-[34px] items-center justify-center rounded-[10px] bg-ds-accent-bg text-ds-accent"
|
||||
>
|
||||
<Waypoints className="h-[19px] w-[19px]" aria-hidden="true" />
|
||||
</button>
|
||||
|
||||
{items.map((item) => {
|
||||
const isActive = activeTab === item.tab
|
||||
return (
|
||||
<button
|
||||
key={item.tab}
|
||||
type="button"
|
||||
onClick={() => setActiveTab(item.tab)}
|
||||
aria-label={item.label}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
title={item.label}
|
||||
className={`relative flex h-[46px] w-[46px] items-center justify-center rounded-xl transition-colors ${
|
||||
isActive ? "bg-ds-surface-2 text-ds-text" : "text-ds-text-3 hover:bg-ds-surface-2 hover:text-ds-text-2"
|
||||
}`}
|
||||
>
|
||||
<item.Icon className="h-5 w-5" aria-hidden="true" />
|
||||
{item.dotVisible && (
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={`absolute right-2 top-2 h-[7px] w-[7px] rounded-full ${
|
||||
item.dotTone === "critical" ? "bg-ds-critical" : "bg-ds-warn"
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
|
||||
<span className="flex-grow" />
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveTab("tab4")}
|
||||
aria-label="Setup & agent API"
|
||||
aria-current={activeTab === "tab4" ? "page" : undefined}
|
||||
title="Setup & agent API"
|
||||
className={`flex h-[46px] w-[46px] items-center justify-center rounded-xl transition-colors ${
|
||||
activeTab === "tab4" ? "bg-ds-surface-2 text-ds-text" : "text-ds-text-3 hover:bg-ds-surface-2 hover:text-ds-text-2"
|
||||
}`}
|
||||
>
|
||||
<Wrench className="h-5 w-5" aria-hidden="true" />
|
||||
</button>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconRail
|
||||
Reference in new issue
Block a user