1
0
Fork 0
mirror of https://github.com/TheTaz25/denis.ergin.git synced 2025-07-06 13:18:49 +00:00

feat(knowledge-base): Rewrite Navigation, add utils, initial page for knowledge-base

This commit is contained in:
Denis Ergin 2024-10-18 11:51:16 +02:00
parent 20d548bec6
commit d207c35805
11 changed files with 283 additions and 58 deletions

View file

@ -0,0 +1,55 @@
---
import { clx } from '../../utils/classes';
type Props = {
className?: string;
type?: 'primary' | 'ghost';
}
const { className, type, ...props } = Astro.props;
const buttonType = type ?? 'primary'
---
<button class={clx({
[buttonType]: true,
}, className)} {...props}>
<slot />
</button>
<style lang="scss">
button {
border: none;
font-size: 1rem;
background-color: unset;
color: var(--foreground-color);
border-radius: 0.5rem 0;
padding: 0.5rem 0.75rem;
&.primary {
color: var(--button-fg-color);
background-color: var(--button-background-color);
border: 2px solid #8da9c4;
&:focus-within, &:hover {
background-color: var(--button-hover-color);
}
&:active {
background-color: var(--button-active-color);
}
}
&.ghost {
&:hover, &:focus-within {
background-color: rgba(255, 255, 255, 0.1);
}
&:active {
background-color: rgba(255, 255, 255, 0.2);
}
}
}
button:hover {
cursor: pointer;
}
</style>

View file

@ -0,0 +1,23 @@
---
interface Props {
to: string;
class?: string;
}
const { to, class: className, ...rest } = Astro.props;
---
<a class:list={["card", className]} href={to} {...rest}>
<slot />
</a>
<style>
.card {
background-color: var(--navigation-background-color);
display: inline-block;
padding: 1rem;
border-radius: 0.25rem;
max-width: 80vw;
text-decoration: none;
}
</style>

View file

@ -0,0 +1,19 @@
<div class="module-slider">
<div class="slider-content">
<slot />
</div>
</div>
<style>
.module-slider {
overflow-x: auto;
display: flex;
}
.slider-content {
display: flex;
flex: 1 1 auto;
flex-wrap: nowrap;
overflow-y: visible;
}
</style>

View file

