calc tooltips
This commit is contained in:
@@ -22,8 +22,24 @@ import {
|
|||||||
import { Slider } from '@/components/ui/slider';
|
import { Slider } from '@/components/ui/slider';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||||
import type { NameType, ValueType } from 'recharts/types/component/DefaultTooltipContent';
|
import type { NameType, ValueType } from 'recharts/types/component/DefaultTooltipContent';
|
||||||
import { Calculator, Percent } from 'lucide-react';
|
import { Calculator, Info, Percent } from 'lucide-react';
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||||
import BlurThing from './blur-thing';
|
import BlurThing from './blur-thing';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
// Helper component for info tooltips next to form labels
|
||||||
|
function InfoTooltip({ content }: Readonly<{ content: string }>) {
|
||||||
|
return (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger type="button" className="ml-1 inline-flex align-middle">
|
||||||
|
<Info className="text-muted-foreground hover:text-foreground h-3.5 w-3.5 transition-colors" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="top" className="max-w-xs">
|
||||||
|
{content}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Schema for form validation
|
// Schema for form validation
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
@@ -359,7 +375,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="startingCapital"
|
name="startingCapital"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Starting Capital</FormLabel>
|
<FormLabel>
|
||||||
|
Starting Capital
|
||||||
|
<InfoTooltip content="Your current invested savings or nest egg. This is the amount you have already saved and invested." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 10000"
|
placeholder="e.g., 10000"
|
||||||
@@ -384,7 +403,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="monthlySavings"
|
name="monthlySavings"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Monthly Savings</FormLabel>
|
<FormLabel>
|
||||||
|
Monthly Savings
|
||||||
|
<InfoTooltip content="The amount you invest each month. This is added to your portfolio during the accumulation phase." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 500"
|
placeholder="e.g., 500"
|
||||||
@@ -409,7 +431,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="currentAge"
|
name="currentAge"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Current Age</FormLabel>
|
<FormLabel>
|
||||||
|
Current Age
|
||||||
|
<InfoTooltip content="Your age today. This is used to calculate the timeline to retirement and beyond." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 30"
|
placeholder="e.g., 30"
|
||||||
@@ -434,7 +459,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="lifeExpectancy"
|
name="lifeExpectancy"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Life Expectancy (Age)</FormLabel>
|
<FormLabel>
|
||||||
|
Life Expectancy (Age)
|
||||||
|
<InfoTooltip content="Your estimated age of death for planning purposes. This determines how long your money needs to last." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 90"
|
placeholder="e.g., 90"
|
||||||
@@ -459,7 +487,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="cagr"
|
name="cagr"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Expected Annual Growth Rate (%)</FormLabel>
|
<FormLabel>
|
||||||
|
Expected Annual Growth Rate (%)
|
||||||
|
<InfoTooltip content="Average yearly investment return (CAGR). The VTI has historically returned ~7%." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 7"
|
placeholder="e.g., 7"
|
||||||
@@ -485,7 +516,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="inflationRate"
|
name="inflationRate"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Annual Inflation Rate (%)</FormLabel>
|
<FormLabel>
|
||||||
|
Annual Inflation Rate (%)
|
||||||
|
<InfoTooltip content="Expected yearly price increase. Historical average is ~2-3%. This adjusts your spending needs over time." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 2"
|
placeholder="e.g., 2"
|
||||||
@@ -511,7 +545,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="desiredMonthlyAllowance"
|
name="desiredMonthlyAllowance"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Desired Monthly Allowance (Today's Value)</FormLabel>
|
<FormLabel>
|
||||||
|
Monthly Allowance (Today's Value)
|
||||||
|
<InfoTooltip content="Your monthly spending needs in retirement, expressed in today's dollars. This will be adjusted for inflation each year." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 2000"
|
placeholder="e.g., 2000"
|
||||||
@@ -538,7 +575,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="retirementAge"
|
name="retirementAge"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Retirement Age: {field.value as number}</FormLabel>
|
<FormLabel>
|
||||||
|
Retirement Age: {field.value as number}
|
||||||
|
<InfoTooltip content="The age when you stop working and start withdrawing from your portfolio to cover living expenses." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Slider
|
<Slider
|
||||||
name="retirementAge"
|
name="retirementAge"
|
||||||
@@ -563,7 +603,13 @@ export default function FireCalculatorForm() {
|
|||||||
name="coastFireAge"
|
name="coastFireAge"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Coast FIRE Age (Optional) - Stop contributing at age:</FormLabel>
|
<FormLabel>
|
||||||
|
<Button variant="link" size={'sm'} asChild>
|
||||||
|
<Link href="/learn/what-is-fire#types-of-fire">Coast FIRE</Link>
|
||||||
|
</Button>{' '}
|
||||||
|
Age (Optional):
|
||||||
|
<InfoTooltip content="The age when you stop making new contributions but keep working to cover current expenses. Your existing investments compound until retirement." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 45 (defaults to Retirement Age)"
|
placeholder="e.g., 45 (defaults to Retirement Age)"
|
||||||
@@ -588,7 +634,13 @@ export default function FireCalculatorForm() {
|
|||||||
name="baristaIncome"
|
name="baristaIncome"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Barista FIRE Income (Monthly during Retirement)</FormLabel>
|
<FormLabel>
|
||||||
|
<Button variant="link" size={'sm'} asChild>
|
||||||
|
<Link href="/learn/what-is-fire#types-of-fire">Barista FIRE</Link>
|
||||||
|
</Button>{' '}
|
||||||
|
Monthly Income
|
||||||
|
<InfoTooltip content="Part-time income during retirement (e.g., from a low-stress job). This reduces the amount you need to withdraw from your portfolio." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 1000"
|
placeholder="e.g., 1000"
|
||||||
@@ -613,7 +665,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="simulationMode"
|
name="simulationMode"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Simulation Mode</FormLabel>
|
<FormLabel>
|
||||||
|
Simulation Mode
|
||||||
|
<InfoTooltip content="Deterministic uses fixed yearly returns. Monte Carlo simulates market randomness with 500 runs to show probability ranges." />
|
||||||
|
</FormLabel>
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(val) => {
|
onValueChange={(val) => {
|
||||||
field.onChange(val);
|
field.onChange(val);
|
||||||
@@ -642,7 +697,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="volatility"
|
name="volatility"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Market Volatility (Std Dev %)</FormLabel>
|
<FormLabel>
|
||||||
|
Market Volatility (Std Dev %)
|
||||||
|
<InfoTooltip content="Standard deviation of annual returns. 15% is typical for stocks. Higher values mean more unpredictable year-to-year swings." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 15"
|
placeholder="e.g., 15"
|
||||||
@@ -668,7 +726,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="withdrawalStrategy"
|
name="withdrawalStrategy"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Withdrawal Strategy</FormLabel>
|
<FormLabel>
|
||||||
|
Withdrawal Strategy
|
||||||
|
<InfoTooltip content="Fixed inflation-adjusted maintains your purchasing power yearly. Percentage of portfolio adjusts spending based on current balance." />
|
||||||
|
</FormLabel>
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(val) => {
|
onValueChange={(val) => {
|
||||||
field.onChange(val);
|
field.onChange(val);
|
||||||
@@ -697,7 +758,10 @@ export default function FireCalculatorForm() {
|
|||||||
name="withdrawalPercentage"
|
name="withdrawalPercentage"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Withdrawal Percentage (%)</FormLabel>
|
<FormLabel>
|
||||||
|
Withdrawal Percentage (%)
|
||||||
|
<InfoTooltip content="Annual withdrawal rate as percentage of current portfolio. 4% is the classic 'safe' rate from the Trinity Study." />
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., 4.0"
|
placeholder="e.g., 4.0"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const buttonVariants = cva(
|
|||||||
'border border-primary/25 bg-background/80 shadow-sm hover:bg-primary/10 hover:text-foreground',
|
'border border-primary/25 bg-background/80 shadow-sm hover:bg-primary/10 hover:text-foreground',
|
||||||
secondary: 'bg-secondary/90 text-secondary-foreground shadow-md hover:bg-secondary',
|
secondary: 'bg-secondary/90 text-secondary-foreground shadow-md hover:bg-secondary',
|
||||||
ghost: 'text-foreground/80 hover:bg-primary/10 hover:text-foreground',
|
ghost: 'text-foreground/80 hover:bg-primary/10 hover:text-foreground',
|
||||||
link: 'text-primary underline-offset-4 hover:underline',
|
link: 'text-primary underline-offset-4 hover:underline px-0! h-auto!',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
default: 'h-9 px-4 py-2 has-[>svg]:px-3.5',
|
default: 'h-9 px-4 py-2 has-[>svg]:px-3.5',
|
||||||
|
|||||||
Reference in New Issue
Block a user