Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/components/AppFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ export function AppFooter() {
const { t } = useTranslation();

return (
<footer className="mt-auto border-t border-brand-dark-green py-6 pb-[calc(1.5rem+4rem+env(safe-area-inset-bottom))] md:pb-6 bg-brand-dark-green">
<div className="container">
<div className="max-w-5xl mx-auto">
<footer className="mt-auto bg-transparent px-4 pb-[calc(1.5rem+4rem+env(safe-area-inset-bottom))] pt-6 md:px-6 md:pb-6">
<div className="mx-auto max-w-6xl">
<div className="rounded-[32px] border border-brand-green/30 bg-brand-dark-green px-5 py-6 shadow-[0_24px_60px_rgba(8,29,23,0.35)] sm:px-6">
{/* Main Footer Content - Side by side on desktop */}
<div className="flex flex-col lg:flex-row lg:items-start lg:justify-between gap-6 mb-6">
{/* Left side - Email signup */}
Expand Down
75 changes: 75 additions & 0 deletions src/components/AppPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { HTMLAttributes, ReactNode } from 'react';

import { cn } from '@/lib/utils';

type AppPageWidth = 'feed' | 'default' | 'detail' | 'wide' | 'full';

const widthClassMap: Record<AppPageWidth, string> = {
feed: 'max-w-[42rem]',
default: 'max-w-[48rem]',
detail: 'max-w-[52rem]',
wide: 'max-w-[72rem]',
full: 'max-w-[88rem]',
};

interface AppPageProps extends HTMLAttributes<HTMLElement> {
width?: AppPageWidth;
}

interface AppPageHeaderProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
eyebrow?: ReactNode;
title: ReactNode;
description?: ReactNode;
actions?: ReactNode;
titleClassName?: string;
descriptionClassName?: string;
}

export function AppPage({
children,
className,
width = 'default',
...props
}: AppPageProps) {
return (
<section className={cn('app-page', className)} {...props}>
<div className={cn('app-page__inner', widthClassMap[width])}>
{children}
</div>
</section>
);
}

export function AppPageHeader({
eyebrow,
title,
description,
actions,
children,
className,
titleClassName,
descriptionClassName,
...props
}: AppPageHeaderProps) {
return (
<header className={cn('app-page__header', className)} {...props}>
<div className="flex flex-col gap-4 md:flex-row md:items-start md:justify-between">
<div className="min-w-0 space-y-2">
{eyebrow ? <div className="app-eyebrow">{eyebrow}</div> : null}
<h1 className={cn('app-title', titleClassName)}>{title}</h1>
{description ? (
<p className={cn('app-subtitle', descriptionClassName)}>
{description}
</p>
) : null}
</div>
{actions ? (
<div className="flex shrink-0 items-center gap-2 self-start md:pt-1">
{actions}
</div>
) : null}
</div>
{children}
</header>
);
}
41 changes: 41 additions & 0 deletions src/components/AppSectionNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { ReactNode } from 'react';

import { SmartLink } from '@/components/SmartLink';
import { cn } from '@/lib/utils';

interface AppSectionNavItem {
label: ReactNode;
to: string;
icon?: ReactNode;
active?: boolean;
ownerPubkey?: string | null;
}

interface AppSectionNavProps {
items: AppSectionNavItem[];
className?: string;
}

export function AppSectionNav({ items, className }: AppSectionNavProps) {
if (!items.length) {
return null;
}

return (
<nav className={cn('app-chip-row', className)} aria-label="Section navigation">
<div className="flex gap-2 pb-2">
{items.map((item) => (
<SmartLink
key={`${item.to}-${typeof item.label === 'string' ? item.label : 'nav-item'}`}
to={item.to}
ownerPubkey={item.ownerPubkey}
className={cn('app-chip min-w-fit', item.active && 'app-chip-active')}
>
{item.icon}
<span>{item.label}</span>
</SmartLink>
))}
</div>
</nav>
);
}
60 changes: 60 additions & 0 deletions src/components/CreatorSectionNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
ChartBar as BarChart3,
LinkSimple as Link2,
List,
Shield,
UserCircle as UserRound,
} from '@phosphor-icons/react';

import { AppSectionNav } from '@/components/AppSectionNav';

type CreatorSection = 'analytics' | 'lists' | 'moderation' | 'linked-accounts' | 'profile';

interface CreatorSectionNavProps {
active: CreatorSection;
profilePath?: string;
}

export function CreatorSectionNav({
active,
profilePath,
}: CreatorSectionNavProps) {
return (
<AppSectionNav
items={[
{
label: 'Analytics',
to: '/analytics',
icon: <BarChart3 className="h-4 w-4" />,
active: active === 'analytics',
},
{
label: 'Lists',
to: '/lists',
icon: <List className="h-4 w-4" />,
active: active === 'lists',
},
{
label: 'Moderation',
to: '/settings/moderation',
icon: <Shield className="h-4 w-4" />,
active: active === 'moderation',
},
{
label: 'Linked Accounts',
to: '/settings/linked-accounts',
icon: <Link2 className="h-4 w-4" />,
active: active === 'linked-accounts',
},
...(profilePath
? [{
label: 'Profile',
to: profilePath,
icon: <UserRound className="h-4 w-4" />,
active: active === 'profile',
}]
: []),
]}
/>
);
}
59 changes: 59 additions & 0 deletions src/components/DiscoverySectionNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
Compass,
Fire as Flame,
Hash,
SquaresFour as LayoutGrid,
Trophy,
} from '@phosphor-icons/react';

