Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5a96a13
feat: improve logs view with keyset pagination, column selection, and…
trieloff Feb 12, 2026
225310c
fix: address PR review feedback for logs view improvements
claude Feb 12, 2026
675c28f
fix: progressively load more logs when chart hover timestamp is beyon…
claude Feb 12, 2026
001ccf9
feat: replace progressive retry with collapsed time-gap rows in logs …
claude Feb 12, 2026
e15dc72
Merge branch 'main' of https://github.com/adobe/klickhaus into logs-v…
claude Feb 12, 2026
b0a3e12
fix: address PR #122 feedback - improve logs view UX and code quality
Feb 12, 2026
a78d20f
fix: make toolbar, chart, and table header sticky in logs view
Feb 12, 2026
4665dc5
fix: make header/chart/table sticky in logs view on page load
Feb 12, 2026
480fb68
fix: correct header height CSS variable to 69px
Feb 12, 2026
2b08fdc
fix: simplify table header sticky to top:0 within its container
Feb 12, 2026
777d580
fix: improve gap row display with time range and left alignment
Feb 12, 2026
7c34839
fix: constrain gap row height and match table background color
Feb 12, 2026
8cbaa3e
fix: use more specific selector for gap row hover background
Feb 12, 2026
5ce5fdc
fix: use content-box sizing and overflow-y:clip for gap cell height
Feb 12, 2026
5157328
fix: override base.css .loading styles on gap row
Feb 12, 2026
b0f7f93
feat: add IntersectionObserver for auto-loading bottom gap row
Feb 12, 2026
0d16250
feat: add bidirectional scroll-scrubber sync
Feb 12, 2026
c4f4191
fix: optimize scroll-sync with proper debouncing
Feb 12, 2026
f0d0a94
fix: separate UI thread from background data operations
Feb 12, 2026
4edb80d
fix: use requestIdleCallback instead of setInterval
Feb 12, 2026
0a6ce5e
feat: use Web Worker for scroll-sync timing
Feb 12, 2026
0d478ba
fix: defer isTimestampLoaded check until cursor rests
Feb 12, 2026
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
80 changes: 80 additions & 0 deletions css/chart.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,55 @@
margin: 0 -24px 24px -24px;
}

/* Sticky chart when logs view is active (not collapsed) */
.logs-active:not(.logs-collapsed) .chart-section {
position: sticky;
top: var(--header-height);
z-index: 20;
}

/* When collapsed, nothing is sticky - normal scroll behavior */
.logs-active.logs-collapsed .chart-section {
position: relative;
}

/* Collapse/expand toggle */
.chart-collapse-toggle {
display: none;
width: 100%;
height: 24px;
border: none;
background: var(--chart-bg);
border-top: 1px solid var(--border);
cursor: pointer;
padding: 0;
color: var(--text-secondary);
font-size: 10px;
line-height: 24px;
text-align: center;
opacity: 0.6;
transition: opacity 0.15s ease;
}

.chart-collapse-toggle:hover {
opacity: 1;
}

.logs-active .chart-collapse-toggle {
display: block;
}

/* Collapsed state */
.chart-section.chart-collapsed .chart-container {
height: 0;
overflow: hidden;
transition: height 0.2s ease;
}

.chart-section:not(.chart-collapsed) .chart-container {
transition: height 0.2s ease;
}

