diff --git a/backend/package.json b/backend/package.json index 7a74f77..72eda2c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -77,7 +77,7 @@ "socket.io": "^4.8.3", "winston": "^3.19.0", "@bytelyst/telemetry-client": "*", - "@bytelyst/devops": "^0.1.2" + "@bytelyst/devops": "^0.1.3" }, "devDependencies": { "@types/node": "^25.0.3", diff --git a/web/package.json b/web/package.json index 8a090ec..97f72c4 100644 --- a/web/package.json +++ b/web/package.json @@ -42,7 +42,7 @@ "react-router-dom": "^7.14.2", "recharts": "^3.6.0", "socket.io-client": "^4.8.3", - "@bytelyst/devops": "^0.1.2" + "@bytelyst/devops": "^0.1.3" }, "devDependencies": { "@eslint/js": "^9.39.4", diff --git a/web/src/layout-fixes.css b/web/src/layout-fixes.css new file mode 100644 index 0000000..865d00a --- /dev/null +++ b/web/src/layout-fixes.css @@ -0,0 +1,149 @@ +/* ============================================================================ + * Layout fixes — global overrides for known overflow / responsiveness issues. + * + * Applied as a separate file so individual fixes are easy to review and revert. + * Imported once from main.tsx after the main index.css. + * ============================================================================ */ + +/* -------------------------------------------------------------------------- + * 1. Don't clip popovers / modals / dropdowns to the main area. + * Allow horizontal clipping (prevents accidental page-wide scroll) but + * keep vertical visible so absolute-positioned UI escapes the row. + * -------------------------------------------------------------------------- */ +.dashboard-main { + overflow: visible !important; +} + +.dashboard-content-row { + overflow: visible !important; +} + +.dashboard-content { + /* Vertical scroll stays. Horizontal overflow becomes a child concern, + not a layout-level concern, so wide tables can scroll inside their + own container instead of being silently clipped. */ + overflow-x: clip; +} + +/* -------------------------------------------------------------------------- + * 2. Collapse the right panel on narrower viewports. + * 308px is too greedy below ~1280px and steals critical content width. + * Below 1024px it's hidden entirely (mobile/tablet view). + * -------------------------------------------------------------------------- */ +@media (max-width: 1279px) { + .dashboard-right-panel, + .right-panel { + width: 260px; + min-width: 260px; + max-width: 260px; + } +} + +@media (max-width: 1023px) { + .dashboard-right-panel, + .right-panel { + display: none !important; + } +} + +/* -------------------------------------------------------------------------- + * 3. Tables and large grids must scroll within their own container. + * Any table that's a direct child of dashboard-content should never + * push the layout horizontally — wrap consumers can opt-in via + * .scroll-x to the same behavior. + * -------------------------------------------------------------------------- */ +.dashboard-content table:not(.no-scroll-fix), +.scroll-x { + display: block; + max-width: 100%; + overflow-x: auto; +} + +/* Preserve table semantics inside the scroll container */ +.dashboard-content table:not(.no-scroll-fix) > thead, +.dashboard-content table:not(.no-scroll-fix) > tbody, +.dashboard-content table:not(.no-scroll-fix) > tfoot { + display: table-row-group; +} + +.dashboard-content table:not(.no-scroll-fix) > thead { + display: table-header-group; +} + +/* -------------------------------------------------------------------------- + * 4. Header should reflow on narrow viewports. + * The fixed 300px search and three indices push each other off-screen + * on laptop widths (~1366px) once the right panel is also showing. + * -------------------------------------------------------------------------- */ +.trading-header { + flex-wrap: wrap; + row-gap: 8px; + min-height: 56px; + height: auto !important; +} + +.trading-header-search { + flex: 1 1 240px; + min-width: 0; + max-width: 360px; +} + +.trading-header-indices { + flex-wrap: wrap; + row-gap: 6px; + column-gap: 20px !important; +} + +@media (max-width: 760px) { + .trading-header-indices { + column-gap: 14px !important; + } + .trading-header-indices > div > div:first-child { + font-size: 10px; + } +} + +/* -------------------------------------------------------------------------- + * 5. Sidebar collapse on narrow viewports. + * The fixed 76px sidebar plus margin-left compounds with content + * overflow on small windows. Below 768px we collapse it to 56px. + * -------------------------------------------------------------------------- */ +@media (max-width: 767px) { + :root { + --trading-shell-sidebar-width: 56px; + } + .trading-sidebar { + width: 56px; + } + .dashboard-content { + padding: 16px 16px 24px !important; + } +} + +/* -------------------------------------------------------------------------- + * 6. Container guard — content never exceeds its column. + * Long unbreakable strings (commit SHAs, URLs) that escape boxes are a + * common source of "elements pushed off-screen". This forces wrap. + * -------------------------------------------------------------------------- */ +.dashboard-content, +.dashboard-content code, +.dashboard-content pre, +.dashboard-content .ux-surface { + overflow-wrap: anywhere; + word-break: break-word; +} + +.dashboard-content pre { + white-space: pre-wrap; +} + +/* -------------------------------------------------------------------------- + * 7. Modal / dialog z-index baseline. + * Anything inside .dashboard-content-row that was clipped by the + * overflow:hidden fix in (1) now needs a stacking context guard. + * -------------------------------------------------------------------------- */ +[role="dialog"], +.modal, +[data-radix-popper-content-wrapper] { + z-index: 100; +} diff --git a/web/src/main.tsx b/web/src/main.tsx index 3610c97..94c2ea5 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -3,6 +3,7 @@ import { createRoot } from 'react-dom/client' import { Agentation } from 'agentation' import './index.css' import './App.css' +import './layout-fixes.css' import App from './App.tsx' import { AuthProvider } from './components/AuthContext'; import { ProductAccessibilityGate } from './components/ProductAccessibilityGate';