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

Support Art direction with custom ArtDirectionImage component #47

Open
wants to merge 7 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
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ module.exports = {
{
ignore: [
"contentlayer/generated",
"next-contentlayer/hooks",
"contentlayer/source-files",
"next-contentlayer2/hooks",
"contentlayer2/source-files",
],
},
],
Expand Down
4 changes: 3 additions & 1 deletion content/blog/android-open-source.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
---
title: Android Open Source Project
date: 2024-02-19
image: /assets/blog/aosp/hero.jpg
image:
base: /assets/blog/aosp/hero.jpg
minWidthM: /assets/blog/aosp/heroL.jpg
descriptionShort: The new-generation infotainment system in the Macan is based on Android Automotive OS. In this contributor story, Michael Eichler highlights the benefits of building upon a well-proven and established open-source platform instead of having to reinvent the wheel.
author:
name: Android Open Source Project
Expand Down
8 changes: 6 additions & 2 deletions content/blog/cookie-consent-banner.mdx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
---
title: Cookie Consent Banner
date: 2024-05-08
image: /assets/blog/ccb/preview.png
hero: /assets/blog/ccb/hero.png
image:
base: /assets/blog/ccb/preview.png
minWidthM: /assets/blog/ccb/preview.png
hero:
base: /assets/blog/ccb/hero.png
minWidthM: /assets/blog/ccb/hero.png
descriptionShort: The Cookie Consent Banner is one of the very first FOSS projects published by Porsche back in 2021. In this Contributor Story, the two maintainers Tim and Patrick share what they have learnt over the past three years and how they managed to keep an eye on the needs of the community.
author:
name: Cookie Consent Banner
Expand Down
3 changes: 2 additions & 1 deletion content/blog/oss-review-toolkit.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
title: OSS Review Toolkit
date: 2023-11-03
image: /assets/blog/ort/hero.jpg
image:
base: /assets/blog/ort/hero.jpg
descriptionShort: In this contributor story, the Open Source Office (OSO) at Porsche AG explains why it has chosen OSS Review Toolkit (ORT) as their core service for all in-house developed initiatives and why they preferred to collaborate with the community rather than buying a commercial solution.
author:
name: OSS Review Toolkit (ORT)
Expand Down
3 changes: 2 additions & 1 deletion content/blog/porsche-design-system.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
title: Porsche Design System
date: 2023-08-30
image: /assets/blog/pds/hero.jpg
image:
base: /assets/blog/pds/hero.jpg
descriptionShort: The Porsche Design System provides all the fundamental UXI guidelines and pattern-based web components to build brand driven, consistent and intuitive designs for digital Porsche products. Marcel Bertram, Specialist Digital Marketing UI/UX at Porsche, explains why this project was published as an open-source project and what his team learned along this way.
author:
name: Porsche Design System
Expand Down
3 changes: 2 additions & 1 deletion content/blog/porsche-digital-campus.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
title: Research @ Porsche Digital Campus
date: 2023-12-18
image: /assets/blog/pdc/hero.jpg
image:
base: /assets/blog/pdc/hero.jpg
descriptionShort: The Porsche Digital Campus is an innovative initiative with the goal of bringing together research and real-world application in the fields of AI, machine learning, and data science.
author:
name: Porsche Digital Campus
Expand Down
34 changes: 29 additions & 5 deletions contentlayer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import {
makeSource,
LocalDocument,
defineNestedType,
} from "contentlayer/source-files";
} from "contentlayer2/source-files";
import {
MediaQueryDescriptor,
mediaQueryDescriptors,
} from "./src/config/layout";

