Skip to content
Merged
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
140 changes: 136 additions & 4 deletions apps/web/src/routes/_view/about.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Icon } from "@iconify-icon/react";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { Mail, XIcon } from "lucide-react";
import { Mail, Menu, X, XIcon } from "lucide-react";
import { AnimatePresence, motion } from "motion/react";
import { useEffect, useState } from "react";

import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@hypr/ui/components/ui/resizable";
import { useIsMobile } from "@hypr/ui/hooks/use-mobile";
import { cn } from "@hypr/utils";

import { Image } from "@/components/image";
Expand Down Expand Up @@ -224,13 +225,44 @@ function AboutContentSection({
selectedItem: SelectedItem | null;
setSelectedItem: (item: SelectedItem | null) => void;
}) {
const isMobile = useIsMobile();
const [drawerOpen, setDrawerOpen] = useState(false);

return (
<section className="px-6 pb-16 lg:pb-24">
<div className="max-w-4xl mx-auto">
<MockWindow title="About" className="rounded-lg w-full max-w-none">
<div className="h-[480px]">
<MockWindow
title="About"
className="rounded-lg w-full max-w-none"
prefixIcons={
isMobile &&
selectedItem && (
<button
onClick={() => setDrawerOpen(true)}
className="p-1 hover:bg-neutral-200 rounded transition-colors"
aria-label="Open navigation"
>
<Menu className="w-4 h-4 text-neutral-600" />
</button>
)
}
>
<div className="h-[480px] relative">
{!selectedItem ? (
<AboutGridView setSelectedItem={setSelectedItem} />
) : isMobile ? (
<>
<MobileSidebarDrawer
open={drawerOpen}
onClose={() => setDrawerOpen(false)}
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
/>
<AboutDetailContent
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
/>
</>
) : (
<AboutDetailView
selectedItem={selectedItem}
Expand Down Expand Up @@ -388,6 +420,106 @@ function AboutDetailView({
);
}

function MobileSidebarDrawer({
open,
onClose,
selectedItem,
setSelectedItem,
}: {
open: boolean;
onClose: () => void;
selectedItem: SelectedItem;
setSelectedItem: (item: SelectedItem) => void;
}) {
return (
<AnimatePresence>
{open && (
<>
<motion.div
className="absolute inset-0 z-40 bg-black/20"
onClick={onClose}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
/>
<motion.div
className="absolute left-0 top-0 bottom-0 z-50 w-72 bg-white border-r border-neutral-200 shadow-lg"
initial={{ x: "-100%" }}
animate={{ x: 0 }}
exit={{ x: "-100%" }}
transition={{ type: "spring", damping: 25, stiffness: 300 }}
>
<div className="flex items-center justify-between px-4 py-3 border-b border-neutral-200 bg-stone-50">
<span className="text-sm font-medium text-stone-600">
Navigation
</span>
<button
onClick={onClose}
className="p-1 hover:bg-neutral-200 rounded transition-colors"
aria-label="Close drawer"
>
<X className="w-4 h-4 text-neutral-600" />
</button>
</div>
<div className="h-[calc(100%-49px)] overflow-y-auto p-4">
<OurStorySidebar
selectedItem={selectedItem}
setSelectedItem={(item) => {
setSelectedItem(item);
onClose();
}}
/>
<FoundersSidebar
selectedItem={selectedItem}
setSelectedItem={(item) => {
setSelectedItem(item);
onClose();
}}
/>
<TeamPhotosSidebar
selectedItem={selectedItem}
setSelectedItem={(item) => {
setSelectedItem(item);
onClose();
}}
/>
</div>
</motion.div>
</>
)}
</AnimatePresence>
);
}

function AboutDetailContent({
selectedItem,
setSelectedItem,
}: {
selectedItem: SelectedItem;
setSelectedItem: (item: SelectedItem | null) => void;
}) {
return (
<div className="h-full flex flex-col">
{selectedItem?.type === "story" && (
<StoryDetail onClose={() => setSelectedItem(null)} />
)}
{selectedItem?.type === "founder" && (
<FounderDetail
founder={selectedItem.data}
onClose={() => setSelectedItem(null)}
/>
)}
{selectedItem?.type === "photo" && (
<PhotoDetail
photo={selectedItem.data}
onClose={() => setSelectedItem(null)}
/>
)}
</div>
);
}

function AboutSidebar({
selectedItem,
setSelectedItem,
Expand Down
142 changes: 139 additions & 3 deletions apps/web/src/routes/_view/brand.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { createFileRoute } from "@tanstack/react-router";
import { XIcon } from "lucide-react";
import { Menu, X, XIcon } from "lucide-react";
import { AnimatePresence, motion } from "motion/react";
import { useState } from "react";

import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@hypr/ui/components/ui/resizable";
import { useIsMobile } from "@hypr/ui/hooks/use-mobile";
import { cn } from "@hypr/utils";

import { MockWindow } from "@/components/mock-window";
Expand Down Expand Up @@ -159,13 +161,44 @@ function BrandContentSection({
selectedItem: SelectedItem | null;
setSelectedItem: (item: SelectedItem | null) => void;
}) {
const isMobile = useIsMobile();
const [drawerOpen, setDrawerOpen] = useState(false);

return (
<section className="px-6 pb-16 lg:pb-24">
<div className="max-w-4xl mx-auto">
<MockWindow title="Brand" className="rounded-lg w-full max-w-none">
<div className="h-[480px]">
<MockWindow
title="Brand"
className="rounded-lg w-full max-w-none"
prefixIcons={
isMobile &&
selectedItem && (
<button
onClick={() => setDrawerOpen(true)}
className="p-1 hover:bg-neutral-200 rounded transition-colors"
aria-label="Open navigation"
>
<Menu className="w-4 h-4 text-neutral-600" />
</button>
)
}
>
<div className="h-[480px] relative">
{!selectedItem ? (
<BrandGridView setSelectedItem={setSelectedItem} />
) : isMobile ? (
<>
<MobileSidebarDrawer
open={drawerOpen}
onClose={() => setDrawerOpen(false)}
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
/>
<BrandDetailContent
selectedItem={selectedItem}
setSelectedItem={setSelectedItem}
/>
</>
) : (
<BrandDetailView
selectedItem={selectedItem}
Expand Down Expand Up @@ -311,6 +344,109 @@ function BrandDetailView({
);
}

function MobileSidebarDrawer({
open,
onClose,
selectedItem,
setSelectedItem,
}: {
open: boolean;
onClose: () => void;
selectedItem: SelectedItem;
setSelectedItem: (item: SelectedItem) => void;
}) {
return (
<AnimatePresence>
{open && (
<>
<motion.div
className="absolute inset-0 z-40 bg-black/20"
onClick={onClose}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
/>
<motion.div
className="absolute left-0 top-0 bottom-0 z-50 w-72 bg-white border-r border-neutral-200 shadow-lg"
initial={{ x: "-100%" }}
animate={{ x: 0 }}
exit={{ x: "-100%" }}
transition={{ type: "spring", damping: 25, stiffness: 300 }}
>
<div className="flex items-center justify-between px-4 py-3 border-b border-neutral-200 bg-stone-50">
<span className="text-sm font-medium text-stone-600">
Navigation
</span>
<button
onClick={onClose}
className="p-1 hover:bg-neutral-200 rounded transition-colors"
aria-label="Close drawer"
>
<X className="w-4 h-4 text-neutral-600" />
</button>
</div>
<div className="h-[calc(100%-49px)] overflow-y-auto p-4">
<VisualAssetsSidebar
selectedItem={selectedItem}
setSelectedItem={(item) => {
setSelectedItem(item);
onClose();
}}
/>
<TypographySidebar
selectedItem={selectedItem}
setSelectedItem={(item) => {
setSelectedItem(item);
onClose();
}}
/>
<ColorsSidebar
selectedItem={selectedItem}
setSelectedItem={(item) => {
setSelectedItem(item);
onClose();
}}
/>
</div>
</motion.div>
</>
)}
</AnimatePresence>
);
}

function BrandDetailContent({
selectedItem,
setSelectedItem,
}: {
selectedItem: SelectedItem;
setSelectedItem: (item: SelectedItem | null) => void;
}) {
return (
<div className="h-full flex flex-col">
{selectedItem.type === "visual" && (
<VisualAssetDetail
asset={selectedItem.data}
onClose={() => setSelectedItem(null)}
/>
)}
{selectedItem.type === "typography" && (
<TypographyDetail
font={selectedItem.data}
onClose={() => setSelectedItem(null)}
/>
)}
{selectedItem.type === "color" && (
<ColorDetail
color={selectedItem.data}
onClose={() => setSelectedItem(null)}
/>
)}
</div>
);
}

function BrandSidebar({
selectedItem,
setSelectedItem,
Expand Down
Loading