feat: initial landing page (#89)

* create basic landing page

* change name in package.json
This commit is contained in:
Preet Sojitra 2022-10-15 20:00:40 +05:30 committed by GitHub
parent d6a7f98e3f
commit e5d4e90805
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 15531 additions and 0 deletions

2
landing-page/.npmrc Normal file
View file

@ -0,0 +1,2 @@
# Expose Astro dependencies for `pnpm` users
shamefully-hoist=true

View file

@ -0,0 +1,2 @@
dist/
.output/

View file

@ -0,0 +1 @@
{}

4
landing-page/.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode", "bradlc.vscode-tailwindcss"],
"unwantedRecommendations": []
}

11
landing-page/.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

9
landing-page/LICENSE Normal file
View file

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2022-present Markus Hsi-Yang Fritz
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

49
landing-page/README.md Normal file
View file

@ -0,0 +1,49 @@
# Welcome to [Astro](https://astro.build)
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics)
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
![basics](https://user-images.githubusercontent.com/4677417/186188965-73453154-fdec-4d6b-9c34-cb35c248ae5b.png)
## 🚀 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 |
| :--------------------- | :------------------------------------------------- |
| `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 preview` |
| `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).

View file

@ -0,0 +1,12 @@
import tailwind from "@astrojs/tailwind";
import { defineConfig } from "astro/config";
export default defineConfig({
site: "https://astro-moon-landing.netlify.app/",
integrations: [tailwind()],
vite: {
ssr: {
external: ["@11ty/eleventy-img", "svgo"],
},
},
});

14593
landing-page/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

29
landing-page/package.json Normal file
View file

@ -0,0 +1,29 @@
{
"name": "astro-reactive-library-landing-page",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro",
"format": "prettier --write .",
"clean": "rimraf dist node_modules"
},
"devDependencies": {
"@astrojs/tailwind": "^2.0.2",
"@types/micromodal": "^0.3.3",
"astro": "^1.4.7",
"astro-eleventy-img": "^0.5.0",
"astro-icon": "^0.7.3",
"prettier": "2.7.1",
"prettier-plugin-astro": "^0.5.5",
"rimraf": "^3.0.2",
"tailwindcss-fluid-type": "^1.3.3"
},
"dependencies": {
"micromodal": "^0.4.10",
"tailwindcss": "^3.1.8"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 627 894" fill="none">
<style>
#letter-a {
fill: black;
}
@media (prefers-color-scheme: dark) {
#letter-a {
fill: white;
}
}
</style>
<path
id="letter-a"
fill-rule="evenodd"
clip-rule="evenodd"
d="M445.433 22.9832C452.722 32.0324 456.439 44.2432 463.873 68.6647L626.281 602.176C566.234 571.026 500.957 548.56 432.115 536.439L326.371 179.099C324.641 173.252 319.27 169.241 313.173 169.241C307.06 169.241 301.68 173.273 299.963 179.14L195.5 536.259C126.338 548.325 60.7632 570.832 0.459473 602.095L163.664 68.5412C171.121 44.1617 174.85 31.9718 182.14 22.9393C188.575 14.9651 196.946 8.77213 206.454 4.95048C217.224 0.621582 229.971 0.621582 255.466 0.621582H372.034C397.562 0.621582 410.326 0.621582 421.106 4.95951C430.622 8.78908 438.998 14.9946 445.433 22.9832Z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M464.867 627.566C438.094 650.46 384.655 666.073 323.101 666.073C247.551 666.073 184.229 642.553 167.426 610.921C161.419 629.05 160.072 649.798 160.072 663.052C160.072 663.052 156.114 728.134 201.38 773.401C201.38 749.896 220.435 730.842 243.939 730.842C284.226 730.842 284.181 765.99 284.144 794.506C284.143 795.36 284.142 796.209 284.142 797.051C284.142 840.333 310.595 877.436 348.215 893.075C342.596 881.518 339.444 868.54 339.444 854.825C339.444 813.545 363.679 798.175 391.845 780.311C414.255 766.098 439.155 750.307 456.315 718.629C465.268 702.101 470.352 683.17 470.352 663.052C470.352 650.68 468.43 638.757 464.867 627.566Z"
fill="#FF5D01"
/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View file

@ -0,0 +1,131 @@
---
import { Icon } from "astro-icon";
import ThemeSwitcher from "~/components/theme-switcher.astro";
const socials = [
{
name: "GitHub",
url: "#",
icon: "fa-brands:github-alt",
},
{
name: "Discord",
url: "#",
icon: "fa-brands:discord",
},
{
name: "Twitter",
url: "#",
icon: "fa-brands:twitter",
},
];
---
<header
id="page-header"
class="absolute bottom-0 z-10 flex items-center justify-between w-full px-8 py-4 text-white border-b border-transparent"
>
<a class="flex items-center gap-3 hover:!text-default" href="#">
<h1 class="sr-only">Astro</h1>
<Icon name="logomark" class="h-10" />
<Icon name="wordmark" class="hidden h-4 sm:block" />
</a>
<div>
<div class="flex items-center gap-6">
<ul class="flex gap-4">
{
socials.map((social) => (
<li class="list-none">
<a
class="flex items-center justify-center w-12 h-12 p-3 border-2 border-current rounded-full"
href={social.url}
>
<Icon name={social.icon} class="h-full" />
</a>
</li>
))
}
</ul>
<button
id="open-nav-button"
type="button"
class="btn sm:hidden"
aria-label="Navigation"
>
<Icon pack="mdi" name="menu" class="h-8" />
</button>
<ThemeSwitcher />
</div>
<div id="menu-modal" class="hidden modal" aria-hidden="true">
<div class="fixed inset-0 px-8 py-4 bg-default text-default">
<div class="space-y-4" role="dialog" aria-modal="true">
<header class="text-right">
<button
id="close-nav-button"
type="button"
class="btn"
aria-label="Close navigation"
>
<Icon pack="mdi" name="close" class="h-8" />
</button>
</header>
<div class="flex justify-center">
<Icon name="logomark" class="h-16" />
</div>
</div>
</div>
</div>
</div>
</header>
<script>
import MicroModal from "micromodal";
const menuModalId = "menu-modal";
const header: HTMLElement = document.querySelector("#page-header");
const page = document.documentElement;
const menu = document.querySelector(`#${menuModalId} ul`);
const openNavButton = document.querySelector("#open-nav-button");
const closeNavButton = document.querySelector("#close-nav-button");
const openMenu = () => {
MicroModal.show(menuModalId, { disableScroll: true });
};
const closeMenu = () => {
MicroModal.close(menuModalId);
};
openNavButton.addEventListener("click", openMenu);
closeNavButton.addEventListener("click", closeMenu);
document.addEventListener("scroll", () => {
const d = page.clientHeight - page.scrollTop - header.offsetHeight;
header.classList.toggle("fixed-header", d < 0);
});
menu.addEventListener("click", (event) => {
if ((event.target as HTMLElement).tagName === "A") {
closeMenu();
}
});
</script>
<noscript>
<style>
#open-nav-button {
display: none;
}
</style>
</noscript>
<style>
.fixed-header {
@apply fixed top-0 bottom-auto;
@apply text-default bg-default border-default;
}
.modal.is-open {
@apply block;
}
</style>