/** @type {import('contentlayer/source-files').ComputedFields} */
/** @type {import('contentlayer2/source-files').ComputedFields} */
const computedFields = {
slug: {
type: "string",
Expand All @@ -31,6 +35,24 @@ const Author = defineNestedType(() => ({
},
}));

type ResponsiveImageFields = Partial<
Record<MediaQueryDescriptor, { type: "string"; required: false }>
>;

const ResponsiveImage = defineNestedType(() => ({
name: "ResponsiveImage",
fields: {
base: { type: "string", required: true },
...mediaQueryDescriptors.reduce<ResponsiveImageFields>(
(acc, breakpointDescriptor) => ({
...acc,
[breakpointDescriptor]: { type: "string", required: false },
}),
{},
),
},
}));

const Blog = defineDocumentType(() => ({
name: "Blog",
filePathPattern: `blog/**/*.mdx`,
Expand Down Expand Up @@ -68,12 +90,14 @@ const Blog = defineDocumentType(() => ({
required: false,
},
image: {
type: "string",
description: "The preview image of the blog post",
type: "nested",
of: ResponsiveImage,
description: "The image of the blog",
required: true,
},
hero: {
type: "string",
type: "nested",
of: ResponsiveImage,
description: "The hero image of the blog post",
required: false,
},
Expand Down
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const nextConfig = {
return config;
},
};
const { withContentlayer } = require("next-contentlayer");
const { withContentlayer } = require("next-contentlayer2");
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
Expand Down
54 changes: 25 additions & 29 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,40 @@
"prettier:ci": "prettier --check ./",
"prettier:fix": "prettier --write ./",
"playwright:run": "yarn playwright test",
"contentlayer:build": "contentlayer build",
"contentlayer:build": "contentlayer2 build",
"test:ci": "yarn contentlayer:build && yarn prettier:ci && yarn tsc --noEmit --noEmitHelpers && yarn lint:ci"
},
"dependencies": {
"@porsche-design-system/components-js": "3.11.0",
"@porsche-design-system/components-react": "3.11.0",
"@primer/octicons": "19.8.0",
"contentlayer": "0.3.4",
"date-fns": "2.30.0",
"next": "13.5.6",
"next-contentlayer": "0.3.4",
"next-image-export-optimizer": "1.12.2",
"@porsche-design-system/components-js": "3.15.1",
"@porsche-design-system/components-react": "3.15.1",
"@primer/octicons": "19.9.0",
"contentlayer2": "0.4.6",
"date-fns": "3.6.0",
"next": "^14.2.3",
"next-contentlayer2": "0.4.6",
"next-image-export-optimizer": "1.13.0",
"prism-react-renderer": "2.3.1",
"react": "18.2.0",
"react-dom": "18.2.0"
"react": "18.3.1",
"react-dom": "18.3.1"
},
"devDependencies": {
"@axe-core/playwright": "4.8.4",
"@next/bundle-analyzer": "13.5.6",
"@next/eslint-plugin-next": "13.5.6",
"@playwright/test": "1.41.1",
"@axe-core/playwright": "4.9.1",
"@next/bundle-analyzer": "14.2.3",
"@next/eslint-plugin-next": "14.2.3",
"@playwright/test": "1.44.1",
"@porscheofficial/eslint-config-porschedigital-react": "4.0.0",
"@porscheofficial/prettier-config-porschedigital": "4.0.0",
"@types/mdx": "2.0.11",
"@types/node": "20.11.14",
"@types/react": "18.2.50",
"@types/react-dom": "18.2.18",
"dotenv": "16.4.1",
"eslint": "8.56.0",
"@types/mdx": "2.0.13",
"@types/node": "20.12.12",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"dotenv": "16.4.5",
"eslint": "8.57.0",
"http-server": "14.1.1",
"js-yaml-loader": "1.2.2",
"playwright-core": "1.41.1",
"prettier": "3.2.4",
"typescript": "5.3.3",
"typescript-plugin-css-modules": "5.0.2"
},
"resolutions": {
"semver": "7.5.3",
"word-wrap": "aashutoshrathi/word-wrap"
"playwright-core": "1.44.1",
"prettier": "3.2.5",
"typescript": "5.4.5",
"typescript-plugin-css-modules": "5.1.0"
}
}
Binary file modified public/assets/blog/aosp/hero.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/blog/aosp/heroL.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions src/app/blog/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import s from "./page.module.scss";
import { Author } from "../../../components/02_molecules/author/author";
import { Section } from "../../../components/02_molecules/section/section";
import { Textblock } from "../../../components/02_molecules/textblock/Textblock";
import { BASE_URL } from "../../../config";
import { BASE_URL } from "../../../config/env";
import { transformContentlayerImage } from "../../../utils/imageHelpers/transformContentlayerImage";

const getParams = (params: { slug?: string[] }): Blog | null => {
const slug = params.slug?.join("/") ?? "";
Expand Down Expand Up @@ -47,7 +48,7 @@ export async function generateMetadata({
url: `${BASE_URL}${doc.slug}`,
title,
description,
images: doc.image,
images: doc.image.base,
},
twitter: {
card: "summary_large_image",
Expand Down Expand Up @@ -82,7 +83,7 @@ const BlogPage: React.FC<PageProps> = ({ params }: PageProps) => {
title={blog.title}
description={description}
subtitle="FOSS@Porsche"
imageSrc={hero}
imageSrc={transformContentlayerImage(hero)}
imageAlt="Hero Image"
position="center center"
/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/docs/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MdxComponents } from "../../../components/01_atoms/MdxComponents";
import { HeroSection } from "../../../components/03_organisms/heroSection/HeroSection";
import { Section } from "../../../components/02_molecules/section/section";
import { Textblock } from "../../../components/02_molecules/textblock/Textblock";
import { BASE_URL } from "../../../config";
import { BASE_URL } from "../../../config/env";

const getParams = (params: { slug?: string[] }): Doc | null => {
const slug = params.slug?.join("/") ?? "";
Expand Down
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { AppProvider } from "../components/AppProvider";
import { PageLayout } from "../components/04_templates/pageLayout/PageLayout";
import "./globals.scss";
import { BASE_URL } from "../config";
import { BASE_URL } from "../config/env";

const siteConfig = {
title: "Porsche Open Source Platform",
Expand Down
2 changes: 1 addition & 1 deletion src/app/sitemap.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MetadataRoute } from "next";
import { allBlogs, allDocs } from "contentlayer/generated";
import { format, parseISO } from "date-fns";
import { BASE_URL } from "../config";
import { BASE_URL } from "../config/env";

const Sitemap = (): MetadataRoute.Sitemap => {
const blogs = allBlogs.map((doc) => ({
Expand Down
2 changes: 1 addition & 1 deletion src/components/01_atoms/MdxComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable react/jsx-props-no-spreading */
import * as React from "react";
import { useMDXComponent } from "next-contentlayer/hooks";
import { useMDXComponent } from "next-contentlayer2/hooks";
import type { MDXComponents } from "mdx/types";
import {
PDisplay,
Expand Down
49 changes: 49 additions & 0 deletions src/components/01_atoms/artDirectionImage/ArtDirectionImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint-disable react/jsx-props-no-spreading */
import type { ImageProps as NextImageProps } from "next/image";
import { forwardRef } from "react";
import { getArtDirectionSourceProps } from "../../../utils/imageHelpers/getArtDirectionSourceProps";
import { ArtDirectionImageData } from "../../../utils/imageHelpers/isArtDirectionAsset";

const fillStyles: React.CSSProperties = {
position: "absolute",
inset: 0,
objectFit: "cover",
backgroundPosition: "center",
width: "100%",
height: "100%",
};

export interface ArtDirectionImageProps extends Omit<NextImageProps, "src"> {
// eslint-disable-next-line react/no-unused-prop-types
src: ArtDirectionImageData;
}

export const ArtDirectionImage = forwardRef<
HTMLPictureElement,
ArtDirectionImageProps
>((props, ref) => {
const sources = getArtDirectionSourceProps(props);
const { className, style, alt } = props;

return (
<picture
ref={ref}
className={className}
style={{ ...fillStyles, ...style }}
>
{sources.map(({ media, srcSet, sizes, breakpointDescriptor }) => (
<source
key={breakpointDescriptor}
media={media}
srcSet={srcSet}
sizes={sizes}
/>
))}
<img
style={props.fill ? fillStyles : undefined}
srcSet={sources[sources.length - 1].srcSet}
alt={alt}
/>
</picture>
);
});
2 changes: 1 addition & 1 deletion src/components/02_molecules/navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export const Navigation: React.FC<NavigationProps> = () => {
className={s.navLinkImage}
>
<ExportedImage
src={firstDoc.image}
src={firstDoc.image.base}
alt={firstDoc.title}
fill
placeholder="blur"
Expand Down
5 changes: 3 additions & 2 deletions src/components/03_organisms/blogsSection/BlogsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const BlogsSection: React.FC<BlogsSectionProps> = ({
);
const firstDoc = posts[0];
const docList = isFeatured ? posts.slice(1, posts.length) : posts;

return (
<div className={s.section}>
{isFeatured && firstDoc.slug && (
Expand All @@ -31,7 +32,7 @@ export const BlogsSection: React.FC<BlogsSectionProps> = ({
title={firstDoc.title}
description={firstDoc.descriptionShort}
url={firstDoc.slug}
imageSrc={firstDoc.image}
imageSrc={firstDoc.image.base}
imageAlt=""
/>
</div>
Expand All @@ -56,7 +57,7 @@ export const BlogsSection: React.FC<BlogsSectionProps> = ({
time={blog.date}
url={blog.slug}
key={blog.slug}
imageSrc={blog.image}
imageSrc={blog.image.base}
imageAlt=""
/>
))}
Expand Down
Loading
Loading