mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-15 01:54:43 +00:00
Standardise page wrapper width and top padding and refresh catalog and theme styling
This commit is contained in:
@@ -34,38 +34,38 @@ h6,
|
||||
--color-base-100: oklch(96% 0.012 82); /* warm parchment */
|
||||
--color-base-200: oklch(92% 0.018 80); /* brushed paper */
|
||||
--color-base-300: oklch(87% 0.025 78); /* tinted linen */
|
||||
--color-base-content: oklch(28% 0.025 58); /* dark brown ink — 15.6:1 on base-100 */
|
||||
--color-base-content: oklch(28% 0.025 58); /* dark brown ink */
|
||||
|
||||
--color-primary: oklch(65% 0.085 62); /* mellow amber */
|
||||
--color-primary-content: oklch(97% 0.02 62); /* warm near-white — 7.2:1 on primary */
|
||||
--color-primary: oklch(47.5% 0.085 62); /* mellow amber */
|
||||
--color-primary-content: oklch(97% 0.02 62); /* warm near-white */
|
||||
|
||||
--color-secondary: oklch(42% 0.05 42); /* softened mahogany */
|
||||
--color-secondary-content: oklch(96% 0.01 76); /* off-white — 14.2:1 on secondary */
|
||||
--color-secondary-content: oklch(96% 0.01 76); /* off-white */
|
||||
|
||||
--color-accent: oklch(93% 0.015 90); /* frothy cream */
|
||||
--color-accent-content: oklch(28% 0.025 58); /* dark brown — 12.8:1 on accent */
|
||||
--color-accent-content: oklch(28% 0.025 58); /* dark brown */
|
||||
|
||||
--color-neutral: oklch(28% 0.02 46); /* warm roast dark */
|
||||
--color-neutral-content: oklch(92% 0.012 80); /* pale parchment — 12.0:1 on neutral */
|
||||
--color-neutral-content: oklch(92% 0.012 80); /* pale parchment */
|
||||
|
||||
--color-info: oklch(46% 0.065 145); /* muted hop green */
|
||||
--color-info-content: oklch(97% 0.008 145); /* near-white — 14.2:1 on info */
|
||||
--color-info-content: oklch(97% 0.008 145); /* near-white */
|
||||
|
||||
--color-success: oklch(70% 0.06 122); /* soft barley gold */
|
||||
--color-success-content: oklch(97% 0.02 122); /* warm near-white — 5.7:1 on success */
|
||||
--color-success: oklch(46.5% 0.06 122); /* soft barley gold */
|
||||
--color-success-content: oklch(97% 0.02 122); /* warm near-white */
|
||||
|
||||
--color-warning: oklch(72% 0.09 56); /* toned amber */
|
||||
--color-warning-content: oklch(97% 0.02 56); /* warm near-white — 4.7:1 on warning */
|
||||
--color-warning: oklch(47.5% 0.09 56); /* toned amber */
|
||||
--color-warning-content: oklch(97% 0.02 56); /* warm near-white */
|
||||
|
||||
--color-error: oklch(54% 0.09 22); /* restrained cherry */
|
||||
--color-error-content: oklch(97% 0.006 15); /* near-white — 11.1:1 on error */
|
||||
--color-error: oklch(48% 0.09 22); /* restrained cherry */
|
||||
--color-error-content: oklch(97% 0.006 15); /* near-white */
|
||||
|
||||
--color-surface: oklch(88% 0.02 82); /* mid parchment, elevated cards */
|
||||
--color-surface-content: oklch(28% 0.025 58); /* dark brown — 9.2:1 on surface */
|
||||
--color-surface-content: oklch(28% 0.025 58); /* dark brown */
|
||||
|
||||
--color-muted: oklch(42% 0.055 62); /* amber-brown — 14.2:1 on base-100, 8.3:1 on surface */
|
||||
--color-muted: oklch(42% 0.055 62); /* amber-brown */
|
||||
--color-highlight: oklch(78% 0.055 65); /* warm amber, hover and active states */
|
||||
--color-highlight-content: oklch(22% 0.025 55); /* dark brown — 4.9:1 on highlight */
|
||||
--color-highlight-content: oklch(22% 0.025 55); /* dark brown */
|
||||
|
||||
--radius-selector: 0.375rem;
|
||||
--radius-field: 0.5rem;
|
||||
@@ -91,38 +91,38 @@ h6,
|
||||
--color-base-100: oklch(14% 0.006 45); /* charred barrel black */
|
||||
--color-base-200: oklch(18% 0.008 43); /* roasted malt dark */
|
||||
--color-base-300: oklch(23% 0.01 42); /* deep brown */
|
||||
--color-base-content: oklch(88% 0.008 75); /* warm off-white — 9.4:1 on base-100 */
|
||||
--color-base-content: oklch(88% 0.008 75); /* warm off-white */
|
||||
|
||||
--color-primary: oklch(68% 0.055 60); /* golden amber */
|
||||
--color-primary-content: oklch(92% 0.012 50); /* warm off-white — 4.6:1 on primary */
|
||||
--color-primary-content: oklch(30.5% 0.012 50); /* warm off-white */
|
||||
|
||||
--color-secondary: oklch(48% 0.035 40); /* deep mahogany ale */
|
||||
--color-secondary-content: oklch(97% 0.005 75); /* near-white — 13.9:1 on secondary */
|
||||
--color-secondary: oklch(62.5% 0.035 40); /* deep mahogany ale */
|
||||
--color-secondary-content: oklch(23.5% 0.005 75); /* near-white */
|
||||
|
||||
--color-accent: oklch(82% 0.01 88); /* frothy cream head */
|
||||
--color-accent-content: oklch(18% 0.012 55); /* near-black — 6.2:1 on accent */
|
||||
--color-accent-content: oklch(18% 0.012 55); /* near-black */
|
||||
|
||||
--color-neutral: oklch(20% 0.008 45); /* near-black with warmth */
|
||||
--color-neutral-content: oklch(88% 0.007 78); /* warm off-white — 9.3:1 on neutral */
|
||||
--color-neutral-content: oklch(88% 0.007 78); /* warm off-white */
|
||||
|
||||
--color-info: oklch(60% 0.04 145); /* cool hop green */
|
||||
--color-info-content: oklch(86% 0.006 145); /* pale green-white — 4.6:1 on info */
|
||||
--color-info: oklch(61.5% 0.04 145); /* cool hop green */
|
||||
--color-info-content: oklch(23% 0.006 145); /* pale green-white */
|
||||
|
||||
--color-success: oklch(66% 0.038 120); /* fresh barley */
|
||||
--color-success-content: oklch(90% 0.012 120); /* pale barley-white — 4.6:1 on success */
|
||||
--color-success-content: oklch(28.5% 0.012 120); /* pale barley-white */
|
||||
|
||||
--color-warning: oklch(70% 0.055 55); /* amber harvest */
|
||||
--color-warning-content: oklch(94% 0.012 55); /* warm near-white — 4.7:1 on warning */
|
||||
--color-warning-content: oklch(32.5% 0.012 55); /* warm near-white */
|
||||
|
||||
--color-error: oklch(50% 0.06 20); /* deep cherry kriek */
|
||||
--color-error-content: oklch(97% 0.004 15); /* near-white — 13.1:1 on error */
|
||||
--color-error: oklch(62.5% 0.06 20); /* deep cherry kriek */
|
||||
--color-error-content: oklch(23% 0.004 15); /* near-white */
|
||||
|
||||
--color-surface: oklch(26% 0.012 45); /* elevated dark panel */
|
||||
--color-surface-content: oklch(88% 0.008 75); /* warm off-white — 9.2:1 on surface */
|
||||
--color-surface-content: oklch(88% 0.008 75); /* warm off-white */
|
||||
|
||||
--color-muted: oklch(78% 0.018 72); /* warm grey — 4.7:1 on base-100, 4.6:1 on surface */
|
||||
--color-muted: oklch(78% 0.018 72); /* warm grey */
|
||||
--color-highlight: oklch(32% 0.025 48); /* warm dark brown, hover and active states */
|
||||
--color-highlight-content: oklch(88% 0.008 75); /* warm off-white — 9.0:1 on highlight */
|
||||
--color-highlight-content: oklch(88% 0.008 75); /* warm off-white */
|
||||
|
||||
--radius-selector: 0.375rem;
|
||||
--radius-field: 0.5rem;
|
||||
@@ -148,40 +148,38 @@ h6,
|
||||
--color-base-100: oklch(13% 0.01 295); /* blackberry-stained near-black */
|
||||
--color-base-200: oklch(17% 0.013 292); /* deep purple-black */
|
||||
--color-base-300: oklch(22% 0.016 290); /* dark grape */
|
||||
--color-base-content: oklch(90% 0.014 300); /* pale lavender-white — 10.7:1 on base-100 */
|
||||
--color-base-content: oklch(90% 0.014 300); /* pale lavender-white */
|
||||
|
||||
--color-primary: oklch(72% 0.075 295); /* cassis berry purple */
|
||||
--color-primary-content: oklch(95% 0.01 295); /* pale lavender — 4.5:1 on primary */
|
||||
--color-primary-content: oklch(34% 0.01 295); /* pale lavender */
|
||||
|
||||
--color-secondary: oklch(68% 0.06 10); /* sour cherry rose */
|
||||
--color-secondary-content: oklch(92% 0.006 10); /* warm near-white — 4.6:1 on secondary */
|
||||
--color-secondary-content: oklch(30% 0.006 10); /* warm near-white */
|
||||
|
||||
--color-accent: oklch(75% 0.045 130); /* tart lime zest */
|
||||
--color-accent-content: oklch(98.5% 0.01 130); /* near-white — 4.8:1 on accent */
|
||||
--color-accent-content: oklch(37.5% 0.01 130); /* near-white */
|
||||
|
||||
--color-neutral: oklch(18% 0.016 290); /* deep blackened grape */
|
||||
--color-neutral-content: oklch(88% 0.01 295); /* pale lavender — 9.3:1 on neutral */
|
||||
--color-neutral-content: oklch(88% 0.01 295); /* pale lavender */
|
||||
|
||||
--color-info: oklch(62% 0.04 250); /* muted indigo */
|
||||
--color-info-content: oklch(88% 0.008 250); /* pale indigo-white — 4.8:1 on info */
|
||||
--color-info-content: oklch(23% 0.008 250); /* pale indigo-white */
|
||||
|
||||
--color-success: oklch(65% 0.04 145); /* elderberry green */
|
||||
--color-success-content: oklch(90% 0.008 145); /* pale green-white — 4.7:1 on success */
|
||||
--color-success-content: oklch(27.5% 0.008 145); /* pale green-white */
|
||||
|
||||
--color-warning: oklch(70% 0.05 65); /* sour apricot */
|
||||
--color-warning-content: oklch(97% 0.03 65); /* near-white — 5.6:1 on warning */
|
||||
--color-warning-content: oklch(32.5% 0.03 65); /* near-white */
|
||||
|
||||
--color-error: oklch(50% 0.055 22); /* kriek red */
|
||||
--color-error-content: oklch(97% 0.006 22); /* near-white — 13.2:1 on error */
|
||||
--color-error: oklch(62% 0.055 22); /* kriek red */
|
||||
--color-error-content: oklch(22% 0.006 22); /* near-white */
|
||||
|
||||
--color-surface: oklch(27% 0.022 292); /* lifted purple-black panel */
|
||||
--color-surface-content: oklch(90% 0.014 300); /* pale lavender-white — 10.4:1 on surface */
|
||||
--color-surface-content: oklch(90% 0.014 300); /* pale lavender-white */
|
||||
|
||||
--color-muted: oklch(
|
||||
77.6% 0.022 300
|
||||
); /* desaturated lavender — 4.6:1 on base-100, 4.5:1 on surface */
|
||||
--color-muted: oklch(77.6% 0.022 300); /* desaturated lavender */
|
||||
--color-highlight: oklch(35% 0.04 295); /* cassis-tinted hover and active state */
|
||||
--color-highlight-content: oklch(90% 0.014 300); /* pale lavender-white — 10.1:1 on highlight */
|
||||
--color-highlight-content: oklch(90% 0.014 300); /* pale lavender-white */
|
||||
|
||||
--radius-selector: 0.5rem;
|
||||
--radius-field: 0.5rem;
|
||||
@@ -207,38 +205,38 @@ h6,
|
||||
--color-base-100: oklch(99% 0.007 112); /* near-white with faint barley-green tint */
|
||||
--color-base-200: oklch(96% 0.012 114); /* pale barley wash */
|
||||
--color-base-300: oklch(92% 0.019 116); /* light straw */
|
||||
--color-base-content: oklch(20% 0.022 122); /* deep green-black — 19.5:1 on base-100 */
|
||||
--color-base-content: oklch(20% 0.022 122); /* deep green-black */
|
||||
|
||||
--color-primary: oklch(52% 0.085 118); /* fresh-cut barley green */
|
||||
--color-primary-content: oklch(97% 0.005 118); /* near-white — 12.5:1 on primary */
|
||||
--color-primary: oklch(50% 0.085 118); /* fresh-cut barley green */
|
||||
--color-primary-content: oklch(97% 0.005 118); /* near-white */
|
||||
|
||||
--color-secondary: oklch(44% 0.055 128); /* muted sage stem */
|
||||
--color-secondary-content: oklch(97% 0.005 128); /* near-white — 14.8:1 on secondary */
|
||||
--color-secondary-content: oklch(97% 0.005 128); /* near-white */
|
||||
|
||||
--color-accent: oklch(93% 0.03 148); /* pale morning dew */
|
||||
--color-accent-content: oklch(22% 0.022 148); /* deep green — 13.4:1 on accent */
|
||||
--color-accent-content: oklch(22% 0.022 148); /* deep green */
|
||||
|
||||
--color-neutral: oklch(76% 0.028 118); /* dried straw, surface differentiation */
|
||||
--color-neutral-content: oklch(98.9% 0.005 118); /* near-white — 4.6:1 on neutral */
|
||||
--color-neutral-content: oklch(38.4% 0.005 118); /* near-white */
|
||||
|
||||
--color-info: oklch(38% 0.065 232); /* clear summer sky */
|
||||
--color-info-content: oklch(98% 0.005 232); /* near-white — 16.8:1 on info */
|
||||
--color-info-content: oklch(98% 0.005 232); /* near-white */
|
||||
|
||||
--color-success: oklch(38% 0.085 145); /* young shoot green */
|
||||
--color-success-content: oklch(98% 0.005 145); /* near-white — 16.8:1 on success */
|
||||
--color-success-content: oklch(98% 0.005 145); /* near-white */
|
||||
|
||||
--color-warning: oklch(68% 0.1 76); /* ripening grain amber */
|
||||
--color-warning-content: oklch(92.5% 0.005 72); /* warm near-white — 4.5:1 on warning */
|
||||
--color-warning: oklch(51% 0.1 76); /* ripening grain amber */
|
||||
--color-warning-content: oklch(92.5% 0.005 72); /* warm near-white */
|
||||
|
||||
--color-error: oklch(52% 0.1 18); /* dusty rose red */
|
||||
--color-error-content: oklch(98% 0.005 15); /* near-white — 12.5:1 on error */
|
||||
--color-error: oklch(51.5% 0.1 18); /* dusty rose red */
|
||||
--color-error-content: oklch(98% 0.005 15); /* near-white */
|
||||
|
||||
--color-surface: oklch(94% 0.012 112); /* soft barley-wash panel */
|
||||
--color-surface-content: oklch(20% 0.022 122); /* deep green-black — 14.0:1 on surface */
|
||||
--color-surface-content: oklch(20% 0.022 122); /* deep green-black */
|
||||
|
||||
--color-muted: oklch(38% 0.055 120); /* sage green — 18.1:1 on base-100, 13.0:1 on surface */
|
||||
--color-muted: oklch(38% 0.055 120); /* sage green */
|
||||
--color-highlight: oklch(85% 0.04 118); /* green-tinted hover and active state */
|
||||
--color-highlight-content: oklch(20% 0.022 122); /* deep green-black — 7.8:1 on highlight */
|
||||
--color-highlight-content: oklch(20% 0.022 122); /* deep green-black */
|
||||
|
||||
--radius-selector: 2rem;
|
||||
--radius-field: 2rem;
|
||||
@@ -249,3 +247,33 @@ h6,
|
||||
--depth: 0;
|
||||
--noise: 0;
|
||||
}
|
||||
|
||||
/* WCAG 1.4.11: form-field borders at >= 3:1 against every base layer */
|
||||
:is(.input, .select, .textarea):not(
|
||||
.input-neutral,
|
||||
.input-primary,
|
||||
.input-secondary,
|
||||
.input-accent,
|
||||
.input-info,
|
||||
.input-success,
|
||||
.input-warning,
|
||||
.input-error,
|
||||
.select-neutral,
|
||||
.select-primary,
|
||||
.select-secondary,
|
||||
.select-accent,
|
||||
.select-info,
|
||||
.select-success,
|
||||
.select-warning,
|
||||
.select-error,
|
||||
.textarea-neutral,
|
||||
.textarea-primary,
|
||||
.textarea-secondary,
|
||||
.textarea-accent,
|
||||
.textarea-info,
|
||||
.textarea-success,
|
||||
.textarea-warning,
|
||||
.textarea-error
|
||||
) {
|
||||
--input-color: color-mix(in oklab, var(--color-base-content) 56%, #0000);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ const AuthFlowDemoCard = () => (
|
||||
<li className="list-row">
|
||||
<div>
|
||||
<p className="font-semibold">Login</p>
|
||||
<p className="text-sm text-base-content/60">
|
||||
<p className="text-sm text-base-content/70">
|
||||
POST to <code className="kbd kbd-sm">/api/auth/login</code> with
|
||||
username & password
|
||||
</p>
|
||||
@@ -20,7 +20,7 @@ const AuthFlowDemoCard = () => (
|
||||
<li className="list-row">
|
||||
<div>
|
||||
<p className="font-semibold">Register</p>
|
||||
<p className="text-sm text-base-content/60">
|
||||
<p className="text-sm text-base-content/70">
|
||||
POST to <code className="kbd kbd-sm">/api/auth/register</code> with full
|
||||
user details
|
||||
</p>
|
||||
@@ -29,7 +29,7 @@ const AuthFlowDemoCard = () => (
|
||||
<li className="list-row">
|
||||
<div>
|
||||
<p className="font-semibold">Session</p>
|
||||
<p className="text-sm text-base-content/60">
|
||||
<p className="text-sm text-base-content/70">
|
||||
JWT access & refresh tokens stored in an HTTP-only cookie
|
||||
</p>
|
||||
</div>
|
||||
@@ -37,7 +37,7 @@ const AuthFlowDemoCard = () => (
|
||||
<li className="list-row">
|
||||
<div>
|
||||
<p className="font-semibold">Protected Routes</p>
|
||||
<p className="text-sm text-base-content/60">
|
||||
<p className="text-sm text-base-content/70">
|
||||
This dashboard requires authentication via{' '}
|
||||
<code className="kbd kbd-sm">requireAuth()</code>
|
||||
</p>
|
||||
@@ -46,7 +46,7 @@ const AuthFlowDemoCard = () => (
|
||||
<li className="list-row">
|
||||
<div>
|
||||
<p className="font-semibold">Token Refresh</p>
|
||||
<p className="text-sm text-base-content/60">
|
||||
<p className="text-sm text-base-content/70">
|
||||
POST to <code className="kbd kbd-sm">/api/auth/refresh</code> with the
|
||||
refresh token in an <code className="kbd kbd-sm">X-Refresh-Token</code>{' '}
|
||||
header
|
||||
@@ -56,7 +56,7 @@ const AuthFlowDemoCard = () => (
|
||||
<li className="list-row">
|
||||
<div>
|
||||
<p className="font-semibold">Account Management</p>
|
||||
<p className="text-sm text-base-content/60">
|
||||
<p className="text-sm text-base-content/70">
|
||||
PATCH <code className="kbd kbd-sm">/api/auth/username</code>,{' '}
|
||||
<code className="kbd kbd-sm">/email</code>,{' '}
|
||||
<code className="kbd kbd-sm">/password</code>,{' '}
|
||||
|
||||
@@ -14,7 +14,7 @@ const SectionCard = ({ icon, title, description, open, onToggle, children }: Sec
|
||||
<div className="card-body">
|
||||
<div className="flex w-full items-center justify-between gap-5">
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="text-base-content/60 mt-1">{icon}</span>
|
||||
<span className="text-base-content/70 mt-1">{icon}</span>
|
||||
<div>
|
||||
<h2 className="card-title text-lg">{title}</h2>
|
||||
<p className="text-sm text-base-content/70">{description}</p>
|
||||
|
||||
@@ -15,7 +15,7 @@ const SessionInfoCard = ({ username, userAccountId }: SessionInfoCardProps) => (
|
||||
</p>
|
||||
|
||||
<div className="bg-base-200 rounded-box p-4 mt-2">
|
||||
<p className="text-xs font-semibold uppercase tracking-widest text-base-content/50 mb-3">
|
||||
<p className="text-xs font-semibold uppercase tracking-widest text-base-content/70 mb-3">
|
||||
Session Info
|
||||
</p>
|
||||
<div className="stats stats-vertical w-full">
|
||||
|
||||
@@ -208,11 +208,11 @@ const AccountPage = ({ loaderData, actionData }: Route.ComponentProps) => {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200">
|
||||
<div className="mx-auto max-w-2xl px-6 py-10 space-y-6">
|
||||
<div className="mx-auto max-w-7xl px-5 pt-10 pb-10 space-y-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<Settings className="size-7" aria-hidden="true" />
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold">Account Settings</h1>
|
||||
<h1 className="font-serif text-5xl font-bold leading-tight">Account Settings</h1>
|
||||
<p className="text-base-content/70">
|
||||
Manage the account details for{' '}
|
||||
<span className="font-mono">{username}</span>
|
||||
@@ -257,7 +257,7 @@ const AccountPage = ({ loaderData, actionData }: Route.ComponentProps) => {
|
||||
|
||||
<Link
|
||||
to="/dashboard"
|
||||
className="link link-hover text-sm text-base-content/60 inline-block"
|
||||
className="link link-hover text-sm text-base-content/70 inline-block"
|
||||
>
|
||||
← Back to dashboard
|
||||
</Link>
|
||||
|
||||
@@ -20,7 +20,7 @@ const Dashboard = ({ loaderData }: Route.ComponentProps) => {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200">
|
||||
<div className="mx-auto max-w-4xl px-6 py-10 space-y-6">
|
||||
<div className="mx-auto max-w-7xl px-5 pt-10 pb-10 space-y-6">
|
||||
<SessionInfoCard username={username} userAccountId={userAccountId} />
|
||||
<AuthFlowDemoCard />
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ const ConfirmSuccess = ({ confirmedDate }: ConfirmSuccessProps) => (
|
||||
<h1 className="card-title text-2xl">Email Confirmed!</h1>
|
||||
<p className="text-base-content/70">Your email address has been successfully verified.</p>
|
||||
<div className="bg-base-200 rounded-box w-full p-3 text-sm text-left">
|
||||
<span className="text-base-content/50 text-xs uppercase tracking-widest font-semibold">
|
||||
<span className="text-base-content/70 text-xs uppercase tracking-widest font-semibold">
|
||||
Confirmed at
|
||||
</span>
|
||||
<p className="font-mono mt-1">{new Date(confirmedDate).toLocaleString()}</p>
|
||||
|
||||
@@ -8,7 +8,7 @@ const LoginCallout = () => (
|
||||
<Link to="/login" className="btn btn-outline btn-sm w-full">
|
||||
Sign in
|
||||
</Link>
|
||||
<Link to="/" className="link link-hover text-sm text-base-content/60">
|
||||
<Link to="/" className="link link-hover text-sm text-base-content/70">
|
||||
Back to home
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@ const RegisterCallout = () => (
|
||||
</Link>
|
||||
<Link
|
||||
to="/"
|
||||
className="link link-hover text-sm text-base-content/60 inline-flex items-center gap-1"
|
||||
className="link link-hover text-sm text-base-content/70 inline-flex items-center gap-1"
|
||||
>
|
||||
<HomeSimpleDoor className="size-4" aria-hidden="true" />
|
||||
Back to home
|
||||
|
||||
@@ -23,12 +23,12 @@ const BeerListCard = ({ beers }: BeerListCardProps) => (
|
||||
>
|
||||
<div className="flex flex-col gap-0.5 min-w-0">
|
||||
<span className="font-bold text-sm">{beer.name}</span>
|
||||
<span className="text-xs text-base-content/60">{beer.description}</span>
|
||||
<span className="text-xs text-base-content/70">{beer.description}</span>
|
||||
</div>
|
||||
<span className="badge badge-ghost bg-base-300 text-xs font-semibold whitespace-nowrap">
|
||||
{beer.style}
|
||||
</span>
|
||||
<span className="text-xs text-base-content/60 tabular-nums whitespace-nowrap">
|
||||
<span className="text-xs text-base-content/70 tabular-nums whitespace-nowrap">
|
||||
{beer.abv.toFixed(1)}% ABV
|
||||
</span>
|
||||
<StarRating value={beer.rating} size="xs" />
|
||||
|
||||
@@ -17,7 +17,7 @@ const BeerStyleBreakdownCard = ({ beers }: BeerStyleBreakdownCardProps) => {
|
||||
<div key={style} className="flex flex-col gap-1">
|
||||
<div className="flex items-baseline justify-between gap-2">
|
||||
<span className="text-sm font-semibold">{style}</span>
|
||||
<span className="text-xs text-base-content/60 tabular-nums">{count}</span>
|
||||
<span className="text-xs text-base-content/70 tabular-nums">{count}</span>
|
||||
</div>
|
||||
<progress
|
||||
className="progress progress-primary h-1.5"
|
||||
|
||||
@@ -8,7 +8,7 @@ interface BreweryDetailsCardProps {
|
||||
|
||||
const DetailRow = ({ label, value }: { label: string; value: string | number }) => (
|
||||
<div className="flex items-center justify-between gap-2 text-sm">
|
||||
<span className="text-base-content/60">{label}</span>
|
||||
<span className="text-base-content/70">{label}</span>
|
||||
<span className="font-semibold">{value}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -26,16 +26,16 @@ const BreweryHeaderCard = ({
|
||||
<div className="card-body gap-4 p-7">
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<span className="text-xs font-bold uppercase tracking-widest text-base-content/50">
|
||||
<span className="text-xs font-bold uppercase tracking-widest text-base-content/70">
|
||||
Brewery
|
||||
</span>
|
||||
<span className="badge bg-[var(--color-highlight)] text-[var(--color-highlight-content)]">
|
||||
Est. {foundedYear}
|
||||
</span>
|
||||
</div>
|
||||
<h1 className="text-4xl leading-tight m-0">{brewery.breweryName}</h1>
|
||||
<h1 className="font-serif text-5xl font-bold leading-tight m-0">{brewery.breweryName}</h1>
|
||||
{brewery.location && (
|
||||
<p className="text-sm text-base-content/60 flex items-center gap-1 m-0">
|
||||
<p className="text-sm text-base-content/70 flex items-center gap-1 m-0">
|
||||
<MapPin className="size-4" aria-hidden="true" />
|
||||
{formatBreweryAddress(brewery.location)}
|
||||
</p>
|
||||
@@ -57,7 +57,7 @@ const BreweryHeaderCard = ({
|
||||
<div className="flex items-baseline gap-1.5">
|
||||
<StarRating value={avgRating} size="sm" />
|
||||
<span className="font-bold">{avgRating.toFixed(1)}</span>
|
||||
<span className="text-sm text-base-content/60">({ratingsCount} ratings)</span>
|
||||
<span className="text-sm text-base-content/70">({ratingsCount} ratings)</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-base-content/70 leading-relaxed text-pretty m-0">
|
||||
|
||||
@@ -8,7 +8,7 @@ interface CommunityStatsCardProps {
|
||||
|
||||
const StatRow = ({ label, value }: { label: string; value: number }) => (
|
||||
<div className="flex items-center justify-between gap-2 text-sm">
|
||||
<span className="text-base-content/60">{label}</span>
|
||||
<span className="text-base-content/70">{label}</span>
|
||||
<span className="font-semibold tabular-nums">{value}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ const YourRatingCard = ({ value, onChange }: YourRatingCardProps) => (
|
||||
<div className="card-body flex-row flex-wrap items-center justify-between gap-4 p-6">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<h3 className="text-xl m-0">Your rating</h3>
|
||||
<p className="text-sm text-base-content/60 m-0">
|
||||
<p className="text-sm text-base-content/70 m-0">
|
||||
{value
|
||||
? `You rated this ${value} of 5. Tap the same star to clear.`
|
||||
: 'Tap a star to rate this brewery.'}
|
||||
|
||||
@@ -31,14 +31,14 @@ const CommentItem = ({ comment, onToggleLike }: CommentItemProps) => {
|
||||
<span className="font-bold text-sm">{comment.user}</span>
|
||||
)}
|
||||
<StarRating value={comment.rating} size="xs" />
|
||||
<span className="text-xs text-base-content/60">{comment.time}</span>
|
||||
<span className="text-xs text-base-content/70">{comment.time}</span>
|
||||
</div>
|
||||
<p className="text-sm leading-relaxed m-0">{comment.text}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onToggleLike(comment.id)}
|
||||
className={`self-start inline-flex items-center gap-1 text-xs font-semibold ${
|
||||
comment.liked ? 'text-primary' : 'text-base-content/60'
|
||||
comment.liked ? 'text-primary' : 'text-base-content/70'
|
||||
}`}
|
||||
>
|
||||
{comment.liked ? (
|
||||
|
||||
@@ -24,7 +24,7 @@ const BreweryCard = ({ brewery }: BreweryCardProps) => (
|
||||
</p>
|
||||
)}
|
||||
{brewery.location && (
|
||||
<p className="text-sm text-base-content/50 mt-2">
|
||||
<p className="text-sm text-base-content/70 mt-2">
|
||||
{formatBreweryAddress(brewery.location)}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -19,14 +19,14 @@ const FeaturedBreweryCard = ({ brewery, onShowOnMap }: FeaturedBreweryCardProps)
|
||||
<div className="card-body gap-3.5 p-8 md:grid md:grid-cols-[1.35fr_1fr] md:gap-10 md:items-start">
|
||||
<div className="flex flex-col gap-3.5">
|
||||
{brewery.location && (
|
||||
<div className="text-sm font-semibold text-base-content/60">
|
||||
<div className="text-sm font-semibold text-base-content/70">
|
||||
{brewery.location.cityName}, {brewery.location.stateProvinceCode}
|
||||
</div>
|
||||
)}
|
||||
<h3 className="font-serif text-4xl leading-tight m-0">{brewery.breweryName}</h3>
|
||||
<p className="text-lg leading-snug text-pretty m-0">{brewery.description}</p>
|
||||
{brewery.location && (
|
||||
<p className="text-sm text-base-content/60 m-0">
|
||||
<p className="text-sm text-base-content/70 m-0">
|
||||
{formatBreweryAddress(brewery.location)}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -17,7 +17,7 @@ const RecentBreweries = ({ breweries }: RecentBreweriesProps) => {
|
||||
<div className="card-body gap-1.5">
|
||||
<h3 className="card-title font-serif text-xl">{brewery.breweryName}</h3>
|
||||
{brewery.location && (
|
||||
<div className="text-sm text-base-content/60">
|
||||
<div className="text-sm text-base-content/70">
|
||||
{brewery.location.cityName},{' '}
|
||||
{brewery.location.stateProvinceCode}
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@ const NearbyBreweriesHeader = ({
|
||||
return (
|
||||
<div className="flex items-baseline justify-between gap-4 flex-wrap mb-3.5">
|
||||
<h2 className="font-serif text-2xl m-0">Breweries near you</h2>
|
||||
<span className="text-sm text-base-content/60">
|
||||
<span className="text-sm text-base-content/70">
|
||||
{center
|
||||
? `${withDistance.length} within ${formatDistance(radiusKm * 1000, unit)} of ${centerLabel}`
|
||||
: 'Finding breweries near you…'}
|
||||
|
||||
@@ -23,7 +23,7 @@ const NearbyBreweryList = ({
|
||||
return (
|
||||
<>
|
||||
{withDistance.length === 0 && center && (
|
||||
<p className="text-sm text-base-content/60">
|
||||
<p className="text-sm text-base-content/70">
|
||||
No partner breweries within {formatDistance(radiusKm * 1000, unit)}.
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -37,7 +37,7 @@ const NearbyBreweryListItem = ({
|
||||
</span>
|
||||
</div>
|
||||
{brewery.location && (
|
||||
<div className="text-sm text-base-content/60">
|
||||
<div className="text-sm text-base-content/70">
|
||||
{brewery.location.cityName}, {brewery.location.stateProvinceCode}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -8,7 +8,7 @@ interface SidebarCardProps {
|
||||
const SidebarCard = ({ title, children }: SidebarCardProps) => (
|
||||
<div className="card bg-base-100 shadow">
|
||||
<div className="card-body gap-3 p-6">
|
||||
<p className="text-xs font-bold uppercase tracking-widest text-base-content/50 m-0">
|
||||
<p className="text-xs font-bold uppercase tracking-widest text-base-content/70 m-0">
|
||||
{title}
|
||||
</p>
|
||||
{children}
|
||||
|
||||
@@ -44,8 +44,8 @@ const Breweries = ({ loaderData }: Route.ComponentProps) => {
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200 text-base-content pb-16">
|
||||
<div className="max-w-7xl mx-auto px-5 pt-10">
|
||||
<h1 className="font-serif text-5xl leading-tight mb-2">Breweries</h1>
|
||||
<p className="text-lg text-base-content/60 max-w-xl m-0">
|
||||
<h1 className="font-serif text-5xl font-bold leading-tight mb-2">Breweries</h1>
|
||||
<p className="text-lg text-base-content/70 max-w-xl m-0">
|
||||
Discover our partner breweries — start with this week's feature, then see
|
||||
what's pouring near you.
|
||||
</p>
|
||||
|
||||
@@ -80,15 +80,15 @@ const BreweryDetail = ({ loaderData }: Route.ComponentProps) => {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200">
|
||||
<div className="max-w-4xl mx-auto px-6 pt-8 pb-16">
|
||||
<div className="mx-auto max-w-7xl px-5 pt-10 pb-16">
|
||||
<Link
|
||||
to="/breweries"
|
||||
className="link link-hover text-sm text-base-content/60 mb-4 inline-block"
|
||||
className="link link-hover text-sm text-base-content/70 mb-4 inline-block"
|
||||
>
|
||||
← Back to breweries
|
||||
</Link>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-[1fr_19rem] gap-5 items-start">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-[1fr_23rem] gap-5 items-start">
|
||||
<div className="flex flex-col gap-5">
|
||||
<BreweryHeaderCard
|
||||
brewery={brewery}
|
||||
|
||||
@@ -72,14 +72,14 @@ const Breweries = ({ loaderData }: Route.ComponentProps) => {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200">
|
||||
<div className="container mx-auto p-14">
|
||||
<div className="mx-auto max-w-7xl px-5 pt-10">
|
||||
<Link
|
||||
to="/breweries"
|
||||
className="link link-hover text-sm text-base-content/60 mb-4 inline-block"
|
||||
className="link link-hover text-sm text-base-content/70 mb-4 inline-block"
|
||||
>
|
||||
← Back to Breweries
|
||||
</Link>
|
||||
<h1 className="text-4xl font-bold mb-4">Full brewery directory</h1>
|
||||
<h1 className="font-serif text-5xl font-bold leading-tight mb-4">Full brewery directory</h1>
|
||||
<p className="text-base-content/70 mb-6">
|
||||
All of our partner breweries, newest first.
|
||||
</p>
|
||||
@@ -93,7 +93,7 @@ const Breweries = ({ loaderData }: Route.ComponentProps) => {
|
||||
</ClientOnly>
|
||||
|
||||
{allBreweries.length === 0 ? (
|
||||
<p className="text-center text-base-content/60 mt-12">
|
||||
<p className="text-center text-base-content/70 mt-12">
|
||||
No breweries found yet.
|
||||
</p>
|
||||
) : (
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Clock, Lock, Tools } from 'iconoir-react';
|
||||
import type { ComponentType } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
type Reason = 'soon' | 'maintenance' | 'auth';
|
||||
|
||||
type Action = { to: string; label: string; className: string };
|
||||
|
||||
type Content = {
|
||||
Icon: ComponentType<{ className?: string }>;
|
||||
title: string;
|
||||
description: string;
|
||||
actions: Action[];
|
||||
};
|
||||
|
||||
const CONTENT: Record<Reason, Content> = {
|
||||
soon: {
|
||||
Icon: Clock,
|
||||
title: 'This feature is not available yet',
|
||||
description: 'This feature is still in development.',
|
||||
actions: [
|
||||
{ to: '/breweries', label: 'Browse breweries', className: 'btn-primary' },
|
||||
{ to: '/', label: 'Back to home', className: 'btn-ghost' },
|
||||
],
|
||||
},
|
||||
maintenance: {
|
||||
Icon: Tools,
|
||||
title: 'This feature is temporarily unavailable',
|
||||
description: 'This feature is offline for maintenance. Try again in a few minutes.',
|
||||
actions: [],
|
||||
},
|
||||
auth: {
|
||||
Icon: Lock,
|
||||
title: 'Sign in to use this feature',
|
||||
description: 'This feature requires a valid session. Log in or create an account to continue.',
|
||||
actions: [
|
||||
{ to: '/login', label: 'Login', className: 'btn-primary' },
|
||||
{ to: '/register', label: 'Register', className: 'btn-outline' },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
type FeatureNotAvailableProps = {
|
||||
reason?: Reason;
|
||||
};
|
||||
|
||||
const FeatureNotAvailable = ({ reason = 'soon' }: FeatureNotAvailableProps) => {
|
||||
const { Icon, title, description, actions } = CONTENT[reason];
|
||||
|
||||
return (
|
||||
<section className="flex flex-col items-center gap-3 rounded-box border border-base-300 bg-base-100 px-6 py-12 text-center">
|
||||
<div className="flex size-14 items-center justify-center rounded-full bg-base-200 text-base-content/70">
|
||||
<Icon className="size-6" />
|
||||
</div>
|
||||
<div className="flex max-w-md flex-col gap-2">
|
||||
<h2 className="font-serif text-2xl font-bold leading-tight">{title}</h2>
|
||||
<p className="text-base-content/70 text-pretty">{description}</p>
|
||||
</div>
|
||||
{actions.length > 0 && (
|
||||
<div className="flex flex-wrap justify-center gap-3 pt-2">
|
||||
{actions.map(({ to, label, className }) => (
|
||||
<Link key={to} to={to} className={`btn btn-sm ${className}`}>
|
||||
{label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeatureNotAvailable;
|
||||
@@ -1,3 +1,4 @@
|
||||
import FeatureNotAvailable from '../components/FeatureNotAvailable';
|
||||
import type { Route } from './+types/beer-styles';
|
||||
|
||||
export const meta = ({}: Route.MetaArgs) => {
|
||||
@@ -7,9 +8,12 @@ export const meta = ({}: Route.MetaArgs) => {
|
||||
const BeerStyles = () => {
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200">
|
||||
<div className="container mx-auto p-4">
|
||||
<h1 className="text-4xl font-bold mb-4">Beer Styles</h1>
|
||||
<div className="mx-auto max-w-7xl px-5 pt-10">
|
||||
<h1 className="font-serif text-5xl font-bold leading-tight mb-4">Beer Styles</h1>
|
||||
<p className="text-base-content/70">Learn about different beer styles.</p>
|
||||
<div className="mt-8">
|
||||
<FeatureNotAvailable />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import FeatureNotAvailable from '../components/FeatureNotAvailable';
|
||||
import type { Route } from './+types/beers';
|
||||
|
||||
export const meta = ({}: Route.MetaArgs) => {
|
||||
@@ -7,9 +8,12 @@ export const meta = ({}: Route.MetaArgs) => {
|
||||
const Beers = () => {
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200">
|
||||
<div className="container mx-auto p-4">
|
||||
<h1 className="text-4xl font-bold mb-4">Beers</h1>
|
||||
<div className="mx-auto max-w-7xl px-5 pt-10">
|
||||
<h1 className="font-serif text-5xl font-bold leading-tight mb-4">Beers</h1>
|
||||
<p className="text-base-content/70">Explore our collection of beers.</p>
|
||||
<div className="mt-8">
|
||||
<FeatureNotAvailable />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -21,10 +21,9 @@ export const meta = ({}: Route.MetaArgs) => [
|
||||
|
||||
export const loader = async ({ request }: Route.LoaderArgs) => {
|
||||
const auth = await getOptionalAuth(request);
|
||||
|
||||
// The rest of the landing page stands on its own, so a brewery service
|
||||
// outage degrades to the empty state instead of an error page.
|
||||
let recentBreweries: Brewery[] = [];
|
||||
|
||||
const randomOffset = Math.random() * 1.0
|
||||
try {
|
||||
recentBreweries = await getBreweries(PARTNER_BREWERY_COUNT, 0);
|
||||
} catch {
|
||||
|
||||
@@ -31,7 +31,7 @@ const TextTokenSample = ({
|
||||
}) => {
|
||||
return (
|
||||
<div className="rounded-box p-3" style={{ backgroundColor: `var(${background})` }}>
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-base-content/50">
|
||||
<p className="text-xs font-semibold uppercase tracking-wide text-base-content/70">
|
||||
{label}
|
||||
</p>
|
||||
<p className="mt-1 text-sm font-medium" style={{ color: `var(${text})` }}>
|
||||
@@ -54,7 +54,7 @@ const ThemePanel = ({ label, value, vibe }: { label: string; value: string; vibe
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="mb-1.5 text-xs font-semibold uppercase tracking-wide text-base-content/50">
|
||||
<p className="mb-1.5 text-xs font-semibold uppercase tracking-wide text-base-content/70">
|
||||
Core
|
||||
</p>
|
||||
<div className="grid gap-2 sm:grid-cols-2">
|
||||
@@ -69,7 +69,7 @@ const ThemePanel = ({ label, value, vibe }: { label: string; value: string; vibe
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="mb-1.5 text-xs font-semibold uppercase tracking-wide text-base-content/50">
|
||||
<p className="mb-1.5 text-xs font-semibold uppercase tracking-wide text-base-content/70">
|
||||
Status
|
||||
</p>
|
||||
<div className="grid gap-2 grid-cols-2 sm:grid-cols-4">
|
||||
@@ -81,7 +81,7 @@ const ThemePanel = ({ label, value, vibe }: { label: string; value: string; vibe
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="mb-1.5 text-xs font-semibold uppercase tracking-wide text-base-content/50">
|
||||
<p className="mb-1.5 text-xs font-semibold uppercase tracking-wide text-base-content/70">
|
||||
Content
|
||||
</p>
|
||||
<div className="grid gap-2 sm:grid-cols-3">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const EmptyState = ({ message }: { message: string }) => (
|
||||
<div className="card bg-base-100 shadow">
|
||||
<div className="card-body items-center py-12">
|
||||
<p className="text-sm text-base-content/60 text-center m-0">{message}</p>
|
||||
<p className="text-sm text-base-content/70 text-center m-0">{message}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -33,7 +33,7 @@ const ProfileSidebarCard = ({
|
||||
<div className="card-body gap-4 p-6">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold m-0 leading-tight">{displayName}</h1>
|
||||
<p className="text-sm text-base-content/60 m-0 mt-0.5">@{username}</p>
|
||||
<p className="text-sm text-base-content/70 m-0 mt-0.5">@{username}</p>
|
||||
</div>
|
||||
|
||||
{isOwnProfile ? (
|
||||
@@ -52,7 +52,7 @@ const ProfileSidebarCard = ({
|
||||
|
||||
<p className="text-sm leading-normal m-0">{bio}</p>
|
||||
|
||||
<div className="flex flex-col gap-1.5 text-sm text-base-content/60">
|
||||
<div className="flex flex-col gap-1.5 text-sm text-base-content/70">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<MapPin className="size-4 shrink-0" aria-hidden="true" />
|
||||
{location}
|
||||
@@ -68,7 +68,7 @@ const ProfileSidebarCard = ({
|
||||
<div className="flex flex-col gap-2">
|
||||
{stats.map((stat) => (
|
||||
<div key={stat.label} className="flex items-center justify-between gap-2">
|
||||
<span className="text-sm text-base-content/60">{stat.label}</span>
|
||||
<span className="text-sm text-base-content/70">{stat.label}</span>
|
||||
<span className="font-serif text-lg font-bold tabular-nums">
|
||||
{stat.value}
|
||||
</span>
|
||||
|
||||
@@ -24,7 +24,7 @@ const ProfileTabs = ({ activeTab, onChange, panels }: ProfileTabsProps) => {
|
||||
{TABS.map((tab) => (
|
||||
<Tab
|
||||
key={tab.id}
|
||||
className="-mb-px border-b-2 border-transparent py-3 text-sm font-semibold text-base-content/60 transition-colors hover:text-base-content focus:outline-none data-[focus]:outline-2 data-[focus]:outline-offset-2 data-[focus]:outline-primary data-[selected]:border-primary data-[selected]:text-primary"
|
||||
className="-mb-px border-b-2 border-transparent py-3 text-sm font-semibold text-base-content/70 transition-colors hover:text-base-content focus:outline-none data-[focus]:outline-2 data-[focus]:outline-offset-2 data-[focus]:outline-primary data-[selected]:border-primary data-[selected]:text-primary"
|
||||
>
|
||||
{tab.label}
|
||||
</Tab>
|
||||
|
||||
@@ -36,11 +36,11 @@ const ActivityTab = ({ activity }: ActivityTabProps) => {
|
||||
</div>
|
||||
)}
|
||||
{item.comment && (
|
||||
<p className="text-sm text-base-content/60 italic mt-1.5 mb-0">
|
||||
<p className="text-sm text-base-content/70 italic mt-1.5 mb-0">
|
||||
“{item.comment}”
|
||||
</p>
|
||||
)}
|
||||
<p className="text-xs text-base-content/60 mt-1.5 mb-0">
|
||||
<p className="text-xs text-base-content/70 mt-1.5 mb-0">
|
||||
{item.time}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +42,7 @@ const FollowingTab = ({ following, onToggleFollow }: FollowingTabProps) => {
|
||||
) : (
|
||||
<p className="font-semibold text-sm m-0 truncate">{f.name}</p>
|
||||
)}
|
||||
<p className="text-xs text-base-content/60 m-0 truncate">{f.meta}</p>
|
||||
<p className="text-xs text-base-content/70 m-0 truncate">{f.meta}</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -18,7 +18,7 @@ const LikedTab = ({ liked }: LikedTabProps) => {
|
||||
<div className="h-[120px] bg-base-300" />
|
||||
<div className="card-body p-4 gap-1">
|
||||
<p className="font-serif font-bold m-0">{item.name}</p>
|
||||
<p className="text-sm text-base-content/60 m-0">{item.meta}</p>
|
||||
<p className="text-sm text-base-content/70 m-0">{item.meta}</p>
|
||||
<div className="mt-1">
|
||||
<StarRating value={item.rating} size="xs" />
|
||||
</div>
|
||||
|
||||
@@ -75,7 +75,7 @@ const ProfileContent = ({ profile, isOwnProfile }: ProfileContentProps) => {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-base-200 pb-16">
|
||||
<div className="max-w-[1080px] mx-auto px-6 pt-8">
|
||||
<div className="mx-auto max-w-7xl px-5 pt-10">
|
||||
<div className="rounded-box h-[190px] bg-base-300" />
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-[300px_1fr] gap-8 items-start -mt-12">
|
||||
|
||||
@@ -13,7 +13,7 @@ import './app.css';
|
||||
import Navbar from './components/ui/navbar/Navbar';
|
||||
import ToastProvider from './components/ui/toast/ToastProvider';
|
||||
import { getOptionalAuth } from './features/auth/auth.server';
|
||||
import AiDisclosureDialog from './features/disclosure/components/AiDisclosureDialog';
|
||||
import AiDisclosureDialog from './features/home/components/AiDisclosureDialog';
|
||||
import { defaultThemeName, parseThemeCookie } from './features/theme/themes';
|
||||
|
||||
export const links: Route.LinksFunction = () => [
|
||||
@@ -86,7 +86,7 @@ export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="pt-16 p-4 container mx-auto">
|
||||
<main className="mx-auto max-w-7xl px-5 pt-10">
|
||||
<h1>{message}</h1>
|
||||
<p>{details}</p>
|
||||
{stack && (
|
||||
|
||||
Reference in New Issue
Block a user