added simple page sceleton
This commit is contained in:
parent
3f58216dd9
commit
9439e3b9a8
15
src/authors/swendel.json
Normal file
15
src/authors/swendel.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"firstName": "Sebastian",
|
||||
"lastName": "Wendel",
|
||||
"bio": "His focus is on software development as well as platform and cloud engineering.",
|
||||
"image": {
|
||||
"default": "/images/sebastian_wendel.jpg",
|
||||
"alt": "Portrait of Sebastian Wendel"
|
||||
},
|
||||
"social": {
|
||||
"mastodon": "@swendel@srx.digital",
|
||||
"linkedin": "https://www.linkedin.com/in/sebastian-wendel-935b8a9a/"
|
||||
},
|
||||
"chat": "swendel@srx.digital",
|
||||
"homepage": "https://srx.digital/"
|
||||
}
|
43
src/components/Footer.tsx
Normal file
43
src/components/Footer.tsx
Normal file
|
@ -0,0 +1,43 @@
|
|||
import type React from 'react'
|
||||
import SRXLogo from '@srx/assets/srx-digital-logo.svg?react'
|
||||
|
||||
interface Props {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const Footer: React.FC<Props> = ({ children }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<div className={'flex gap-8 flex-col justify-between md:pt-0.5 z-10 lg:col-start-2 lg:col-span-5 col-span-1'}>
|
||||
<div>
|
||||
<SRXLogo className={'h-8 md:h-10'} />
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-6 items-start'>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={'z-10 col-span-1 lg:col-span-6'}>
|
||||
<h3 className={'text-xl md:text-bb-3xl font-grotesk'}>
|
||||
Du möchtest mit uns zusammenarbeiten? Wir freuen uns auf deine E-Mail.
|
||||
</h3>
|
||||
|
||||
<div className={'flex flex-col md:flex-row justify-between text-base md:text-lg leading-[1.4] mt-[11.5rem] md:mt-[17.875rem]'}>
|
||||
<div>
|
||||
srx digital<br />
|
||||
Development & Operations<br />
|
||||
</div>
|
||||
|
||||
<address className={'not-italic mt-8 md:mt-0'}>
|
||||
Sebastian Wendel<br />
|
||||
Wohlwillstraße 2<br />
|
||||
20359 Hamburg<br />
|
||||
</address>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Footer
|
41
src/components/HeroSection.tsx
Normal file
41
src/components/HeroSection.tsx
Normal file
|
@ -0,0 +1,41 @@
|
|||
import React from 'react'
|
||||
|
||||
interface Props {
|
||||
title: string
|
||||
subtitle?: string
|
||||
buttonCaption?: string
|
||||
}
|
||||
|
||||
const HeroSection: React.FC<Props> = ({ title, subtitle, buttonCaption }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<div className='flex flex-col items-start pt-[18.625rem] pb-24 lg:pt-36 lg:pb-32 bg-bb-grey-200 px-5 lg:px-0 col-span-1 lg:col-span-5 lg:col-start-2'>
|
||||
<h1 className='text-black font-grotesk font-medium text-[1.75rem] lg:text-5xl mt-7 leading-tight'>
|
||||
{title}
|
||||
</h1>
|
||||
{subtitle && <p className='text-base lg:text-xl mt-6 text-bb-grey-500'>{subtitle}</p>}
|
||||
{buttonCaption}
|
||||
</div>
|
||||
|
||||
<div className='relative lg:pt-28 w-full overflow-visible bg-bb-grey-200 col-span-1 lg:col-start-8 lg:col-span-6'>
|
||||
<div className={'lg:absolute h-[64vw] lg:h-[46rem] w-full overflow-hidden'}>
|
||||
<picture>
|
||||
<source srcSet='/images/swendel_portrait.webp' type='image/webp' />
|
||||
<source srcSet='/images/swendel_portrait.jpg' type='image/jpeg' />
|
||||
<img
|
||||
src='/images/swendel_portrait.webp'
|
||||
alt={
|
||||
''
|
||||
}
|
||||
width={671}
|
||||
height={736}
|
||||
className='relative lg:top-0 -top-[18vw] w-full lg:h-full object-cover'
|
||||
/>
|
||||
</picture>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default HeroSection
|
30
src/components/LinkButton.tsx
Normal file
30
src/components/LinkButton.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { ArrowRightIcon } from "lucide-react"
|
||||
|
||||
interface Props {
|
||||
caption: string
|
||||
className?: string
|
||||
href?: string
|
||||
dark?: boolean
|
||||
newTab?: boolean
|
||||
small?: boolean
|
||||
}
|
||||
|
||||
const LinkButton: React.FC<Props> = ({
|
||||
caption,
|
||||
className,
|
||||
dark = false,
|
||||
href,
|
||||
newTab,
|
||||
small,
|
||||
}: Props) => {
|
||||
return (
|
||||
<a href={href} className={`flex w-fit gap-2 py-4 px-5 rounded-full items-center font-medium hover:bg-opacity-75 ${dark ? 'bg-black text-white' : 'bg-white text-bb-grey-500'
|
||||
} ${small ? 'py-[10px] px-4' : 'py-4 px-5'} ${className || ''}`}
|
||||
{...(newTab ? { target: '_blank' } : {})}>
|
||||
{caption}
|
||||
<ArrowRightIcon className='h-6 w-6' />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
export default LinkButton
|
25
src/components/Navbar.tsx
Normal file
25
src/components/Navbar.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import type { Props } from 'astro'
|
||||
import type React from 'react'
|
||||
import { useState } from 'react'
|
||||
import { SectionGridContainer } from '@srx/components'
|
||||
import SrxLogo from '@srx/assets/srx-digital-logo.svg?react'
|
||||
|
||||
const Navbar: React.FC<Props> = ({ }) => {
|
||||
const [navListOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<SectionGridContainer className='fixed top-0 bg-white w-full z-20 border border-b-bb-grey-200'>
|
||||
<div className={`${navListOpen ? 'flex-col h-dvh' : 'flex-row'} flex justify-between lg:items-center lg:col-start-2 col-span-1 lg:col-span-11`}>
|
||||
<nav className={`flex ${navListOpen ? 'flex-col h-full' : 'flex-row'} w-full justify-between items-start lg:items-center px-5 lg:px-0`}>
|
||||
<div className='flex justify-between items-center w-full h-20'>
|
||||
<a href={'/'}>
|
||||
<SrxLogo className={'h-8'} />
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</SectionGridContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default Navbar
|
37
src/components/SectionGridContainer.tsx
Normal file
37
src/components/SectionGridContainer.tsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import type React from 'react'
|
||||
import type { ElementType } from 'react'
|
||||
|
||||
interface SectionGridContainerProps {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
innerClassName?: string
|
||||
breakpoint?: 'lg' | 'xl' | '2xl'
|
||||
as?: ElementType
|
||||
}
|
||||
|
||||
const SectionGridContainer: React.FC<SectionGridContainerProps> = ({
|
||||
children,
|
||||
className,
|
||||
innerClassName,
|
||||
breakpoint = 'lg',
|
||||
as: Tag = 'section',
|
||||
}) => {
|
||||
const innerGridBreakpointClasses = {
|
||||
lg: 'lg:grid-cols-inner lg:gap-4',
|
||||
xl: 'xl:grid-cols-inner xl:gap-4',
|
||||
'2xl': '2xl:grid-cols-inner 2xl:gap-4',
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`2xl:grid 2xl:grid-cols-outer 2xl:grid-wrapper ${className ?? ''}`}>
|
||||
<Tag
|
||||
className={`grid grid-cols-1 relative ${innerGridBreakpointClasses[breakpoint] ?? ''} ${
|
||||
innerClassName || ''
|
||||
}`}
|
||||
>
|
||||
{children}
|
||||
</Tag>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default SectionGridContainer
|
13
src/components/index.ts
Normal file
13
src/components/index.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import Navbar from "@srx/components/Navbar";
|
||||
import HeroSection from "@srx/components/HeroSection";
|
||||
import Footer from "@srx/components/Footer";
|
||||
import SectionGridContainer from "@srx/components/SectionGridContainer";
|
||||
import LinkButton from "@srx/components/LinkButton";
|
||||
|
||||
export {
|
||||
Navbar,
|
||||
HeroSection,
|
||||
Footer,
|
||||
SectionGridContainer,
|
||||
LinkButton,
|
||||
}
|
22
src/content/config.ts
Normal file
22
src/content/config.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { z, defineCollection } from 'astro:content'
|
||||
|
||||
const authorCollection = defineCollection({
|
||||
type: 'data',
|
||||
schema: z.object({
|
||||
firstName: z.string(),
|
||||
lastName: z.string(),
|
||||
image: z.object({
|
||||
default: z.string(),
|
||||
webp: z.string().optional(),
|
||||
alt: z.string(),
|
||||
}),
|
||||
chat: z.string().optional(),
|
||||
social: z.string().optional(),
|
||||
homepage: z.string().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const collections = {
|
||||
authors: authorCollection,
|
||||
}
|
||||
|
|
@ -1,3 +1,92 @@
|
|||
---
|
||||
import "@srx-styles/base.css";
|
||||
import "@fontsource-variable/literata";
|
||||
import "@fontsource-variable/manrope";
|
||||
import "@fontsource-variable/martian-mono";
|
||||
import "@srx/styles/base.css";
|
||||
import { Footer, Navbar, SectionGridContainer } from "@srx/components";
|
||||
|
||||
interface Props {
|
||||
metaTitle?: string;
|
||||
metaSubtitle?: string;
|
||||
metaDescription?: string;
|
||||
metaImage?: string;
|
||||
metaAuthors?: string[];
|
||||
metaType?: string;
|
||||
metaDate?: string;
|
||||
metaSchema?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
metaTitle = "srx digital",
|
||||
metaSubtitle = "Development & Operations",
|
||||
metaDescription = "",
|
||||
metaImage = "https://srx.digital/srx_digital_opengraph.jpg",
|
||||
metaAuthors = ["Sebastian Wendel"],
|
||||
metaType = "website",
|
||||
metaDate,
|
||||
metaSchema,
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en" class="overflow-x-hidden scroll-smooth">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>{`${metaTitle} - ${metaSubtitle}`}</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<meta name="description" content={metaDescription} />
|
||||
<meta property="og:type" content={metaType} />
|
||||
<meta
|
||||
name="title"
|
||||
property="og:title"
|
||||
content={`${metaTitle} - ${metaSubtitle}`}
|
||||
/>
|
||||
<meta
|
||||
name="description"
|
||||
property="og:description"
|
||||
content={metaDescription}
|
||||
/>
|
||||
<meta property="og:url" content={Astro.url} />
|
||||
<meta name="image" property="og:image" content={metaImage} />
|
||||
{
|
||||
metaDate && (
|
||||
<meta
|
||||
name="date"
|
||||
property="og:article:published_time"
|
||||
content={metaDate}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
metaAuthors?.map((author) => (
|
||||
<meta
|
||||
property="og:article:author"
|
||||
name="author"
|
||||
content={author}
|
||||
/>
|
||||
))
|
||||
}
|
||||
{
|
||||
metaSchema && (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
set:html={metaSchema}
|
||||
is:inline
|
||||
/>
|
||||
)
|
||||
}
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col overflow-x-hidden pt-20">
|
||||
<Navbar buttonCaption="Schreib mir!" client:only="react" />
|
||||
<slot />
|
||||
<SectionGridContainer
|
||||
as="footer"
|
||||
className="bg-bb-grey-200 overflow-y-hidden"
|
||||
innerClassName="pt-20 pb-14 relative px-5 2xl:px-0 gap-y-12"
|
||||
>
|
||||
<Footer />
|
||||
</SectionGridContainer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,18 +1,5 @@
|
|||
---
|
||||
import BaseLayout from "@srx-layouts/BaseLayout.astro";
|
||||
import BaseLayout from "@srx/layouts/BaseLayout.astro";
|
||||
---
|
||||
|
||||
<BaseLayout />
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Astro</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Astro</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue