Improvements to the UI

This commit is contained in:
pricewowen
2026-05-24 08:49:37 -06:00
parent d35b4e57d9
commit ec1bfa3fbe
60 changed files with 669 additions and 391 deletions

View File

@@ -6,8 +6,8 @@ import { AppShell } from "@/components/layout/app-shell";
export default function AvatarPage() {
return (
<AppShell
title="Your Habit Pet"
description="Watch your pet roam, breathe, and react to how you care for them."
title="Your bit"
description="Watch your digital self roam, breathe, and react to how you care for yourself."
fillViewport
centered
>

View File

@@ -7,8 +7,8 @@ export default function CustomizePage() {
return (
<AppShell
wide
title="Customize your pet"
description="Change your pet's name, styles, colors, and room."
title="Customize your bit"
description="Change your bit's name, styles, colors, and room."
>
<Suspense fallback={<p className="text-xs text-muted-foreground">Loading...</p>}>
<CustomizePageContent />

View File

@@ -29,7 +29,7 @@ export default function Page({
searchParams: Promise<{ error: string }>;
}) {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="flex w-full flex-1 items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<div className="flex flex-col gap-6">
<Card>

View File

@@ -2,7 +2,7 @@ import { ForgotPasswordForm } from "@/components/forgot-password-form";
export default function Page() {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="flex w-full flex-1 items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<ForgotPasswordForm />
</div>

View File

@@ -1,14 +1,7 @@
import { AuthBottomNav } from "@/components/layout/auth-bottom-nav";
export default function AuthLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<>
{children}
<AuthBottomNav />
</>
);
return <div className="flex min-h-0 flex-1 flex-col pb-nav">{children}</div>;
}

View File

@@ -2,7 +2,7 @@ import { LoginForm } from "@/components/login-form";
export default function Page() {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="flex w-full flex-1 items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<LoginForm />
</div>

View File

@@ -8,7 +8,7 @@ import {
export default function Page() {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="flex w-full flex-1 items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<div className="flex flex-col gap-6">
<Card>
@@ -22,7 +22,7 @@ export default function Page() {
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Your account is ready. You can sign in and start using Habit Pet.
Your account is ready. You can sign in and start using HaBit.
</p>
</CardContent>
</Card>

View File

@@ -2,7 +2,7 @@ import { SignUpForm } from "@/components/sign-up-form";
export default function Page() {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="flex w-full flex-1 items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<SignUpForm />
</div>

View File

@@ -2,7 +2,7 @@ import { UpdatePasswordForm } from "@/components/update-password-form";
export default function Page() {
return (
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
<div className="flex w-full flex-1 items-center justify-center p-6 md:p-10">
<div className="w-full max-w-sm">
<UpdatePasswordForm />
</div>

View File

@@ -4,7 +4,7 @@
@layer base {
:root {
--app-topbar-height: 3.5rem;
--app-topbar-height: 3.25rem;
--app-viewport-bottom-offset: 0px;
--app-nav-offset: 6rem;
--bottom-nav-height: 6rem;
@@ -117,7 +117,7 @@
border: 3px solid hsl(var(--lcd-border));
}
/* Matches pet-tab LCD: max-w-lg main minus px-5 and shell p-4 */
/* Matches bit-tab LCD: max-w-lg main minus px-5 and shell p-4 */
.tamagotchi-lcd-pet-match {
@apply aspect-[4/3] w-full shrink-0;
max-width: calc(32rem - 2.5rem - 2rem);
@@ -127,6 +127,15 @@
.tamagotchi-lcd-landing {
@apply aspect-[4/3] w-full shrink-0;
max-height: clamp(120px, 36vw, 240px);
container-type: inline-size;
}
.tamagotchi-lcd-landing .lcd-readable-name-landing {
max-width: 58%;
padding: 0.125rem 0.375rem;
font-size: clamp(0.4rem, 4.5cqi, 0.5625rem);
line-height: 1.2;
box-shadow: 1px 1px 0 0 hsl(280 45% 28%);
}
.tamagotchi-lcd-landing > div.absolute svg {
@@ -149,16 +158,6 @@
aspect-ratio: auto;
}
.customize-body {
min-height: 26rem;
}
@media (min-width: 1024px) {
.customize-body {
min-height: 30rem;
}
}
.retro-btn {
@apply inline-flex items-center justify-center border-2 border-border bg-primary text-primary-foreground;
box-shadow: var(--retro-shadow-sm);
@@ -244,6 +243,31 @@
.form-section-locked label {
@apply text-muted-foreground;
}
.lcd-readable-label {
@apply border-2 border-border bg-card px-2.5 py-1.5 text-center font-pixel text-[8px] leading-snug text-card-foreground sm:text-[9px];
box-shadow: var(--retro-shadow-sm);
}
.lcd-readable-name {
@apply border-2 border-border bg-card px-2 py-1 font-pixel leading-snug text-card-foreground;
box-shadow: var(--retro-shadow-sm);
}
}
@keyframes emotion-pop {
0% {
opacity: 0;
transform: translateY(4px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.animate-emotion-pop {
animation: emotion-pop 0.2s steps(4) both;
}
@keyframes pet-breathe {

View File

@@ -3,6 +3,7 @@ import { Press_Start_2P, Share_Tech_Mono } from "next/font/google";
import { ThemeProvider } from "next-themes";
import { GlobalBottomNav } from "@/components/layout/global-bottom-nav";
import { SiteHeader } from "@/components/layout/site-header";
import { ToastProvider } from "@/components/ui/toast-provider";
import "./globals.css";
@@ -12,8 +13,8 @@ const defaultUrl = process.env.VERCEL_URL
export const metadata: Metadata = {
metadataBase: new URL(defaultUrl),
title: "Habit Pet",
description: "Build habits, care for your pixel pet, and track wellness every day.",
title: "HaBit",
description: "Build habits, grow your digital self, and track wellness every day.",
};
export const viewport: Viewport = {
@@ -52,7 +53,8 @@ export default function RootLayout({
disableTransitionOnChange
>
<ToastProvider>
{children}
<SiteHeader />
<div className="flex min-h-dvh flex-col pt-topbar">{children}</div>
<GlobalBottomNav />
</ToastProvider>
</ThemeProvider>

View File

@@ -2,7 +2,6 @@ import { Suspense } from "react";
import { LandingPetPreview } from "@/components/landing/landing-pet-preview";
import { LandingHeroActions } from "@/components/layout/landing-hero-actions";
import { SiteFooter, SiteHeader } from "@/components/layout/site-header";
import {
Card,
CardContent,
@@ -13,22 +12,17 @@ import {
export default function Home() {
return (
<main className="flex min-h-svh flex-col">
<SiteHeader />
<main className="flex flex-1 flex-col pb-nav">
<div className="mx-auto flex w-full max-w-5xl flex-1 flex-col gap-12 px-5 py-12">
<section className="grid gap-10 lg:grid-cols-[1.1fr_0.9fr] lg:items-center">
<div className="space-y-6">
<p className="text-sm uppercase tracking-[0.25em] text-muted-foreground">
Calgary Hackathon MVP
</p>
<h1 className="text-4xl font-semibold tracking-tight sm:text-5xl">
Build habits. Care for your pixel pet.
Build habits. Grow your digital self.
</h1>
<p className="max-w-xl text-base text-muted-foreground sm:text-lg">
HaBit turns daily check-ins, wellness sliders, and journaling
into a simple game. Keep streaks alive, take your once-per-day
quiz, and watch your pet change with you.
HaBit turns daily check-ins, wellness sliders, and journaling into
a simple game. Keep streaks alive, take your once-per-day quiz,
and watch your bit change with you.
</p>
<Suspense fallback={null}>
<LandingHeroActions />
@@ -59,8 +53,8 @@ export default function Home() {
description: "Sliders and a daily reflection box.",
},
{
title: "Pet that responds",
description: "Avatar mood changes from your input.",
title: "A bit that responds",
description: "Your digital self reflects your daily input.",
},
].map((feature) => (
<Card key={feature.title}>
@@ -72,8 +66,6 @@ export default function Home() {
))}
</section>
</div>
<SiteFooter />
</main>
);
}