@ -15,58 +15,34 @@ const currentPath = new URL(Astro.url).pathname.split('/')[1];
a {
text-decoration: none;
color: white;
font-size: larger;
font-size: large;
position: relative;
&::before {
content: "{";
transform: translateX(-2rem);
left: 0;
position: absolute;
transition-property: transform, opacity;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
&::after {
content: "}";
transform: translateX(2rem);
right: 0;
position: absolute;
font-family: monospace;
content: ".clickable";
transition-property: transform, opacity;
transition-duration: 150ms;
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
&:not(.current) {
&::after,
&::before {
&::after {
opacity: 0;
}
&:hover,
&:focus-within {
&::before,
&::after {
opacity: 1;
}
&::before { transform: translateX(-1rem); }
&::after { transform: translateX(1rem); }
}
}
&.current {
&::before {
transition: transform 100ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
transform: translateX(-2rem);
}
&:hover::before,
&:focus-visible::before {
transform: translateX(-1rem);
}
&::after {
content: '.current';
transform: translateX(2rem);
transition: transform 100ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
}

77
src/components/nav.astro Normal file
View file

@ -0,0 +1,77 @@
---
import { Icon } from 'astro-icon/components';
import Button from './atoms/Button.astro';
import Link from './atoms/Link.astro';
---
<div class="nav-wrapper">
<Button className="nav-open">
<Icon name="ham" />
Menü
</Button>
</div>
<nav aria-hidden="true" class="main">
<Button className="nav-close" aria-label="Navigation schließen" type="ghost">
Menü schließen
</Button>
<ul>
<li><Link to="/">Startseite</Link></li>
<li><Link to="/knowledge-base">Knowledge-Base</Link></li>
</ul>
</nav>
<script>
function toggleMenu() {
const targetAttr = 'aria-hidden';
const nav = document.querySelector('nav.main') as HTMLElement;
const nextState = nav.getAttribute(targetAttr) === 'true' ? 'false' : 'true';
nav.setAttribute(targetAttr, nextState);
}
const openbutton = document.querySelector('button.nav-open') as HTMLButtonElement;
openbutton.addEventListener('click', toggleMenu);
const closeButton = document.querySelector('button.nav-close') as HTMLButtonElement;
closeButton.addEventListener('click', toggleMenu);
</script>
<style lang="scss">
div.nav-wrapper {
position: relative;
}
nav.main {
position: absolute;
height: calc(100vh - 2rem);
max-width: 90vw;
width: 300px;
top: 0;
padding: 0;
margin: 0;
transition: left 150ms ease-out;
background-color: var(--navigation-background-color);
border-right: 2px solid #8da9c4;
padding-left: 2rem;
padding-top: 2rem;
}
nav.main ul {
list-style: none;
padding-left: 0;
line-height: 2.5rem;
font-size: 1.3rem;
}
nav.main[aria-hidden="true"] {
left: -100vw;
}
nav.main[aria-hidden="false"] {
left: 0rem;
}
button.nav-open {
display: inline-flex;
gap: 1rem;
align-items: center;
}
</style>

5
src/icons/ham.svg Normal file
View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
<rect width="16" height="2" y="3" rx="1"/>
<rect width="16" height="2" y="7" rx="1" />
<rect width="16" height="2" y="11" rx="1" />
</svg>

After

Width:  |  Height:  |  Size: 225 B

View file

@ -1,6 +1,6 @@
---
import Link from '../components/atoms/Link.astro';
import { getLangFromUrl, useTranslations } from '../i18n/utils';
import Navigation from '../components/nav.astro'
import { getLangFromUrl } from '../i18n/utils';
import '../styles/global.css'
interface Props {
@ -9,7 +9,7 @@ interface Props {
const { title } = Astro.props;
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
// const t = useTranslations(lang);
---
<!doctype html>
@ -24,10 +24,7 @@ const t = useTranslations(lang);
</head>
<body>
<header>
<nav>
<Link to="/">{t('nav.home')}</Link>
<Link to="/else">{t('nav.knowledgeBase')}</Link>
</nav>
<Navigation />
</header>
<main>
<slot />
@ -35,23 +32,12 @@ const t = useTranslations(lang);
</body>
</html>
<style is:global lang="scss">
:root {
--accent: 136, 58, 234;
--accent-light: 224, 204, 250;
--accent-dark: 49, 10, 101;
--accent-gradient: linear-gradient(
45deg,
rgb(var(--accent)),
rgb(var(--accent-light)) 30%,
white 60%
);
}
html {
html, a:visited {
font-family: system-ui, sans-serif;
background: #13151a;
color: white;
background-color: var(--background-color);
color: var(--foreground-color);
}
main {
body {
max-width: 1200px;
margin: 0 auto;
}
@ -66,11 +52,10 @@ const t = useTranslations(lang);
Courier New,
monospace;
}
nav {
display: flex;
align-items: center;
justify-content: center;
gap: 4rem;
margin: 1rem 0 2rem 0;
header {
margin: 1rem 1rem;
}
main {
margin: 0 1rem;
}
</style>

View file

@ -1,7 +1,6 @@
---
import Layout from '../layouts/Layout.astro';
import { useTranslations } from '../i18n/utils';
import '../styles/homepage-markdown.scss';
import { Icon } from 'astro-icon/components';
const t = useTranslations();

View file

@ -0,0 +1,68 @@
---
import { Icon } from 'astro-icon/components'
import Card from '../../components/atoms/Card.astro'
import HorizontalSlider from '../../components/atoms/HorizontalSlider.astro'
import { getCollection } from 'astro:content'
import Layout from '../../layouts/Layout.astro'
const dhbwModules = await getCollection('dhbw', (module) => module.data.show);
---
<Layout title="Startseite der Knowledge-Base">
<section>
<h1>Startseite der Knowledge-Base</h1>
<p>
Hier findet Ihr verschiedene Einträge / Beiträge / innere Monologe jedweder Art von Wissen, die ich als Entwickler sammeln und teilen kann oder will. Die Inhalte sollten (im besten Fall) mit der Zeit mehr werden, eine Garantie "regelmäßig" etwas zu verfassen kann ich aber nicht geben.
</p>
<p>
Zusätzlich zu den Inhalten werden hier auch Informationen aufbereitet, die ich als Dozent an der DHBW Karlsruhe in den Module Web Engineering I sowie Web Engineering II präsentiere.
</p>
</section>
<section>
<h2>DHBW Module</h2>
<p>
Hier findet Ihr alles rund um die Module die ich als Dozent für die DHBW verfasst habe.
</p>
<HorizontalSlider>
{dhbwModules.map((module) => (
<Card to={`${module.data.staticPath}${module.slug}`} class="module-card">
<span class="card-title">{module.data.title}</span>
<Icon name="arrow" class="arrow" />
</Card>
))}
</HorizontalSlider>
</section>
</Layout>
<style>
.module-card {
height: 5rem;
display: inline-flex;
min-width: 250px;
justify-content: space-between;
margin-right: 1rem;
color: var(--foreground-color);
border-bottom: 2px solid transparent;
transition: border-bottom 100ms ease-in;
}
.module-card:hover {
border-bottom: 2px solid white;
}
.module-card .arrow {
--size: 2rem;
border-radius: 50%;
height: calc(var(--size) / 2);
width: calc(var(--size) / 2);
padding: calc(var(--size) / 3);
background-color: var(--button-background-color);
align-self: flex-end;
}
.module-card .card-title {
font-size: 1.5rem;
font-weight: bold;
}
</style>

View file

@ -0,0 +1,11 @@
:root {
--background-color: #051923;
--foreground-color: #eef4ed;
--navigation-background-color: #003554;
--button-background-color: #0582ca;
--button-background-color-translucent: #0582ca33;
--button-hover-color: #006494;
--button-active-color: #051923;
--button-fg-color: white;
}

7
src/utils/classes.ts Normal file
View file

@ -0,0 +1,7 @@
export const clx = (c: Record<string, boolean>, additional?: string) => {
const converted = Object.entries(c).map(([key, value]) => value ? key : null).filter((key) => !!key).join(' ');
if (additional) {
return `${converted} ${additional}`;
}
return converted;
}