From 30c6d200e836040ddef8c509da1f0285da18c22f Mon Sep 17 00:00:00 2001 From: Aneeb Date: Sat, 4 Jul 2026 17:52:38 +0500 Subject: [PATCH 1/2] Redesign UI: teal brand, light+dark theme, elevation, table polish Bland flat dark-only UI with generic indigo accent and hardcoded dark-only status colors (unreadable if light mode ever shipped). Wires up next-themes (already a dependency, unused), swaps accent to teal, adds real elevation layering, promotes status colors to semantic theme tokens, and upgrades the shared DataTable primitive (pagination, sticky header) used by every table in the app. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01Vo2PcDtDzHok5EFJ4STR8F --- public/icon.svg | 2 +- public/manifest.json | 4 +- src/app/(app)/account/ai-settings-card.tsx | 4 +- .../(app)/account/change-password-form.tsx | 6 +- src/app/(app)/account/page.tsx | 2 +- src/app/(app)/financials/page.tsx | 4 +- .../[id]/cost-sheet/cost-import-button.tsx | 4 +- .../[id]/cost-sheet/cost-item-form-button.tsx | 4 +- .../[id]/cost-sheet/cost-sheet-board.tsx | 6 +- .../(app)/hustles/[id]/cost-sheet/page.tsx | 2 +- .../[id]/cost-sheet/product-form-button.tsx | 4 +- .../[id]/customers/[customerId]/page.tsx | 2 +- .../[id]/customers/customer-form-button.tsx | 4 +- .../[id]/customers/customers-table.tsx | 2 +- src/app/(app)/hustles/[id]/customers/page.tsx | 2 +- .../[id]/financials/financials-board.tsx | 6 +- .../(app)/hustles/[id]/financials/page.tsx | 2 +- .../financials/transaction-form-button.tsx | 4 +- .../inventory/inventory-adjust-button.tsx | 4 +- .../[id]/inventory/inventory-form-button.tsx | 4 +- .../inventory/inventory-import-button.tsx | 4 +- .../[id]/inventory/inventory-table.tsx | 2 +- src/app/(app)/hustles/[id]/inventory/page.tsx | 2 +- src/app/(app)/hustles/[id]/loading.tsx | 2 +- .../orders/[orderId]/order-payment-dialog.tsx | 2 +- .../hustles/[id]/orders/[orderId]/page.tsx | 2 +- .../(app)/hustles/[id]/orders/order-form.tsx | 8 +- src/app/(app)/hustles/[id]/orders/page.tsx | 2 +- src/app/(app)/hustles/[id]/page.tsx | 14 +-- src/app/(app)/hustles/[id]/products/page.tsx | 2 +- .../[id]/products/product-detail-sheet.tsx | 2 +- src/app/(app)/hustles/[id]/research/page.tsx | 2 +- .../hustles/[id]/research/research-board.tsx | 2 +- .../hustles/[id]/research/research-sheet.tsx | 6 +- .../hustles/[id]/settings/danger-zone.tsx | 4 +- src/app/(app)/hustles/[id]/settings/page.tsx | 2 +- .../[id]/suppliers/[supplierId]/page.tsx | 2 +- src/app/(app)/hustles/[id]/suppliers/page.tsx | 2 +- .../hustles/[id]/suppliers/supplier-form.tsx | 6 +- .../[id]/suppliers/suppliers-table.tsx | 2 +- src/app/(app)/hustles/[id]/tasks/page.tsx | 2 +- .../hustles/[id]/tasks/task-form-button.tsx | 2 +- .../(app)/hustles/[id]/tasks/tasks-board.tsx | 10 +- src/app/(app)/hustles/hustle-form.tsx | 8 +- src/app/(app)/hustles/loading.tsx | 2 +- src/app/(app)/hustles/page.tsx | 2 +- src/app/(app)/loading.tsx | 2 +- src/app/(app)/page.tsx | 2 +- src/app/(auth)/login/login-form.tsx | 4 +- src/app/(auth)/setup/setup-form.tsx | 8 +- src/app/globals.css | 115 +++++++++++++----- src/app/layout.tsx | 11 +- src/app/track/[orderId]/page.tsx | 2 +- src/components/charts/donut-chart.tsx | 13 +- src/components/charts/grouped-bar-chart.tsx | 16 ++- src/components/charts/line-chart.tsx | 16 ++- src/components/charts/palette.ts | 14 +-- src/components/charts/stacked-bar-chart.tsx | 13 +- src/components/layout/sidebar.tsx | 5 +- src/components/layout/topbar.tsx | 4 +- src/components/shared/currency.tsx | 8 +- src/components/shared/data-table.tsx | 77 +++++++++++- src/components/shared/stat-card.tsx | 24 +++- src/components/shared/theme-toggle.tsx | 37 ++++++ src/components/ui/badge.tsx | 8 +- src/components/ui/card.tsx | 8 +- src/components/ui/sonner.tsx | 4 +- src/lib/constants.ts | 66 +++++----- src/schemas/hustle.ts | 2 +- 69 files changed, 418 insertions(+), 209 deletions(-) create mode 100644 src/components/shared/theme-toggle.tsx diff --git a/public/icon.svg b/public/icon.svg index 4a11f0d..648fee1 100644 --- a/public/icon.svg +++ b/public/icon.svg @@ -1,5 +1,5 @@ - + diff --git a/public/manifest.json b/public/manifest.json index 7f491c3..03e55cf 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -2,8 +2,8 @@ "name": "Sidekit", "short_name": "Sidekit", "description": "Operating system for solo founders managing multiple businesses.", - "theme_color": "#6366f1", - "background_color": "#0f172a", + "theme_color": "#0a0a0d", + "background_color": "#0a0a0d", "display": "standalone", "orientation": "portrait", "start_url": "/", diff --git a/src/app/(app)/account/ai-settings-card.tsx b/src/app/(app)/account/ai-settings-card.tsx index 4ff3965..9647412 100644 --- a/src/app/(app)/account/ai-settings-card.tsx +++ b/src/app/(app)/account/ai-settings-card.tsx @@ -125,7 +125,7 @@ export function AiSettingsCard({ provider, model, baseUrl, hasKey }: Props) { {revealKey ? : } - {errors.apiKey ?

{errors.apiKey.message}

: null} + {errors.apiKey ?

{errors.apiKey.message}

: null}
@@ -138,7 +138,7 @@ export function AiSettingsCard({ provider, model, baseUrl, hasKey }: Props) { {errors.baseUrl ? ( -

{errors.baseUrl.message}

+

{errors.baseUrl.message}

) : null}
) : null} diff --git a/src/app/(app)/account/change-password-form.tsx b/src/app/(app)/account/change-password-form.tsx index e2f36d6..a54da53 100644 --- a/src/app/(app)/account/change-password-form.tsx +++ b/src/app/(app)/account/change-password-form.tsx @@ -50,7 +50,7 @@ export function ChangePasswordForm() { {...register("currentPassword")} /> {errors.currentPassword ? ( -

{errors.currentPassword.message}

+

{errors.currentPassword.message}

) : null}
@@ -63,7 +63,7 @@ export function ChangePasswordForm() { {...register("newPassword")} /> {errors.newPassword ? ( -

{errors.newPassword.message}

+

{errors.newPassword.message}

) : null}
@@ -75,7 +75,7 @@ export function ChangePasswordForm() { {...register("confirmPassword")} /> {errors.confirmPassword ? ( -

{errors.confirmPassword.message}

+

{errors.confirmPassword.message}

) : null}
diff --git a/src/app/(app)/account/page.tsx b/src/app/(app)/account/page.tsx index 835f6cb..b94fd8e 100644 --- a/src/app/(app)/account/page.tsx +++ b/src/app/(app)/account/page.tsx @@ -16,7 +16,7 @@ export default async function AccountPage() { if (!user) redirect("/login"); return ( -
+
diff --git a/src/app/(app)/financials/page.tsx b/src/app/(app)/financials/page.tsx index e956450..ec32df4 100644 --- a/src/app/(app)/financials/page.tsx +++ b/src/app/(app)/financials/page.tsx @@ -71,7 +71,7 @@ export default async function ConsolidatedFinancialsPage({ const allTransactions = await transactionService.list({ from, to }); return ( -
+
{parseError ? ( -

{parseError}

+

{parseError}

) : parsed ? ( -

{parsed.length} item{parsed.length === 1 ? "" : "s"} ready to import.

+

{parsed.length} item{parsed.length === 1 ? "" : "s"} ready to import.

) : null}
diff --git a/src/app/(app)/hustles/[id]/cost-sheet/cost-item-form-button.tsx b/src/app/(app)/hustles/[id]/cost-sheet/cost-item-form-button.tsx index 6e054ae..a556689 100644 --- a/src/app/(app)/hustles/[id]/cost-sheet/cost-item-form-button.tsx +++ b/src/app/(app)/hustles/[id]/cost-sheet/cost-item-form-button.tsx @@ -132,7 +132,7 @@ export function CostItemFormButton({ hustleId, suppliers, products, item, trigge
- {errors.name ?

{errors.name.message}

: null} + {errors.name ?

{errors.name.message}

: null}
@@ -230,7 +230,7 @@ export function CostItemFormButton({ hustleId, suppliers, products, item, trigge
- {errors.url ?

{errors.url.message}

: null} + {errors.url ?

{errors.url.message}

: null}
} @@ -364,7 +364,7 @@ export function CostSheetBoard({ hustleId, currency, items, suppliers, products onConfirm={() => handleDelete(i.id)} trigger={ e.preventDefault()} > Delete @@ -457,7 +457,7 @@ export function CostSheetBoard({ hustleId, currency, items, suppliers, products = 30 ? "text-emerald-300" : grossMargin >= 10 ? "text-amber-300" : "text-rose-300"}`}> + = 30 ? "text-success" : grossMargin >= 10 ? "text-warning" : "text-destructive"}`}> {percent(grossMargin)} } diff --git a/src/app/(app)/hustles/[id]/cost-sheet/page.tsx b/src/app/(app)/hustles/[id]/cost-sheet/page.tsx index 2e06339..1f58830 100644 --- a/src/app/(app)/hustles/[id]/cost-sheet/page.tsx +++ b/src/app/(app)/hustles/[id]/cost-sheet/page.tsx @@ -32,7 +32,7 @@ export default async function CostSheetPage({ params }: { params: Promise<{ id: })); return ( -
+
- {errors.name ?

{errors.name.message}

: null} + {errors.name ?

{errors.name.message}

: null}
@@ -139,7 +139,7 @@ export function ProductFormButton({ hustleId, item, trigger }: Props) { {errors.coverImageUrl ? ( -

{errors.coverImageUrl.message}

+

{errors.coverImageUrl.message}

) : null}
diff --git a/src/app/(app)/hustles/[id]/customers/[customerId]/page.tsx b/src/app/(app)/hustles/[id]/customers/[customerId]/page.tsx index c267b0e..ea07e2c 100644 --- a/src/app/(app)/hustles/[id]/customers/[customerId]/page.tsx +++ b/src/app/(app)/hustles/[id]/customers/[customerId]/page.tsx @@ -34,7 +34,7 @@ export default async function CustomerDetailPage({ const totalSpent = customer.orders.reduce((s, o) => s + toNumber(o.total), 0); return ( -
+
- {errors.name ?

{errors.name.message}

: null} + {errors.name ?

{errors.name.message}

: null}
@@ -114,7 +114,7 @@ export function CustomerFormButton({ hustleId, customer, trigger }: Props) {
- {errors.email ?

{errors.email.message}

: null} + {errors.email ?

{errors.email.message}

: null}
diff --git a/src/app/(app)/hustles/[id]/customers/customers-table.tsx b/src/app/(app)/hustles/[id]/customers/customers-table.tsx index be3afd9..496a497 100644 --- a/src/app/(app)/hustles/[id]/customers/customers-table.tsx +++ b/src/app/(app)/hustles/[id]/customers/customers-table.tsx @@ -96,7 +96,7 @@ export function CustomersTable({ hustleId, customers }: Props) { onConfirm={() => handleDelete(c.id)} trigger={ e.preventDefault()} > Delete diff --git a/src/app/(app)/hustles/[id]/customers/page.tsx b/src/app/(app)/hustles/[id]/customers/page.tsx index 87d07d2..4bcd433 100644 --- a/src/app/(app)/hustles/[id]/customers/page.tsx +++ b/src/app/(app)/hustles/[id]/customers/page.tsx @@ -11,7 +11,7 @@ export default async function CustomersPage({ params }: { params: Promise<{ id: const customers = await customerService.list(id); return ( -
+
@@ -296,7 +296,7 @@ export function FinancialsBoard({ onConfirm={() => handleDelete(t.id)} trigger={ e.preventDefault()} > Delete diff --git a/src/app/(app)/hustles/[id]/financials/page.tsx b/src/app/(app)/hustles/[id]/financials/page.tsx index 2f075b1..240515e 100644 --- a/src/app/(app)/hustles/[id]/financials/page.tsx +++ b/src/app/(app)/hustles/[id]/financials/page.tsx @@ -44,7 +44,7 @@ export default async function FinancialsPage({ ); return ( -
+
))} - {errors.category ?

{errors.category.message}

: null} + {errors.category ?

{errors.category.message}

: null}
- {errors.amount ?

{errors.amount.message}

: null} + {errors.amount ?

{errors.amount.message}

: null}
diff --git a/src/app/(app)/hustles/[id]/inventory/inventory-adjust-button.tsx b/src/app/(app)/hustles/[id]/inventory/inventory-adjust-button.tsx index a0b366b..fe1cb29 100644 --- a/src/app/(app)/hustles/[id]/inventory/inventory-adjust-button.tsx +++ b/src/app/(app)/hustles/[id]/inventory/inventory-adjust-button.tsx @@ -68,12 +68,12 @@ export function InventoryAdjustButton({ hustleId, itemId, trigger }: Props) {
- {errors.delta ?

{errors.delta.message}

: null} + {errors.delta ?

{errors.delta.message}

: null}
- {errors.reason ?

{errors.reason.message}

: null} + {errors.reason ?

{errors.reason.message}

: null}
diff --git a/src/app/(app)/hustles/[id]/inventory/inventory-table.tsx b/src/app/(app)/hustles/[id]/inventory/inventory-table.tsx index d1006a7..b29f971 100644 --- a/src/app/(app)/hustles/[id]/inventory/inventory-table.tsx +++ b/src/app/(app)/hustles/[id]/inventory/inventory-table.tsx @@ -200,7 +200,7 @@ export function InventoryTable({ hustleId, currency, items }: Props) { onConfirm={() => handleDelete(i.id)} trigger={ e.preventDefault()} > Delete diff --git a/src/app/(app)/hustles/[id]/inventory/page.tsx b/src/app/(app)/hustles/[id]/inventory/page.tsx index 8c99f14..ec708f4 100644 --- a/src/app/(app)/hustles/[id]/inventory/page.tsx +++ b/src/app/(app)/hustles/[id]/inventory/page.tsx @@ -19,7 +19,7 @@ export default async function InventoryPage({ params }: { params: Promise<{ id: ]); return ( -
+
))}
-
+
diff --git a/src/app/(app)/hustles/[id]/orders/[orderId]/order-payment-dialog.tsx b/src/app/(app)/hustles/[id]/orders/[orderId]/order-payment-dialog.tsx index 4c0bdc6..94f27cd 100644 --- a/src/app/(app)/hustles/[id]/orders/[orderId]/order-payment-dialog.tsx +++ b/src/app/(app)/hustles/[id]/orders/[orderId]/order-payment-dialog.tsx @@ -82,7 +82,7 @@ export function OrderPaymentDialog({ hustleId, orderId }: Props) {
- {errors.amount ?

{errors.amount.message}

: null} + {errors.amount ?

{errors.amount.message}

: null}
diff --git a/src/app/(app)/hustles/[id]/orders/[orderId]/page.tsx b/src/app/(app)/hustles/[id]/orders/[orderId]/page.tsx index d11c836..e8f9b3f 100644 --- a/src/app/(app)/hustles/[id]/orders/[orderId]/page.tsx +++ b/src/app/(app)/hustles/[id]/orders/[orderId]/page.tsx @@ -68,7 +68,7 @@ export default async function OrderDetailPage({ const outstanding = Math.max(0, toNumber(order.total) - toNumber(order.amountPaid)); return ( -
+
Customer name (display) {errors.customerName ? ( -

{errors.customerName.message}

+

{errors.customerName.message}

) : null}
@@ -195,7 +195,7 @@ export function OrderForm({ hustleId, customers, order, onDone }: Props) { type="button" variant="ghost" size="icon" - className="text-rose-300" + className="text-destructive" onClick={() => itemsArray.remove(i)} disabled={itemsArray.fields.length <= 1} > @@ -204,7 +204,7 @@ export function OrderForm({ hustleId, customers, order, onDone }: Props) {
))}
- {errors.items ?

{errors.items.message}

: null} + {errors.items ?

{errors.items.message}

: null}
@@ -294,7 +294,7 @@ export function OrderForm({ hustleId, customers, order, onDone }: Props) { type="button" variant="ghost" size="icon" - className="text-rose-300" + className="text-destructive" onClick={() => customsArray.remove(i)} > diff --git a/src/app/(app)/hustles/[id]/orders/page.tsx b/src/app/(app)/hustles/[id]/orders/page.tsx index 177b0f2..9cee26c 100644 --- a/src/app/(app)/hustles/[id]/orders/page.tsx +++ b/src/app/(app)/hustles/[id]/orders/page.tsx @@ -30,7 +30,7 @@ export default async function OrdersPage({ params }: { params: Promise<{ id: str })); return ( -
+
+
@@ -130,8 +130,8 @@ export default async function HustleOverviewPage({ data={monthly} currency={hustle.currency} series={[ - { key: "income", label: "Income", color: "#10b981" }, - { key: "expenses", label: "Expenses", color: "#ef4444" }, + { key: "income", label: "Income", color: "var(--color-success)" }, + { key: "expenses", label: "Expenses", color: "var(--color-destructive)" }, ]} /> @@ -208,7 +208,7 @@ export default async function HustleOverviewPage({ {upcomingTasks.map((t) => (
  • {t.status === "DONE" ? ( - + ) : ( )} @@ -229,9 +229,9 @@ export default async function HustleOverviewPage({
  • {lowStock.length > 0 ? ( - + - + Low stock alerts {lowStock.length} @@ -243,7 +243,7 @@ export default async function HustleOverviewPage({ className="flex items-center justify-between rounded-md border border-border px-3 py-2 text-sm" > {i.name} - + {i.quantity.toString()} {i.unit} diff --git a/src/app/(app)/hustles/[id]/products/page.tsx b/src/app/(app)/hustles/[id]/products/page.tsx index 0367a73..f428ed7 100644 --- a/src/app/(app)/hustles/[id]/products/page.tsx +++ b/src/app/(app)/hustles/[id]/products/page.tsx @@ -25,7 +25,7 @@ export default async function ProductsPage({ params }: { params: Promise<{ id: s })); return ( -
    +
    )} {previewError && ( -

    Image couldn't be previewed - some sites block embedding. It may still display when saved.

    +

    Image couldn't be previewed - some sites block embedding. It may still display when saved.

    )}
    diff --git a/src/app/(app)/hustles/[id]/research/page.tsx b/src/app/(app)/hustles/[id]/research/page.tsx index 253c586..3ae281b 100644 --- a/src/app/(app)/hustles/[id]/research/page.tsx +++ b/src/app/(app)/hustles/[id]/research/page.tsx @@ -20,7 +20,7 @@ export default async function ResearchPage({ params }: { params: Promise<{ id: s })); return ( -
    +
    diff --git a/src/app/(app)/hustles/[id]/research/research-board.tsx b/src/app/(app)/hustles/[id]/research/research-board.tsx index 98727a0..a3f1929 100644 --- a/src/app/(app)/hustles/[id]/research/research-board.tsx +++ b/src/app/(app)/hustles/[id]/research/research-board.tsx @@ -186,7 +186,7 @@ export function ResearchBoard({ hustleId, notes }: Props) {