View file

@ -0,0 +1,89 @@
---
import { generateImage } from "astro-eleventy-img";
import { Icon } from "astro-icon";
import Starfield from "~/components/starfield.astro";
const widths = [450, 800];
const sizes = "(min-width: 640px) 42vw, 67vw";
const { webp, avif, png } = generateImage("src/assets/astronaut.png", {
widths,
formats: ["webp", "avif", "png"],
outputDir: "public/assets/images/astronaut",
urlPath: "/assets/images/astronaut",
});
const avifSrcset = avif.map(({ srcset }) => srcset).join(",");
const webpSrcset = webp.map(({ srcset }) => srcset).join(",");
const pngSrcset = png.map(({ srcset }) => srcset).join(",");
---
<section class="relative h-full bg-black">
<Starfield />
<div class="relative grid h-full sm:grid-cols-2 place-items-center">
<h2
class="flex flex-col self-end gap-2 sm:gap-4 sm:self-auto sm:justify-self-end"
>
<Icon name="logomark" class="h-24 text-white md:h-32" />
<div
class="font-extrabold tracking-tighter text-center text-8xl gradient-text"
>
Build fast
<br /> websites,
<br /> faster.
</div>
</h2>
<picture
class="self-start w-2/3 max-w-3xl sm:w-10/12 sm:self-auto sm:justify-self-start"
>
<source type="image/avif" srcset={avifSrcset} sizes={sizes} />
<source type="image/webp" srcset={webpSrcset} sizes={sizes} />
<source type="image/png" srcset={pngSrcset} sizes={sizes} />
<img
class="object-cover w-full h-full"
src={png[0].url}
width={png[0].width}
height={png[0].height}
alt="A floating astronaut in a space suit"
/>
</picture>
</div>
</section>
<noscript>
<style>
#splash-bg-fallback {
display: block;
}
</style>
</noscript>
<style>
@keyframes float {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(0, 30px, 0);
}
}
picture {
animation: float linear 2.5s infinite alternate;
}
@media (prefers-reduced-motion: reduce) {
picture {
@apply animate-none;
}
:global(#starfield) {
@apply hidden;
}
#splash-bg-fallback {
@apply block;
}
}
</style>

