One Calendar is a privacy-first calendar web app built with Next.js. It has modern security features, including e2ee, password-protected sharing, and self-destructing share links ๐Ÿ“… calendar.xyehr.cn

Update hero reveal animation and encrypted comparison demo

+54 -42
+17
app/globals.css
··· 10 .text-balance { 11 text-wrap: balance; 12 } 13 } 14 15 @layer components {
··· 10 .text-balance { 11 text-wrap: balance; 12 } 13 + 14 + .landing-hero-reveal { 15 + animation: landing-hero-reveal 900ms cubic-bezier(0.22, 1, 0.36, 1) both; 16 + } 17 + } 18 + 19 + @keyframes landing-hero-reveal { 20 + from { 21 + opacity: 0; 22 + filter: blur(12px); 23 + transform: translateY(10px); 24 + } 25 + to { 26 + opacity: 1; 27 + filter: blur(0); 28 + transform: translateY(0); 29 + } 30 } 31 32 @layer components {
+33 -38
components/landing/landing-hero-demo.tsx
··· 1 "use client"; 2 3 import { cn } from "@/lib/utils"; 4 5 type DemoEvent = { ··· 38 }, 39 ]; 40 41 - const dayColumns = ["Mon", "Tue", "Wed", "Thu", "Fri"]; 42 43 function WeekViewEventBlock({ event }: { event: DemoEvent }) { 44 return ( ··· 61 <div className="mt-6 grid gap-4 lg:grid-cols-[1.2fr_1fr]"> 62 <div className="rounded-xl border border-white/10 bg-[var(--landing-panel)] p-4"> 63 <p className="mb-3 text-xs uppercase tracking-[0.14em] text-[var(--landing-subtle)]">Week View</p> 64 - <div className="grid grid-cols-5 gap-2"> 65 - {dayColumns.map((day) => ( 66 - <div key={day} className="rounded-md border border-white/10 bg-black/20 p-2 text-center text-xs text-[var(--landing-muted)]"> 67 - {day} 68 - </div> 69 - ))} 70 - </div> 71 - <div className="mt-3 space-y-2"> 72 {demoEvents.map((event) => ( 73 <WeekViewEventBlock key={event.id} event={event} /> 74 ))} ··· 76 </div> 77 78 <div className="rounded-xl border border-white/10 bg-[var(--landing-panel)] p-4"> 79 - <p className="mb-3 text-xs uppercase tracking-[0.14em] text-[var(--landing-subtle)]">Planning Insights</p> 80 - <div className="space-y-3"> 81 - <div> 82 - <div className="mb-1 flex items-center justify-between text-xs text-[var(--landing-muted)]"> 83 - <span>Focus time</span> 84 - <span>68%</span> 85 - </div> 86 - <div className="h-2 rounded-full bg-white/10"> 87 - <div className="h-2 w-[68%] rounded-full bg-white/80" /> 88 - </div> 89 - </div> 90 - <div> 91 - <div className="mb-1 flex items-center justify-between text-xs text-[var(--landing-muted)]"> 92 - <span>Meetings</span> 93 - <span>22%</span> 94 - </div> 95 - <div className="h-2 rounded-full bg-white/10"> 96 - <div className="h-2 w-[22%] rounded-full bg-white/60" /> 97 - </div> 98 - </div> 99 - <div> 100 - <div className="mb-1 flex items-center justify-between text-xs text-[var(--landing-muted)]"> 101 - <span>Buffer</span> 102 - <span>10%</span> 103 - </div> 104 - <div className="h-2 rounded-full bg-white/10"> 105 - <div className="h-2 w-[10%] rounded-full bg-white/50" /> 106 - </div> 107 - </div> 108 </div> 109 </div> 110 </div>
··· 1 "use client"; 2 3 + import { Fragment } from "react"; 4 import { cn } from "@/lib/utils"; 5 6 type DemoEvent = { ··· 39 }, 40 ]; 41 42 + const encryptedRows = [ 43 + { 44 + cipher: "A9F4-77C1-98D2-E31B", 45 + plain: "Project roadmap planning", 46 + }, 47 + { 48 + cipher: "7B22-4D11-C0EF-6A8A", 49 + plain: "Design review with team", 50 + }, 51 + { 52 + cipher: "EE91-23AA-44B8-90F2", 53 + plain: "Focus block: implementation", 54 + }, 55 + ]; 56 57 function WeekViewEventBlock({ event }: { event: DemoEvent }) { 58 return ( ··· 75 <div className="mt-6 grid gap-4 lg:grid-cols-[1.2fr_1fr]"> 76 <div className="rounded-xl border border-white/10 bg-[var(--landing-panel)] p-4"> 77 <p className="mb-3 text-xs uppercase tracking-[0.14em] text-[var(--landing-subtle)]">Week View</p> 78 + <div className="space-y-2"> 79 {demoEvents.map((event) => ( 80 <WeekViewEventBlock key={event.id} event={event} /> 81 ))} ··· 83 </div> 84 85 <div className="rounded-xl border border-white/10 bg-[var(--landing-panel)] p-4"> 86 + <p className="mb-3 text-xs uppercase tracking-[0.14em] text-[var(--landing-subtle)]">Encrypted vs Plain</p> 87 + <div className="grid grid-cols-[1fr_auto_1fr] gap-3 text-xs text-[var(--landing-muted)]"> 88 + <div className="mb-1 uppercase tracking-[0.12em]">Encrypted</div> 89 + <div className="opacity-0">|</div> 90 + <div className="mb-1 uppercase tracking-[0.12em]">Readable</div> 91 + 92 + {encryptedRows.map((row) => ( 93 + <Fragment key={row.cipher}> 94 + <div className="rounded-md border border-white/10 bg-black/20 px-2 py-2 font-mono text-[11px] text-white/75"> 95 + {row.cipher} 96 + </div> 97 + <div className="w-px bg-white/20" /> 98 + <div className="rounded-md border border-white/10 bg-black/10 px-2 py-2 text-[11px] text-white/85"> 99 + {row.plain} 100 + </div> 101 + </Fragment> 102 + ))} 103 </div> 104 </div> 105 </div>
+4 -4
components/landing/landing-hero.tsx
··· 4 return ( 5 <section id="top" className="py-14 md:py-20"> 6 <div className="mx-auto max-w-4xl text-center"> 7 - <h1 className="text-3xl font-semibold leading-tight tracking-tight text-white md:text-5xl"> 8 - Plan smarter. 9 <br /> 10 - Ship faster. 11 </h1> 12 <p className="mx-auto mt-5 max-w-2xl text-sm text-[var(--landing-muted)] md:text-base"> 13 - One Calendar keeps planning clear, collaborative, and calm across your product workflow. 14 </p> 15 <div className="mt-8 flex justify-center gap-3"> 16 <a href="/sign-up" aria-label="Get started" className="rounded-md bg-white px-5 py-2.5 text-sm font-medium text-black transition duration-200 hover:-translate-y-0.5 hover:brightness-110">
··· 4 return ( 5 <section id="top" className="py-14 md:py-20"> 6 <div className="mx-auto max-w-4xl text-center"> 7 + <h1 className="landing-hero-reveal text-4xl font-semibold leading-tight tracking-tight text-white md:text-[56px]"> 8 + The calendar that keeps 9 <br /> 10 + your life private 11 </h1> 12 <p className="mx-auto mt-5 max-w-2xl text-sm text-[var(--landing-muted)] md:text-base"> 13 + Secure by design. Powerful by default. 14 </p> 15 <div className="mt-8 flex justify-center gap-3"> 16 <a href="/sign-up" aria-label="Get started" className="rounded-md bg-white px-5 py-2.5 text-sm font-medium text-black transition duration-200 hover:-translate-y-0.5 hover:brightness-110">