From fab9e9b57aa5da6340b988ac69d5f974135aad36 Mon Sep 17 00:00:00 2001 From: Aleksandr Slepchenkov Date: Thu, 16 Jan 2025 13:13:54 +0100 Subject: [PATCH] feat: generic grouping of steps and mobile view --- src/components/Recipe.astro | 108 +++++++++++++-------- src/content/config.ts | 3 +- src/content/recipes/en/pourover/barn-01.md | 5 + src/i18n/locales/recipe/en.ts | 4 +- 4 files changed, 78 insertions(+), 42 deletions(-) diff --git a/src/components/Recipe.astro b/src/components/Recipe.astro index bac0281..e18ca28 100644 --- a/src/components/Recipe.astro +++ b/src/components/Recipe.astro @@ -22,6 +22,7 @@ const recipeMessages = getRecipeMessages(locale) const { time, weight } = createPropertyFormatters(Astro.currentLocale) const href = getRelativeLocaleUrl(locale, `/recipes/${recipe.method}`) +const DEFAULT_GROUP = Symbol('default') const formattedSteps = recipe.steps ?.reduce<({ endTime: number; startTime: number; totalWater: number } & Exclude[number])[]>((acc, step, index) => { @@ -43,6 +44,19 @@ const formattedSteps = recipe.steps totalWater: weight(step.totalWater), water: weight(step.water) })) + +const groupedSteps = formattedSteps + ?.reduce((acc, step) => { + const lastGroup = acc[acc.length - 1] + const group = step.group ?? DEFAULT_GROUP + + if (lastGroup && lastGroup[0] === group) { + lastGroup[1].push(step) + } else { + acc.push([group, [step]]) + } + return acc + }, [] as [string | typeof DEFAULT_GROUP, typeof formattedSteps][]) ---
@@ -52,39 +66,29 @@ const formattedSteps = recipe.steps
{ - formattedSteps + groupedSteps ? ( <>

Recipe

- - - - - - - - - - - - - - {formattedSteps.slice(1).map(it => { - return ( - - - - - - ) - })} - -
- {recipeMessages.prewetting} -
{formattedSteps[0].startTime} ⇒ {formattedSteps[0].endTime}{formattedSteps[0].totalWater}{formattedSteps[0].description}
- {recipeMessages.infusions} -
{it.startTime} ⇒ {it.endTime}{it.totalWater}{it.description}
- +
+
{recipeMessages.startTime}
+
{recipeMessages.totalWeight}
+ {groupedSteps.map(([group, steps]) => + ( + <> + {group !== DEFAULT_GROUP + ?
{group}
+ : null} + {steps.map(step => ( + <> +
{step.startTime}
+
{step.totalWater}
+
{step.description}
+ ))} + + ))} +
+ ) : null } @@ -124,30 +128,54 @@ const formattedSteps = recipe.steps color: inherit; } + .recipe-steps { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + margin-block-end: 32px; + } + .recipe-steps-subheader { + margin-block-start: 24px; color: var(--text-secondary); font-size: 14px; text-transform: uppercase; font-weight: 600; + grid-column: 1 / -1; } - table { - margin-block-end: 24px; + .cell { + padding: 6px 12px; } - th, - td { - padding: 6px 12px; + .cell--header { + font-weight: 600; } - th:first-child, - td:first-child { + .cell--first { padding-inline-start: 0; } - th:last-child, - td:last-child { - padding-inline-end: 0; + /* Special case required only for the header of the last column to take the place of description column header if there are 3 columns. */ + .cell--header.cell--last { + grid-column: 2 / -1; + } + + /* These classes grouped under one query since changes are highly coupled */ + @media screen and (max-width: 600px) { + + .recipe-steps { + grid-template-columns: 1fr 1fr; + } + + .cell--description { + grid-column: 1 / -1; + padding-inline: 0; + margin-block-end: 24px; + } + + .cell--description:empty { + display: none; + } } .source { diff --git a/src/content/config.ts b/src/content/config.ts index aa83552..a30b940 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -4,7 +4,8 @@ import { defineCollection, z } from 'astro:content' const recipeStep = z.object({ description: z.string().optional(), time: z.string(), - water: z.number() + water: z.number(), + group: z.string().optional() }) const recipesCollection = defineCollection({ diff --git a/src/content/recipes/en/pourover/barn-01.md b/src/content/recipes/en/pourover/barn-01.md index bec41bd..ff160b5 100644 --- a/src/content/recipes/en/pourover/barn-01.md +++ b/src/content/recipes/en/pourover/barn-01.md @@ -14,14 +14,19 @@ properties: steps: - water: 35 time: '0:30' + group: Pre-wetting - water: 65 time: '0:30' + group: Infusions - water: 50 time: '0:20' + group: Infusions - water: 50 time: '0:25' + group: Infusions - water: 50 time: '0:25' + group: Infusions author: The Barn authorImg: barn diff --git a/src/i18n/locales/recipe/en.ts b/src/i18n/locales/recipe/en.ts index f3d69cf..6c9e073 100644 --- a/src/i18n/locales/recipe/en.ts +++ b/src/i18n/locales/recipe/en.ts @@ -3,6 +3,8 @@ import { t } from '../../utils' export const getRecipeMessages = (locale?: string) => { return t(locale, 'recipe', { infusions: 'Infusions', - prewetting: 'Pre-wetting' + prewetting: 'Pre-wetting', + startTime: 'Start at', + totalWeight: 'Total weight' }) }