mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 02:29:55 +02:00
feat(docs): streamline product and privacy pages
This commit is contained in:
@@ -37,8 +37,11 @@ export function AppIcon({ className, title }: BrandAssetProps) {
|
||||
export function Brand({ compact = false }: { compact?: boolean }) {
|
||||
return (
|
||||
<Link className="brand" href="/" aria-label="VniDrop home">
|
||||
<BrandMark className="brand-mark-image" />
|
||||
{!compact && <span className="brand-name">VniDrop</span>}
|
||||
<span className="brand-primary">
|
||||
<BrandMark className="brand-mark-image" />
|
||||
{!compact && <span className="brand-name">VniDrop</span>}
|
||||
</span>
|
||||
{!compact && <span className="brand-tagline">Send files directly. Stay in control.</span>}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,17 @@
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.brand-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
width: max-content;
|
||||
height: 47px;
|
||||
}
|
||||
|
||||
.brand-mark-image {
|
||||
@@ -42,6 +49,17 @@
|
||||
letter-spacing: -0.045em;
|
||||
}
|
||||
|
||||
.brand-tagline {
|
||||
margin-top: -4px;
|
||||
margin-left: 4px;
|
||||
color: #756c79;
|
||||
font-size: 9px;
|
||||
font-weight: 580;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.01em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.header-github-button {
|
||||
display: inline-flex;
|
||||
min-height: 40px;
|
||||
@@ -57,15 +75,19 @@
|
||||
font-size: 12px;
|
||||
font-weight: 680;
|
||||
line-height: 1;
|
||||
transition: background 160ms ease, border-color 160ms ease, box-shadow 160ms ease,
|
||||
transform 160ms ease;
|
||||
animation: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.header-github-button:hover {
|
||||
border-color: #403944;
|
||||
background: #29242d;
|
||||
box-shadow: 0 10px 26px rgba(23, 20, 25, 0.17), inset 0 1px rgba(255, 255, 255, 0.12);
|
||||
transform: translateY(-1px);
|
||||
border-color: #6f6475;
|
||||
background: #302a34;
|
||||
box-shadow: 0 11px 28px rgba(23, 20, 25, 0.2), inset 0 0 0 1px rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.header-github-button:focus-visible {
|
||||
outline: 3px solid rgba(168, 85, 247, 0.28);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.header-github-button svg {
|
||||
@@ -85,10 +107,20 @@
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.brand-primary {
|
||||
height: 43px;
|
||||
}
|
||||
|
||||
.brand-name {
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.brand-tagline {
|
||||
margin-top: -3px;
|
||||
margin-left: 3px;
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
.header-github-button {
|
||||
min-height: 38px;
|
||||
gap: 7px;
|
||||
@@ -107,6 +139,10 @@
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.brand-tagline {
|
||||
font-size: 7.5px;
|
||||
}
|
||||
|
||||
.header-github-button {
|
||||
min-height: 36px;
|
||||
padding-inline: 10px;
|
||||
|
||||
@@ -267,8 +267,9 @@
|
||||
|
||||
.platform-orbit { width: 112%; margin-left: -6%; }
|
||||
.platform-center { width: 112px; height: 112px; border-radius: 30px; }
|
||||
.platform-center svg { width: 68px; height: 68px; }
|
||||
.platform-chip { padding: 8px 10px; font-size: 9px; }
|
||||
.platform-center img { width: 68px; height: 68px; }
|
||||
.platform-chip { width: 48px; height: 48px; padding: 0; }
|
||||
.platform-chip .platform-glyph { width: 25px; height: 25px; }
|
||||
.platform-chip-1 { left: 10%; }
|
||||
.platform-chip-2 { right: 0; }
|
||||
.platform-chip-3 { right: -2%; }
|
||||
|
||||
90
docs/components/platform-icon.tsx
Normal file
90
docs/components/platform-icon.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import type { SVGProps } from "react";
|
||||
|
||||
export const supportedPlatforms = ["Android", "iOS", "macOS", "Windows", "Linux"] as const;
|
||||
|
||||
export type PlatformName = (typeof supportedPlatforms)[number];
|
||||
|
||||
type PlatformIconProps = Omit<SVGProps<SVGSVGElement>, "children"> & {
|
||||
platform: PlatformName;
|
||||
};
|
||||
|
||||
function AndroidIcon() {
|
||||
return (
|
||||
<>
|
||||
<path
|
||||
d="M7.25 8.15h9.5a1.5 1.5 0 0 1 1.5 1.5v6.1a1.5 1.5 0 0 1-1.5 1.5h-9.5a1.5 1.5 0 0 1-1.5-1.5v-6.1a1.5 1.5 0 0 1 1.5-1.5Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path d="M8.15 8.1a3.95 3.95 0 0 1 7.7 0" fill="currentColor" />
|
||||
<path d="m8.35 4.45-1.2-1.7M15.65 4.45l1.2-1.7" stroke="currentColor" strokeWidth="1.25" strokeLinecap="round" />
|
||||
<path d="M4.2 10.05v5.15M19.8 10.05v5.15M8.5 17v3.05M15.5 17v3.05" stroke="currentColor" strokeWidth="2.1" strokeLinecap="round" />
|
||||
<circle cx="9.5" cy="6.65" r="0.62" fill="white" />
|
||||
<circle cx="14.5" cy="6.65" r="0.62" fill="white" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AppleIcon() {
|
||||
return (
|
||||
<path
|
||||
d="M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.32.07 2.24.76 3.01.82 1.15-.23 2.25-.89 3.44-.8 1.43.12 2.51.68 3.22 1.7-2.96 1.78-2.26 5.68.46 6.77-.54 1.42-1.24 2.83-2.13 4.48ZM12.03 7.25c-.15-2.13 1.59-3.89 3.58-4.06.27 2.46-2.23 4.3-3.58 4.06Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function MacIcon() {
|
||||
return (
|
||||
<>
|
||||
<rect x="2.5" y="2.5" width="19" height="19" rx="5.5" fill="currentColor" />
|
||||
<path d="M12 2.5v19" stroke="white" strokeOpacity="0.72" />
|
||||
<path d="M8 9.15h.01M16 9.15h.01" stroke="white" strokeWidth="1.9" strokeLinecap="round" />
|
||||
<path d="M7.1 15.2c2.7 1.45 7.1 1.45 9.8 0" stroke="white" strokeWidth="1.35" strokeLinecap="round" />
|
||||
<path d="m13.55 6.25-2.45 8.3" stroke="white" strokeWidth="1.1" strokeLinecap="round" strokeOpacity="0.82" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function WindowsIcon() {
|
||||
return (
|
||||
<path
|
||||
d="M3 5.15 11 4v7H3V5.15Zm9-1.3L21 2.5V11h-9V3.85ZM3 12h8v7l-8-1.15V12Zm9 0h9v8.5l-9-1.35V12Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function LinuxIcon() {
|
||||
return (
|
||||
<>
|
||||
<ellipse cx="12" cy="12.6" rx="5.25" ry="7.55" fill="#242027" />
|
||||
<ellipse cx="12" cy="14.55" rx="3.45" ry="4.7" fill="#f8f7f9" />
|
||||
<ellipse cx="9.95" cy="8.45" rx="1.35" ry="1.8" fill="white" />
|
||||
<ellipse cx="14.05" cy="8.45" rx="1.35" ry="1.8" fill="white" />
|
||||
<circle cx="10.35" cy="8.65" r="0.55" fill="#242027" />
|
||||
<circle cx="13.65" cy="8.65" r="0.55" fill="#242027" />
|
||||
<path d="m9.8 10.15 2.2-1 2.2 1-2.2 2.1-2.2-2.1Z" fill="#f5b82e" />
|
||||
<path d="M6.15 18.45c1.2-1 2.45-1.3 3.75-.75-.7 1.6-2.35 2.45-4.9 2.2.2-.6.58-1.08 1.15-1.45ZM17.85 18.45c-1.2-1-2.45-1.3-3.75-.75.7 1.6 2.35 2.45 4.9 2.2-.2-.6-.58-1.08-1.15-1.45Z" fill="#f5b82e" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function PlatformIcon({ platform, className, ...props }: PlatformIconProps) {
|
||||
return (
|
||||
<svg
|
||||
className={className}
|
||||
data-platform={platform.toLowerCase()}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
{...props}
|
||||
>
|
||||
{platform === "Android" && <AndroidIcon />}
|
||||
{platform === "iOS" && <AppleIcon />}
|
||||
{platform === "macOS" && <MacIcon />}
|
||||
{platform === "Windows" && <WindowsIcon />}
|
||||
{platform === "Linux" && <LinuxIcon />}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -1,23 +1,27 @@
|
||||
import { BrandMark } from "@/components/brand";
|
||||
|
||||
const platforms = ["Android", "iOS", "macOS", "Windows", "Linux"];
|
||||
import { PlatformIcon, supportedPlatforms } from "@/components/platform-icon";
|
||||
|
||||
export function PlatformOrbit() {
|
||||
return (
|
||||
<div className="platform-orbit" aria-label="VniDrop supports Android, iOS, macOS, Windows, and Linux">
|
||||
<div
|
||||
className="platform-orbit"
|
||||
role="img"
|
||||
aria-label="VniDrop supports Android, iOS, macOS, Windows, and Linux"
|
||||
>
|
||||
<div className="platform-ring platform-ring-outer" aria-hidden="true" />
|
||||
<div className="platform-ring platform-ring-inner" aria-hidden="true" />
|
||||
<div className="platform-center" aria-hidden="true">
|
||||
<span className="platform-center-glow" />
|
||||
<BrandMark />
|
||||
</div>
|
||||
{platforms.map((platform, index) => (
|
||||
{supportedPlatforms.map((platform, index) => (
|
||||
<span
|
||||
key={platform}
|
||||
className={`platform-chip platform-chip-${index + 1}`}
|
||||
title={platform}
|
||||
>
|
||||
<i />
|
||||
{platform}
|
||||
<PlatformIcon className="platform-glyph" platform={platform} />
|
||||
<span className="sr-only">{platform}</span>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -75,24 +75,20 @@
|
||||
z-index: 4;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 14px;
|
||||
justify-content: center;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
border: 1px solid #e2d9e6;
|
||||
border-radius: 999px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.93);
|
||||
box-shadow: 0 12px 35px rgba(53, 34, 61, 0.1);
|
||||
color: #4b4350;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
animation: platform-chip-float 5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.platform-chip i {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--brand-500);
|
||||
box-shadow: 0 0 0 4px var(--brand-100);
|
||||
.platform-chip .platform-glyph {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.platform-chip-1 { top: 8%; left: 17%; animation-delay: -1s; }
|
||||
@@ -100,3 +96,8 @@
|
||||
.platform-chip-3 { right: 1%; bottom: 22%; animation-delay: -4s; }
|
||||
.platform-chip-4 { bottom: 7%; left: 24%; animation-delay: -0.5s; }
|
||||
.platform-chip-5 { top: 45%; left: 0; animation-delay: -3.2s; }
|
||||
|
||||
.platform-glyph[data-platform="android"] { color: #2fbf71; }
|
||||
.platform-glyph[data-platform="ios"] { color: #201c23; }
|
||||
.platform-glyph[data-platform="macos"] { color: #1687f8; }
|
||||
.platform-glyph[data-platform="windows"] { color: #008de5; }
|
||||
|
||||
@@ -5,38 +5,24 @@ import { Icon } from "@/components/icons";
|
||||
export function SiteFooter() {
|
||||
return (
|
||||
<footer className="site-footer">
|
||||
<div className="footer-main page-shell">
|
||||
<div className="footer-brand">
|
||||
<span className="footer-mark">
|
||||
<BrandMark />
|
||||
</span>
|
||||
<div>
|
||||
<p className="footer-name">VniDrop</p>
|
||||
<p>Send files directly. Stay in control.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer-links">
|
||||
<div>
|
||||
<p className="footer-label">Explore</p>
|
||||
<Link href="/#how-it-works">How it works</Link>
|
||||
<Link href="/#privacy">Privacy by design</Link>
|
||||
<Link href="/#platforms">Platforms</Link>
|
||||
</div>
|
||||
<div>
|
||||
<p className="footer-label">Project</p>
|
||||
<a href="https://github.com/vnidrop/vnidrop" target="_blank" rel="noreferrer">
|
||||
GitHub <Icon name="github" />
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/vnidrop/vnidrop/blob/master/LICENSE"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Apache 2.0 <Icon name="arrow" />
|
||||
</a>
|
||||
<Link href="/privacy/">Privacy policy</Link>
|
||||
</div>
|
||||
<div className="footer-inner page-shell">
|
||||
<div className="footer-identity">
|
||||
<BrandMark />
|
||||
<span>VniDrop</span>
|
||||
</div>
|
||||
<nav className="footer-links" aria-label="Footer navigation">
|
||||
<a href="https://github.com/vnidrop/vnidrop" target="_blank" rel="noreferrer">
|
||||
<Icon name="github" /> GitHub
|
||||
</a>
|
||||
<Link href="/privacy/">Privacy</Link>
|
||||
<a
|
||||
href="https://github.com/vnidrop/vnidrop/blob/master/LICENSE"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Apache 2.0
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div className="footer-bottom page-shell">
|
||||
<p>© 2026 VniDrop contributors.</p>
|
||||
|
||||
Reference in New Issue
Block a user