feat: Added overflow: hidden, word-break, max-width: 100%, and min-widt…

- "frontend/src/App.css"

GSD-Task: S05/T01
This commit is contained in:
jlightner 2026-03-30 19:41:41 +00:00
parent 9dfa568bb3
commit f2cc72376c
9 changed files with 411 additions and 3 deletions

View file

@ -9,6 +9,6 @@ Make the pipeline fully transparent — every LLM call's full prompt and respons
| S01 | Pipeline Debug Mode — Full LLM I/O Capture and Token Accounting | medium | — | ✅ | Toggle debug mode on for a video, trigger pipeline, see full prompt + response stored for every LLM call with per-stage token breakdown |
| S02 | Debug Payload Viewer — Inline View, Copy, and Export in Admin UI | low | S01 | ✅ | Admin clicks an LLM call event, sees full prompt and response in a readable viewer, copies to clipboard, or downloads as JSON |
| S03 | Transcript Folder Watcher — Auto-Ingest Service | medium | — | ✅ | Drop a transcript JSON into the watch folder on ub01 → file is detected, validated, POSTed to /ingest, pipeline triggers automatically |
| S04 | Admin UX Audit — Prune, Streamline, and Polish | low | S02 | | Admin pipeline page is cleaner and more efficient for daily content management. Dead UI elements removed. Workflow improvements visible. |
| S04 | Admin UX Audit — Prune, Streamline, and Polish | low | S02 | | Admin pipeline page is cleaner and more efficient for daily content management. Dead UI elements removed. Workflow improvements visible. |
| S05 | Key Moment Card Text Overflow Fix | low | — | ⬜ | Key moment cards with long filenames and timestamp ranges display cleanly — text truncated with ellipsis or wrapped within card bounds, no horizontal bleed |
| S06 | Mobile Viewport Overflow Fix — Technique Pages and Global Content | low | S05 | ⬜ | Technique page on Galaxy S25 Ultra renders cleanly — body text wraps, tags don't overflow, metadata stays within viewport, no horizontal scroll |

View file

@ -0,0 +1,84 @@
---
id: S04
parent: M007
milestone: M007
provides:
- Cleaner AdminPipeline page with debug toggle, status filter, pruned UI, and review queue cross-links
requires:
- slice: S02
provides: Debug payload viewer and debug mode backend endpoints
affects:
- S05
- S06
key_files:
- frontend/src/pages/AdminPipeline.tsx
- frontend/src/api/public-client.ts
- frontend/src/App.css
key_decisions:
- Reused mode-toggle CSS pattern for debug toggle
- StatusFilter shows counts in pill labels and hides when only 1 status exists
- Lifted debug mode state from DebugModeToggle to AdminPipeline parent so trigger button can show debug indicator
patterns_established:
- Debug-mode-aware UI elements: pass debugMode state down from parent to child components that need to reflect the current mode
observability_surfaces:
- none
drill_down_paths:
- .gsd/milestones/M007/slices/S04/tasks/T01-SUMMARY.md
- .gsd/milestones/M007/slices/S04/tasks/T02-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-03-30T19:37:50.191Z
blocker_discovered: false
---
# S04: Admin UX Audit — Prune, Streamline, and Polish
**Cleaned up AdminPipeline page with debug mode toggle, status filter pills, pruned dead UI, clearer labels, debug-aware trigger button, and review queue cross-links.**
## What Happened
Two tasks delivered eight discrete UX improvements to the AdminPipeline page.
T01 added two new interactive features: a DebugModeToggle component in the header (reads/writes via GET/PUT /admin/pipeline/debug-mode) and a StatusFilter pill bar that filters the video list client-side by processing_status. The status filter shows per-status counts and auto-hides when only one status exists. Both reuse existing CSS patterns (mode-toggle for the debug switch, filter-tab for the pills).
T02 pruned dead UI and improved workflow clarity: renamed the cryptic "Head"/"Tail" event log toggle to "Oldest first"/"Newest first"; removed the duplicate event-level refresh button (page-level refresh is sufficient); removed the truncated UUID from expanded video details (low-value noise); lifted debugMode state to the parent component so the trigger button shows "▶ Trigger (debug)" when debug mode is active; added a "→ Moments" cross-link on each video card linking to the review queue.
All changes are frontend-only (AdminPipeline.tsx, public-client.ts, App.css). The Docker build compiles TypeScript cleanly and produces the nginx image.
## Verification
Docker build of chrysopedia-web service succeeds with exit 0. TypeScript compiles cleanly, Vite bundles 48 modules, nginx image produced.
## Requirements Advanced
None.
## Requirements Validated
None.
## New Requirements Surfaced
None.
## Requirements Invalidated or Re-scoped
None.
## Deviations
Docker service name is chrysopedia-web (not chrysopedia-web-8096 as referenced in plan). Backend debug-mode response uses debug_mode (snake_case) not enabled as task plan implied.
## Known Limitations
Review queue cross-link navigates to /admin/review without video-specific filtering — the review queue doesn't yet support URL-based video filtering.
## Follow-ups
Add URL-based video filtering to the review queue so the → Moments cross-link can deep-link to a specific video's moments.
## Files Created/Modified
- `frontend/src/pages/AdminPipeline.tsx` — Added DebugModeToggle, StatusFilter, renamed view toggle labels, removed dead UI, added debug indicator on trigger button, added review queue cross-link
- `frontend/src/api/public-client.ts` — Added fetchDebugMode() and setDebugMode() API client functions
- `frontend/src/App.css` — Added debug-toggle and moments-link CSS styles

