chart style and descripitons
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
'use client';
|
||||
|
||||
import { Line, LineChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card';
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
@@ -45,6 +52,9 @@ const generateData = () => {
|
||||
const data = generateData();
|
||||
|
||||
const chartConfig = {
|
||||
age: {
|
||||
label: 'Age',
|
||||
},
|
||||
Standard: {
|
||||
label: 'Standard Path',
|
||||
color: 'var(--chart-4)',
|
||||
@@ -75,16 +85,22 @@ export function CoastFireChart() {
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
tickMargin={8}
|
||||
tickFormatter={(value: number) => `$${String(value / 1000)}k`}
|
||||
tickFormatter={(value: number) => {
|
||||
if (value < 1000) {
|
||||
return `$${String(value)}`;
|
||||
}
|
||||
if (value < 1000000) {
|
||||
return `$${String(value / 1000)}k`;
|
||||
}
|
||||
if (value < 1000000000) {
|
||||
return `$${String(value / 1000000)}M`;
|
||||
}
|
||||
return `$${String(value / 1000000000)}B`;
|
||||
}}
|
||||
/>
|
||||
<ChartTooltip
|
||||
cursor={false}
|
||||
content={
|
||||
<ChartTooltipContent
|
||||
labelFormatter={(value) => `Age ${String(value)}`}
|
||||
indicator="line"
|
||||
/>
|
||||
}
|
||||
content={<ChartTooltipContent indicator="line" labelKey="age" />}
|
||||
/>
|
||||
<Line
|
||||
dataKey="Standard"
|
||||
@@ -103,6 +119,12 @@ export function CoastFireChart() {
|
||||
<ChartLegend content={<ChartLegendContent />} />
|
||||
</LineChart>
|
||||
</ChartContainer>
|
||||
<CardFooter>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Simulation assumes 7% returns. Standard: Save $10k/yr (age 25-65). Coast: Save $30k/yr (age
|
||||
25-35), then $0.
|
||||
</p>
|
||||
</CardFooter>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
'use client';
|
||||
|
||||
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card';
|
||||
import {
|
||||
ChartContainer,
|
||||
ChartLegend,
|
||||
@@ -96,6 +103,15 @@ export function FourPercentRuleChart() {
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<div>
|
||||
<p className="font-medium">4% balances safety and spending power</p>
|
||||
<p className="text-muted-foreground leading-none">
|
||||
A 5% withdrawal rate risks depleting your portfolio within 30 years, while 3% leaves a large
|
||||
surplus. The 4% rule is widely considered the safe "sweet spot."
|
||||
</p>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ export default function CoastVsLeanPage() {
|
||||
discipline.
|
||||
</p>
|
||||
|
||||
<Separator className="my-12" />
|
||||
<Separator className="my-16" />
|
||||
|
||||
<h2>Run The Numbers</h2>
|
||||
<p>The best way to decide is to see the math. Use our calculator to simulate both scenarios:</p>
|
||||
|
||||
@@ -209,7 +209,7 @@ function ChartTooltipContent({
|
||||
<span className="text-muted-foreground">{itemConfig?.label ?? item.name}</span>
|
||||
</div>
|
||||
{item.value && (
|
||||
<span className="text-foreground font-mono font-medium tabular-nums">
|
||||
<span className="text-foreground pl-2 font-mono font-medium tabular-nums">
|
||||
{item.value.toLocaleString()}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
@import 'tailwindcss';
|
||||
@import 'tw-animate-css';
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme {
|
||||
--font-sans:
|
||||
var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
@@ -60,9 +60,7 @@
|
||||
--secondary: oklch(0.49 0.1326 259.29); /* denim */
|
||||
--secondary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||
--muted: oklch(0.67 0.0763 198.81 / 20%); /* verdigris with opacity */
|
||||
--muted-foreground: oklch(
|
||||
0.39 0.0215 96.47 / 80%
|
||||
); /* black olive with opacity */
|
||||
--muted-foreground: oklch(0.39 0.0215 96.47 / 80%); /* black olive with opacity */
|
||||
--accent: oklch(0.49 0.1326 259.29); /* denim */
|
||||
--accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||
--destructive: oklch(0.33 0.1316 336.24); /* palatinate */
|
||||
@@ -80,9 +78,7 @@
|
||||
--sidebar-primary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||
--sidebar-accent: oklch(0.49 0.1326 259.29); /* denim */
|
||||
--sidebar-accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||
--sidebar-border: oklch(
|
||||
0.67 0.0763 198.81 / 20%
|
||||
); /* verdigris with opacity */
|
||||
--sidebar-border: oklch(0.67 0.0763 198.81 / 20%); /* verdigris with opacity */
|
||||
--sidebar-ring: oklch(0.67 0.0763 198.81); /* verdigris */
|
||||
}
|
||||
|
||||
@@ -116,9 +112,7 @@
|
||||
--sidebar-primary-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||
--sidebar-accent: oklch(0.49 0.1326 259.29); /* denim */
|
||||
--sidebar-accent-foreground: oklch(0.97 0.0228 95.96); /* cosmic latte */
|
||||
--sidebar-border: oklch(
|
||||
0.97 0.0228 95.96 / 10%
|
||||
); /* cosmic latte with opacity */
|
||||
--sidebar-border: oklch(0.97 0.0228 95.96 / 10%); /* cosmic latte with opacity */
|
||||
--sidebar-ring: oklch(0.67 0.0763 198.81); /* verdigris */
|
||||
}
|
||||
|
||||
@@ -142,7 +136,7 @@
|
||||
@apply scroll-m-20 text-xl font-semibold tracking-tight;
|
||||
}
|
||||
p {
|
||||
@apply leading-7 [&:not(:first-child)]:mt-6;
|
||||
@apply mb-2 leading-7 [&:not(:first-child)]:mt-6;
|
||||
}
|
||||
blockquote {
|
||||
@apply mt-6 border-l-2 pl-6 italic;
|
||||
@@ -151,6 +145,6 @@
|
||||
@apply my-6 ml-6 list-disc [&>li]:mt-2;
|
||||
}
|
||||
code {
|
||||
@apply bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold
|
||||
@apply bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user