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:
parent
5791b61a48
commit
518b819fe8
13
README.md
13
README.md
@ -2,8 +2,7 @@
|
||||
|
||||
# tempblade Creator
|
||||
|
||||
tempblade creator is a motion design application, build with typescript, skia, rust using tauri.
|
||||
Its currently in an early alpha stage, and there may be larger design changes to the overall structuring
|
||||
tempblade creator is a motion design application, built on top of rust and skia. Its main goal is to be a flexible motion design toolkit, to be used in different environments. Right now it consists of an Editor/UI built with tauri where the ui uses react/typescript and the interpolation/timeline calculations are done in rust. It should also easily possible to run completly in the browser thanks to wasm. The project is currently in an early alpha stage, and there may be larger design changes to the overall structuring
|
||||
of the project.
|
||||
|
||||
## Why?
|
||||
@ -31,6 +30,12 @@ to the frontend in javascript/typescript. This happens using tauris IPC.
|
||||
- Caching of skia entity instances like fonts etc.
|
||||
- Pretty fast (if compared to After Effects)
|
||||
|
||||
### Possible use cases
|
||||
|
||||
- Typical motion design creation
|
||||
- Data driven motion design -> craft your animation and automate the rendering/data population thanks to the soon coming typescript library
|
||||
- Creation of generative art
|
||||
|
||||
### Features currently w.i.p
|
||||
|
||||
- Effects system for skias built in image filters like blurring
|
||||
@ -39,5 +44,7 @@ to the frontend in javascript/typescript. This happens using tauris IPC.
|
||||
|
||||
- Integration with OpenFX inside rust
|
||||
- Standalone rust rust rendering using vulkan and or metal by using rust-skia
|
||||
- Standalone package for drawing (currently the logic is already decoupled from ui)
|
||||
- Standalone ts package for drawing (currently the logic is already decoupled from ui)
|
||||
- Standalone ts package for populating & rendering project files for enabling data driven integrations
|
||||
- Caching system for the rendered keyframes (currently interpolation calculation happens during playback, this could easily be cached)
|
||||
- Full pipeline automation with integrations for blender, houdini in more (Already working on this)
|
||||
|
7
web/.vscode/settings.json
vendored
7
web/.vscode/settings.json
vendored
@ -1,3 +1,8 @@
|
||||
{
|
||||
"typescript.inlayHints.parameterNames.enabled": "all"
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
[
|
||||
"cva\\(([^)]*)\\)",
|
||||
"[\"'`]([^\"'`]*).*?[\"'`]"
|
||||
]
|
||||
]
|
||||
}
|
@ -1,14 +1,55 @@
|
||||
# tempblade Creator
|
||||
# Astro Starter Kit: Basics
|
||||
|
||||
This is a web based motion design creator built on astro.
|
||||
```
|
||||
npm create astro@latest -- --template basics
|
||||
```
|
||||
|
||||
## Commands
|
||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics)
|
||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics)
|
||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||

