feat(THI-52): modernize results tab - #22
Merged
tdody merged 1 commit intoApr 19, 2026
Merged
Conversation
Rebuild the Results tab around the THI-45/46 design system, introducing
two new shared primitives and restyling every section around tokens.
New primitives
- shared/SensitivityCard.tsx: labeled card wrapping an SVG line chart with
accent stroke, token-colored axes, and zero line. Takes an array of
{label,value} points plus an optional $ | % yLabel.
- shared/ExpenseBreakdown.tsx: stacked horizontal bar + legend. Sorts the
breakdown descending, assigns distinct oklch colors per slice, and shows
each category's $ amount and percentage in the legend.
Headline
- 3-cell MetricStrip at top: Annual Cashflow (emphasis=large serif),
IRR (from irr_with_exit when available, else projections' operating IRR),
Break-even Occupancy with warn tone above 70%
- Secondary 4-cell strip: Cash-on-Cash, Cap Rate, DSCR, NOI
- Tertiary strip: Gross Yield, Year-1 ROI, optional ROI-w-appreciation or
After-Tax Monthly, Guest Cost per Night
10-year projection table with inline bars
- ProjectionTable component: each row's Cashflow cell now includes a thin
horizontal bar below the value, width proportional to |value| / max,
colored accent (positive) or negative. Table preserves every existing
column (Gross / NOI / Cashflow / Cum CF / CoC / Value / Balance / Equity
/ After-tax).
Sensitivity
- STR occupancy + rate sweeps now render as two <SensitivityCard> side by
side. LTR sensitivity (vacancy + rent) in the comparison section uses
the same primitive. Hold-period IRR sweep uses SensitivityCard with
yLabel="%".
Expense breakdown
- STR and LTR expense sections use <ExpenseBreakdown> for a stacked bar +
legend view, paired with a compact housing-costs mini-table on the right.
Other modernization
- Replaced every MetricCard usage with MetricCell / MetricStrip
- Warnings (DSCR, occupancy, rental delay) become token-based
WarnBanner / InfoBanner helpers (internal to the file)
- Collapsible sections (tax analysis, monthly cashflow, projections + exit,
amortization, STR/LTR comparison) consolidated into a shared Disclosure
helper with caret + serif title
- MonthlyCashflowChart rewritten to use accent / negative / rule-strong
tokens and JetBrains Mono axis labels
- Scenario selector now uses the same bottom-rule select style as the
Financing tab's loan-type picker, plus a RentalBadge-style caps pill
- All indigo / violet / sky / emerald / amber / red / slate classes removed
Preserved behavior
- All data-fetching logic unchanged (getResults / getResultsForScenario /
getLTRResults / getSensitivity / getLTRSensitivity / getAmortization /
getProjections / getMonthlyBreakdown) with identical loading flow
- Scenario selector, STR ↔ LTR comparison, monthly breakdown, exit analysis,
hold-period sweep, amortization, depreciation, tax analysis all still
present and fetched on-demand via collapsibles
- Prop interface for ResultsTab unchanged
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Rebuilds the Results tab (1400 → 2088 lines, most of the growth from splitting the monolith into named helper components) around the THI-45/46 design system. Introduces two new shared primitives and restyles every section around tokens.
New primitives
shared/SensitivityCard.tsx— labeled card wrapping an SVG line chart with accent stroke, token-colored axes, dashed zero line. Takes{label,value}[]plus optionalyLabel: "$" | "%".shared/ExpenseBreakdown.tsx— stacked horizontal bar + legend. Sorts breakdown descending, assigns distinct oklch colors per slice, shows each category's $ and % in the legend.Headline strip (3-col)
Per the ticket: Annual Cashflow (emphasis=large serif), IRR (from
irr_with_exitwhen projections are loaded, else projections' operating IRR), Break-even Occupancy withwarntone above 70%. Followed by two secondary strips covering Cash-on-Cash, Cap Rate, DSCR, NOI, Gross Yield, Year-1 ROI, After-Tax Monthly, Guest Cost per Night.10-year projection table with inline bars
ProjectionTablehelper — each row's Cashflow cell now renders a thin horizontal bar below the value, width proportional to|value| / max, coloredaccentfor positive andnegativefor negative. All existing columns preserved (Gross / NOI / Cashflow / Cum CF / CoC / Value / Balance / Equity / After-tax).Sensitivity
<SensitivityCard>in a 2-col gridSensitivityCardwithyLabel="%"Expense breakdown
STR and LTR expense sections now use
<ExpenseBreakdown>for a stacked bar + legend, paired with a compact housing-costs mini-table on the right.Other modernization
MetricCardusage →MetricCell/MetricStripWarnBanner/InfoBannerhelpers usingwarn/accenttokensDisclosurehelper with caret + serif titleMonthlyCashflowChartrewritten to use token colors and JetBrains Mono axis labelsPreserved behavior
getResults/getResultsForScenario/getLTRResults/getSensitivity/getLTRSensitivity/getAmortization/getProjections/getMonthlyBreakdown)ResultsTabprop interface unchangedTest plan
npm run lint— cleannpm run build— passes, CSS 52.09 kB, JS 454.97 kB (-9 kB), 118 modules🤖 Generated with Claude Code