root = Card([header, monthPicker, overviewCard, categoriesCard, largestExpense, recentCard, addExpense], "card", "column", "l")
header = CardHeader("Personal Budget", "March 2025 — see where your money went")
monthPicker = Card([monthForm], "sunk")
monthForm = Form("month-picker", monthButtons, [monthField])
monthField = FormControl("View a different month", monthSelect)
monthSelect = Select("month", [sepM, octM, novM, decM, janM, febM, marM], "Select a month", null, "2025-03")
sepM = SelectItem("2025-09", "September 2025")
octM = SelectItem("2025-10", "October 2025")
novM = SelectItem("2025-11", "November 2025")
decM = SelectItem("2025-12", "December 2025")
janM = SelectItem("2025-01", "January 2025")
febM = SelectItem("2025-02", "February 2025")
marM = SelectItem("2025-03", "March 2025")
monthButtons = Buttons([viewBtn])
viewBtn = Button("View month", null, "primary")
overviewCard = Card([overviewTitle, kpis, budgetBar, statusCallout], "sunk")
overviewTitle = Heading("Budget overview", "h3")
kpis = Table([kpiName, kpiValue])
kpiName = Col("Metric", ["Spent", "Budget", "Remaining"])
kpiValue = Col("Amount", ["$2,850", "$3,500", "$650"])
budgetBar = SingleStackedBarChart(["Spent", "Remaining"], [2850, 650])
statusCallout = Callout("success", "Under budget", "You have $650 left for the rest of March.")
categoriesCard = Card([categoriesTitle, categoriesChart], "sunk")
categoriesTitle = Heading("Spending by category", "h3")
categoriesChart = PieChart(["Housing", "Food", "Transport", "Utilities", "Entertainment", "Other"], [1200, 610, 320, 280, 190, 250], "donut")
largestExpense = Callout("info", "Largest expense", "Rent — $1,200, which is 42% of March spending.")
recentCard = Card([recentTitle, recentTable], "sunk")
recentTitle = Heading("Recent expenses", "h3")
recentTable = Table([recentDate, recentMerchant, recentAmount])
recentDate = Col("Date", ["Mar 14", "Mar 12", "Mar 10", "Mar 08"])
recentMerchant = Col("Description", ["Rent — Maple Apartments", "Grocery store", "Electric bill", "Gas station"])
recentAmount = Col("Amount", ["$1,200.00", "$86.40", "$92.10", "$48.00"])
addExpense = DialogBlock("Add expense", "Add a new expense", "Record a new expense for March 2025.", [addForm])
addForm = Form("add-expense", addButtons, [amountField, categoryField, descriptionField, dateField])
amountField = FormControl("Amount ($)", amountInput, "Enter a positive number")
amountInput = Input("amount", "0.00", "number")
categoryField = FormControl("Category", categorySelect)
categorySelect = Select("category", [catHousing, catFood, catTrans, catUtils, catEnt, catOther], "Choose a category")
catHousing = SelectItem("housing", "Housing")
catFood = SelectItem("food", "Food")
catTrans = SelectItem("transport", "Transport")
catUtils = SelectItem("utilities", "Utilities")
catEnt = SelectItem("entertainment", "Entertainment")
catOther = SelectItem("other", "Other")
descriptionField = FormControl("Description", descriptionInput, "Optional note")
descriptionInput = Input("description", "e.g. Weekly groceries", "text")
dateField = FormControl("Date", dateInput)
dateInput = DatePicker("expense-date", "single")
addButtons = Buttons([saveBtn, cancelBtn])
saveBtn = Button("Save expense", null, "primary")
cancelBtn = Button("Cancel", null, "tertiary")