refactor: update styles and layout for log viewer components

This commit is contained in:
Nawaz Dhandala
2026-03-07 10:53:22 +00:00
parent 43ac4a7ef1
commit de0c6881b7
9 changed files with 64 additions and 67 deletions

View File

@@ -54,14 +54,14 @@ const CopyTextButton: FunctionComponent<ComponentProps> = (
const variantClasses: Record<typeof variant, string> = {
ghost:
"bg-transparent border border-slate-600 text-slate-300 hover:bg-slate-700/40",
soft: "bg-slate-700 text-white border border-slate-600 hover:bg-slate-600",
"bg-transparent border border-gray-200 text-gray-400 hover:bg-gray-50 hover:text-gray-600",
soft: "bg-gray-100 text-gray-600 border border-gray-200 hover:bg-gray-200",
solid:
"bg-indigo-600 text-white border border-indigo-600 hover:bg-indigo-500",
} as const;
const copiedClasses: string =
"bg-emerald-600/20 border border-emerald-500 text-emerald-300";
"bg-emerald-50 border border-emerald-200 text-emerald-600";
return (
<button

View File

@@ -427,7 +427,7 @@ const LogsViewer: FunctionComponent<ComponentProps> = (
props.showFacetSidebar !== false && !!props.facetData;
return (
<div className="space-y-4">
<div className="space-y-2">
{props.showFilters && (
<div>
<LogsFilterCard
@@ -476,7 +476,7 @@ const LogsViewer: FunctionComponent<ComponentProps> = (
)}
{/* Main content: sidebar + table */}
<div className="flex gap-4">
<div className="flex gap-3">
{showSidebar && props.facetData && (
<LogsFacetSidebar
facetData={props.facetData}

View File

@@ -38,7 +38,7 @@ const FacetSection: FunctionComponent<FacetSectionProps> = (
: 0;
return (
<div className="border-b border-gray-100 py-2.5">
<div className="border-b border-gray-100 py-2">
<button
type="button"
className="flex w-full items-center justify-between px-2 py-1 text-left"

View File

@@ -42,7 +42,7 @@ const FacetValueRow: FunctionComponent<FacetValueRowProps> = (
</button>
<div className="flex items-center gap-1.5">
<div className="w-14">
<div className="w-12">
<div className="h-1.5 w-full rounded-full bg-gray-100">
<div
className="h-1.5 rounded-full opacity-70 transition-all"
@@ -53,7 +53,7 @@ const FacetValueRow: FunctionComponent<FacetValueRowProps> = (
/>
</div>
</div>
<span className="min-w-[2.5rem] text-right font-mono text-[11px] text-gray-400">
<span className="min-w-[2rem] text-right font-mono text-[10px] tabular-nums text-gray-400">
{props.count.toLocaleString()}
</span>
</div>

View File

@@ -106,7 +106,7 @@ const LogsFacetSidebar: FunctionComponent<LogsFacetSidebarProps> = (
}, [props.facetData]);
return (
<div className="flex h-full w-52 flex-none flex-col overflow-y-auto rounded-lg border border-gray-200 bg-white">
<div className="flex h-full w-56 flex-none flex-col overflow-y-auto rounded-lg border border-gray-200 bg-white">
<div className="border-b border-gray-100 px-3 py-2.5">
<h3 className="text-[11px] font-semibold uppercase tracking-widest text-gray-400">
Filters

View File

@@ -33,9 +33,9 @@ const LogsFilterCard: FunctionComponent<LogsFilterCardProps> = (
];
return (
<div className="rounded-lg border border-gray-200 bg-white shadow-sm">
<div className="p-4">
<div className="mb-3">
<div>
<div className="flex items-start gap-3">
<div className="min-w-0 flex-1">
<LogSearchBar
value={props.searchQuery}
onChange={props.onSearchQueryChange}
@@ -43,45 +43,44 @@ const LogsFilterCard: FunctionComponent<LogsFilterCardProps> = (
suggestions={searchBarSuggestions}
/>
</div>
<FiltersForm<Log>
id="logs-filter"
showFilter={true}
filterData={props.filterData}
onFilterChanged={props.onFilterChanged}
onAdvancedFiltersToggle={props.onAdvancedFiltersToggle}
isFilterLoading={props.isFilterLoading}
filterError={props.filterError}
onFilterRefreshClick={props.onFilterRefreshClick}
filters={[
{
key: "severityText",
filterDropdownOptions:
DropdownUtil.getDropdownOptionsFromEnum(LogSeverity),
type: FieldType.Dropdown,
title: "Log Severity",
isAdvancedFilter: true,
},
{
key: "time",
type: FieldType.DateTime,
title: "Start and End Date",
isAdvancedFilter: true,
},
{
key: "attributes",
type: FieldType.JSON,
title: "Filter by Attributes",
jsonKeys: props.logAttributes,
isAdvancedFilter: true,
},
]}
/>
<div className="flex-none pt-0.5">
{props.toolbar}
</div>
</div>
<div className="border-t border-gray-100 bg-gray-50/50 px-4 py-2.5">
{props.toolbar}
</div>
<FiltersForm<Log>
id="logs-filter"
showFilter={true}
filterData={props.filterData}
onFilterChanged={props.onFilterChanged}
onAdvancedFiltersToggle={props.onAdvancedFiltersToggle}
isFilterLoading={props.isFilterLoading}
filterError={props.filterError}
onFilterRefreshClick={props.onFilterRefreshClick}
filters={[
{
key: "severityText",
filterDropdownOptions:
DropdownUtil.getDropdownOptionsFromEnum(LogSeverity),
type: FieldType.Dropdown,
title: "Log Severity",
isAdvancedFilter: true,
},
{
key: "time",
type: FieldType.DateTime,
title: "Start and End Date",
isAdvancedFilter: true,
},
{
key: "attributes",
type: FieldType.JSON,
title: "Filter by Attributes",
jsonKeys: props.logAttributes,
isAdvancedFilter: true,
},
]}
/>
</div>
);
};

View File

@@ -145,7 +145,7 @@ const LogsHistogram: FunctionComponent<LogsHistogramProps> = (
if (props.isLoading && pivotedData.length === 0) {
return (
<div className="flex h-20 items-center justify-center rounded-lg border border-gray-100 bg-white">
<div className="flex h-16 items-center justify-center bg-white">
<ComponentLoader />
</div>
);
@@ -156,8 +156,8 @@ const LogsHistogram: FunctionComponent<LogsHistogramProps> = (
}
return (
<div className="rounded-lg border border-gray-100 bg-white px-2 pb-1 pt-3">
<div className="h-20">
<div className="bg-white px-2 pb-0 pt-2">
<div className="h-16">
<ResponsiveContainer width="100%" height="100%">
<BarChart
data={pivotedData}
@@ -165,7 +165,7 @@ const LogsHistogram: FunctionComponent<LogsHistogramProps> = (
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
barCategoryGap="12%"
barCategoryGap="15%"
>
<XAxis
dataKey="time"
@@ -192,7 +192,7 @@ const LogsHistogram: FunctionComponent<LogsHistogramProps> = (
dataKey={severity}
stackId="severity"
fill={getSeverityColor(severity).fill}
radius={[1, 1, 0, 0]}
radius={[3, 3, 0, 0]}
isAnimationActive={false}
/>
))}

View File

@@ -6,6 +6,7 @@ import OneUptimeDate from "../../../../Types/Date";
import CopyTextButton from "../../CopyTextButton/CopyTextButton";
import ComponentLoader from "../../ComponentLoader/ComponentLoader";
import SeverityBadge from "./SeverityBadge";
import { getSeverityTheme, SeverityTheme } from "./severityTheme";
import SortOrder from "../../../../Types/BaseDatabase/SortOrder";
import Icon from "../../Icon/Icon";
import IconProp from "../../../../Types/Icon/IconProp";
@@ -114,7 +115,7 @@ const LogsTable: FunctionComponent<LogsTableProps> = (
</button>
</th>
<th scope="col" className="px-4 py-2.5">
Service
<span>Service</span>
</th>
<th scope="col" className="px-4 py-2.5">
<button
@@ -162,6 +163,9 @@ const LogsTable: FunctionComponent<LogsTableProps> = (
const spanId: string = log.spanId?.toString() || "";
const isSelected: boolean = props.selectedLogId === rowId;
const severityTheme: SeverityTheme = getSeverityTheme(
log.severityText,
);
return (
<Fragment key={rowId}>
@@ -169,7 +173,7 @@ const LogsTable: FunctionComponent<LogsTableProps> = (
onClick={() => {
props.onRowClick(log, rowId);
}}
className={`group cursor-pointer align-top transition-colors hover:bg-gray-50/70 ${
className={`group cursor-pointer align-top transition-colors hover:bg-gray-50/70 border-l-[3px] ${severityTheme.borderClass} ${
isSelected
? "bg-indigo-50/50 ring-1 ring-inset ring-indigo-200"
: ""
@@ -177,14 +181,14 @@ const LogsTable: FunctionComponent<LogsTableProps> = (
aria-selected={isSelected}
aria-expanded={isSelected}
>
<td className="whitespace-nowrap px-4 py-2.5 text-[13px] font-mono text-gray-600">
<td className="whitespace-nowrap px-4 py-2 text-[13px] font-mono text-gray-600">
{log.time
? OneUptimeDate.getDateAsUserFriendlyFormattedString(
log.time,
)
: "-"}
</td>
<td className="px-4 py-2.5">
<td className="px-4 py-2">
<div className="flex items-center gap-3 text-sm text-gray-700">
<span
className="h-2.5 w-2.5 flex-none rounded-full shadow-sm"
@@ -196,10 +200,10 @@ const LogsTable: FunctionComponent<LogsTableProps> = (
</span>
</div>
</td>
<td className="px-4 py-2.5">
<td className="px-4 py-2">
<SeverityBadge severity={log.severityText} />
</td>
<td className="px-4 py-2.5">
<td className="px-4 py-2">
<div className="flex items-start justify-between gap-3">
<div className="flex min-w-0 flex-1 flex-col gap-1">
<p
@@ -221,6 +225,7 @@ const LogsTable: FunctionComponent<LogsTableProps> = (
variant="ghost"
iconOnly={true}
title="Copy log message"
className="opacity-0 group-hover:opacity-100 transition-opacity"
/>
</div>
</td>

View File

@@ -271,13 +271,6 @@ These changes directly improve the daily log investigation experience for every
## Phase 4: Advanced Features (P3) — Differentiation
### 4.1 Log Patterns (ML Clustering)
- Implement a clustering algorithm that groups logs by message structure
- Replace variable parts (IPs, UUIDs, numbers) with wildcards
- Show pattern frequency over time with sparklines
- Enable creating alerts directly from a pattern
- This is a significant backend feature requiring a background job that periodically clusters recent logs
### 4.2 Keyboard Shortcuts