learning_ai_invt_trdg/docs/ui/UI_AUDIT.md
Devin 3949062435 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>
2026-05-10 08:27:04 +00:00

13 KiB
Raw Blame History

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 5072 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 240360px, 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.

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,1578table-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:127gridTemplateColumns: '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,1832clamp(... 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-[80260px] 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 34 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)

  1. 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)
  2. 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)

  1. Refactor OverviewTab + HomeView to extract inline styles into a home.css / overview.css partial. Highest user impact (these are the landing pages).
  2. 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

# 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.