View file

@ -0,0 +1,58 @@
# S04: Admin UX Audit — Prune, Streamline, and Polish — UAT
**Milestone:** M007
**Written:** 2026-03-30T19:37:50.191Z
## UAT: Admin UX Audit — Prune, Streamline, and Polish
### Preconditions
- Chrysopedia stack running on ub01 (`docker ps --filter name=chrysopedia` shows all services healthy)
- At least 2 videos in the pipeline with different processing_status values
- Web UI accessible at http://ub01:8096
### Test 1: Debug Mode Toggle
1. Navigate to http://ub01:8096/admin/pipeline
2. Locate the debug mode toggle in the header area (next to WorkerStatus)
3. **Expected:** Toggle switch visible with "Debug Mode" label, showing current state (on/off)
4. Click the toggle to change state
5. **Expected:** Toggle visually flips, state persists on page reload
6. Refresh the page
7. **Expected:** Toggle reflects the state you set in step 4
### Test 2: Debug Indicator on Trigger Button
1. Enable debug mode via the toggle
2. Find any video card's trigger button
3. **Expected:** Button text reads "▶ Trigger (debug)" instead of "▶ Trigger"
4. Disable debug mode via the toggle
5. **Expected:** Button text reverts to "▶ Trigger"
### Test 3: Status Filter Pills
1. On the pipeline page, locate the filter pill bar below the header
2. **Expected:** "All" pill plus one pill per unique processing_status, each showing a count (e.g., "completed (3)")
3. Click a specific status pill (e.g., "completed")
4. **Expected:** Only videos with that status are shown; the clicked pill is highlighted
5. Click "All" pill
6. **Expected:** All videos shown again
### Test 4: Status Filter — Single Status Edge Case
1. If all videos have the same status, the filter bar should be hidden (only 1 status = no filtering value)
2. **Expected:** No filter pills visible when all videos share the same processing_status
### Test 5: View Toggle Labels
1. Expand a video to see the event log
2. Locate the view toggle buttons
3. **Expected:** Buttons read "Oldest first" and "Newest first" (NOT "Head" / "Tail")
### Test 6: Dead UI Removal — No Event Refresh Button
1. Expand a video's event log
2. **Expected:** No "↻ Refresh" button in the event log header (page-level refresh in main header is sufficient)
### Test 7: Dead UI Removal — No Truncated ID
1. Expand a video's detail section
2. **Expected:** Created and Updated dates visible, but NO "ID: abc123…" truncated UUID
### Test 8: Review Queue Cross-Link
1. On the pipeline page, find a video card
2. **Expected:** "→ Moments" link visible in the video meta area
3. Click the "→ Moments" link
4. **Expected:** Navigates to /admin/review page

View file

@ -0,0 +1,24 @@
{
"schemaVersion": 1,
"taskId": "T02",
"unitId": "M007/S04/T02",
"timestamp": 1774899407871,
"passed": false,
"discoverySource": "task-plan",
"checks": [
{
"command": "ssh ub01 \"cd /vmPool/r/repos/xpltdco/chrysopedia",
"exitCode": 2,
"durationMs": 4,
"verdict": "fail"
},
{
"command": "docker compose build chrysopedia-web\" succeeds with exit 0",
"exitCode": 2,
"durationMs": 3,
"verdict": "fail"
}
],
"retryAttempt": 1,
"maxRetries": 2
}

