Add UI audit report
Catalogs systemic UI issues by pattern (root causes), what was already fixed in this session, and prioritized recommendations for further work. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
343ffb48af
commit
3949062435
238
docs/ui/UI_AUDIT.md
Normal file
238
docs/ui/UI_AUDIT.md
Normal file
@ -0,0 +1,238 @@
|
||||
# Trading Web UI Audit
|
||||
|
||||
> **Last updated:** 2026-05-10
|
||||
> **Scope:** `learning_ai_invt_trdg/web/src` (~13,000 lines of UI code across views/tabs/components)
|
||||
> **Method:** Pattern-based grep audit + manual inspection of fixed components
|
||||
|
||||
This doc catalogs UI issues by **pattern** (so you fix root causes, not symptoms), tells you **which files are affected**, and recommends **concrete fixes**.
|
||||
|
||||
---
|
||||
|
||||
## 1. Summary — what's the state of the codebase?
|
||||
|
||||
| Metric | Count | Note |
|
||||
|---|---|---|
|
||||
| Files using `style={{...}}` inline blocks | 25 | A few have 50–72 blocks each — major drift source |
|
||||
| `!important` declarations in `index.css` | 122 | Indicates repeated style-override fights |
|
||||
| `<Button>` (primitive) usages | 31 files | Has known overlap-with-block-children issue (we hit it in Copilot) |
|
||||
| `<table>` direct usages | 6 files | Several without scroll containers |
|
||||
| Largest views | `PositionsTab` 2035, `SimpleView` 1635, `OverviewTab` 1061, `AdminTab` 990, `HomeView` 917 | High UI surface = high bug surface |
|
||||
|
||||
The codebase has **pattern bugs**, not just one-off issues. The same root causes recur across files. Fixing them centrally (CSS overrides, lint rules) is much cheaper than file-by-file.
|
||||
|
||||
---
|
||||
|
||||
## 2. Already fixed in this session
|
||||
|
||||
| # | Issue | Fix | Commit |
|
||||
|---|---|---|---|
|
||||
| 1 | Plans page: saved-setup cards clipped Edit/Delete buttons; chips truncated with ellipsis instead of wrapping; outer grid forced 380px on saved column | Refactored saved-setup-card to `overflow: visible`, flex-wrap topline, real chip wrap, single-column form below 1440px | `46a357c` |
|
||||
| 2 | Critical alert banner overflowed at narrow widths; loud red styling | Restructured into wrapper + inner row with min-width:0 text + shrink-0 CTA, max-width 1280px, soft tinted background | `1fa2bcd` |
|
||||
| 3 | Sidebar logo: "ByteLyst / Trading OS" clipped due to two competing CSS rules (44×44 grid vs 56px flex) | Forced flex layout with min-height 60px, brand text ellipsis-only | `1fa2bcd` |
|
||||
| 4 | AI Trading Copilot: Quick Action title and prompt overlapped; not responsive | Replaced `<Button>` with native `<button>` with explicit flex-column; responsive 1/2-col grid; line-clamp on prompt | `343ffb4` |
|
||||
| 5 | DevOps panel tables overflowed | Wrapped in `overflow-x: auto`, table-layout: fixed, break-word on cells | `d2420f5d` |
|
||||
| 6 | Global: `.dashboard-main { overflow: hidden }` clipped popovers/modals | `overflow: visible !important` | `f463ff6` |
|
||||
| 7 | Global: right panel covers main on narrow viewports | Collapses to 260px below 1280px, hidden below 1024px | `f463ff6` |
|
||||
| 8 | Global: tables push layout horizontally | `.dashboard-content table` wrapped with `overflow-x: auto` | `f463ff6` |
|
||||
| 9 | Global: header search/indices crowd each other | flex-wrap, search shrinks 240–360px, indices wrap | `f463ff6` |
|
||||
|
||||
All centralized in `web/src/layout-fixes.css` (495 lines). Single file = single review surface.
|
||||
|
||||
---
|
||||
|
||||
## 3. Issue patterns (root causes)
|
||||
|
||||
### Pattern A — `<Button>` primitive ate block children
|
||||
|
||||
**Symptom:** Two `<span style={{display:block}}>` inside a `<Button>` overlap each other.
|
||||
**Root cause:** `<Button>` from `@bytelyst/ui` is `inline-flex` internally; block children get treated as inline-flex items.
|
||||
**Fix pattern:** Use native `<button>` with explicit `display: flex; flex-direction: column` for cards-as-buttons.
|
||||
**Where to look:** any `<Button>` containing 2+ stacked text spans/divs.
|
||||
|
||||
```bash
|
||||
grep -rn "<Button" --include="*.tsx" web/src | wc -l # 31 files
|
||||
```
|
||||
|
||||
### Pattern B — Inline styles instead of classes
|
||||
|
||||
**Symptom:** Style drift, no responsive breakpoints, can't override via CSS without `!important`.
|
||||
**Files:** `OverviewTab` (72 blocks), `MyStrategiesTab` (64), `HomeView` (55), `ChatControl` (28), `MembershipTab` (26), `MarketplaceTab` (23), `VisualRuleBuilder` (22).
|
||||
**Why bad:** Inline styles can't have `@media` queries, can't be tweaked via theme, fight `index.css` for specificity.
|
||||
**Fix pattern:** Lift repeated patterns into named CSS classes; keep one-off positional styles inline.
|
||||
|
||||
### Pattern C — Hardcoded pixel widths in JSX
|
||||
|
||||
**Symptom:** Doesn't shrink on narrow viewports → horizontal overflow.
|
||||
**Findings:**
|
||||
- `App.tsx:226` `maxWidth: 420` (toast container)
|
||||
- `Header.tsx:77` `width: 300` (search) — already fixed via CSS override
|
||||
- `MembershipTab.tsx:48,160` `width: 44`, `maxWidth: 1400`
|
||||
- `VisualRuleBuilder.tsx:111,326` `width: 70`, `width: 260`
|
||||
- `RightPanel.tsx:109` `width: 52, height: 44` (image — fine, intentional thumbnail)
|
||||
- `PositionsTab.tsx` multiple `truncate max-w-[80px/120px/180px/220px/260px]`
|
||||
|
||||
**Fix pattern:** Replace fixed widths with flex/grid + `min-width: 0` + `flex: 0 1 <basis>`. For images, keep fixed but add `flex-shrink: 0`.
|
||||
|
||||
### Pattern D — `overflow: hidden` on cards that have anchored children
|
||||
|
||||
**Symptom:** Buttons, badges, dropdowns clipped.
|
||||
**Findings (current):**
|
||||
- `ReconciliationAuditPanel.tsx:447,509,579` — `<Card className="overflow-hidden rounded-2xl">` × 3
|
||||
- `AdminTab.tsx:372,608,843` — admin panel sections with overflow-hidden
|
||||
- `PositionsTab.tsx:1392,1578` — `table-container ... overflow-hidden` (this one is correct — it's the wrapper for a horizontal-scroll table)
|
||||
|
||||
**Fix pattern:** Use `overflow: hidden` only when intentionally clipping (e.g. rounded corners over images). For cards that contain actionable children, prefer `overflow: visible` and let children manage their own bounds.
|
||||
|
||||
### Pattern E — Truncation without `title` attribute
|
||||
|
||||
**Symptom:** User sees "PKRBKDW7…" with no way to read the full value.
|
||||
**Findings:** 11 instances of `className="...truncate..."` without a sibling `title=` attribute (a11y + UX regression).
|
||||
**Fix pattern:** Always pair `truncate` with `title={value}` so hover/focus shows full content.
|
||||
|
||||
### Pattern F — Grid templates without `minmax(0, 1fr)`
|
||||
|
||||
**Symptom:** Grid children with content wider than `1fr` push past container.
|
||||
**Findings:**
|
||||
- `index.css:1230` `grid-template-columns: 2fr 1.2fr 1fr 1.2fr` (no minmax)
|
||||
- `index.css:1895` `grid-template-columns: repeat(3, 1fr)` (no minmax)
|
||||
- `index.css:2325` `grid-template-columns: 100px minmax(220px, 1fr) 90px ...` — fine
|
||||
- `MarketplaceTab.tsx:36,86`, `MembershipTab.tsx:100`, `MyStrategiesTab.tsx:127` — `gridTemplateColumns: '1fr 1fr'` inline
|
||||
|
||||
**Fix pattern:** Always use `minmax(0, 1fr)` not bare `1fr` in grid templates. Default `min-width` is `auto` which equals `min-content` of children; minmax(0,...) lets the column shrink.
|
||||
|
||||
### Pattern G — Two competing CSS rules for the same class
|
||||
|
||||
**Symptom:** Styles you can't reason about; depends on rule order in 3000-line stylesheet.
|
||||
**Where seen:** `.trading-sidebar-logo` (44×44 grid block at line 349 + 56px flex block at line 1546). The logo bug we fixed was a direct consequence.
|
||||
**Likely more:** `index.css` has 122 `!important` declarations — each one suggests a fight between two rules. Worth a future cleanup pass.
|
||||
|
||||
### Pattern H — `100vw` / `vw` units inside layouts with a fixed sidebar
|
||||
|
||||
**Symptom:** Element widths don't subtract sidebar/scrollbar width → overflow.
|
||||
**Findings:**
|
||||
- `index.css:1620` `width: min(42vw, 460px) !important;`
|
||||
- `index.css:1791,1798,1822,1832` — `clamp(... vw ...)` for fluid typography (these are fine)
|
||||
- `ChatControl.tsx:635` `maxWidth: 'calc(100vw - 32px)'` (acceptable — modal portaled to body, no sidebar offset)
|
||||
- `TradeProfileManager.tsx:908` `max-w-[92vw]` (also portaled side-drawer — acceptable)
|
||||
|
||||
**Fix pattern:** Inside the dashboard shell use `100%` not `100vw`. `vw` only safe for elements outside the sidebar layout (modals, banners).
|
||||
|
||||
---
|
||||
|
||||
## 4. High-impact components still to address
|
||||
|
||||
### 4.1 PositionsTab.tsx (2035 lines, Portfolio page)
|
||||
|
||||
**Issues:**
|
||||
- 6+ instances of `truncate max-w-[80–260px]` for trade IDs / sub-tags
|
||||
- `<table className="pro-table">` already has horizontal scroll wrapper, but the inner `pro-table` has hardcoded `min-width: 980px` — fine for desktop, but on narrow viewports the table scrolls within itself (correct behavior, by design)
|
||||
- 3 separate scroll regions (`.positions-section`, `.orders-section`, `.history-tab`) each with their own min-widths
|
||||
- Many badges with hardcoded font/padding via inline style
|
||||
|
||||
**Recommendation:** Keep horizontal scroll behavior (it's correct for data tables). Add `title={fullValue}` to the 6 truncate instances that don't have it. Audit badge inline styles → lift to `.position-badge` class.
|
||||
|
||||
### 4.2 OverviewTab.tsx (1061 lines, dashboard landing)
|
||||
|
||||
**Issues:**
|
||||
- 72 inline `style={{...}}` blocks
|
||||
- Likely uses many `<Button>` with multiple-span content → potential overlap (Pattern A)
|
||||
- No responsive breakpoints in inline styles
|
||||
|
||||
**Recommendation:** Highest-payoff refactor target. Move colors/spacing into Tailwind utilities or `.overview-*` classes. Estimated 3–4 hours for a clean pass.
|
||||
|
||||
### 4.3 HomeView.tsx (917 lines, root /)
|
||||
|
||||
**Issues:**
|
||||
- 55 inline style blocks
|
||||
- Hero panel uses `clamp(... vw ...)` for fluid typography — looks intentional
|
||||
- Action grid likely uses `gridTemplateColumns: '1fr 1fr'` (Pattern F)
|
||||
|
||||
**Recommendation:** Same as OverviewTab — extract into classes. Verify mobile breakpoint for action grid (`grid-cols-1 md:grid-cols-2 xl:grid-cols-3`).
|
||||
|
||||
### 4.4 TradeProfileManager.tsx (slide-over drawer)
|
||||
|
||||
**Issues:**
|
||||
- Uses `w-[520px] max-w-[92vw]` — fixed width on desktop. May feel cramped for forms with many fields.
|
||||
- Drawer slides in from right, portaled to body (good).
|
||||
|
||||
**Recommendation:** Consider `w-[640px]` on `xl:` breakpoint for more breathing room. Inspect the form layout for the same overlap-with-Button issue we saw in Copilot.
|
||||
|
||||
### 4.5 ConfigTab.tsx + AdminTab.tsx tables
|
||||
|
||||
**ConfigTab:**
|
||||
- `<th className="min-w-[200px/300px/400px]">` — guarantees horizontal scroll. Acceptable for a config table; user can scroll.
|
||||
|
||||
**AdminTab:**
|
||||
- `max-h-[400px] overflow-y-auto` × 2 instances. Bounded height for log/audit panels — likely intentional.
|
||||
- `max-w-[260px]` truncate on token displays — good (these are secrets, full value isn't useful).
|
||||
|
||||
**Recommendation:** No urgent fix. Both pages are admin-only and the scroll behavior is appropriate for their content density.
|
||||
|
||||
### 4.6 ChatControl.tsx (Copilot, just fixed)
|
||||
|
||||
Quick Actions block fixed (commit `343ffb4`). Remaining minor:
|
||||
- 28 inline-style blocks (background gradients, animations) — keep, they're animation-specific
|
||||
- Floating button portal styles — fine
|
||||
- Backdrop styles — fine
|
||||
|
||||
**No further action needed.**
|
||||
|
||||
---
|
||||
|
||||
## 5. Recommendations
|
||||
|
||||
### Immediate (1 commit, 1 hour)
|
||||
|
||||
1. Add `title=` to the 11 untitled truncate instances. Quick a11y win.
|
||||
2. Add `minmax(0, 1fr)` to the 5 inline `gridTemplateColumns: '1fr 1fr'` instances in MarketplaceTab/MembershipTab/MyStrategiesTab. Prevents overflow when content gets long.
|
||||
3. Convert `<Button>` to native `<button>` in any Button that has 2+ block children inside (audit needed).
|
||||
|
||||
### Short-term (1 week)
|
||||
|
||||
4. **ESLint rules** (preventive):
|
||||
- `tailwindcss/no-custom-classname` to catch inline arbitrary widths like `w-[80px]`
|
||||
- Custom rule: `truncate` requires `title` (catches Pattern E)
|
||||
- Custom rule: flag `gridTemplateColumns` containing bare `1fr` without `minmax`
|
||||
- Custom rule: warn on inline `style` blocks with > 5 properties (encourage class extraction)
|
||||
5. **CSS audit:** scan `index.css` for class names with multiple definitions; consolidate. Aim to reduce `!important` count from 122 → < 60.
|
||||
|
||||
### Medium-term (2-3 weeks)
|
||||
|
||||
6. **Refactor OverviewTab + HomeView** to extract inline styles into a `home.css` / `overview.css` partial. Highest user impact (these are the landing pages).
|
||||
7. **Component primitives audit:** the `<Button>` overlap issue suggests `@bytelyst/ui` Button needs a documented prop for stacked children, or a separate `<CardButton>` primitive. Worth a discussion with the design system team.
|
||||
|
||||
---
|
||||
|
||||
## 6. Quick verification commands
|
||||
|
||||
```bash
|
||||
# Check current state
|
||||
cd /opt/bytelyst/learning_ai_invt_trdg/web/src
|
||||
|
||||
# Truncate without title
|
||||
grep -rn "truncate\b" --include='*.tsx' | grep -v test | grep -v "title=" | wc -l
|
||||
|
||||
# Inline style blocks per file (drift indicator)
|
||||
for f in $(grep -rln "style={{" --include='*.tsx' | grep -v test); do
|
||||
count=$(grep -c "style={{" "$f")
|
||||
[ "$count" -gt 20 ] && echo "$count $f"
|
||||
done | sort -rn
|
||||
|
||||
# !important count
|
||||
grep -c "!important" index.css
|
||||
|
||||
# Hardcoded pixel widths in JSX
|
||||
grep -rEn "(width|minWidth|maxWidth):\s*[0-9]+(px)?[,$]" --include='*.tsx' | grep -v test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Files changed in recent UI fix sweep
|
||||
|
||||
- `web/src/layout-fixes.css` (new, 495 lines) — all global UI overrides centralized
|
||||
- `web/src/main.tsx` — imports layout-fixes.css
|
||||
- `web/src/App.tsx` — refactored alert banner JSX
|
||||
- `web/src/components/ChatControl.tsx` — refactored Quick Actions
|
||||
- `web/src/components/layout/AppShell.tsx` — added /devops redirect
|
||||
|
||||
The single-file approach (`layout-fixes.css`) is intentional: every global UI fix lands there with a numbered section + comment explaining the issue. Easy to review, easy to revert one section without touching others.
|
||||
Loading…
Reference in New Issue
Block a user