Initial commit
This commit is contained in:
commit
0edbbb015e
12 changed files with 228 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
bun.lockb
|
20
package.json
Normal file
20
package.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "@codespacecz/web",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Astro website components for CodeSpace websites",
|
||||||
|
"author": "CodeSpace (https://codespace.cz)",
|
||||||
|
"license": "LGPL-3.0-or-later",
|
||||||
|
"exports": {
|
||||||
|
"./components": "./src/components/index.ts",
|
||||||
|
"./types": "./src/types.ts",
|
||||||
|
"./style.css": "./src/css/style.css"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"astro-icon": "^1.1.0",
|
||||||
|
"@iconify-json/tabler": "^1.1.110"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"astro": "^4.9.3",
|
||||||
|
"typescript": "^5.4.5"
|
||||||
|
}
|
||||||
|
}
|
30
src/components/MetaTags.astro
Normal file
30
src/components/MetaTags.astro
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
---
|
||||||
|
import type { Meta } from '../types';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
meta: Meta
|
||||||
|
}
|
||||||
|
|
||||||
|
const { meta } = Astro.props;
|
||||||
|
|
||||||
|
const title = meta.title + (meta.use_title_suffix ? meta.title_suffix : "");
|
||||||
|
const card = meta.image_type == "banner" ? "summary_large_image" : "summary";
|
||||||
|
---
|
||||||
|
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>{title}</title>
|
||||||
|
<meta name="description" content={meta.desc} />
|
||||||
|
<meta name="theme-color" content={meta.color}>
|
||||||
|
<meta name="description" content={meta.desc}>
|
||||||
|
<meta property="og:site_name" content={meta.site_name}>
|
||||||
|
<meta property="og:title" content={meta.title}>
|
||||||
|
<meta property="og:description" content={meta.desc}>
|
||||||
|
<meta property="og:image" content={meta.image}>
|
||||||
|
<meta property="twitter:site_name" content={meta.site_name}>
|
||||||
|
<meta property="twitter:title" content={meta.title}>
|
||||||
|
<meta property="twitter:description" content={meta.desc}>
|
||||||
|
<meta property="twitter:image" content={meta.image}>
|
||||||
|
<meta property="twitter:card" content={card}>
|
||||||
|
<meta name="author" content={meta.author}>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<link rel="icon" href={meta.favicon} />
|
32
src/components/Nav.astro
Normal file
32
src/components/Nav.astro
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
import { Icon } from 'astro-icon/components';
|
||||||
|
import type { NavProps, RecursivePartial } from '../types';
|
||||||
|
import "../css/nav.css";
|
||||||
|
|
||||||
|
type Props = RecursivePartial<NavProps>;
|
||||||
|
|
||||||
|
const logo = {
|
||||||
|
link: "/",
|
||||||
|
image: "/assets/logo.webp",
|
||||||
|
...Astro.props.logo
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
<input type="checkbox" id="menu-toggle">
|
||||||
|
<nav>
|
||||||
|
<div class="inner">
|
||||||
|
<div class="title">
|
||||||
|
<slot name="logo">
|
||||||
|
<a href={ logo.link } class="logo">
|
||||||
|
<img src={ logo.image } />
|
||||||
|
</a>
|
||||||
|
</slot>
|
||||||
|
<label for="menu-toggle">
|
||||||
|
<Icon name="tabler:menu-2" class="icon" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<slot />
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
14
src/components/NavLink.astro
Normal file
14
src/components/NavLink.astro
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
import type { HTMLAttributes } from 'astro/types';
|
||||||
|
|
||||||
|
type Props = HTMLAttributes<'a'>;
|
||||||
|
|
||||||
|
const { href, class: className, ...props } = Astro.props;
|
||||||
|
|
||||||
|
const { pathname } = Astro.url;
|
||||||
|
const isActive = href === pathname;
|
||||||
|
---
|
||||||
|
|
||||||
|
<a href={href} class:list={[className, { active: isActive }]} {...props}>
|
||||||
|
<slot />
|
||||||
|
</a>
|
3
src/components/index.ts
Normal file
3
src/components/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export { default as MetaTags } from './MetaTags.astro';
|
||||||
|
export { default as Nav } from './Nav.astro';
|
||||||
|
export { default as NavLink } from './NavLink.astro';
|
14
src/css/global.css
Normal file
14
src/css/global.css
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
html, body {font-family: Cantarell, sans-serif; background-color: var(--bg-color); color: var(--text-color); margin: 0; line-height: 1.5; font-size: 20px; display: flex; flex-direction: column; justify-content: space-between; min-height: 100vh;}
|
||||||
|
|
||||||
|
:is(nav, header, section, footer) > .inner {max-width: var(--site-width); margin: auto; padding: 0 var(--site-padding);}
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
:root {
|
||||||
|
--site-padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5 {color: var(--title-color); font-weight: 900;}
|
||||||
|
|
||||||
|
a {color: var(--link-color);}
|
||||||
|
a:hover {color: var(--link-hover-color);}
|
49
src/css/nav.css
Normal file
49
src/css/nav.css
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
nav {position: relative; top: 0; left: 0; width: 100%; border-bottom: 1px solid var(--border-color); height: var(--nav-height);}
|
||||||
|
|
||||||
|
.style-white-nav nav img {filter: grayscale(1) brightness(10);}
|
||||||
|
|
||||||
|
nav .inner {display: flex; gap: 30px; align-items: center;}
|
||||||
|
|
||||||
|
nav .title > * {display: none;}
|
||||||
|
nav .title img {height: 30px;}
|
||||||
|
nav .title .icon {padding: 20px; margin: -20px; cursor: pointer; font-size: 24px; color: var(--title-color);}
|
||||||
|
nav .title .logo {display: flex;}
|
||||||
|
|
||||||
|
nav :is(a, label) {display: flex; align-items: center;}
|
||||||
|
|
||||||
|
nav ul {list-style: none; padding: 0; margin: 0; display: flex; gap: 20px; font-size: 20px; flex: 1;}
|
||||||
|
nav ul a {gap: 8px; color: var(--text-color); text-decoration: none; font-weight: 700; padding: 22px 0;}
|
||||||
|
|
||||||
|
nav a.active {color: var(--nav-link-color); box-shadow: 0 1px 0 0 var(--nav-link-color);}
|
||||||
|
nav a:hover {color: var(--text-hover-color);}
|
||||||
|
|
||||||
|
nav ul li.right {margin-left: auto;}
|
||||||
|
|
||||||
|
#menu-toggle {display: none;}
|
||||||
|
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--nav-height: 64px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {overflow: hidden;}
|
||||||
|
#menu-toggle:checked + nav {height: 100%;}
|
||||||
|
|
||||||
|
nav .inner {display: block; flex-direction: column-reverse;}
|
||||||
|
nav .title {display: grid; gap: 15px; grid-template-columns: 1fr max-content; border-bottom: 1px solid var(--border-color); height: var(--nav-height);}
|
||||||
|
nav .title > *, .nav .title {display: flex; align-items: center;}
|
||||||
|
nav .title img {height: 24px;}
|
||||||
|
|
||||||
|
nav ul {flex-direction: column; margin: 20px 0; gap: 0px;}
|
||||||
|
nav ul li {margin: 0 !important;}
|
||||||
|
|
||||||
|
nav ul a {padding: 6px 20px; padding-left: 51px; margin: 0 -20px; font-size: 18px; position: relative; text-decoration: none;}
|
||||||
|
nav ul a.active {font-weight: 900; box-shadow: none;}
|
||||||
|
|
||||||
|
nav ul a::before {content: ""; width: 11px; height: 2px; background-color: var(--nav-inactive-color); position: absolute; left: 23px; top: 50%; border-radius: 5px;}
|
||||||
|
nav ul a.active::before {background-color: var(--brand-color-1);}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(#menu-toggle:checked) + nav + header.under-nav {margin-top: calc(-1px - var(--nav-height)); padding-top: calc(1px + var(--nav-height));}
|
13
src/css/sections.css
Normal file
13
src/css/sections.css
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/* Sections */
|
||||||
|
|
||||||
|
:is(header, section, footer) > .inner {margin: 70px auto; padding: 0 var(--site-padding);}
|
||||||
|
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
|
||||||
|
header > .inner {padding: 0 var(--site-padding);}
|
||||||
|
header {overflow: hidden;}
|
||||||
|
|
||||||
|
header:not(.no-line) + section {border-top: 1px solid var(--border-color);}
|
||||||
|
|
||||||
|
.in-header {margin-top: -50px;}
|
3
src/css/style.css
Normal file
3
src/css/style.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
@import "./variables.css";
|
||||||
|
@import "./global.css";
|
||||||
|
@import "./sections.css";
|
23
src/css/variables.css
Normal file
23
src/css/variables.css
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
:root {
|
||||||
|
|
||||||
|
--bg-color: #18181b;
|
||||||
|
--alt-bg-color: #232327;
|
||||||
|
|
||||||
|
--border-color: rgba(255, 255, 255, 0.1);
|
||||||
|
|
||||||
|
--nav-link-color: #fff;
|
||||||
|
--nav-inactive-color: #fff5;
|
||||||
|
--nav-height: 75px;
|
||||||
|
|
||||||
|
--title-color: #fff;
|
||||||
|
--text-color: #fffa;
|
||||||
|
--text-hover-color: #fffd;
|
||||||
|
--text-active-color: #fff;
|
||||||
|
|
||||||
|
--link-color: #dd4379;
|
||||||
|
--link-hover-color: #c21f58;
|
||||||
|
|
||||||
|
--site-padding: 40px;
|
||||||
|
--site-width: 1200px;
|
||||||
|
|
||||||
|
}
|
25
src/types.ts
Normal file
25
src/types.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
export type RecursivePartial<T> = {
|
||||||
|
[P in keyof T]?: RecursivePartial<T[P]>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Meta {
|
||||||
|
site_name: string,
|
||||||
|
author: string,
|
||||||
|
title: string,
|
||||||
|
desc: string,
|
||||||
|
title_suffix: string,
|
||||||
|
use_title_suffix: boolean,
|
||||||
|
image: string,
|
||||||
|
image_type: "banner" | "icon",
|
||||||
|
favicon: string,
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NavProps {
|
||||||
|
logo: NavLogo
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NavLogo {
|
||||||
|
link: string,
|
||||||
|
image: string
|
||||||
|
}
|
Loading…
Reference in a new issue