View file

@ -1,6 +1,44 @@
# S05: Key Moment Card Text Overflow Fix
**Goal:** Fix text overflow on key moment cards. Source filenames and timestamp ranges must respect card width. Apply overflow: hidden, text-overflow: ellipsis, white-space: nowrap for single-line fields. Use word-break: break-word where wrapping is appropriate.
**Goal:** Key moment cards display cleanly with no text overflow — long filenames truncate with ellipsis within card bounds, long titles wrap gracefully, no horizontal bleed on desktop or mobile.
**Demo:** After this: Key moment cards with long filenames and timestamp ranges display cleanly — text truncated with ellipsis or wrapped within card bounds, no horizontal bleed
## Tasks
- [x] **T01: Added overflow: hidden, word-break, max-width: 100%, and min-width: 0 to key moment card CSS rules to prevent text bleed** — Apply four CSS property changes to `frontend/src/App.css` to prevent key moment card text from overflowing the sidebar bounds.
The key moment cards live in the technique page sidebar (22rem wide, ~20rem inner after padding). Long filenames in `.technique-moment__source` have `max-width: 20rem` which can exceed the actual container. Titles have no wrapping control. The card container has no overflow clip.
## Steps
1. Read `frontend/src/App.css` lines ~15121555 (the `.technique-moment*` rules)
2. Add `overflow: hidden` to `.technique-moment` (the card container) — clips any child that escapes card bounds
3. Add `word-break: break-word` to `.technique-moment__title` — long titles wrap instead of overflowing (wrapping preferred over truncation since titles are meaningful)
4. Change `max-width: 20rem` to `max-width: 100%` on `.technique-moment__source` — respects actual container width instead of a fixed value that may exceed the sidebar
5. Add `min-width: 0` to `.technique-moment__meta` — required for flex child truncation to work reliably in a flex container
6. Run `cd frontend && npm run build` to verify zero errors
## Must-Haves
- [ ] `.technique-moment` has `overflow: hidden`
- [ ] `.technique-moment__title` has `word-break: break-word`
- [ ] `.technique-moment__source` uses `max-width: 100%` not `max-width: 20rem`
- [ ] `.technique-moment__meta` has `min-width: 0`
- [ ] Frontend builds with zero errors
## Verification
- `cd frontend && npm run build` passes
- `grep 'overflow: hidden' frontend/src/App.css` shows the `.technique-moment` rule
- `grep 'word-break: break-word' frontend/src/App.css` shows the title rule
- `grep 'max-width: 100%' frontend/src/App.css` shows the source rule
## Inputs
- `frontend/src/App.css` — existing CSS with `.technique-moment*` rules around lines 15121555
## Expected Output
- `frontend/src/App.css` — modified with four overflow-fix properties added/changed
- Estimate: 15m
- Files: frontend/src/App.css
- Verify: cd frontend && npm run build 2>&1 | tail -5 && echo '---' && grep -A2 'technique-moment {' frontend/src/App.css | grep -q 'overflow: hidden' && echo 'overflow: hidden ✓' && grep -q 'word-break: break-word' frontend/src/App.css && echo 'word-break ✓' && grep 'technique-moment__source' frontend/src/App.css | grep -q 'max-width: 100%' && echo 'max-width fix ✓'

View file

