fix(web): trade plans page — clipped chips, action buttons, cramped layout
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>
This commit is contained in:
parent
f463ff64de
commit
46a357c0f1
@ -7,143 +7,230 @@
|
|||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* 1. Don't clip popovers / modals / dropdowns to the main area.
|
* 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 {
|
.dashboard-main { overflow: visible !important; }
|
||||||
overflow: visible !important;
|
.dashboard-content-row { overflow: visible !important; }
|
||||||
}
|
.dashboard-content { overflow-x: clip; }
|
||||||
|
|
||||||
.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.
|
* 2. Right panel — collapses on narrow 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) {
|
@media (max-width: 1279px) {
|
||||||
.dashboard-right-panel,
|
.dashboard-right-panel,
|
||||||
.right-panel {
|
.right-panel { width: 260px; min-width: 260px; max-width: 260px; }
|
||||||
width: 260px;
|
|
||||||
min-width: 260px;
|
|
||||||
max-width: 260px;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1023px) {
|
@media (max-width: 1023px) {
|
||||||
.dashboard-right-panel,
|
.dashboard-right-panel,
|
||||||
.right-panel {
|
.right-panel { display: none !important; }
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* 3. Tables and large grids must scroll within their own container.
|
* 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),
|
.dashboard-content table:not(.no-scroll-fix),
|
||||||
.scroll-x {
|
.scroll-x { display: block; max-width: 100%; overflow-x: auto; }
|
||||||
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) > thead,
|
||||||
.dashboard-content table:not(.no-scroll-fix) > tbody,
|
.dashboard-content table:not(.no-scroll-fix) > tbody,
|
||||||
.dashboard-content table:not(.no-scroll-fix) > tfoot {
|
.dashboard-content table:not(.no-scroll-fix) > tfoot { display: table-row-group; }
|
||||||
display: table-row-group;
|
.dashboard-content table:not(.no-scroll-fix) > thead { display: table-header-group; }
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-content table:not(.no-scroll-fix) > thead {
|
|
||||||
display: table-header-group;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* 4. Header should reflow on narrow viewports.
|
* 4. Header reflows 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 {
|
.trading-header { flex-wrap: wrap; row-gap: 8px; min-height: 56px; height: auto !important; }
|
||||||
flex-wrap: wrap;
|
.trading-header-search { flex: 1 1 240px; min-width: 0; max-width: 360px; }
|
||||||
row-gap: 8px;
|
.trading-header-indices { flex-wrap: wrap; row-gap: 6px; column-gap: 20px !important; }
|
||||||
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) {
|
@media (max-width: 760px) {
|
||||||
.trading-header-indices {
|
.trading-header-indices { column-gap: 14px !important; }
|
||||||
column-gap: 14px !important;
|
.trading-header-indices > div > div:first-child { font-size: 10px; }
|
||||||
}
|
|
||||||
.trading-header-indices > div > div:first-child {
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* 5. Sidebar collapse on narrow viewports.
|
* 5. Sidebar collapse on small 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) {
|
@media (max-width: 767px) {
|
||||||
:root {
|
:root { --trading-shell-sidebar-width: 56px; }
|
||||||
--trading-shell-sidebar-width: 56px;
|
.trading-sidebar { width: 56px; }
|
||||||
}
|
.dashboard-content { padding: 16px 16px 24px !important; }
|
||||||
.trading-sidebar {
|
|
||||||
width: 56px;
|
|
||||||
}
|
|
||||||
.dashboard-content {
|
|
||||||
padding: 16px 16px 24px !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* 6. Container guard — content never exceeds its column.
|
* 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,
|
||||||
.dashboard-content code,
|
.dashboard-content code,
|
||||||
.dashboard-content pre,
|
.dashboard-content pre,
|
||||||
.dashboard-content .ux-surface {
|
.dashboard-content .ux-surface { overflow-wrap: anywhere; word-break: break-word; }
|
||||||
overflow-wrap: anywhere;
|
.dashboard-content pre { white-space: pre-wrap; }
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-content pre {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* 7. Modal / dialog z-index baseline.
|
* 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"],
|
[role="dialog"],
|
||||||
.modal,
|
.modal,
|
||||||
[data-radix-popper-content-wrapper] {
|
[data-radix-popper-content-wrapper] { z-index: 100; }
|
||||||
z-index: 100;
|
|
||||||
|
/* ============================================================================
|
||||||
|
* TRADE PLANS PAGE — surgical fixes for clipped chips, action buttons, and
|
||||||
|
* cramped layout. Targets existing class names (saved-setup-*, trade-plans-*).
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
/* 8. Outer two-column grid: don't force a min 380px on the saved-setups column,
|
||||||
|
* which causes the form column to be too narrow on 1280–1440px screens. */
|
||||||
|
.trade-plans-page > .grid {
|
||||||
|
/* Use flexible columns: form gets ~58%, saved gets ~42% above 1440px;
|
||||||
|
stack at 1279px. */
|
||||||
|
grid-template-columns: minmax(0, 1fr) !important;
|
||||||
|
gap: 24px !important;
|
||||||
}
|
}
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
.trade-plans-page > .grid {
|
||||||
|
grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 9. Saved-setups card: NEVER clip children. Action button MUST be visible. */
|
||||||
|
.saved-setups-panel {
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saved-setup-card {
|
||||||
|
overflow: visible !important;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 10. Topline: title block + actions. On narrow widths, actions wrap below. */
|
||||||
|
.saved-setup-topline {
|
||||||
|
display: flex !important;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.saved-setup-title-block {
|
||||||
|
flex: 1 1 320px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.saved-setup-actions {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 11. Symbol heading + side badge wrap on narrow widths */
|
||||||
|
.saved-setup-asset-row {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px 10px;
|
||||||
|
}
|
||||||
|
.saved-setup-asset-row h3 {
|
||||||
|
word-break: break-word;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 12. Meta chips: REAL wrapping. The existing rule has nowrap + ellipsis +
|
||||||
|
max-width:100% which truncates each chip awkwardly. Fix it: */
|
||||||
|
.saved-setup-meta-grid {
|
||||||
|
display: flex !important;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.saved-setup-meta-grid span,
|
||||||
|
.saved-setup-meta-grid button {
|
||||||
|
max-width: 100% !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
text-overflow: clip !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
word-break: break-word;
|
||||||
|
line-height: 1.3 !important;
|
||||||
|
padding: 4px 10px !important;
|
||||||
|
min-height: 26px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 13. Trade-id badges: long IDs should not blow out the card */
|
||||||
|
.saved-setup-meta-grid .badge,
|
||||||
|
.saved-setup-card [class*="cursor-pointer"][class*="badge"] {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 14. Timeline progression: horizontal scroll if container too narrow */
|
||||||
|
.saved-setup-timeline {
|
||||||
|
min-width: 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 15. Form column: ensure it can shrink (avoid fixed-width form blowing out grid) */
|
||||||
|
.trade-plans-page form {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.trade-plans-page form section {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16. Setup-type buttons: equal heights, never overflow */
|
||||||
|
.trade-plans-page form section > .grid {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.trade-plans-page form section > .grid > button {
|
||||||
|
min-width: 0;
|
||||||
|
white-space: normal;
|
||||||
|
height: auto;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 17. Saved-setup card timeline children (the "Armed/Entry sent/Filled/..." pills)
|
||||||
|
should wrap on narrow widths */
|
||||||
|
.saved-setup-card .saved-setup-timeline > * {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 18. CRITICAL alert banner — soften (less harsh red, integrated look) */
|
||||||
|
.critical-alert-banner {
|
||||||
|
background: color-mix(in oklab, var(--card) 96%, var(--destructive)) !important;
|
||||||
|
color: var(--foreground) !important;
|
||||||
|
border-bottom: 1px solid color-mix(in oklab, var(--destructive) 18%, var(--border)) !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
letter-spacing: 0 !important;
|
||||||
|
text-transform: none !important;
|
||||||
|
font-size: 13px !important;
|
||||||
|
padding: 10px 18px !important;
|
||||||
|
}
|
||||||
|
.critical-alert-banner:hover {
|
||||||
|
background: color-mix(in oklab, var(--card) 92%, var(--destructive)) !important;
|
||||||
|
color: var(--foreground) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 19. Right-panel content — improve empty state contrast & spacing */
|
||||||
|
.right-panel-empty {
|
||||||
|
padding: 16px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
}
|
||||||
|
.right-panel-empty div + div {
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 20. Inputs and selects: ensure they don't push past their container */
|
||||||
|
.trade-plans-page input,
|
||||||
|
.trade-plans-page select,
|
||||||
|
.trade-plans-page textarea {
|
||||||
|
max-width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 21. Saved-setups header: count badge and title don't crowd each other */
|
||||||
|
.saved-setups-header {
|
||||||
|
display: flex !important;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.saved-setups-header > div { flex: 1 1 280px; min-width: 0; }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user