@media (max-width: 600px) {
.chart-section {
margin: 0 -12px 16px -12px;
Expand Down Expand Up @@ -106,6 +155,37 @@
opacity: 0.6;
}

/* Scrubber active state (row hover) */
.chart-scrubber-line.active {
background: var(--primary);
opacity: 0.8;
}

/* Scrubber waiting state (chart hover, waiting to scroll) */
.chart-scrubber-line.waiting {
background: var(--primary);
opacity: 0.5;
animation: scrubber-pulse 1s ease-in-out;
}

/* Scrubber loading state (fetching gap data) */
.chart-scrubber-line.loading {
background: var(--primary);
opacity: 0.8;
animation: scrubber-blink 0.3s ease-in-out infinite;
}

@keyframes scrubber-pulse {
0% { opacity: 0.3; }
50% { opacity: 0.7; }
100% { opacity: 0.5; }
}

@keyframes scrubber-blink {
0%, 100% { opacity: 0.4; }
50% { opacity: 0.9; }
}

.chart-scrubber-status {
position: absolute;
bottom: 0;
Expand Down
12 changes: 12 additions & 0 deletions css/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ body.header-fixed main {
padding-top: 70px;
}

/* Sticky header when logs view is active (not collapsed) */
#dashboard:has(.logs-active:not(.logs-collapsed)) header {
position: sticky;
top: 0;
z-index: 30;
}

/* When collapsed, header is not sticky */
#dashboard:has(.logs-active.logs-collapsed) header {
position: relative;
}

@media (max-width: 600px) {
header {
padding: 12px;
Expand Down
81 changes: 81 additions & 0 deletions css/logs.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
border-bottom: 1px solid var(--border);
position: sticky;
top: 0;
z-index: 10;
white-space: nowrap;
cursor: pointer;
user-select: none;
Expand Down Expand Up @@ -175,6 +176,86 @@
color: var(--text-secondary);
}

/* Gap rows — unloaded time ranges between log islands */
.logs-gap-row {
cursor: default;
height: 33px; /* Match regular row height */
max-height: 33px;
}

.logs-gap-row td {
border-bottom: 1px solid var(--border);
background: var(--card-bg); /* Match table background */
}

.logs-table tr.logs-gap-row:hover td {
background: var(--card-bg);
}

.logs-gap-cell {
text-align: left;
padding: 8px 12px;
height: 17px; /* Content height only, padding adds to 33px total */
line-height: 17px;
box-sizing: content-box;
overflow: hidden;
overflow-y: clip;
}

.logs-gap-button {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0;
border: none;
background: transparent;
color: var(--text-secondary);
font-size: 12px;
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
cursor: pointer;
transition: color 0.15s;
height: 17px; /* Fixed height to prevent layout shift */
line-height: 17px;
/* Keep button visible when table is wider than viewport */
position: sticky;
left: 12px;
}

.logs-gap-button:hover {
color: var(--primary);
}

.logs-gap-row.loading {
display: table-row; /* Override base.css .loading display:flex */
padding: 0; /* Override base.css .loading padding:40px */
}

.logs-gap-row.loading .logs-gap-button {
cursor: wait;
}

.logs-gap-icon {
font-size: 14px;
line-height: 1;
width: 14px;
text-align: center;
}

.logs-gap-spinner {
display: inline-block;
width: 12px;
height: 12px;
border: 1.5px solid var(--text-secondary);
border-top-color: transparent;
border-radius: 50%;
animation: gap-spin 0.8s linear infinite;
flex-shrink: 0;
}

@keyframes gap-spin {
to { transform: rotate(360deg); }
}

/* Copy feedback toast */
.copy-feedback {
position: fixed;
Expand Down
7 changes: 7 additions & 0 deletions css/modals.css
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,13 @@
margin-bottom: 12px;
}

.log-detail-loading {
padding: 40px 20px;
text-align: center;
color: var(--text-secondary);
font-size: 14px;
}

@media (max-width: 600px) {
#logDetailModal {
width: 100vw;
Expand Down
4 changes: 4 additions & 0 deletions css/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
*/

:root {
/* Sticky layout heights for logs view */
--header-height: 69px;
--chart-height: 250px;
--chart-toggle-height: 24px;
--primary: #eb1000;
--primary-dark: #c40d00;
--bg: #f9fafb;
Expand Down
1 change: 1 addition & 0 deletions dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ <h2>Requests over time</h2>
<div class="chart-container">
<canvas id="chart"></canvas>
</div>
<button class="chart-collapse-toggle" id="chartCollapseToggle" title="Collapse chart"><span aria-hidden="true">&#9650;</span> Hide chart</button>
</section>

<!-- Filters View (Breakdowns) -->
Expand Down
Loading
Loading