View file

@ -0,0 +1,97 @@
<div id="starfield" class="absolute inset-0">
<canvas id="starfield-canvas"></canvas>
</div>
<script>
const COUNT = 800;
const SPEED = 0.1;
class Star {
x: number;
y: number;
z: number;
xPrev: number;
yPrev: number;
constructor(x = 0, y = 0, z = 0) {
this.x = x;
this.y = y;
this.z = z;
this.xPrev = x;
this.yPrev = y;
}
update(width: number, height: number, speed: number) {
this.xPrev = this.x;
this.yPrev = this.y;
this.z += speed * 0.0675;
this.x += this.x * (speed * 0.0225) * this.z;
this.y += this.y * (speed * 0.0225) * this.z;
if (
this.x > width / 2 ||
this.x < -width / 2 ||
this.y > height / 2 ||
this.y < -height / 2
) {
this.x = Math.random() * width - width / 2;
this.y = Math.random() * height - height / 2;
this.xPrev = this.x;
this.yPrev = this.y;
this.z = 0;
}
}
draw(ctx: CanvasRenderingContext2D) {
ctx.lineWidth = this.z;
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.xPrev, this.yPrev);
ctx.stroke();
}
}
const stars = Array.from({ length: COUNT }, () => new Star(0, 0, 0));
let rafId = 0;
const canvas: HTMLCanvasElement = document.querySelector("#starfield-canvas");
const ctx = canvas.getContext("2d");
const container = document.querySelector("#starfield");
const resizeObserver = new ResizeObserver(setup);
resizeObserver.observe(container);
function setup() {
rafId > 0 && cancelAnimationFrame(rafId);
const { clientWidth: width, clientHeight: height } = container;
const dpr = window.devicePixelRatio || 1;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
ctx.scale(dpr, dpr);
for (const star of stars) {
star.x = Math.random() * width - width / 2;
star.y = Math.random() * height - height / 2;
star.z = 0;
}
ctx.translate(width / 2, height / 2);
ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
ctx.strokeStyle = "white";
rafId = requestAnimationFrame(frame);
}
function frame() {
const { clientWidth: width, clientHeight: height } = container;
for (const star of stars) {
star.update(width, height, SPEED);
star.draw(ctx);
}
ctx.fillRect(-width / 2, -height / 2, width, height);
rafId = requestAnimationFrame(frame);
}
</script>

View file

