Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: projects #85

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions base.css
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,13 @@
body :is(h1, h2, h3, h4, h5, h6) {
@apply tracking-[-0.03em] font-aktiv;
}

.projects-gradient {
background: linear-gradient(
180deg,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0.217) 40.39%,
rgba(0, 0, 0, 0.7) 74.77%
);
}
}
36 changes: 36 additions & 0 deletions public/tolocar_illustration_projects.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/arrow-up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/components/ButtonLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const ButtonLink: React.FC<Props> = ({
const classes = {
light:
"bg-white z-10 text-tolo-green flex gap-2 justify-center items-center px-3 py-2 rounded-full font-semibold text-lg lg:mt-4 h-10 w-44",
dark: "bg-black z-10 text-white flex gap-2 justify-center items-center px-3 rounded-full font-semibold text-lg lg:mt-4 h-10 w-44",
dark: "bg-neutral-700 z-10 text-white flex gap-2.5 justify-center items-center px-6 rounded-full font-semibold lg:text-lg lg:leading-6 text-base leading-[22px] h-10 w-fit",
search:
"bg-black z-10 inline-flex items-center bg-opacity-20 opacity-90 rounded-full py-4 px-5 mt-8",
github:
Expand All @@ -39,6 +39,7 @@ const ButtonLink: React.FC<Props> = ({
{variant === "search" && (
<ArrowIcon className="h-5 w-5 ml-8 text-white" />
)}
{variant === "dark" && <ArrowIcon className="h-5 w-5 text-white" />}
</a>
);
};
Expand Down
8 changes: 3 additions & 5 deletions src/components/CommunityGridCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import { ConditionalLinkWrapper } from "@components";

interface Props {
className?: string;
Expand All @@ -15,7 +16,7 @@ const CommunityGridCard: React.FC<Props> = ({
}: Props) => {
return (
<div className={`col-span-1 bg-neutral-50 ${className}`}>
<LinkWrapper
<ConditionalLinkWrapper
condition={Boolean(target)}
wrapper={(children) => (
<a
Expand All @@ -38,12 +39,9 @@ const CommunityGridCard: React.FC<Props> = ({
{target && <div>{target}</div>}
</div>
</div>
</LinkWrapper>
</ConditionalLinkWrapper>
</div>
);
};

const LinkWrapper = ({ condition, wrapper, children }) =>
condition ? wrapper(children) : children;

export default CommunityGridCard;
4 changes: 4 additions & 0 deletions src/components/ConditionalLinkWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const ConditionalLinkWrapper = ({ condition, wrapper, children }) =>
condition ? wrapper(children) : children;

export default ConditionalLinkWrapper;
44 changes: 44 additions & 0 deletions src/components/ProjectCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";
import type { IProjectsFrontmatter } from "@interfaces/IProjects";
import { ReactComponent as ArrowUpIcon } from "@assets/arrow-up.svg";
import { ConditionalLinkWrapper } from "@components";

interface Props extends IProjectsFrontmatter {
className?: string;
href?: string;
}

const ProjectCard: React.FC<Props> = ({
className,
title,
img,
teaser,
href,
}) => {
return (
<ConditionalLinkWrapper
condition={Boolean(href)}
wrapper={(children) => <a href={href}>{children}</a>}
>
<div className={`h-[406px] relative ${className || ""}`}>
<img
className="h-full w-full object-cover aspect-[200/203]"
src={img}
alt="Project photo"
/>
<div className="h-full w-full absolute top-0 projects-gradient" />
<div className="absolute bottom-0 flex flex-col gap-2 w-full h-full p-8 text-white items-start justify-end">
{title && (
<h1 className="font-semibold text-2xl leading-7 font-aktiv">
{title}
<ArrowUpIcon className="h-3.5 w-3.5 ml-4 inline-block" />
</h1>
)}
{teaser && <p className="font-medium text-lg leading-7">{teaser}</p>}
</div>
</div>
</ConditionalLinkWrapper>
);
};

export default ProjectCard;
29 changes: 29 additions & 0 deletions src/components/ProjectsHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import { HeadlineUnderlined } from "@components";

interface Props {
className?: string;
title?: string;
text?: string;
}

const ProjectsHeader: React.FC<Props> = ({ className, title, text }: Props) => {
return (
<div
className={`w-full h-full md:h-[614px] bg-illustration-projects bg-no-repeat bg-[right_bottom_0] sm:bg-[right_top_100px] bg-neutral-50 mt-10 md:mt-20 pt-16 lg:pt-20 lg:pb-16 ${
className || ""
}`}
>
<div className="container-width flex flex-col gap-y-5 lg:gap-y-6 items-start sm:mb-16 mb-64 flex-1">
<HeadlineUnderlined large variant={8}>
{title}
</HeadlineUnderlined>
<div className="pb-16 md:pb-24 md:w-[60%] h-full items-start text-base leading-6 lg:text-lg lg:leading-7 text-neutral-500 font-normal">
{text}
</div>
</div>
</div>
);
};

export default ProjectsHeader;
35 changes: 35 additions & 0 deletions src/components/ProjectsHeroImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import type { IProjectsFrontmatter } from "@interfaces/IProjects";

interface Props extends IProjectsFrontmatter {
className?: string;
}

const ProjectsHeroImage: React.FC<Props> = ({
className,
title,
teaser,
img,
}: Props) => {
return (
<div
style={{ backgroundImage: `url(${img})` }}
className={`relative w-full h-[308px] bg-blend-darken bg-black/40 overflow-hidden bg-cover bg-center ${
className || ""
}`}
>
<div className="px-6 pb-[29px] md:p-12 text-white absolute h-full flex flex-col items-start justify-end lg:justify-center gap-2 lg:gap-8">
<h1 className="text-[32px] leading-10 lg:text-5xl font-semibold lg:leading-[52px] font-aktiv">
{title}
</h1>
{teaser && (
<p className="font-inter lg:font-aktiv text-base lg:text-2xl font-medium w-full md:w-2/5">
{teaser}
</p>
)}
</div>
</div>
);
};

export default ProjectsHeroImage;
55 changes: 55 additions & 0 deletions src/components/ProjectsSection.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
import { IProjectsFrontmatter } from "@interfaces/IProjects";
import { ProjectCard, ButtonLink } from "@components";
import { trimAndSortProjects } from "@util/ContentTransformer";
const rawProjectsContent = await Astro.glob<IProjectsFrontmatter>(
"../pages/en/projects/*.mdx"
);
const projectCount = 3;
const trimmedAndSorted = trimAndSortProjects(rawProjectsContent, projectCount);
---

<div class="relative flex flex-col h-full gap-8">
<div
class="container-width mt-[51px] md:mt-[113px] md:mb-4 flex flex-col gap-6"
>
<div
class="text-neutral-900 text-lg leading-6 lg:text-2xl lg:leading-7 font-aktiv font-semibold"
>
Latest projects
</div>
<div class="text-base md:hidden">
Within the Tolocar Project <strong>
we support different projects with our equipment, knowledge and
capacities.</strong
>
<br />
<br />
The projects are in areas like insulation, energy supply, connectivity and
sewage water.
</div>
</div>
<div
class="container-width flex flex-col lg:flex-row lg:justify-between gap-2"
>
{
trimmedAndSorted.map((project) => (
<ProjectCard
href={project.url}
img={project.frontmatter.img}
title={project.frontmatter.title}
teaser={project.frontmatter.teaser}
/>
))
}
</div>
<div
class="pb-2 lg:pb-[18px] text-white items-center w-full h-full flex justify-center z-20"
>
<ButtonLink
target="en/projects"
caption="See all projects"
variant="dark"
/>
</div>
</div>
7 changes: 4 additions & 3 deletions src/components/TableOfContents.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { MarkdownHeading } from 'astro';
import type { MarkdownHeading } from "astro";

interface Props {
title: string;
headlines: Array<MarkdownHeading>;
}


const buildTocList = (input: Array<MarkdownHeading>) => {
// Create a ordered list of depth and remove duplicates
let map = new Map(
Expand Down Expand Up @@ -37,7 +36,9 @@ const TableOfContents: React.FC<Props> = ({ title, headlines }) => {
const leftPadding = paddingMapping[headline.depth];
return (
<li key={index} className={leftPadding}>
<a className="hover:text-neutral-900" href={`#${headline.slug}`}>{headline.text}</a>
<a className="hover:text-tolo-green" href={`#${headline.slug}`}>
{headline.text}
</a>
</li>
);
})}
Expand Down
5 changes: 5 additions & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,9 @@ export { default as ImpactListItem } from "@components/ImpactListItem";
export { default as CommunityBanner } from "@components/CommunityBanner";
export { default as CommunityGridCard } from "@components/CommunityGridCard";
export { default as CommunityHeader } from "@components/CommunityHeader";
export { default as ProjectsHeader } from "@components/ProjectsHeader";
export { default as ProjectCard } from "@components/ProjectCard";
export { default as ConditionalLinkWrapper } from "@components/ConditionalLinkWrapper";
export { default as ProjectsHeroImage } from "@components/ProjectsHeroImage";
export { default as LanguageSwitcher } from "@components/LanguageSwitcher";
export { default as ProjectsSection } from "@components/ProjectsSection.astro";
6 changes: 6 additions & 0 deletions src/interfaces/IProjects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface IProjectsFrontmatter {
title: string;
teaser?: string;
img?: string;
order?: number;
}
52 changes: 52 additions & 0 deletions src/layouts/ProjectsIndex.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
import BaseLayout from "./BaseLayout.astro";
import { IProjectsFrontmatter } from "@interfaces/IProjects";
import {
ProjectsHeader,
ProjectCard,
ContentSection,
WideCard,
} from "@components";
import { trimAndSortProjects } from "@util/ContentTransformer";

const { frontmatter, url, file, headings } = Astro.props;
const rawProjectsContent = await Astro.glob<IProjectsFrontmatter>(
"../pages/en/projects/*.mdx"
);
const trimmedAndSorted = trimAndSortProjects(rawProjectsContent);
---

<BaseLayout footerGrey={true} frontmatter={frontmatter}>
<ProjectsHeader
className="-z-10"
title="Projects"
text="Within the Tolocar project we support different projects with our equipment, knowledge and capacities. Within these projects we want to meet urgent needs in areas like rebuilding, insulation, energy supply, connectivity, waste water and much more."
/>
<div class="container-width -mt-48 sm:-mt-20 lg:-mt-36">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
{
trimmedAndSorted.map((project) => (
<ProjectCard
href={project.url}
title={project.frontmatter?.title}
teaser={project.frontmatter?.teaser}
img={project.frontmatter?.img}
/>
))
}
</div>
</div>
<ContentSection variant="white">
<WideCard
className="mt-28 lg:mt-16"
title="Participate in the development of our projects!"
text="We're using GitHub to collaboratively develop our projects."
target="https://www.github.com/tolocar-project/community"
newTab={true}
caption="Open GitHub"
linkButtonVariant="github"
bg={2}
/>
<div class="absolute w-full bg-neutral-50 h-52 bottom-0"></div>
</ContentSection>
</BaseLayout>
Loading