|
||||
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
/
|
||||
├── public/
|
||||
│ └── favicon.svg
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ └── Card.astro
|
||||
│ ├── layouts/
|
||||
│ │ └── Layout.astro
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :--------------------- | :----------------------------------------------- |
|
||||
| `yarn dev` | Starts local dev server at `localhost:3000` |
|
||||
| `yarn build` | Build your production site to `./dist/` |
|
||||
| `yarn preview` | Preview your build locally, before deploying |
|
||||
| `yarn astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:3000` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
|
12
web/astro.config.mjs
Normal file
12
web/astro.config.mjs
Normal file
@ -0,0 +1,12 @@
|
||||
import { defineConfig } from "astro/config";
|
||||
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [
|
||||
tailwind({
|
||||
applyBaseStyles: false,
|
||||
}),
|
||||
],
|
||||
});
|
@ -1,11 +0,0 @@
|
||||
import { defineConfig } from "astro/config";
|
||||
import UnoCSS from "unocss/astro";
|
||||
|
||||
import react from "@astrojs/react";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [UnoCSS({
|
||||
injectReset: true
|
||||
}), react()]
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "creator",
|
||||
"name": "web",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
@ -10,21 +10,17 @@
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/react": "^2.1.1",
|
||||
"@types/react": "^18.0.21",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@astrojs/tailwind": "^3.1.3",
|
||||
"@unom/style": "^0.2.14",
|
||||
"astro": "^2.3.0",
|
||||
"motion": "^10.15.5",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jasikpark/astro-svg-loader": "^0.1.0",
|
||||
"@unocss/postcss": "^0.51.4",
|
||||
"@unocss/preset-mini": "^0.51.4",
|
||||
"@unocss/reset": "^0.51.4",
|
||||
"postcss-preset-env": "^8.3.1",
|
||||
"unocss": "^0.51.4"
|
||||
"astro": "^2.5.0",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"class-variance-authority": "^0.6.0",
|
||||
"clsx": "^1.2.1",
|
||||
"motion": "^10.16.2",
|
||||
"postcss": "^8.4.24",
|
||||
"postcss-custom-media": "^9.1.5",
|
||||
"postcss-import": "^15.1.0",
|
||||
"tailwind-merge": "^1.13.2",
|
||||
"tailwindcss": "^3.0.24"
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
"@unocss/postcss": {},
|
||||
"postcss-preset-env": {
|
||||
features: {
|
||||
"nesting-rules": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
const postcssImport = require("postcss-import");
|
||||
const nesting = require("tailwindcss/nesting");
|
||||
const tailwind = require("tailwindcss");
|
||||
const autoprefixer = require("autoprefixer");
|
||||
const customMedia = require("postcss-custom-media");
|
||||
|
||||
const config = {
|
||||
plugins: [postcssImport, nesting, tailwind, autoprefixer, customMedia],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
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,8 +42,9 @@ const tree: Array<NavigationGroup> = [
|
||||
];
|
||||
---
|
||||
|
||||
<footer class="py-4">
|
||||
<div class="m-auto flex flex-row flex-wrap gap-12 inner-container">
|
||||
<footer class="bg-neutral-accent">
|
||||
<Section>
|
||||
<div class="flex flex-row flex-wrap gap-12">
|
||||
{
|
||||
tree.map((group) => (
|
||||
<div>
|
||||
@ -55,16 +58,5 @@ const tree: Array<NavigationGroup> = [
|
||||
))
|
||||
}
|
||||
</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">
|
||||
<RootLayout title="tempblade - Creator">
|
||||
<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>
|
||||
<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>
|
||||
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!
|
||||
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>
|
||||
</div>
|
||||
<div class="illustration-container">
|
||||
<svg viewBox="0 0 1000 1000">
|
||||
<circle cx="500" cy="500" r="300"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
</section>
|
||||
<SectionHighlights />
|
||||
<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>
|
||||
<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>
|
||||
|
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];
|
||||
}
|
59
web/tailwind.config.cjs
Normal file
59
web/tailwind.config.cjs
Normal file
@ -0,0 +1,59 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
|
||||
theme: {
|
||||
extend: {
|
||||
screens: { "2xl": "1400px", "3xl": "1850px" },
|
||||
borderRadius: {
|
||||
card: "0.5rem",
|
||||
md: "0.5rem",
|
||||
},
|
||||
colors: {
|
||||
main: "hsl(var(--color-main))",
|
||||
primary: "hsl(var(--color-primary))",
|
||||
secondary: "hsl(var(--color-secondary))",
|
||||
neutral: "hsl(var(--color-neutral))",
|
||||
"neutral-accent": "hsl(var(--color-neutral-accent))",
|
||||
success: "hsl(var(--color-success))",
|
||||
error: "hsl(var(--color-error))",
|
||||
},
|
||||
transitionTimingFunction: {
|
||||
"in-sine": "cubic-bezier(0.47, 0, 0.745, 0.715)",
|
||||
"out-sine": "cubic-bezier(0.39, 0.575, 0.565, 1)",
|
||||
"in-out-sine": "cubic-bezier(0.445, 0.05, 0.55, 0.95)",
|
||||
"in-quad": "cubic-bezier(0.55, 0.085, 0.68, 0.53)",
|
||||
"out-quad": "cubic-bezier(0.25, 0.46, 0.45, 0.94)",
|
||||
"in-out-quad": "cubic-bezier(0.455, 0.03, 0.515, 0.955)",
|
||||
"in-cubic": "cubic-bezier(0.55, 0.055, 0.675, 0.19)",
|
||||
"out-cubic": "cubic-bezier(0.215, 0.61, 0.355, 1)",
|
||||
"in-out-cubic": "cubic-bezier(0.645, 0.045, 0.355, 1)",
|
||||
"in-quart": "cubic-bezier(0.895, 0.03, 0.685, 0.22)",
|
||||
"out-quart": "cubic-bezier(0.165, 0.84, 0.44, 1)",
|
||||
"in-out-quart": "cubic-bezier(0.77, 0, 0.175, 1)",
|
||||
"in-quint": "cubic-bezier(0.755, 0.05, 0.855, 0.06)",
|
||||
"out-quint": "cubic-bezier(0.23, 1, 0.32, 1)",
|
||||
"in-out-quint": "cubic-bezier(0.86, 0, 0.07, 1)",
|
||||
"in-expo": "cubic-bezier(0.95, 0.05, 0.795, 0.035)",
|
||||
"out-expo": "cubic-bezier(0.19, 1, 0.22, 1)",
|
||||
"in-out-expo": "cubic-bezier(1, 0, 0, 1)",
|
||||
"in-circ": "cubic-bezier(0.6, 0.04, 0.98, 0.335)",
|
||||
"out-circ": "cubic-bezier(0.075, 0.82, 0.165, 1)",
|
||||
"in-out-circ": "cubic-bezier(0.785, 0.135, 0.15, 0.86)",
|
||||
},
|
||||
gap: {
|
||||
main: "var(--spacing-main)",
|
||||
card: "var(--gap-card)",
|
||||
},
|
||||
padding: {
|
||||
main: "var(--padding-main)",
|
||||
card: "var(--padding-card)",
|
||||
},
|
||||
|
||||
maxWidth: {
|
||||
section: "var(--max-width-section)",
|
||||
form: "var(--max-width-form)",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
@ -1,8 +1,11 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"baseUrl": "src",
|
||||
"jsxImportSource": "react"
|
||||
"baseUrl": "./src",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
import { defineConfig } from "unocss";
|
||||
import presetMini from "@unocss/preset-mini";
|
||||
|
||||
export default defineConfig({
|
||||
presets: [presetMini()],
|
||||
theme: {
|
||||
breakpoints: {
|
||||
s: "576px",
|
||||
m: "768px",
|
||||
l: "992px",
|
||||
xl: "1200px",
|
||||
"2xl": "1400px",
|
||||
"3xl": "1600px",
|
||||
},
|
||||
},
|
||||
});
|
2591
web/yarn.lock
2591
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user