@ -0,0 +1,60 @@
---
import { Icon } from "astro-icon";
---
<!--
negative margin is sum of button width (8) and gap size of flex parent (6)
TODO don't hardcode these values
-->
<button
id="theme-switcher"
type="button"
class="scale-0 transition-all origin-[right_center] duration-500 -ml-14"
>
<div id="icon-theme-light">
<Icon name="theme/light" class="h-8" />
<span class="sr-only">Use light theme</span>
</div>
<div id="icon-theme-dark" class="hidden">
<Icon name="theme/dark" class="h-8" />
<span class="sr-only">Use dark theme</span>
</div>
</button>
<script>
const themes = ["light", "dark"];
const button = document.querySelector("#theme-switcher");
const getThemeCurrent = () => document.documentElement.dataset.theme;
const getThemeNext = () => {
const themeCurrent = getThemeCurrent();
const indexThemeCurrent = themes.indexOf(themeCurrent);
return themes[(indexThemeCurrent + 1) % themes.length];
};
const updateIcon = () => {
const themeCurrent = getThemeCurrent();
document
.querySelector(`#icon-theme-${themeCurrent}`)
.classList.add("hidden");
const themeNext = getThemeNext();
document
.querySelector(`#icon-theme-${themeNext}`)
.classList.remove("hidden");
};
button.addEventListener("click", () => {
const themeNext = getThemeNext();
document.documentElement.dataset.theme = themeNext;
localStorage.setItem("theme", themeNext);
updateIcon();
});
updateIcon();
</script>
<style>
:global(.fixed-header) #theme-switcher {
@apply scale-100 ml-0;
}
</style>

1
landing-page/src/env.d.ts vendored Normal file
View file

@ -0,0 +1 @@
/// <reference types="astro/client" />

View file

