Advisor Portal · Jul – Nov 2026
Page-level design fixes across the advisor portal — book-of-business lists, Client 360 (overview, accounts, margin, meeting prep, Shariah), Portfolio 360, trading, bulk orders and opportunities. Every change is scoped to the advisor-portal app — no design-system (dionysus-ui) package changes.
| PR | Scope | Status |
|---|---|---|
| #747 ↗ | Clients list | ✓ Merged27 Jul 2026 |
| #752 ↗ | Portfolios & Accounts lists | ✓ Merged27 Jul 2026 |
| #887 ↗ | Client 360 — detail page | ✓ Merged30 Jul 2026 |
| #1758 ↗ | Client 360 — Accounts tab | ✓ Merged7 Oct 2026 |
| #1777 ↗ | Advisor Home — My tasks | ✓ Merged7 Oct 2026 |
| #1788 ↗ | Portfolio 360 | ✓ Merged8 Oct 2026 |
| #1809 ↗ | Client 360 — Margin (cash breakdown) | ✓ Merged8 Oct 2026 |
| #1807 ↗ | Client 360 — Margin (cards) | ✓ Merged9 Oct 2026 |
| #1811 ↗ | Client 360 — Margin (facility bar) | ✓ Merged9 Oct 2026 |
| #1825 ↗ | Client 360 — Overview (Portfolios card) | ✓ Merged9 Oct 2026 |
| #1826 ↗ | Tab strips — tenant colour | ✓ Merged11 Oct 2026 |
| #1868 ↗ | Client 360 — Meeting briefing drawer | ✓ Merged12 Oct 2026 |
| #1882 ↗ | Portfolio 360 — Overview | ✓ Merged12 Oct 2026 |
| #1885 ↗ | Client 360 — Overview (metrics, facility tag) | ✓ Merged12 Oct 2026 |
| #1957 ↗ | Trading — order hub & drawer | ✓ Merged16 Oct 2026 |
| #1964 ↗ | Bulk orders — send button | ✓ Merged19 Oct 2026 |
| #1993 ↗ | Bulk orders — portfolios table | ✓ Merged22 Oct 2026 |
| #2011 ↗ | Bulk orders — security search | ✓ Merged22 Oct 2026 |
| #2039 ↗ | Opportunities | ✓ Merged27 Oct 2026 |
| #2083 ↗ | Client 360 — Zakat (first pass) | ✓ Mergedinto the #2079 branch · 27 Oct 2026 — ships with #2099 |
| #2079 ↗ | Client 360 — Shariah purification | ✓ Merged1 Nov 2026 |
| #2099 ↗ | Client 360 — Zakat | ● Openin review · opened 28 Oct 2026 |
| Fix | Detail |
|---|---|
| Download control removed | The Home My tasks card passes hasExportControl={false}, so no download renders; the full Tasks page and the embedded client/account lists keep export (prop defaults to true). |
| Fix | Detail |
|---|---|
| Single-line headers | whitespace-nowrap — no header wraps to 2 lines |
| Client column | Fixed 172px width with text-wrapping |
| Sort / info icons | Normalized to 16×16 box, 12×12 glyph, 8px gap to label |
| Tasks badge | 24×24 background |
| Grey task badge | Normal (non-red) counts get a grey badge, same 24×24; white on row hover |
| Assisted tag | 56×20, 10px font, turns white on row hover |
| Table fit | Trimmed cell padding so the table fits with no horizontal scroll; symmetric left/right margins |
| Sticky header | z-index lifted above the row-actions icon |
| Overflow (⋯) menu | 14px items, fit-content width, symmetric spacing, offset tightened to the icon |
| Tooltip | Placement moved to bottom |
| Text color | Confirmed text-secondary token for table text |
| Sidebar | Logo 16px start margin |
| Fix | Detail |
|---|---|
| Single-line headers | whitespace-nowrap |
| Sort / info icons | 16×16 box, 12×12 glyph, 8px gap (matches Clients) |
| Tasks tooltip dimming | Removed sortField/sortDisabled so the info icon no longer inherits the sort button's 50% opacity |
| Overflow (⋯) menu | fit-content, 14px, symmetric spacing |
| Export / download control | Removed |
| Filter toolbar | Left spacing aligned to Clients |
| Sticky header | z-index above body rows |
| Fix | Detail |
|---|---|
| Single-line headers | whitespace-nowrap (without touching the horizontal scroll) |
| Sort / info icons | 16×16 box, 12×12 glyph, 8px gap |
| Overflow (⋯) menu | fit-content, 14px, symmetric spacing |
| Export / download control | Removed |
| Filter toolbar | Left spacing aligned |
| ★ Pinned actions column | ⋯ column stays fixed while the rest scrolls horizontally (dionysus sticky: "right") |
| Pinned column shadow | Soft edge gradient following the common data-table pattern (Ant Design / TanStack / MUI), not a hard box-shadow |
| Sticky header | z-index above the pinned column |
| Fix | Detail |
|---|---|
| Header tabs — full width | The tab bar was inset and clipped ~12px on each side (shared HeaderTabs -mx-3 + overflow-x); expanded it to span the full content width, matching the header above it. Sticky-on-scroll preserved. |
| Tooltips — width & wrap | Info tooltips now hug their content (width: max-content) up to a 360px cap with text wrapping — short tooltips collapse to a single full line (no lonely trailing word / right-hand gap), long ones wrap. Were ~587px wide & unwrapped; follows shadcn / Radix / MUI guidance |
| Tooltips — z-index | Raised z-index 10 → 60 so tooltips sit above the sticky tab bar / adjacent cards (were rendering behind) |
| Client metrics — alignment | Reserved two label lines so every value lands on one baseline (wrapping labels no longer stagger their values). Fonts & colours unchanged. |
| Client metrics — title gap | Band keeps its left/right inset, but the extra 16px top margin was removed so the title-to-band gap now matches the standard cards (20px, same as Key metrics) |
| Client metrics — empty-chart spacing | Collapsed the empty chart placeholder (:empty) so the gap below the band matches the 16px above; real charts keep their padding |
| Client metrics — vertical padding | Added top & bottom padding inside the grey band so the metrics row isn't flush to the band edges (content sits ~14px off top/bottom) |
| Client metrics — divider | Aligned the section divider to the inset band (was a full-width rule crossing under an inset band) |
| Client metrics — text size | Reduced label & value text −2px (16 → 14px) for a tighter row; colours unchanged |
| Key metrics — sub-row spacing | Set the gap between each sub-metric label and its value to 8px (Unrealized / Realized P/L) — were pushed apart by justify-between |
| ★ Quick actions — compact menu | Overrode the fixed 240px list width so it hugs content (~176px) and shrank rows from 36 → 32px (16 → 14px text, tighter padding) to match the compact action menus elsewhere |
| ★ Quick actions — chevron state | The custom trigger's chevron was static; now rotates 180° when open (driven by aria-expanded, smooth transition), matching the other header dropdowns |
| Client info — value alignment | An empty field value (e.g. no Client ID) collapsed to 0 height and pulled the whole value column up, so values no longer lined up with their labels. Reserve one line per value cell so every row stays aligned — robust to any empty field |
| Client info — balanced groups | The two field groups were content-sized, so the left (short values) came out much narrower than the right (long email). Split the leftover width so the two halves read balanced |
| ★ Copy button — click effect | The dionysus button's press-glow (::before inset -4px + 12px shadow) bloomed left over the email on click. Dropped the glow pseudo-elements (kept the active:scale feedback) and set an 8px gap to the icon |
| ★ Header tabs — underline | Non-selected tabs each carried a grey underline and the row a grey baseline; removed both so only the active tab shows its indicator. Also removed a stray 1px vertical scrollbar on the tablist |
| Header tabs — active indicator | Active tab underline set to 3px teal (design-system text-text-subtle confirmed for the non-active labels) |
| ★ Period dropdown — width & selected | List shipped a fixed 240px; now hugs content. The current value wasn't marked — the selected option is now highlighted (surface-selected tint) |
| ★ Period dropdown — chevron & hover | Chevron now rotates while open (all .button-dropdown triggers). Item hover paired a light background with white text (unreadable) — hover text is now dark; disabled options get no hover highlight |
| Key metrics — label / value gap | Added 8px between each metric label and its number (were flush) so they read as two distinct lines |
| Client metrics — tab labels | Tightened the label leading (loose 24px → 20px) and wrap long titles onto two lines (e.g. "Total relationship / value"); short labels stay one line |
| Fix | Detail | PR |
|---|---|---|
| Client metrics moved up | The Client metrics chart is now second, before the Portfolios card (which used to sit between the bridge and the trajectory). | #1825 |
| "See all" in the header | The Portfolios card uses the overview card header (border-0 px-4 py-5) with the tab link beside the title — it was in the footer. | #1825 |
| Muted label band | Headers alpheya-label-sm text-text-tertiary (12px) → alpheya-label-md on bg-surface-gray-subtle, matching the margin accounts table. | #1825 |
| Figures without monospace | font-mono 12px → alpheya-numerics-md tabular-nums. | #1825 |
| Footer at body size | text-xs "Top 2 of 9 · See all" → alpheya-body-text-md "Top 2 of 9". | #1825 |
| Whole row clickable | Clicking anywhere on a row opens that portfolio through the number's own link — one navigation. | #1825 |
| Net assets in the title | The single-tab ChartSelector is dropped; Net assets shows as a figure at the end of the card title in a subtle panel, with the value-history chart below. | #1885 |
| Failed read shows a dash | A failed live read shows "–" (not 0) and hides the chart, with no error panel. | #1885 |
| Indicative tag right-aligned | The facility card's "indicative" tag moves to the inline-end of the heading row, opposite the title. | #1885 |
| Fix | Detail |
|---|---|
| Download control removed | The Accounts tab no longer passes the table export prop; other Client 360 tabs and the Closed Accounts page keep export. |
| Column headers wrap | Column headers now wrap to two lines. |
| Valuation note as a callout | The valuation note becomes an info-styled callout. |
| Filter row aligned | The filter row now aligns with the table. |
| Balance label copy | "Account value/balance" → "Account balance" / "رصيد الحساب" (en + ar), wherever those labels render. |
| Fix | Detail | PR |
|---|---|---|
| Header inset 32 → 16px | Both cards share a new MarginCard wrapper with the Client 360 card chrome: header px-4 (was 32px), body p-4, the standard card title. | #1807 |
| Equal-height cards | The grid uses items-stretch and the cards h-full, so both cards are the same height. | #1807 |
| Tinted hero panel | Hero rows sit on a LedgerHero panel (bg-surface-gray-subtle, rounded-lg); values alpheya-numerics-lg → alpheya-metrics-sm, labels alpheya-body-text-lg. | #1807 |
| Ledger rows 12px → body | Rows alpheya-body-text-sm/numerics-sm (12px) → alpheya-body-text-md/alpheya-numerics-md. | #1807 |
| Matching bar thickness | The balance card's "Margin used" bar now matches the facility bar — it was half as thick. | #1807 |
| Breakdown open by default | The cash-account breakdown starts expanded and still folds on request. | #1809 |
| Scrolling table | A fixed 5-column table in 520px let amounts overlap; now an overflow-auto max-h-96 scroller with a w-full min-w-max table and no-wrap cells, scrolling on both axes. | #1809 |
| Sticky header | Sticky top, bg-surface-gray-subtle, label-md, 40px tall. | #1809 |
| Pinned account column | The account cell (number over type) stays pinned at inline-start while scrolling. | #1809 |
| Right-aligned numerics | Cells use numerics-md, px-4 py-3 and hairline dividers; rows measure 53px. | #1809 |
| Sticky total row | The tfoot is sticky at the bottom, medium weight on bg-background, repeating the card totals. | #1809 |
| Segment tooltip on hover | Each facility bar band shows label, amount and share of drawing power — e.g. "Drawn / $32,000,000.00 · 15.20%". | #1811 |
| Indicative bar tooltip | With no active facility, the single bar reads "Drawing power / $210,470,000.00 · 34.34%". | #1811 |
| Bar stops clipping | The container no longer clips the tooltip; first and last bands round their own ends; height and colours unchanged. | #1811 |
| Zero-share bands hidden | A band is not drawn when its share is 0 or rounds to 0.00%. | #1811 |
| Fix | Detail |
|---|---|
| Drawer title weight | alpheya-headline-sm font-normal 24/28 light → alpheya-title-lg 24/28 medium. |
| Section titles 12 → 16px | Section titles and the loading/timeout/empty headings: body-text-sm font-bold 12/16 → alpheya-title-md 16/24. |
| Body copy 12 → 14px | Snapshot, bullets, talking points, descriptions and error rows: body-text-sm 12/16 → body-text-md 14/20. |
| Internal-note callout | Text 12 → 14px, padding 12 → 16px; the warning icon changes from dark to text-text-error red. |
| Field labels | alpheya-body-text-sm → alpheya-label-md. |
| Hints 10 → 12px | Hints, date errors and the window caption: body-text-xs 10/14 → body-text-sm 12/16; all spacing now on the DS 4px grid. |
| Fix | Detail |
|---|---|
| One summary card | Four bordered KPI tiles → one CardV2: the lead purification amount plus three divided rows (needing attention, awaiting approval, paid to charity). |
| DS stacked bar chart | StackedBarChartNew replaces the axis-less hand-built chart — 0–1,200 axis, gridlines, Jan–Sep labels, Paid/Approved/Calculated/Pending legend; the tooltip shows each status plus the month total. |
| Line tabs for the view switch | Pill SegmentedControls → TabsV2 variant="line" (Distribution events / By holding). |
| Filter chips with dots | The "(count)" buttons become ButtonV2 chips with a series dot and count, e.g. "Calculated 2". |
| Status badges with dots | BadgeV2 with a leading series-coloured dot. |
| Sample-data note softened | The bold outline "Illustrative sample data" badge becomes a subtle Info-icon note. |
| Tokens + one-line header | The dead alpheya-body-sm class is replaced with alpheya-body-text-*, alpheya-numerics-* and data-visualisation-* tokens; "Gross received" stays on one line. |
| Fix | Detail |
|---|---|
| Zakat-due calculation card | One CardV2 leads with the Zakat-due amount and an Estimate dot badge (the left column used to lead with the hawl date). |
| Vertical waterfall | zakatable → − liabilities → = net base → × rate, with operator chips (was horizontal). |
| Hawl progress bar | At the card foot with a bg-interaction-color-primary-bg fill. |
| Supporting cards | Consolidation (accounts + declared external assets), the breakdown and the Zakat history each sit in their own CardV2, with CheckboxV2 inclusion rows. |
| Tables on DS DataTable | Breakdown and history (previously a raw <table>) use the DS DataTable with one-line headers. |
| Status dot badges | BadgeV2 dots — Estimate → data-visualisation-orange-02, Paid → data-visualisation-green; dead alpheya-body-sm/xs → alpheya-body-text-sm/xs. |
| Fix | Detail | PR |
|---|---|---|
| Tab strip to the page edge | Runs to the inline-end page edge (RTL-safe -me-6); the first tab stays aligned with the content and the white band is gone. | #1788 |
| Accounts widget — no download | Download control removed from the Overview Accounts widget. | #1788 |
| Accounts widget — single scroll | Nested card-body and table-wrapper scrollbars collapse into one vertical scroll. | #1788 |
| Bridge operators inline | +/−/= sit inline on the figure baseline with tight spacing (were separate centred items ~12px away). | #1788 |
| Bridge row padding | Figure row padding py-4 → py-8. | #1788 |
| Allocation card tidy | Download removed; the drift figure is text-text-secondary (was the blue data-viz colour); value column right-aligned. | #1788 |
| Portfolio history as a standard card | The live net value becomes a figure on the period-selector row instead of a tab; the two stacked plots share one width. | #1882 |
| Period pill in tenant colour | The selected period pill uses the tenant primary — a shared selector, so history, income & expense and P&L breakdown all follow. | #1882 |
| Income & expense hero tiles | Two side-by-side hero figures on subtle tiles; the trading-fees row loses its leading accent border. | #1882 |
| Header dividers restored | Income & expense and Key metrics get the DS header divider back (opt-in showHeaderDivider). | #1882 |
| Relevant news spacing | Controls sit below the header with standard p-4 spacing. | #1882 |
| Top 5 holdings type | Uses the DS type scale, with "See all" in the card footer. | #1882 |
| Allocation after Top 5 | The Holdings allocation card is ordered directly after Top 5 holdings. | #1882 |
| Fix | Detail |
|---|---|
| Create order icon, centred | A leading Plus icon (h-4 w-4) matches the Order-book CTA; the button is centred in the header. |
| Hub margins match the gutter | p-4 space-y-6 → space-y-6, so the cards align to the dashboard gutter. |
| Download controls removed | Accounts, Holdings, Recent Orders and the drawer's Executions tables drop export. |
| Hover only on clickable rows | Row hover removed from Accounts and Holdings; kept on Recent Orders, whose rows open the drawer. |
| Recent Orders ID & headers | The Order ID sits flush-left (OMS live-status indicator dropped); headers use whitespace-nowrap. |
| Drawer Order ID size | alpheya-body-text-lg → alpheya-body-text-sm (12px caption). |
| Reference-code card on one line | Label, code and copy control sit in one wrapping row — shared, so every error panel and the error modal follow. |
| Fix | Detail | PR |
|---|---|---|
| Send button copy | "Send block order" → "Send bulk order", matching the "Bulk order" title and the Arabic. | #1964 |
| Header matches DS DataTable | alpheya-label-md text-text-secondary px-4 py-3 → bg-muted (#F2F6F9) alpheya-label-lg text-foreground p-3 h-12 (48px). | #1993 |
| Rows 56px, middle-aligned | px-4 py-3 align-top → p-3 h-14 (56px), aligned to the middle. | #1993 |
| Row dividers | border-separate + border-t border-border-subtle → border-collapse + border-b border-border. | #1993 |
| Numeric figures | tabular-nums → alpheya-numerics-md. | #1993 |
| Search dropdown overlays the field | The panel is now absolute inset-x-0 top-full z-30 w-full — the old in-flow w-3/4 min-w-[424px] reflowed the filter bar and spilled over the Side control; the order-ticket modal is unchanged. | #2011 |
| Fix | Detail |
|---|---|
| Long references truncate | Long reference numbers (e.g. portfolio_<uuid>) truncate to one line in the table and the drawer via the shared OpportunityReferenceNumber — they used to overflow and wrap. |
| Full value on hover | A native title shows the full value; a missing reference shows the empty-state placeholder. |
| Linked-to cell constrained | min-w-0 keeps content inside the column; short KFH-UHNW-* ids show in full. |
| Co-owner count stays visible | (+N) sits in its own non-shrinking span when a long primary name truncates, and is added to the hover title. |
| Fix | Detail |
|---|---|
| Selected tab in tenant colour | The selected-tab underline uses the tenant's primary interaction colour instead of DS teal — tab bottom border, status-strip underline and the TabsV2 indicator. |
| 3:1 contrast fallback | Uses the first of primary/hover/pressed with ≥3:1 on white and on the page background — KFH primary #AA9F8C (2.61:1) yields to hover #887F70 (3.95:1). |
| DS default when none pass | Tenants with no primary, or all shades below 3:1, keep the DS underline; focus rings, the progress bar and the spinner keep the DS highlight. |