Skip to content

Commit

Permalink
v3 - customer case split section (#841)
Browse files Browse the repository at this point in the history
* feat(Text): adjust font sizes

* feat(CustomerCase): main image top padding

* fix(ImageBlock): handle missing image alt for preview

* feat(CustomerCase): split section

* feat(SplitSection): column flex on narrow screens

* feat(SplitSection): hide empty section on narrow screens
  • Loading branch information
mathiazom authored Oct 30, 2024
1 parent d8811d9 commit dd5e67f
Show file tree
Hide file tree
Showing 21 changed files with 356 additions and 142 deletions.
36 changes: 1 addition & 35 deletions src/components/customerCases/customerCase/CustomerCase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,13 @@ import Text from "src/components/text/Text";
import { fetchEmployeesByEmails } from "src/utils/employees";
import {
CustomerCase as CustomerCaseDocument,
CustomerCaseSection as CustomerCaseSectionObject,
Delivery,
} from "studioShared/lib/interfaces/customerCases";

import styles from "./customerCase.module.css";
import FeaturedCases from "./featuredCases/FeaturedCases";
import CustomerCaseConsultants from "./sections/customerCaseConsultants/CustomerCaseConsultants";
import ImageSection from "./sections/image/ImageSection";
import RichTextSection from "./sections/richText/RichTextSection";

function CustomerCaseSection({
section,
}: {
section: CustomerCaseSectionObject;
}) {
switch (section._type) {
case "richTextBlock":
return <RichTextSection section={section} />;
case "quoteBlock":
return (
section.quote && (
<div className={styles.quoteBlock}>
<div
className={`${styles.quoteBlockInner} ${section.author ? styles.withAuthor : styles.withoutAuthor}`}
>
<Text type="quoteNormal">
{"“"}
{section.quote}
{"”"}
</Text>
{section.author && (
<Text type="labelRegular">- {section.author}</Text>
)}
</div>
</div>
)
);
case "imageBlock":
return <ImageSection section={section} />;
}
}
import { CustomerCaseSection } from "./sections/CustomerCaseSection";

export interface CustomerCaseProps {
customerCase: CustomerCaseDocument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
width: 100%;
height: 36.5rem;
overflow: hidden;
padding-top: 1.5rem;
padding-bottom: 2rem;
}

Expand Down Expand Up @@ -109,30 +110,3 @@
flex-direction: column;
gap: 4.5rem;
}

.quoteBlock {
align-self: center;
max-width: 960px;
width: 100%;
border: 2px solid var(--primary-yellow-warning);
border-radius: 0.5rem;
background-color: var(--primary-yellow-warning);
}

.quoteBlockInner {
display: flex;
flex-direction: column;
background-color: var(--primary-bg);
border-radius: 2rem;
gap: 1.25rem;
width: 100%;
align-items: center;
}

.withAuthor {
padding: 4.5rem 0.5rem 3.5rem 0.5rem;
}

