Style/Revamp #4

Merged
me merged 12 commits from feature/home_revamp into main 2026-05-08 03:16:16 +00:00
3 changed files with 52 additions and 24 deletions
Showing only changes of commit aeead98570 - Show all commits
@@ -3,19 +3,23 @@ import { GearFineIcon } from "@phosphor-icons/react";
interface DrawerSectionProps { interface DrawerSectionProps {
id: string; id: string;
title: string; title: string;
count: string; count: number;
subtext: string;
isOpen: boolean; isOpen: boolean;
onClick: () => void; onClick: () => void;
children: React.ReactNode; children: React.ReactNode;
icon: React.ReactNode;
} }
export function DrawerSection({ export function DrawerSection({
id, id,
title, title,
count, count,
subtext,
isOpen, isOpen,
onClick, onClick,
children, children,
icon,
}: DrawerSectionProps) { }: DrawerSectionProps) {
return ( return (
<div <div
@@ -23,20 +27,29 @@ export function DrawerSection({
className={`join-item group flex flex-col transition-colors duration-3000 ease-in-out ${isOpen ? "bg-base-300/30" : ""}`} className={`join-item group flex flex-col transition-colors duration-3000 ease-in-out ${isOpen ? "bg-base-300/30" : ""}`}
> >
<div <div
className={`transition-all duration-1500 ease-in-out bg-neutral/10 ${ className={`bg-neutral/10 transition-all duration-1000 ease-in-out overflow-visible ${isOpen ? "max-h-125" : "max-h-0 pointer-events-none"}`}
isOpen
? "max-h-125 opacity-100 py-3 border-b border-base-content/5 overflow-visible"
: "max-h-0 opacity-0 pointer-events-none"
}`}
> >
{children} <div
className={`transition-opacity ease-in-out ${
isOpen
? "opacity-100 py-3 border-b border-base-content/5 duration-700 delay-500"
: "opacity-0 duration-100"
}`}
>
{children}
{count === 0 && (
<div className="text-sm text-center text-neutral">
This drawer remains silent...
</div>
)}
</div>
</div> </div>
<button <button
type="button" type="button"
onClick={onClick} onClick={onClick}
data-testid={`drawer-section-${id}`} data-testid={`drawer-section-${id}`}
className={`w-full p-[24px_28px] cursor-pointer flex items-center gap-5 transition-all duration-2000 ease-in-out outline-none focus-visible:ring-2 focus-visible:ring-primary/50 border border-base-content/10 text-left bg-linear-to-r from-transparent to-base-100/40`} className="w-full relative p-[24px_28px] cursor-pointer flex items-center gap-5 transition-all duration-2000 ease-in-out outline-none focus-visible:ring-2 overflow-hidden focus-visible:ring-primary/50 border border-base-content/10 text-left bg-linear-to-r from-transparent to-base-100/40"
> >
<div className="flex-1"> <div className="flex-1">
<div <div
@@ -48,8 +61,14 @@ export function DrawerSection({
> >
{title} {title}
</div> </div>
<div className="font-sans text-[0.6rem] text-base-content/20 mt-1"> <div className="font-sans text-xs text-base-content/20 mt-1">
{count} <span className="font-mono text-xs md:text-base -mt-1 absolute text-primary/30">
{count}
</span>{" "}
<span className="ml-3">{subtext}</span>
</div>
<div className="absolute right-5 -translate-y-15 text-base-content/4">
{icon}
</div> </div>
</div> </div>
@@ -36,7 +36,7 @@ export function LetterItem({
data-testid={`letter-item-${id}`} data-testid={`letter-item-${id}`}
className={`${isLocked ? "pointer-events-none" : ""} p-4 border-base-content/3 flex items-start gap-4 hover:bg-base-300 transition-all delay-75 duration-100 group text-left cursor-pointer w-9/12 mx-auto hover:scale-120 hover:h-24 hover:-translate-y-3 hover:pb-4 hover:border-x-5 hover:border-t-5 border-t-2 hover:-mb-2`} className={`${isLocked ? "pointer-events-none" : ""} p-4 border-base-content/3 flex items-start gap-4 hover:bg-base-300 transition-all delay-75 duration-100 group text-left cursor-pointer w-9/12 mx-auto hover:scale-120 hover:h-24 hover:-translate-y-3 hover:pb-4 hover:border-x-5 hover:border-t-5 border-t-2 hover:-mb-2`}
> >
<div className="text-[0.85rem] italic text-base-content/40 flex-1 truncate group-hover:text-base-content/60 transition-none animate-[opacity_200ms_linear_forwards]"> <div className="text-sm italic text-base-content/40 flex-1 truncate group-hover:text-base-content/60">
{preview} {preview}
</div> </div>
{unlock_at ? ( {unlock_at ? (
@@ -53,7 +53,7 @@ export function LetterItem({
)} )}
</div> </div>
) : ( ) : (
<div className="font-sans text-[0.6rem] text-base-content/20 transition-none"> <div className="font-sans text-xs text-base-content/20">
{timestamp} {timestamp}
</div> </div>
)} )}
+21 -12
View File
@@ -1,4 +1,10 @@
import { FeatherIcon } from "@phosphor-icons/react"; import {
ArchiveIcon,
FeatherIcon,
FileDashedIcon,
PaperPlaneTiltIcon,
VaultIcon,
} from "@phosphor-icons/react";
import { useState } from "react"; import { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { DrawerSection } from "../components/drawer/DrawerSection.tsx"; import { DrawerSection } from "../components/drawer/DrawerSection.tsx";
@@ -47,7 +53,7 @@ export default function Drawer() {
{isAuthRequired && <PasskeyModal />} {isAuthRequired && <PasskeyModal />}
<header className="text-center mb-12 z-10 animate-in fade-in slide-in-from-top-4 duration-500"> <header className="text-center mb-12 z-10 animate-in fade-in slide-in-from-top-4 duration-500">
<Logo /> <Logo type="logo" />
<div className="font-sans text-xs tracking-widester uppercase text-base-content/40 mt-2"> <div className="font-sans text-xs tracking-widester uppercase text-base-content/40 mt-2">
Personal Archive Personal Archive
</div> </div>
@@ -77,9 +83,11 @@ export default function Drawer() {
<DrawerSection <DrawerSection
id="drafts" id="drafts"
title="Drafts" title="Drafts"
count={`${drafts.length} unfinished whispers`} count={drafts.length}
subtext="unfinished whispers"
isOpen={openSection === "drafts"} isOpen={openSection === "drafts"}
onClick={() => toggleSection("drafts")} onClick={() => toggleSection("drafts")}
icon={<FileDashedIcon weight="thin" size={128} />}
> >
{drafts.map((draft) => ( {drafts.map((draft) => (
<LetterItem <LetterItem
@@ -95,9 +103,11 @@ export default function Drawer() {
<DrawerSection <DrawerSection
id="kept" id="kept"
title="Kept" title="Kept"
count={`${kept.length} private letters`} count={kept.length}
subtext="private letters"
isOpen={openSection === "kept"} isOpen={openSection === "kept"}
onClick={() => toggleSection("kept")} onClick={() => toggleSection("kept")}
icon={<ArchiveIcon weight="thin" size={128} />}
> >
{kept.map((letter) => ( {kept.map((letter) => (
<LetterItem <LetterItem
@@ -112,9 +122,11 @@ export default function Drawer() {
<DrawerSection <DrawerSection
id="sent" id="sent"
title="Sent" title="Sent"
count={`${sent.length} shared truths`} count={sent.length}
subtext="shared truths"
isOpen={openSection === "sent"} isOpen={openSection === "sent"}
onClick={() => toggleSection("sent")} onClick={() => toggleSection("sent")}
icon={<PaperPlaneTiltIcon weight="thin" size={128} />}
> >
{sent.map((letter) => ( {sent.map((letter) => (
<LetterItem <LetterItem
@@ -125,18 +137,15 @@ export default function Drawer() {
timestamp={formatRelativeDate(letter.updated_at)} timestamp={formatRelativeDate(letter.updated_at)}
/> />
))} ))}
{sent.length === 0 && (
<p className="text-center text-base-content/20 mt-4">
This drawer remains silent
</p>
)}
</DrawerSection> </DrawerSection>
<DrawerSection <DrawerSection
id="vault" id="vault"
title="Vault" title="Vault"
count={`${vault.length} things locked;not lost;in time`} count={vault.length}
subtext="things locked—not lost—in time"
isOpen={openSection === "vault"} isOpen={openSection === "vault"}
onClick={() => toggleSection("vault")} onClick={() => toggleSection("vault")}
icon={<VaultIcon weight="thin" size={128} />}
> >
{vault.map((letter) => ( {vault.map((letter) => (
<LetterItem <LetterItem
@@ -179,7 +188,7 @@ export default function Drawer() {
</span> </span>
</button> </button>
<footer className="mt-25 font-sans text-[0.6rem] tracking-widester uppercase text-base-content/10 z-10"> <footer className="mt-25 font-sans text-xs tracking-widester uppercase text-base-content/10 z-10">
For your unsaid. For your unsaid.
</footer> </footer>
{!showWelcomeLetter && ( {!showWelcomeLetter && (