@ -0,0 +1,14 @@
<svg viewBox="0 0 627 894" fill="none">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M445.433 22.9832C452.722 32.0324 456.439 44.2432 463.873 68.6647L626.281 602.176C566.234 571.026 500.957 548.56 432.115 536.439L326.371 179.099C324.641 173.252 319.27 169.241 313.173 169.241C307.06 169.241 301.68 173.273 299.963 179.14L195.5 536.259C126.338 548.325 60.7632 570.832 0.459473 602.095L163.664 68.5412C171.121 44.1617 174.85 31.9718 182.14 22.9393C188.575 14.9651 196.946 8.77213 206.454 4.95048C217.224 0.621582 229.971 0.621582 255.466 0.621582H372.034C397.562 0.621582 410.326 0.621582 421.106 4.95951C430.622 8.78908 438.998 14.9946 445.433 22.9832Z"
fill="currentColor"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M464.867 627.566C438.094 650.46 384.655 666.073 323.101 666.073C247.551 666.073 184.229 642.553 167.426 610.921C161.419 629.05 160.072 649.798 160.072 663.052C160.072 663.052 156.114 728.134 201.38 773.401C201.38 749.896 220.435 730.842 243.939 730.842C284.226 730.842 284.181 765.99 284.144 794.506C284.143 795.36 284.142 796.209 284.142 797.051C284.142 840.333 310.595 877.436 348.215 893.075C342.596 881.518 339.444 868.54 339.444 854.825C339.444 813.545 363.679 798.175 391.845 780.311C414.255 766.098 439.155 750.307 456.315 718.629C465.268 702.101 470.352 683.17 470.352 663.052C470.352 650.68 468.43 638.757 464.867 627.566Z"
fill="#FF5D01"
/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,161 @@
<!-- source: https://github.com/basmilius/weather-icons -->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512"
>
<defs>
<linearGradient
id="a"
x1="54.33"
y1="29.03"
x2="187.18"
y2="259.13"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="currentColor" />
<stop offset="0.45" stop-color="currentColor" />
<stop offset="1" stop-color="currentColor" />
</linearGradient>
<linearGradient
id="b"
x1="294"
y1="112.82"
x2="330"
y2="175.18"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="currentColor" />
<stop offset="0.45" stop-color="currentColor" />
<stop offset="1" stop-color="currentColor" />
</linearGradient>
<linearGradient
id="c"
x1="295.52"
y1="185.86"
x2="316.48"
y2="222.14"
xlink:href="#b"
/>
<linearGradient
id="d"
x1="356.29"
y1="194.78"
x2="387.71"
y2="249.22"
xlink:href="#b"
/>
<symbol id="e" viewBox="0 0 270 270" overflow="visible">
<!-- moon -->
<path
d="M252.25,168.63C178.13,168.63,118,109.35,118,36.21A130.48,130.48,0,0,1,122.47,3C55.29,10.25,3,66.37,3,134.58,3,207.71,63.09,267,137.21,267,199.69,267,252,224.82,267,167.79A135.56,135.56,0,0,1,252.25,168.63Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="6"
fill="url(#a)"
>
<animateTransform
attributeName="transform"
additive="sum"
type="rotate"
values="-15 135 135; 9 135 135; -15 135 135"
dur="6s"
repeatCount="indefinite"
/>
</path>
</symbol>
</defs>
<!-- star-1 -->
<path
d="M282.83,162.84l24.93-6.42a1.78,1.78,0,0,1,1.71.46l18.37,18a1.8,1.8,0,0,0,3-1.73l-6.42-24.93a1.78,1.78,0,0,1,.46-1.71l18-18.37a1.8,1.8,0,0,0-1.73-3l-24.93,6.42a1.78,1.78,0,0,1-1.71-.46l-18.37-18a1.8,1.8,0,0,0-3,1.73l6.42,24.93a1.78,1.78,0,0,1-.46,1.71l-18,18.37A1.8,1.8,0,0,0,282.83,162.84Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
fill="url(#b)"
>
<animateTransform
attributeName="transform"
additive="sum"
type="rotate"
values="-15 312 144; 15 312 144; -15 312 144"
dur="6s"
calcMode="spline"
keySplines=".42, 0, .58, 1; .42, 0, .58, 1"
repeatCount="indefinite"
/>
<animate
attributeName="opacity"
values="1; .75; 1; .75; 1; .75; 1"
dur="6s"
/>
</path>
<!-- star-2 -->
<path
d="M285.4,193.44l12,12.25a1.19,1.19,0,0,1,.3,1.14l-4.28,16.62a1.2,1.2,0,0,0,2,1.15l12.25-12a1.19,1.19,0,0,1,1.14-.3l16.62,4.28a1.2,1.2,0,0,0,1.15-2l-12-12.25a1.19,1.19,0,0,1-.3-1.14l4.28-16.62a1.2,1.2,0,0,0-2-1.15l-12.25,12a1.19,1.19,0,0,1-1.14.3l-16.62-4.28A1.2,1.2,0,0,0,285.4,193.44Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
fill="url(#c)"
>
<animateTransform
attributeName="transform"
additive="sum"
type="rotate"
values="-15 306 204; 15 306 204; -15 306 204"
begin="-.33s"
dur="6s"
calcMode="spline"
keySplines=".42, 0, .58, 1; .42, 0, .58, 1"
repeatCount="indefinite"
/>
<animate
attributeName="opacity"
values="1; .75; 1; .75; 1; .75; 1"
begin="-.33s"
dur="6s"
/>
</path>
<!-- star-3 -->
<path
d="M337.32,223.73l24.8,6.9a1.83,1.83,0,0,1,1.25,1.25l6.9,24.8a1.79,1.79,0,0,0,3.46,0l6.9-24.8a1.83,1.83,0,0,1,1.25-1.25l24.8-6.9a1.79,1.79,0,0,0,0-3.46l-24.8-6.9a1.83,1.83,0,0,1-1.25-1.25l-6.9-24.8a1.79,1.79,0,0,0-3.46,0l-6.9,24.8a1.83,1.83,0,0,1-1.25,1.25l-24.8,6.9A1.79,1.79,0,0,0,337.32,223.73Z"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
fill="url(#d)"
>
<animateTransform
attributeName="transform"
additive="sum"
type="rotate"
values="-15 372 222; 15 372 222; -15 372 222"
begin="-.67s"
dur="6s"
calcMode="spline"
keySplines=".42, 0, .58, 1; .42, 0, .58, 1"
repeatCount="indefinite"
/>
<animate
attributeName="opacity"
values="1; .75; 1; .75; 1; .75; 1"
begin="-.67s"
dur="6s"
/>
</path>
<use
width="270"
height="270"
transform="translate(121 121)"
xlink:href="#e"
/>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -0,0 +1,53 @@
<!-- source: https://github.com/basmilius/weather-icons -->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512 512"
>
<defs>
<linearGradient
id="a"
x1="149.99"
y1="119.24"
x2="234.01"
y2="264.76"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="currentColor" />
<stop offset="0.45" stop-color="currentColor" />
<stop offset="1" stop-color="currentColor" />
</linearGradient>
<symbol id="b" viewBox="0 0 384 384">
<!-- core -->
<circle
cx="192"
cy="192"
r="84"
stroke="currentColor"
stroke-miterlimit="10"
stroke-width="6"
fill="url(#a)"
/>
<!-- rays -->
<path
d="M192,61.66V12m0,360V322.34M284.17,99.83l35.11-35.11M64.72,319.28l35.11-35.11m0-184.34L64.72,64.72M319.28,319.28l-35.11-35.11M61.66,192H12m360,0H322.34"
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-miterlimit="10"
stroke-width="24"
>
<animateTransform
attributeName="transform"
additive="sum"
type="rotate"
values="0 192 192; 45 192 192"
dur="6s"
repeatCount="indefinite"
/>
</path>
</symbol>
</defs>
<use width="384" height="384" transform="translate(64 64)" xlink:href="#b" />
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,22 @@
<svg viewBox="0 0 1847 457" fill="none">
<path
d="M134.148 456.833C202.08 456.833 253.03 432.665 273.93 391.516C273.93 411.111 275.23 431.36 278.5 447.036H390.19C384.97 424.173 382.36 392.82 382.36 351.671V251.081C382.36 155.717 326.18 110.648 201.43 110.648C92.3441 110.648 19.188 155.717 10.697 229.527H126.963C130.882 197.521 157.66 179.885 201.43 179.885C244.53 179.885 268.7 197.521 268.7 234.1V243.896L150.48 254.347C92.997 260.227 60.338 270.023 37.477 285.7C13.31 302.028 0.898987 326.851 0.898987 357.549C0.898987 418.948 51.847 456.833 134.148 456.833ZM177.26 388.902C139.37 388.902 116.512 373.88 116.512 349.712C116.512 324.892 135.45 311.827 183.14 305.949L270.66 296.805V316.4C270.66 360.163 232.78 388.902 177.26 388.902Z"
fill="currentColor"
/>
<path
d="M625.77 456.833C739.43 456.833 797.56 414.377 797.56 345.793C797.56 288.966 764.9 257.613 685.87 247.162L587.23 236.059C559.15 232.138 547.39 224.953 547.39 209.277C547.39 190.336 566.33 181.844 609.44 181.844C668.88 181.844 710.03 195.561 743.35 222.342L796.25 169.434C759.67 131.55 696.32 110.648 617.94 110.648C507.55 110.648 446.15 149.838 446.15 215.809C446.15 273.289 484.03 305.295 562.41 315.745L651.25 326.196C686.52 330.769 696.97 337.302 696.97 354.283C696.97 373.88 677.37 384.331 631.65 384.331C563.72 384.331 518 366.041 487.3 332.076L427.21 381.717C467.05 431.36 534.98 456.833 625.77 456.833Z"
fill="currentColor"
/>
<path
d="M889.78 194.255V332.076C889.78 413.07 935.5 454.221 1033.48 454.221C1063.53 454.221 1087.04 450.955 1109.25 444.423V359.508C1097.49 362.122 1083.12 364.734 1064.18 364.734C1023.03 364.734 1002.78 346.446 1002.78 307.908V194.255H1109.9V120.445H1002.78V0.914001L889.78 42.717V120.445H816.62V194.255H889.78Z"
fill="currentColor"
/>
<path
d="M1272.13 120.445H1168.93V447.036H1281.93V324.892C1281.93 289.618 1289.77 257.613 1311.33 237.364C1328.31 221.687 1352.48 213.198 1386.44 213.198C1398.85 213.198 1408.65 214.502 1419.75 215.809V113.26C1412.57 111.954 1407.34 111.954 1398.2 111.954C1333.53 111.954 1289.77 149.185 1272.13 209.932V120.445Z"
fill="currentColor"
/>
<path
d="M1643.05 456.833C1762.59 456.833 1846.85 393.475 1846.85 283.088C1846.85 173.353 1762.59 110.648 1643.05 110.648C1522.87 110.648 1438.61 173.353 1438.61 283.088C1438.61 393.475 1522.87 456.833 1643.05 456.833ZM1643.05 381.717C1588.19 381.717 1553.57 346.446 1553.57 283.088C1553.57 219.728 1588.19 185.763 1643.05 185.763C1697.27 185.763 1731.89 219.728 1731.89 283.088C1731.89 346.446 1697.27 381.717 1643.05 381.717Z"
fill="currentColor"
/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,83 @@
---
import Header from "~/components/header.astro";
import Splash from "~/components/splash.astro";
import "~/styles/index.css";
const { site } = Astro;
const image = new URL("social.jpg", site);
const description =
"Build fast websites, faster. Astro is a new kind of site builder for the modern web. Lightning-fast performance meets powerful developer experience.";
---
<html lang="en" class="h-full motion-safe:scroll-smooth" data-theme="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" href="/favicon.ico" sizes="any" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<title>Astro Reactive Library</title>
<meta name="description" content={description} />
<!-- fonts -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="preload"
as="style"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;800&display=swap"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;800&display=swap"
media="print"
onload="this.media='all'"
/>
<noscript>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;800&display=swap"
/>
</noscript>
<!-- social media -->
<meta property="og:title" content="Astro" />
<meta property="og:type" content="website" />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<meta property="og:url" content={site} />
<meta name="twitter:card" content="summary_large_image" />
<!-- initialize theme -->
<script is:inline>
const themeSaved = localStorage.getItem("theme");
if (themeSaved) {
document.documentElement.dataset.theme = themeSaved;
} else {
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)"
).matches;
document.documentElement.dataset.theme = prefersDark ? "dark" : "light";
}
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", (event) => {
if (!localStorage.getItem("theme")) {
document.documentElement.dataset.theme = event.matches
? "dark"
: "light";
}
});
</script>
</head>
<body
class="h-full overflow-x-hidden text-base bg-default text-default selection:bg-secondary selection:text-white"
>
<Header />
<Splash />
<div class="h-screen">
<h1>This section is added just to test the sticky header</h1>
</div>
</body>
</html>

