update readme
recreate web - now using tailwind instead of unocss - created theme/design system - created first components - add first sections/content
This commit is contained in:
44
web/src/components/Button.astro
Normal file
44
web/src/components/Button.astro
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const button = cva(
|
||||
cn(
|
||||
"inline-flex items-center justify-center rounded-md text-sm font-medium",
|
||||
"transition-colors focus-visible:outline-none",
|
||||
"ring-main focus-visible:ring-2 focus-visible:ring-ring",
|
||||
"focus-visible:ring-offset-2 disabled:opacity-50",
|
||||
"disabled:pointer-events-none ring-offset-background"
|
||||
),
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-main text-neutral hocus:bg-main/80",
|
||||
destructive:
|
||||
"bg-error text-destructive-foreground hocus:bg-destructive/90",
|
||||
outline:
|
||||
"border border-input hover:bg-accent hover:text-accent-foreground",
|
||||
secondary: "bg-main/10 text-main hocus:bg-main/20",
|
||||
ghost: "hocus:bg-accent hocus:text-accent-foreground",
|
||||
link: "underline-offset-4 hocus:underline text-primary",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 text-base py-2 px-4",
|
||||
sm: "h-9 px-3 rounded-md",
|
||||
lg: "h-11 px-8 rounded-md",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export interface Props
|
||||
extends HTMLAttributes<"button">,
|
||||
VariantProps<typeof button> {}
|
||||
|
||||
const { variant = "default", size = "default", ...props } = Astro.props;
|
||||
---
|
||||
|
||||
<button {...props} class={button({ variant, size })}>
|
||||
<slot />
|
||||
</button>
|
||||
31
web/src/components/Card.astro
Normal file
31
web/src/components/Card.astro
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import { VariantProps, cva } from "class-variance-authority";
|
||||
|
||||
const card = cva(
|
||||
"rounded-card transition-colors bg-neutral-accent ring-2 ring-main/10",
|
||||
{
|
||||
variants: {
|
||||
interactable: {
|
||||
false: "transition-shadow focus-within:shadow-lg ring-2 ring-neutral",
|
||||
true: "cursor-pointer shadow-sm hocus:bg-neutral-accent/50 \
|
||||
hocus:shadow-lg hocus:ring-2 hocus:outline-none",
|
||||
},
|
||||
padding: {
|
||||
true: "p-card",
|
||||
false: "p-0",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export interface Props
|
||||
extends HTMLAttributes<"div">,
|
||||
VariantProps<typeof card> {}
|
||||
|
||||
const { interactable = false, padding = true, ...props } = Astro.props;
|
||||
---
|
||||
|
||||
<div {...props} class={card({ interactable, padding })}>
|
||||
<slot />
|
||||
</div>
|
||||
18
web/src/components/Cards/CardFeature.astro
Normal file
18
web/src/components/Cards/CardFeature.astro
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
import Card from "../Card.astro";
|
||||
export interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
const { title, description } = Astro.props;
|
||||
---
|
||||
|
||||
<Card>
|
||||
<h4>
|
||||
{title}
|
||||
</h4>
|
||||
<p>
|
||||
{description}
|
||||
</p>
|
||||
</Card>
|
||||
@@ -1,39 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
const { title, description } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="container">
|
||||
<div class="icon-container mb-8">
|
||||
<slot name="icon" />
|
||||
</div>
|
||||
<h3 class="mb-2">{title}</h3>
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 400px;
|
||||
|
||||
& p {
|
||||
max-width: 300px;
|
||||
line-height: 1.1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
& .icon-container {
|
||||
& svg {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
import SVG from "@jasikpark/astro-svg-loader";
|
||||
|
||||
type IconName = "resolution" | "smooth" | "local";
|
||||
|
||||
export interface Props {
|
||||
name: IconName;
|
||||
}
|
||||
|
||||
const { name } = Astro.props;
|
||||
|
||||
const icons: Record<IconName, Promise<typeof import("*.svg")>> = {
|
||||
resolution: import("./Icon_Resolution.svg?raw"),
|
||||
smooth: import("./Icon_Smooth.svg?raw"),
|
||||
local: import("./Icon_Local.svg?raw"),
|
||||
};
|
||||
|
||||
const iconSrc = icons[name];
|
||||
---
|
||||
|
||||
<SVG src={iconSrc} aria-label={name} />
|
||||
@@ -1,4 +0,0 @@
|
||||
<svg width="133" height="133" viewBox="0 0 133 133" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="66.5" cy="66.5" r="66.5" fill="#D9D9D9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M75 64.8956L90 53V75.3636L66.5 94L43 75.3636V53L56 63.3095L56 0H75L75 64.8956Z" fill="#161616"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 307 B |
@@ -1,23 +0,0 @@
|
||||
<svg width="118" height="118" viewBox="0 0 118 118" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g style="mix-blend-mode:luminosity">
|
||||
<rect x="0.00012207" y="59.0001" width="59" height="59" fill="white"/>
|
||||
<rect x="59.0001" y="6.10352e-05" width="59" height="59" fill="#2D2D2D"/>
|
||||
<rect x="59.0001" y="59.0001" width="59" height="59" fill="#737373"/>
|
||||
</g>
|
||||
<g style="mix-blend-mode:luminosity">
|
||||
<rect y="29.5" width="29.5" height="29.5" fill="white"/>
|
||||
<rect x="29.5" width="29.5" height="29.5" fill="#2D2D2D"/>
|
||||
<rect x="29.5" y="29.5" width="29.5" height="29.5" fill="#737373"/>
|
||||
</g>
|
||||
<g style="mix-blend-mode:luminosity">
|
||||
<rect y="15" width="15" height="15" fill="white"/>
|
||||
<rect x="15" width="15" height="15" fill="#2D2D2D"/>
|
||||
<rect x="15" y="15" width="15" height="15" fill="#737373"/>
|
||||
</g>
|
||||
<g style="mix-blend-mode:luminosity">
|
||||
<rect y="7.5" width="7.5" height="7.5" fill="white"/>
|
||||
<rect x="7.5" width="7.5" height="7.5" fill="#2D2D2D"/>
|
||||
<rect x="7.5" y="7.5" width="7.5" height="7.5" fill="#737373"/>
|
||||
<rect width="7.5" height="7.5" fill="#828282"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg width="133" height="133" viewBox="0 0 133 133" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<ellipse cx="66.5" cy="40" rx="39.5" ry="39" fill="#D9D9D9" fill-opacity="0.4"/>
|
||||
<ellipse cx="66.5" cy="94" rx="39.5" ry="39" fill="#D9D9D9" fill-opacity="0.58"/>
|
||||
<circle cx="67" cy="68" r="39" fill="#D9D9D9" fill-opacity="0.4"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 337 B |
@@ -1,4 +1,6 @@
|
||||
---
|
||||
import Section from "../Section.astro";
|
||||
|
||||
type NavigationItem = {
|
||||
path: string;
|
||||
label: string;
|
||||
@@ -40,31 +42,21 @@ const tree: Array<NavigationGroup> = [
|
||||
];
|
||||
---
|
||||
|
||||
<footer class="py-4">
|
||||
<div class="m-auto flex flex-row flex-wrap gap-12 inner-container">
|
||||
{
|
||||
tree.map((group) => (
|
||||
<div>
|
||||
<h3 class="mb-2">{group.title}</h3>
|
||||
<div class="flex flex-col">
|
||||
{group.items.map((item) => (
|
||||
<a href={item.path}>{item.label}</a>
|
||||
))}
|
||||
<footer class="bg-neutral-accent">
|
||||
<Section>
|
||||
<div class="flex flex-row flex-wrap gap-12">
|
||||
{
|
||||
tree.map((group) => (
|
||||
<div>
|
||||
<h3 class="mb-2">{group.title}</h3>
|
||||
<div class="flex flex-col">
|
||||
{group.items.map((item) => (
|
||||
<a href={item.path}>{item.label}</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</Section>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
background-color: var(--color-neutral-accent);
|
||||
|
||||
& .inner-container {
|
||||
max-width: var(--content-max-width);
|
||||
margin: auto;
|
||||
padding: var(--padding-main);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
---
|
||||
import Logo from "components/Logo.astro";
|
||||
---
|
||||
|
||||
<header id="main-header">
|
||||
<div class="inner-container">
|
||||
<Logo />
|
||||
<button id="get-started-button" class="button">Get Started</button>
|
||||
</div>
|
||||
</header>
|
||||
<script>
|
||||
import { animate } from "motion";
|
||||
import { ease } from "@unom/style";
|
||||
|
||||
const getStartedButton = document.getElementById("get-started-button");
|
||||
const header = document.getElementById("main-header");
|
||||
|
||||
if (header) {
|
||||
animate(header, { opacity: [0, 1], y: ["-101%", 0] }, ease.quart(0.6).out);
|
||||
}
|
||||
|
||||
if (getStartedButton) {
|
||||
animate(
|
||||
getStartedButton,
|
||||
{ scale: [0, 1] },
|
||||
{ ...ease.quart(0.6).out, delay: 0 }
|
||||
);
|
||||
}
|
||||
</script>
|
||||
<style lang="postcss">
|
||||
header {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 2rem;
|
||||
z-index: 99;
|
||||
|
||||
& .inner-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
border-radius: 100px;
|
||||
margin: auto;
|
||||
max-width: var(--content-max-width);
|
||||
padding: var(--padding-main);
|
||||
background-color: var(--color-neutral-accent);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,42 +0,0 @@
|
||||
<a id="logo" class="block" href="/">
|
||||
<h1 class="text-4xl leading-8 font-bold">
|
||||
<span>p</span><span>l</span><span>a</span><span>y</span>
|
||||
</h1>
|
||||
</a>
|
||||
<style>
|
||||
a {
|
||||
display: block;
|
||||
overflow: visible;
|
||||
}
|
||||
h1 {
|
||||
display: block;
|
||||
padding: 4px;
|
||||
margin-bottom: 0.25rem;
|
||||
background-image: linear-gradient(180deg, white, rgba(255, 255, 255, 0.4));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
width: fit-content;
|
||||
|
||||
&:hover {
|
||||
-webkit-text-stroke: 1px #eee;
|
||||
}
|
||||
|
||||
& span {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { animate, stagger } from "motion";
|
||||
import { ease } from "@unom/style";
|
||||
|
||||
const logoText = document.querySelectorAll("#logo h1")[0];
|
||||
|
||||
console.log(logoText);
|
||||
|
||||
animate(
|
||||
logoText.children as any,
|
||||
{ y: [-30, 0], opacity: [0, 1] },
|
||||
{ ...ease.quint(0.7).out, delay: stagger(0.1) }
|
||||
);
|
||||
</script>
|
||||
27
web/src/components/Section.astro
Normal file
27
web/src/components/Section.astro
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
|
||||
const section = cva("relative w-full", {
|
||||
variants: {
|
||||
padding: {
|
||||
true: "p-main",
|
||||
false: "p-0",
|
||||
},
|
||||
maxWidth: {
|
||||
true: "max-w-section mx-auto",
|
||||
false: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export interface Props
|
||||
extends HTMLAttributes<"section">,
|
||||
VariantProps<typeof section> {}
|
||||
|
||||
const { padding = true, maxWidth = true, ...props } = Astro.props;
|
||||
---
|
||||
|
||||
<section {...props} class={section({ padding, maxWidth })}>
|
||||
<slot />
|
||||
</section>
|
||||
@@ -1,116 +0,0 @@
|
||||
---
|
||||
import Header from "components/Layout/Header.astro";
|
||||
import Footer from "components/Layout/Footer.astro";
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>tempblade Creator - {title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<Header />
|
||||
<slot />
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
<style is:global>
|
||||
:root {
|
||||
--font-main: "Gilroy", system-ui, sans-serif;
|
||||
|
||||
--font-size-s: 0.8rem;
|
||||
--font-size-m: 1rem;
|
||||
--font-size-l: 1.2rem;
|
||||
--font-size-xl: 2.5rem;
|
||||
--font-size-xxl: 3rem;
|
||||
|
||||
--color-neutral: #222;
|
||||
--color-neutral-accent: #333;
|
||||
--color-main: #eee;
|
||||
|
||||
--padding-main: 24px 48px;
|
||||
|
||||
--content-max-width: 1600px;
|
||||
}
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
color: var(--color-main);
|
||||
background-color: var(--color-neutral);
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono,
|
||||
DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 800;
|
||||
font-size: var(--font-size-xxl);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 700;
|
||||
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
font-size: var(--font-size-l);
|
||||
}
|
||||
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-weight: 500;
|
||||
font-size: var(--font-size-m);
|
||||
}
|
||||
|
||||
p {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: var(--font-main);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
p,
|
||||
li,
|
||||
button,
|
||||
a {
|
||||
font-family: var(--font-main);
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: #563795;
|
||||
padding: 0.75rem 1.25rem;
|
||||
border-radius: 30px;
|
||||
transition: filter 0.1s linear;
|
||||
font-weight: 600;
|
||||
|
||||
&:hover {
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
.default-section {
|
||||
max-width: var(--content-max-width);
|
||||
padding: var(--padding-main);
|
||||
margin: auto;
|
||||
}
|
||||
</style>
|
||||
26
web/src/layouts/RootLayout.astro
Normal file
26
web/src/layouts/RootLayout.astro
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
import Footer from "@/components/Layout/Footer.astro";
|
||||
import "@/styles/global.css";
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="Astro description" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
6
web/src/lib/utils.ts
Normal file
6
web/src/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import clsx, { type ClassValue } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
@@ -1,78 +1,43 @@
|
||||
---
|
||||
import Layout from "layouts/Layout.astro";
|
||||
import SectionHighlights from "sections/Start/Highlights.astro";
|
||||
import RootLayout from "@/layouts/RootLayout.astro";
|
||||
import Section from "@/components/Section.astro";
|
||||
import Button from "@/components/Button.astro";
|
||||
import Landing from "@/sections/Landing.astro";
|
||||
import Introduction from "@/sections/Introduction.astro";
|
||||
import Features from "@/sections/Features.astro";
|
||||
---
|
||||
|
||||
<Layout title="Free Intro Maker">
|
||||
<main>
|
||||
<section class="default-section" id="header">
|
||||
<div class="heading-container">
|
||||
<h1 class="my-4 font-bold">
|
||||
Motion Graphics made easy, <br /> for free!
|
||||
</h1>
|
||||
<p>
|
||||
Thats right! Create an intro, outro or other motion graphic elements
|
||||
right in your browser for free. How is this possible? Through the
|
||||
power of open source software!
|
||||
</p>
|
||||
</div>
|
||||
<div class="illustration-container">
|
||||
<svg viewBox="0 0 1000 1000">
|
||||
<circle cx="500" cy="500" r="300"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
</section>
|
||||
<SectionHighlights />
|
||||
</main>
|
||||
<script>
|
||||
import { animate, stagger } from "motion";
|
||||
import { ease } from "@unom/style";
|
||||
|
||||
const headingContainer = document.querySelectorAll(
|
||||
"#header .heading-container"
|
||||
)[0];
|
||||
|
||||
console.log(headingContainer);
|
||||
|
||||
animate(
|
||||
headingContainer.children as any,
|
||||
{ y: [50, 0], opacity: [0, 1] },
|
||||
{ ...ease.quart(0.6).out, delay: stagger(0.1) }
|
||||
);
|
||||
window.sessionStorage.setItem("did_animation_run", "1");
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#header {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
|
||||
& .heading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
& .illustration-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
& svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@screen 2xl {
|
||||
#header {
|
||||
flex-direction: row;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</Layout>
|
||||
<RootLayout title="tempblade - Creator">
|
||||
<main>
|
||||
<Section>
|
||||
<Landing />
|
||||
</Section>
|
||||
<Section>
|
||||
<Introduction />
|
||||
</Section>
|
||||
<Section>
|
||||
<Features />
|
||||
</Section>
|
||||
<Section id="test">
|
||||
<h1>Hallo!</h1>
|
||||
<h2>Wie gehts</h2>
|
||||
<h3>Wie gehts</h3>
|
||||
<h4>Wie gehts</h4>
|
||||
<h5>Wie gehts</h5>
|
||||
<p>
|
||||
cssnano is powered by PostCSS, a tool for transforming styles
|
||||
with JavaScript. Specifically, its plugin architecture allows us
|
||||
to compose cssnano out of small modules with limited
|
||||
responsibilities. It also allows you to easily insert cssnano
|
||||
into your build step, along with other processors that can lint
|
||||
your CSS for errors, or transpile future syntax.
|
||||
</p>
|
||||
<Button>Hallo</Button>
|
||||
<Button variant="secondary">Hallo</Button>
|
||||
<Button variant="ghost">Hallo</Button>
|
||||
<Button variant="destructive">Hallo</Button>
|
||||
<Button variant="outline">Hallo</Button>
|
||||
<Button variant="link">Hallo</Button>
|
||||
</Section>
|
||||
</main>
|
||||
</RootLayout>
|
||||
|
||||
26
web/src/sections/Features.astro
Normal file
26
web/src/sections/Features.astro
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
import CardFeature from "@/components/Cards/CardFeature.astro";
|
||||
type Feature = {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const features: Array<Feature> = [
|
||||
{
|
||||
title: "Fast",
|
||||
description:
|
||||
"Thanks to rust with multithreading and skia we're really fast!",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<div class="flex flex-row">
|
||||
{
|
||||
features.map((feature) => (
|
||||
<CardFeature
|
||||
title={feature.title}
|
||||
description={feature.description}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
23
web/src/sections/Introduction.astro
Normal file
23
web/src/sections/Introduction.astro
Normal file
@@ -0,0 +1,23 @@
|
||||
<div class="flex flex-col gap-4">
|
||||
<h2>The next generation motion design tool</h2>
|
||||
<p>
|
||||
We believe tools for expressing yourself should be accessible to
|
||||
everybody. Not constrained to proprietary operating systems or monthly
|
||||
subscriptions. You should own the tools you work with.
|
||||
</p>
|
||||
<p>
|
||||
tempblade Creator aims to get a feasable alternative to current motion
|
||||
design tools, and even exceed them in certain aspects like
|
||||
extensibility. This is only possible due to our open source approach.
|
||||
Currently we are in a early alpha stage, and the program has to be seen
|
||||
as a proof of concept rather then a finished product.
|
||||
</p>
|
||||
<p>
|
||||
You're a developer, like our idea and want to help? Join our discord or
|
||||
check out the repository!
|
||||
</p>
|
||||
<p>
|
||||
You're not a developer but still want to support the work? I've got a
|
||||
patreon!
|
||||
</p>
|
||||
</div>
|
||||
50
web/src/sections/Landing.astro
Normal file
50
web/src/sections/Landing.astro
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
import Button from "@/components/Button.astro";
|
||||
---
|
||||
|
||||
<div class="h-[80vh] relative">
|
||||
<div
|
||||
class="z-0 absolute top-0 flex items-center w-full h-full justify-center object-center object-contain"
|
||||
id="landing-bg-container"
|
||||
>
|
||||
<canvas
|
||||
width="1920"
|
||||
height="1080"
|
||||
style="filter:blur(100px)"
|
||||
class="w-[800px]"
|
||||
id="landing-bg"></canvas>
|
||||
</div>
|
||||
<div
|
||||
class="z-10 relative w-full h-full flex items-center flex-col justify-center"
|
||||
>
|
||||
<div class="flex flex-col justify-center items-center gap-2">
|
||||
<h1 class="text-5xl text-center font-black">tempblade Creator</h1>
|
||||
<h2 class="text-center text-xl font-normal">
|
||||
Rust Based Open Source Motion Design Editor & Toolkit
|
||||
</h2>
|
||||
<Button>Explore now!</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { animate, inView } from "motion";
|
||||
import { ease } from "@unom/style";
|
||||
|
||||
const landingBgContainer = document.getElementById("landing-bg");
|
||||
|
||||
if (landingBgContainer) {
|
||||
inView(landingBgContainer, () => {
|
||||
animate(
|
||||
landingBgContainer,
|
||||
{
|
||||
scale: [0.7, 1],
|
||||
opacity: [0, 1],
|
||||
},
|
||||
{ ...ease.quint(2).out }
|
||||
);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="./bg.ts"></script>
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
import HighlightCard from "components/Cards/Highlight.astro";
|
||||
import HighlightIcon from "components/Icons/Highlights/HighlightsIcon.astro";
|
||||
---
|
||||
|
||||
<section class="default-section">
|
||||
<HighlightCard
|
||||
title="Local"
|
||||
description="Unleash the power of any machine rocking a modern browser"
|
||||
>
|
||||
<HighlightIcon slot="icon" name="local" />
|
||||
</HighlightCard>
|
||||
<HighlightCard
|
||||
title="Resolution"
|
||||
description="Experience high fidelity motion graphics like never before"
|
||||
>
|
||||
<HighlightIcon slot="icon" name="resolution" />
|
||||
</HighlightCard>
|
||||
<HighlightCard
|
||||
title="Smooth"
|
||||
description="Our Animations range from 24-60FPS"
|
||||
>
|
||||
<HighlightIcon slot="icon" name="smooth" />
|
||||
</HighlightCard>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
section {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
@screen l {
|
||||
section {
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
75
web/src/sections/bg.ts
Normal file
75
web/src/sections/bg.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface VoronoiCell {
|
||||
site: Point;
|
||||
vertices: Point[];
|
||||
}
|
||||
|
||||
function generateVoronoiPattern(
|
||||
canvas: HTMLCanvasElement,
|
||||
points: Array<Point>
|
||||
) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
if (ctx) {
|
||||
// Draw Voronoi regions
|
||||
for (let x = 0; x < canvas.width; x++) {
|
||||
for (let y = 0; y < canvas.height; y++) {
|
||||
let closestPointIndex = 0;
|
||||
let closestDistance = distance(x, y, points[0].x, points[0].y);
|
||||
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
const dist = distance(x, y, points[i].x, points[i].y);
|
||||
if (dist < closestDistance) {
|
||||
closestDistance = dist;
|
||||
closestPointIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
const { x: px, y: py, color } = points[closestPointIndex];
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function distance(x1: number, y1: number, x2: number, y2: number) {
|
||||
const dx = x2 - x1;
|
||||
const dy = y2 - y1;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
// Get canvas element and generate Voronoi pattern
|
||||
const canvas = document.getElementById("landing-bg") as HTMLCanvasElement;
|
||||
generateVoronoiPattern(canvas, [
|
||||
{
|
||||
x: 200,
|
||||
y: 200,
|
||||
color: "#8AFFAD",
|
||||
},
|
||||
{
|
||||
x: 800,
|
||||
y: 500,
|
||||
color: "#326CCC",
|
||||
},
|
||||
{
|
||||
x: 1100,
|
||||
y: 300,
|
||||
color: "#95B2F5",
|
||||
},
|
||||
{
|
||||
x: 1200,
|
||||
y: 600,
|
||||
color: "#32C3E3",
|
||||
},
|
||||
{
|
||||
x: 300,
|
||||
y: 900,
|
||||
color: "purple",
|
||||
},
|
||||
]);
|
||||
5
web/src/styles/breakpoints.css
Normal file
5
web/src/styles/breakpoints.css
Normal file
@@ -0,0 +1,5 @@
|
||||
@custom-media --sm-viewport screen and (min-width: 640px);
|
||||
@custom-media --md-viewport screen and (min-width: 768px);
|
||||
@custom-media --lg-viewport screen and (min-width: 1024px);
|
||||
@custom-media --xl-viewport screen and (min-width: 1280px);
|
||||
@custom-media --2xl-viewport screen and (min-width: 1536px);
|
||||
80
web/src/styles/global.css
Normal file
80
web/src/styles/global.css
Normal file
@@ -0,0 +1,80 @@
|
||||
@import "./breakpoints.css";
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--color-main: 0 0% 0%;
|
||||
--color-primary: 0 0% 0%;
|
||||
--color-neutral: 0 0% 100%;
|
||||
--color-neutral-accent: 0 0% 93%;
|
||||
--color-highlight: 264 100% 50%;
|
||||
--color-success: 132 100% 78%;
|
||||
--color-error: 335 100% 62%;
|
||||
|
||||
--padding-main: 25px 25px;
|
||||
--padding-card: 1.25rem 1.25rem;
|
||||
|
||||
--spacing-main: 20px;
|
||||
|
||||
--max-width-section: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-main: 0 0% 100%;
|
||||
--color-primary: 0 0% 0%;
|
||||
--color-neutral: 264 100% 6%;
|
||||
--color-neutral-accent: 271 100% 10%;
|
||||
--color-highlight: 336 100% 60%;
|
||||
--color-success: 132 100% 78%;
|
||||
--color-error: 335 100% 62%;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
@apply bg-neutral text-main;
|
||||
font-family: system-ui, sans-serif;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-main;
|
||||
}
|
||||
|
||||
@media (--lg-viewport) {
|
||||
:root {
|
||||
--max-width-section: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (--xl-viewport) {
|
||||
:root {
|
||||
--max-width-section: 1550px;
|
||||
|
||||
--padding-main: 45px 100px;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
@apply text-3xl font-bold;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@apply text-2xl font-semibold;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@apply text-xl font-medium;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
p {
|
||||
@apply max-w-[600px];
|
||||
}
|
||||
Reference in New Issue
Block a user