@ -0,0 +1,69 @@
# S05 Research — Key Moment Card Text Overflow Fix
## Summary
Key moment cards live in the technique page **sidebar** (22rem wide, in `TechniquePage.tsx` lines ~430460). The sidebar is a CSS grid column (`technique-columns__sidebar`) that collapses to full-width at 768px. Long filenames and moment titles can overflow the card bounds because the container has no `overflow: hidden` and the title element has no truncation CSS.
This is a straightforward CSS fix — no new components, no API changes, no structural markup changes needed.
## Recommendation
Add overflow protection at three levels:
1. **Card container** (`.technique-moment`) — add `overflow: hidden` to clip any runaway children
2. **Title** (`.technique-moment__title`) — add `overflow: hidden; text-overflow: ellipsis; white-space: nowrap` (or allow wrapping with `word-break: break-word` — wrapping is probably better for titles since truncation loses meaning)
3. **Source filename** (`.technique-moment__source`) — change `max-width: 20rem` to `max-width: 100%` so it respects the actual container width instead of a fixed value that may exceed the sidebar
## Implementation Landscape
### Files to modify
| File | What | Lines |
|------|------|-------|
| `frontend/src/App.css` | CSS overflow fixes on `.technique-moment`, `.technique-moment__title`, `.technique-moment__source` | ~15121555 |
One file, one task. No TSX markup changes needed — the existing class names cover all the elements.
### Current state (what exists)
**Markup** (`TechniquePage.tsx` ~436458):
```
li.technique-moment
h3.technique-moment__title → moment title text
div.technique-moment__meta → flex row, flex-wrap: wrap ✓
span.technique-moment__source → video filename (monospace)
span.technique-moment__time → "00:12 01:45"
span.badge.badge--content-type → e.g. "tutorial"
p.technique-moment__summary → summary paragraph
```
**CSS** (`App.css` ~15121555):
- `.technique-moment``padding: 0.875rem 1rem; background; border; border-radius` — **no overflow handling**
- `.technique-moment__title``font-size/weight/line-height` — **no overflow handling**
- `.technique-moment__meta``display: flex; flex-wrap: wrap; gap: 0.5rem` — wrapping is good
- `.technique-moment__source` — has `overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 20rem`**max-width is too large** (sidebar is ~20rem after padding, so 20rem source can still bleed)
- `.technique-moment__summary` — basic text styles, no overflow issue (natural word wrap)
**Container context:**
- Sidebar column: `22rem` fixed width (`technique-columns`, grid)
- Card inner width: ~20rem (22rem - 2×1rem padding)
- At mobile (≤768px): sidebar becomes `1fr` (full viewport width), same overflow risk on very narrow screens
### Specific CSS changes needed
1. `.technique-moment` — add `overflow: hidden` (clip any child that escapes)
2. `.technique-moment__title` — add `word-break: break-word` (long titles wrap instead of truncate — titles are meaningful and shouldn't be clipped)
3. `.technique-moment__source` — change `max-width: 20rem``max-width: 100%` (respect actual container width)
4. `.technique-moment__meta` — add `min-width: 0` (flex container needs this for truncation of flex children to work reliably)
### Verification
- `cd frontend && npm run build` — zero errors
- Visual check: load a technique page with long filenames and verify no horizontal overflow on the card or page
### Constraints and non-issues
- No TSX changes needed
- No API changes
- Summary text (`.technique-moment__summary`) already wraps naturally — no fix needed
- Badge (`.badge--content-type`) is short text, inline-block in a wrapping flex row — no fix needed
- Time spans are fixed-format short strings — no fix needed

View file

@ -0,0 +1,55 @@
---
estimated_steps: 24
estimated_files: 1
skills_used: []
---
# T01: Fix key moment card CSS overflow for titles, filenames, and meta row
Apply four CSS property changes to `frontend/src/App.css` to prevent key moment card text from overflowing the sidebar bounds.
The key moment cards live in the technique page sidebar (22rem wide, ~20rem inner after padding). Long filenames in `.technique-moment__source` have `max-width: 20rem` which can exceed the actual container. Titles have no wrapping control. The card container has no overflow clip.
## Steps
1. Read `frontend/src/App.css` lines ~15121555 (the `.technique-moment*` rules)
2. Add `overflow: hidden` to `.technique-moment` (the card container) — clips any child that escapes card bounds
3. Add `word-break: break-word` to `.technique-moment__title` — long titles wrap instead of overflowing (wrapping preferred over truncation since titles are meaningful)
4. Change `max-width: 20rem` to `max-width: 100%` on `.technique-moment__source` — respects actual container width instead of a fixed value that may exceed the sidebar
5. Add `min-width: 0` to `.technique-moment__meta` — required for flex child truncation to work reliably in a flex container
6. Run `cd frontend && npm run build` to verify zero errors
## Must-Haves
- [ ] `.technique-moment` has `overflow: hidden`
- [ ] `.technique-moment__title` has `word-break: break-word`
- [ ] `.technique-moment__source` uses `max-width: 100%` not `max-width: 20rem`
- [ ] `.technique-moment__meta` has `min-width: 0`
- [ ] Frontend builds with zero errors
## Verification
- `cd frontend && npm run build` passes
- `grep 'overflow: hidden' frontend/src/App.css` shows the `.technique-moment` rule
- `grep 'word-break: break-word' frontend/src/App.css` shows the title rule
- `grep 'max-width: 100%' frontend/src/App.css` shows the source rule
## Inputs
- `frontend/src/App.css` — existing CSS with `.technique-moment*` rules around lines 15121555
## Expected Output
- `frontend/src/App.css` — modified with four overflow-fix properties added/changed
## Inputs
- `frontend/src/App.css`
## Expected Output
- `frontend/src/App.css`
## Verification
cd frontend && npm run build 2>&1 | tail -5 && echo '---' && grep -A2 'technique-moment {' frontend/src/App.css | grep -q 'overflow: hidden' && echo 'overflow: hidden ✓' && grep -q 'word-break: break-word' frontend/src/App.css && echo 'word-break ✓' && grep 'technique-moment__source' frontend/src/App.css | grep -q 'max-width: 100%' && echo 'max-width fix ✓'

View file

@ -0,0 +1,77 @@
---
id: T01
parent: S05
milestone: M007
provides: []
requires: []
affects: []
key_files: ["frontend/src/App.css"]
key_decisions: ["Used word-break: break-word for titles (wrap) vs text-overflow: ellipsis (truncate) since titles are meaningful content"]
patterns_established: []
drill_down_paths: []
observability_surfaces: []
duration: ""
verification_result: "Frontend build passes (zero errors, 821ms). Grep checks confirm all four CSS properties present in the correct rules."
completed_at: 2026-03-30T19:41:33.455Z
blocker_discovered: false
---
# T01: Added overflow: hidden, word-break, max-width: 100%, and min-width: 0 to key moment card CSS rules to prevent text bleed
> Added overflow: hidden, word-break, max-width: 100%, and min-width: 0 to key moment card CSS rules to prevent text bleed
## What Happened
---
id: T01
parent: S05
milestone: M007
key_files:
- frontend/src/App.css
key_decisions:
- Used word-break: break-word for titles (wrap) vs text-overflow: ellipsis (truncate) since titles are meaningful content
duration: ""
verification_result: passed
completed_at: 2026-03-30T19:41:33.455Z
blocker_discovered: false
---
# T01: Added overflow: hidden, word-break, max-width: 100%, and min-width: 0 to key moment card CSS rules to prevent text bleed
**Added overflow: hidden, word-break, max-width: 100%, and min-width: 0 to key moment card CSS rules to prevent text bleed**
## What Happened
Applied four CSS property changes to `.technique-moment*` rules in `frontend/src/App.css`: overflow: hidden on the card container, word-break: break-word on the title, max-width: 100% on the source filename, and min-width: 0 on the meta flex row. All changes prevent text from overflowing the sidebar card bounds.
## Verification
Frontend build passes (zero errors, 821ms). Grep checks confirm all four CSS properties present in the correct rules.
## Verification Evidence
| # | Command | Exit Code | Verdict | Duration |
|---|---------|-----------|---------|----------|
| 1 | `cd frontend && npm run build` | 0 | ✅ pass | 3100ms |
| 2 | `grep 'overflow: hidden' frontend/src/App.css` | 0 | ✅ pass | 10ms |
| 3 | `grep 'word-break: break-word' frontend/src/App.css` | 0 | ✅ pass | 10ms |
| 4 | `grep 'max-width: 100%' frontend/src/App.css` | 0 | ✅ pass | 10ms |
## Deviations
None.
## Known Issues
None.
## Files Created/Modified
- `frontend/src/App.css`
## Deviations
None.
## Known Issues
None.

View file

@ -1514,6 +1514,7 @@ a.app-footer__repo:hover {
background: var(--color-bg-surface);
border: 1px solid var(--color-border);
border-radius: 0.5rem;
overflow: hidden;
}
.technique-moment__title {
@ -1522,6 +1523,7 @@ a.app-footer__repo:hover {
font-size: 0.9375rem;
font-weight: 600;
line-height: 1.3;
word-break: break-word;
}
.technique-moment__meta {
@ -1530,6 +1532,7 @@ a.app-footer__repo:hover {
gap: 0.5rem;
margin-bottom: 0.25rem;
flex-wrap: wrap;
min-width: 0;
}
.technique-moment__time {
@ -1542,7 +1545,7 @@ a.app-footer__repo:hover {
font-size: 0.75rem;
color: var(--color-text-muted);
font-family: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace;
max-width: 20rem;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;