View file

@ -0,0 +1,12 @@
/* TODO: consider creating <Button> and <GradientText> components */
a,
.btn {
@apply transition-colors duration-200;
@apply hover:text-secondary;
@apply focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-transparent focus:ring-secondary;
}
.gradient-text {
@apply text-transparent bg-clip-text;
@apply bg-gradient-to-br from-indigo-500 via-fuchsia-500 to-pink-500;
}

View file

@ -0,0 +1,2 @@
@import "global.css";
@import "theme.css";

View file

@ -0,0 +1,19 @@
[data-theme="light"] {
--color-primary: theme("colors.pink.500");
--color-secondary: theme("colors.indigo.500");
--color-text: theme("colors.gray.900");
--color-text-offset: theme("colors.gray.600");
--color-background: theme("colors.gray.50");
--color-background-offset: theme("colors.gray.100");
--color-border: theme("colors.gray.900" / 10%);
}
[data-theme="dark"] {
--color-primary: theme("colors.pink.400");
--color-secondary: theme("colors.indigo.400");
--color-text: theme("colors.gray.50");
--color-text-offset: theme("colors.gray.400");
--color-background: theme("colors.gray.900");
--color-background-offset: theme("colors.gray.800");
--color-border: theme("colors.gray.50" / 10%);
}

