mirror of
https://github.com/Since-3/since3-website.git
synced 2026-10-12 21:41:16 +00:00
added full design
This commit is contained in:
parent
c641cfed7e
commit
b2b4a0b076
67 changed files with 4884 additions and 153 deletions
105
modules/landingPage/ui/components/projects/project-visual.tsx
Normal file
105
modules/landingPage/ui/components/projects/project-visual.tsx
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import Image from "next/image"
|
||||
|
||||
import type { Project } from "@/modules/landingPage/data/content"
|
||||
|
||||
/**
|
||||
* Abstract stand-in visuals until real screenshots exist.
|
||||
* Each project gets its own composition so the track does not feel repetitive.
|
||||
*/
|
||||
export function ProjectVisual({ project, index }: { project: Project; index: number }) {
|
||||
if (project.image) {
|
||||
return (
|
||||
<Image
|
||||
src={project.image.src}
|
||||
alt={project.image.alt}
|
||||
fill
|
||||
sizes="(min-width: 768px) 60vw, 90vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const variant = index % 3
|
||||
|
||||
if (variant === 0) {
|
||||
// Typography poster, sized so the longest word always fits the card
|
||||
const words = project.title.split(" ")
|
||||
const longest = Math.max(...words.map((word) => word.length))
|
||||
const fontSize = Math.min(14, 70 / (longest * 0.5))
|
||||
return (
|
||||
<div className="flex size-full flex-col justify-center bg-ink-100 p-[6cqi] text-black">
|
||||
{words.map((word, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="block leading-[0.85] type-poster"
|
||||
style={{ fontSize: `${fontSize}cqi`, paddingLeft: `${i * 6}cqi` }}
|
||||
>
|
||||
{word}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (variant === 1) {
|
||||
// Interface skeleton
|
||||
return (
|
||||
<div className="grid size-full grid-cols-[22%_1fr] gap-3 bg-ink-900 p-5 md:p-8">
|
||||
<div className="flex flex-col gap-2 rounded-xl bg-ink-800 p-3">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<div key={i} className="h-2 rounded-full bg-ink-700" style={{ width: `${90 - i * 9}%` }} />
|
||||
))}
|
||||
</div>
|
||||
<div className="grid grid-rows-[auto_1fr] gap-3">
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
{["128", "4.2k", "99%"].map((value) => (
|
||||
<div key={value} className="rounded-xl bg-ink-800 p-3 md:p-4">
|
||||
<div className="h-1.5 w-1/2 rounded-full bg-ink-700" />
|
||||
<p className="mt-3 text-2xl text-white type-poster md:text-4xl">{value}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="relative overflow-hidden rounded-xl bg-ink-800">
|
||||
<svg viewBox="0 0 300 100" preserveAspectRatio="none" className="absolute inset-0 size-full">
|
||||
<path
|
||||
d="M0 85 C 30 80, 50 60, 80 62 S 130 30, 160 40 S 220 10, 250 18 S 290 5, 300 4"
|
||||
fill="none"
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
vectorEffect="non-scaling-stroke"
|
||||
/>
|
||||
<path
|
||||
d="M0 85 C 30 80, 50 60, 80 62 S 130 30, 160 40 S 220 10, 250 18 S 290 5, 300 4 V 100 H 0 Z"
|
||||
fill="white"
|
||||
fillOpacity="0.06"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Orbit: automation as moving parts
|
||||
return (
|
||||
<div className="relative grid size-full place-items-center overflow-hidden rounded-glass border border-line bg-ink-950">
|
||||
{[1, 2, 3, 4].map((ring) => (
|
||||
<div
|
||||
key={ring}
|
||||
className="absolute aspect-square rounded-full border border-white/15"
|
||||
style={{ width: `${ring * 22}%` }}
|
||||
/>
|
||||
))}
|
||||
{[0, 60, 150, 230, 300].map((angle, i) => (
|
||||
<div
|
||||
key={angle}
|
||||
className="absolute size-2.5 rounded-full bg-white"
|
||||
style={{
|
||||
transform: `rotate(${angle}deg) translateX(${(i % 4) * 11 + 11}cqi)`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<p className="relative font-mono text-label text-white">input → ki → output</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue