The Quick Actions in the AI Trading Copilot floating modal were broken:
- Always 2 columns regardless of viewport (cards overflowed at narrow widths).
- Used <Button> from primitives which is inline-flex internally; the two
inline-block <span> children for title and prompt overlapped.
- Prompt was truncated client-side with .slice(0, 55)+'...' instead of
proper CSS line-clamp, causing inconsistent display.
- No min-width: 0 on grid/card/text so content could push the card past
the modal width (460px).
Refactored:
- Replaced <Button> with native <button> (cleaner default styling base).
- New CSS classes copilot-quick-action-card, -title, -prompt with explicit
flex-direction: column so title and description stack reliably.
- Responsive grid: single column below 480px, 2 columns above. The modal
is 460px wide on desktop and shrinks to viewport-32 on smaller screens,
so this prevents card overflow on narrow phones.
- Title: single-line truncate with ellipsis, full text exposed via title
attribute on the button (tooltip + a11y).
- Prompt: -webkit-line-clamp: 2 (no JS slice). Wraps cleanly on long
prompts. word-break + overflow-wrap as guards.
- Card: min-height 64px so they align in a row without text-length
jumping. Hover, active, and focus-visible states for keyboard a11y.
- Body container gets bottom padding so the last card is reachable above
the composer input.
Container changes:
- .copilot-body class added to messages scroll container; bottom padding
ensures composer doesn't crowd content.
- The modal shell (existing) already uses display:flex; flex-direction:
column; overflow:hidden so header stays top, body scrolls, composer
stays bottom — preserved unchanged.
No breaking changes to chat behavior, sendMessage flow, or quick action
prompts.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Alert banner (top of every page when critical events exist):
- Refactored from a single anchor with inline spans into a structured
wrapper + inner row with a real CTA link.
- Inner row uses flex-wrap with max-width: 1280px container so the text
never overflows the viewport.
- Text takes flex: 1 1 auto with min-width: 0 + overflow-wrap: anywhere
so long messages wrap cleanly. CTA stays shrink-0 so "Go to Admin Panel"
is always visible.
- On viewports ≤560px the text wraps to its own row above the CTA.
- CTA links directly to /settings?section=Admin%20Panel (the URL the
Settings router actually consumes), not just /settings.
- Singular/plural ("issue" vs "issues") fixed for n=1.
- Softer styling: card+destructive color-mix instead of bright red,
no shadow, normal weight, no uppercase.
Sidebar logo / brand block (was clipped):
- Two competing CSS rules (one made it a 44×44 icon-only grid, the
other a 56px-tall flex row). The grid one was clipping the brand text.
Now an explicit flex row with min-height: 60px, gap: 12px.
- Icon: shrink-0 22×22.
- Brand wrapper: min-width: 0, two stacked lines with line-height: 1.2/1.3.
- "ByteLyst" and "Trading OS" never clip vertically; they ellipsis-truncate
if the sidebar is somehow constrained horizontally.
- Below 1279px (tablet sidebar): logo block recenters at 52px tall to fit
the icon-only narrow sidebar.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The Plans page (/plans) had multiple known overflow / clipping bugs:
1. .saved-setup-card { overflow: hidden } clipped the right-side action
buttons (Edit, Delete) on cards with long content.
2. .saved-setup-meta-grid chips used white-space: nowrap + overflow: hidden
+ text-overflow: ellipsis, which truncated each chip awkwardly instead
of wrapping. Long Trade ID and Order ID badges blew out the card.
3. .saved-setup-topline used a CSS Grid with auto column for actions, so
actions could push the title block off-screen at narrow widths.
4. .saved-setup-timeline used 5 fixed-min-width columns that caused
horizontal overflow on cards <440px wide.
5. The outer two-column grid forced minmax(380px, ...) on the saved-setups
column which squeezed the form on 1280–1440px screens.
6. The critical alert banner used a loud high-contrast red background and
uppercase letterspaced text — visually inconsistent with the rest of
the app.
Fixes applied in web/src/layout-fixes.css (extends existing layout fixes):
- saved-setup-card → overflow visible, never clip children.
- saved-setup-topline → flexbox with flex-wrap, title flexes to 320px
before actions wrap below to a new row.
- saved-setup-actions → flex-wrap with right-justified items.
- saved-setup-meta-grid chips → real wrapping (white-space: normal,
overflow visible, max-width 100%, line-height tightened, padding
expanded slightly for readability).
- Trade-id badges → break-all so long IDs wrap inside their pill.
- saved-setup-timeline → overflow-x: auto so progression scrolls
inside the card on narrow widths instead of pushing the layout.
- Outer grid → single column below 1440px, two-column 1.15fr/0.85fr
above. Form gets adequate width on common laptop sizes.
- Alert banner → soft tinted background using card+destructive mix,
normal weight, no uppercase, integrated with the app shell aesthetic.
- saved-setups-header, asset-row, form sections → flex-wrap + min-width: 0
so nothing forces horizontal scroll.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Adds web/src/layout-fixes.css imported once from main.tsx — surgical
overrides applied with !important so they win against the existing
3000+ line index.css without rewriting it.
Issues fixed:
1. Modals/popovers/dropdowns clipped by .dashboard-main { overflow: hidden }
→ now overflow: visible. Stacking context guard for [role=dialog].
2. Right panel (308px fixed) covers main content on laptop/tablet
→ 260px below 1280px, hidden below 1024px.
3. Tables extending off-screen
→ .dashboard-content table wrapped with display:block + overflow-x:auto
so they scroll inside their column. Also exposes .scroll-x utility.
4. Header search/indices push each other off-screen
→ flex-wrap on .trading-header, search shrinks to 240–360px range,
indices wrap with smaller column gap on narrow.
5. Long unbreakable strings (commit SHAs, URLs) escaping containers
→ overflow-wrap: anywhere + word-break: break-word + pre-wrap on <pre>.
6. Sidebar 76px doesn't collapse on mobile
→ 56px below 768px with reduced content padding.
Bumps @bytelyst/devops to ^0.1.3 (responsive panel) in backend + web.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The DevOps panel lives inside Settings, but typing /devops directly hit
the catch-all NotFoundView. Add a Navigate redirect so the shorthand URL
works.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Backend:
- /api/devops/info now requires admin role (was: any authenticated user).
Exposes env keys, dep checks, and socket counts — admin-only by design.
- New /api/devops/version (public, no auth) returns build SHA/branch/image
for ops/CI rollback verification.
- Dep checks: live ping for Cosmos (trading_users) and platform-service.
- Service version read dynamically via readServiceVersion(import.meta.url)
— no more hardcoded '0.1.0'.
- extra: socketIoConnections + tradingApiUrl for runtime debugging.
- saveCurrentUserProfile no longer accepts client-supplied role —
prevents drift with platform JWT (which is authoritative).
Web:
- DevOps tab is now admin-only (gated behind isAdmin like Bot Config and
Admin Panel). Both the section list and content render are guarded.
- Service version baked into bundle via Vite `define` (__WEB_SERVICE_VERSION__)
read from web/package.json — no more hardcoded VERSION constant.
- Bumps @bytelyst/devops dep to ^0.1.2.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Backend:
- Fix role drift: /api/me/profile now returns JWT role authoritatively (was reading
drifting role from trading_users). PATCH strips client-supplied role.
- Add /api/devops/info endpoint backed by @bytelyst/devops/server.
- Dockerfile: bake BYTELYST_COMMIT_SHA / BYTELYST_BUILT_AT / etc. as build args.
Web:
- Migrate from vendor/ + .pnpmfile.cjs to Gitea npm registry (consistency with backend).
- Replace file: refs in web/package.json with semver ranges resolved from Gitea.
- Drop vendor/bytelyst/* tree and .pnpmfile.cjs.
- Add DevOpsTab in Settings using @bytelyst/devops/ui (tabbed: Build/Runtime/Config/Deps/Raw).
- Vite alias: restrict @bytelyst/* catch-all to single-segment names so subpath
imports (@bytelyst/devops/ui) resolve via package exports map.
- Bake BYTELYST_* metadata into the bundle as VITE_BYTELYST_* env.
Generated with [Devin](https://cli.devin.ai/docs)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Installed Playwright and Storybook packages
- Created playwright.config.ts with viewport matrix and browser configurations
- Installed Playwright chromium browser
- Created e2e/viewport-matrix.spec.ts for viewport matrix testing
- Created e2e/horizontal-overflow.spec.ts for horizontal overflow testing
- Added test scripts to package.json (test:e2e, test:e2e:ui, test:e2e:viewport, test:e2e:overflow)
- Updated LAUNCH_READY_UI_UX_ROADMAP.md checklist with testing infrastructure status
- Replace .stat-chip with Badge in PresetMarketplace, BacktestTab, MembershipTab
- Replace .saved-setup-id-chip with Badge in SimpleView
- Replace .screener-sector-chip with Badge in ScreenerView
- Replace .health-pill with Badge in TradeProfileManager
- Remove CSS definitions for one-off classes from index.css
- All components now use shared Badge from product adapter
- Verify: audit:ui (0 findings), audit:ui:strict (0 findings), typecheck, build