View file

@ -0,0 +1,31 @@
const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = {
content: ["./src/**/*.{astro,html,js,jsx,svelte,ts,tsx,vue}"],
theme: {
extend: {
fontFamily: {
sans: ["Inter", ...defaultTheme.fontFamily.sans],
},
colors: {
primary: "var(--color-primary)",
secondary: "var(--color-secondary)",
},
textColor: {
default: "var(--color-text)",
offset: "var(--color-text-offset)",
},
backgroundColor: {
default: "var(--color-background)",
offset: "var(--color-background-offset)",
},
borderColor: {
default: "var(--color-border)",
},
},
},
corePlugins: {
fontSize: false,
},
plugins: [require("tailwindcss-fluid-type")],
};

View file

@ -0,0 +1,20 @@
{
"compilerOptions": {
// Enable top-level await, and other modern ESM features.
"target": "ESNext",
"module": "ESNext",
// Enable node-style module resolution, for things like npm package imports.
"moduleResolution": "node",
// Enable JSON imports.
"resolveJsonModule": true,
// Enable stricter transpilation for better output.
"isolatedModules": true,
// Astro will directly run your TypeScript code, no transpilation needed.
"noEmit": true,
// Alias `src/` to `~`
"baseUrl": ".",
"paths": {
"~/*": ["src/*"]
}
}
}