.withoutAuthor {
padding: 4.5rem 0.5rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { CustomerCaseSection as CustomerCaseSectionObject } from "studioShared/lib/interfaces/customerCases";

import ImageSection from "./image/ImageSection";
import QuoteBlock from "./quote/QuoteBlock";
import RichTextSection from "./richText/RichTextSection";
import SplitSection from "./splitSection/SplitSection";

export function CustomerCaseSection({
section,
}: {
section: CustomerCaseSectionObject;
}) {
switch (section._type) {
case "splitSection":
return <SplitSection section={section} />;
case "richTextBlock":
return <RichTextSection section={section} />;
case "quoteBlock":
return <QuoteBlock section={section} />;
case "imageBlock":
return <ImageSection section={section} />;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Text from "src/components/text/Text";
import { QuoteBlock as QuoteBlockObject } from "studioShared/lib/interfaces/quoteBlock";

import styles from "./quoteBlock.module.css";

export interface QuoteBlockProps {
section: QuoteBlockObject;
}

export default function QuoteBlock({ section }: QuoteBlockProps) {
return (
section.quote && (
<div className={styles.quoteBlock}>
<div
className={`${styles.quoteBlockInner} ${section.author ? styles.withAuthor : styles.withoutAuthor}`}
>
<Text type="quoteNormal">
{"“"}
{section.quote}
{"”"}
</Text>
{section.author && (
<Text type="labelRegular">- {section.author}</Text>
)}
</div>
</div>
)
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.quoteBlock {
align-self: center;
max-width: 960px;
width: 100%;
border: 2px solid var(--primary-yellow-warning);
border-radius: 0.5rem;
background-color: var(--primary-yellow-warning);
}

.quoteBlockInner {
display: flex;
flex-direction: column;
background-color: var(--primary-bg);
border-radius: 2rem;
gap: 1.25rem;
width: 100%;
align-items: center;
}

.withAuthor {
padding: 4.5rem 0.5rem 3.5rem 0.5rem;
}

.withoutAuthor {
padding: 4.5rem 0.5rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CustomerCaseSection } from "src/components/customerCases/customerCase/sections/CustomerCaseSection";
import {
SplitSection as SplitSectionObject,
SplitSectionSection as SplitSectionSectionObject,
} from "studioShared/lib/interfaces/splitSection";

import styles from "./splitSection.module.css";

export interface SplitSectionProps {
section: SplitSectionObject;
}

function SplitSectionSection({
section,
}: {
section: SplitSectionSectionObject;
}) {
switch (section._type) {
case "emptySection":
return <div className={styles.emptySection}></div>;
}
return <CustomerCaseSection section={section} />;
}

export default function SplitSection({ section }: SplitSectionProps) {
return (
<div className={styles.wrapper}>
<div className={styles.content}>
{section.sections.map((section) => (
<SplitSectionSection key={section._key} section={section} />
))}
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
}

.content {
width: 100%;
max-width: 960px;
display: flex;
justify-content: space-evenly;
gap: 2rem;

@media (max-width: 1024px) {
flex-direction: column;
}
}

.content > * {
flex-basis: 0;
flex-grow: 1;
}

.emptySection {
@media (max-width: 1024px) {
display: none;
}
}
36 changes: 1 addition & 35 deletions src/components/text/text.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,17 @@
font-style: normal;
font-weight: 600;
line-height: 120%;

@media (min-width: 1024px) {
font-size: 4.25rem;
}
}

.h2 {
font-size: 2.5625rem;
font-weight: 500;
line-height: 110%;

@media (min-width: 1024px) {
font-size: 3.375;
line-height: 120%;
}
}

.h3 {
font-size: 2.125rem;
font-weight: 600;

@media (min-width: 1024px) {
font-size: 2.25rem;
}
}

/* TODO: add font variables */
Expand All @@ -69,49 +56,28 @@
font-size: 10rem;
line-height: 100%;
font-weight: 500;

@media (min-width: 1024px) {
font-size: 5.25rem;
line-height: normal;
}
}

.bodyXl {
font-size: 2.125rem;
font-weight: 500;

@media (min-width: 1024px) {
font-size: 2.625rem;
}
}

.bodyBig {
font-size: 1.5rem;
font-style: normal;
font-weight: 400;
line-height: 130%;

@media (min-width: 1024px) {
font-size: 1.875rem;
}
}

.bodyNormal {
font-size: 1.25rem;
font-size: 20px;
font-weight: 400;

@media (min-width: 1024px) {
font-size: 1.5rem;
}
}

.bodySmall {
font-size: 1rem;
font-weight: 400;

@media (min-width: 1024px) {
font-size: 1.25rem;
}
}

/* TODO: add font variables */
Expand Down
14 changes: 14 additions & 0 deletions studio/lib/interfaces/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,17 @@ export interface InternationalizedValueRecord<T> {
}

export type InternationalizedString = InternationalizedValueRecord<string>[];

export function isSanityKeyTypeObject(value: unknown): value is {
_key: string;
_type: string;
} {
return (
typeof value === "object" &&
value !== null &&
"_key" in value &&
typeof value._key === "string" &&
"_type" in value &&
typeof value._type === "string"
);
}
16 changes: 2 additions & 14 deletions studio/lib/interfaces/richText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
isPortableTextTextBlock,
} from "sanity";

import { isSanityKeyTypeObject } from "./global";

export function isRichText(value: unknown): value is PortableTextBlock[] {
return (
Array.isArray(value) && value.every((item) => isPortableTextBlock(item))
Expand All @@ -21,17 +23,3 @@ export function isPortableTextObject(
): value is PortableTextObject {
return isSanityKeyTypeObject(value);
}

function isSanityKeyTypeObject(value: unknown): value is {
_key: string;
_type: string;
} {
return (
typeof value === "object" &&
value !== null &&
"_key" in value &&
typeof value._key === "string" &&
"_type" in value &&
typeof value._type === "string"
);
}
5 changes: 3 additions & 2 deletions studio/schemas/fields/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ export const internationalizedImage = defineField({
media: "asset",
},
prepare({ alt, media }) {
if (!isInternationalizedString(alt)) {
if (alt !== undefined && !isInternationalizedString(alt)) {
throw new TypeError(
`Expected 'alt' to be InternationalizedString, was ${typeof alt}`,
);
}
return {
title: firstTranslation(alt) ?? undefined,
title:
alt !== undefined ? (firstTranslation(alt) ?? undefined) : undefined,
media,
};
},
Expand Down
Loading

0 comments on commit dd5e67f

Please sign in to comment.