import { AppSectionNav } from '@/components/AppSectionNav';

type DiscoverySection =
| 'discover'
| 'trending'
| 'hashtags'
| 'categories'
| 'leaderboard';

interface DiscoverySectionNavProps {
active: DiscoverySection;
}

export function DiscoverySectionNav({ active }: DiscoverySectionNavProps) {
return (
<AppSectionNav
items={[
{
label: 'Discover',
to: '/discovery/classics',
icon: <Compass className="h-4 w-4" />,
active: active === 'discover',
},
{
label: 'Trending',
to: '/trending',
icon: <Flame className="h-4 w-4" />,
active: active === 'trending',
},
{
label: 'Hashtags',
to: '/hashtags',
icon: <Hash className="h-4 w-4" />,
active: active === 'hashtags',
},
{
label: 'Categories',
to: '/category',
icon: <LayoutGrid className="h-4 w-4" />,
active: active === 'categories',
},
{
label: 'Leaderboard',
to: '/leaderboard',
icon: <Trophy className="h-4 w-4" />,
active: active === 'leaderboard',
},
]}
/>
);
}
25 changes: 11 additions & 14 deletions src/components/MarketingHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,24 @@

import { Link } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { ArrowRight } from "@phosphor-icons/react";

export function MarketingHeader() {
const { t } = useTranslation();

return (
<nav className="fixed top-0 left-0 right-0 z-50 bg-brand-dark-green border-b border-brand-green">
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
{/* Logo */}
<Link to="/">
<div className="flex h-16 items-center justify-between gap-4">
<Link to="/" className="shrink-0">
<img
src="/divine-logo.svg"
alt="Divine"
className="h-5"
/>
</Link>

{/* Navigation Links */}
<div className="flex items-center gap-8">
<div className="hidden items-center gap-8 md:flex">
<a
href="https://about.divine.video/"
className="text-sm font-medium text-brand-off-white hover:text-brand-green transition-colors"
Expand Down Expand Up @@ -52,16 +51,14 @@ export function MarketingHeader() {
>
{t('menu.merch')}
</Link>
<Link
to="/discovery"
className="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-semibold bg-primary text-primary-foreground rounded-full hover:brightness-110 transition-colors"
>
Try it
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
</svg>
</Link>
</div>
<Link
to="/discovery"
className="inline-flex shrink-0 items-center gap-1.5 rounded-full bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground transition-colors hover:brightness-110"
>
Try it
<ArrowRight className="h-4 w-4" />
</Link>
</div>
</div>
</nav>
Expand Down
6 changes: 3 additions & 3 deletions src/components/MarketingLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ interface MarketingLayoutProps {

export function MarketingLayout({ children }: MarketingLayoutProps) {
return (
<div className="min-h-screen flex flex-col bg-background">
<div className="min-h-screen flex flex-col bg-background text-foreground">
<MarketingHeader />
<div className="flex-1 pt-16">
<main className="marketing-shell pt-[6.25rem] md:pt-28">
{children}
</div>
</main>
<AppFooter />
</div>
);
Expand Down
7 changes: 7 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
--sar: env(safe-area-inset-right, 0px);
--sab: env(safe-area-inset-bottom, 0px);
--sal: env(safe-area-inset-left, 0px);
--app-header-height: 4rem;

/* Design tokens for improved styling */
--radius-small: 0.5rem;
Expand Down Expand Up @@ -183,6 +184,12 @@

--sidebar-ring: 158 67% 46%;
}

@media (min-width: 768px) {
:root {
--app-header-height: 0px;
}
}
}

/* Prevent browser overflow anchoring from shifting feed on dynamic updates */
Expand Down
2 changes: 1 addition & 1 deletion src/pages/AboutPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function AboutPage() {

return (
<MarketingLayout>
<div className="container mx-auto px-4 py-8 max-w-4xl">
<div className="marketing-page marketing-page--default marketing-stack">
<ZendeskWidget />
<h1 className="text-4xl font-bold mb-8">{t('title')}</h1>

Expand Down
2 changes: 1 addition & 1 deletion src/pages/AuthenticityPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function AuthenticityPage() {

return (
<MarketingLayout>
<div className="container max-w-4xl mx-auto py-8 px-4 space-y-8">
<div className="marketing-page marketing-page--default marketing-stack">
<ZendeskWidget />
{/* Hero Section */}
<div className="text-center space-y-4 py-8">
Expand Down
2 changes: 1 addition & 1 deletion src/pages/FAQPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function FAQPage() {

return (
<MarketingLayout>
<div className="container mx-auto px-4 py-8 max-w-4xl">
<div className="marketing-page marketing-page--default marketing-stack">
<ZendeskWidget />
<div className="text-center space-y-4 mb-8">
<div className="flex items-center justify-center gap-3">
Expand Down
2 changes: 1 addition & 1 deletion src/pages/GetEmbedPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function GetEmbedPage() {

return (
<MarketingLayout>
<div className="container mx-auto px-4 py-8 max-w-4xl">
<div className="marketing-page marketing-page--default marketing-stack">
<div className="flex items-center gap-3 mb-2">
<Code className="h-8 w-8 text-brand-green" />
<h1 className="text-4xl font-bold">{t('getEmbedPage.title')}</h1>
Expand Down
Loading
Loading