diff --git a/src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.css b/src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.css new file mode 100644 index 0000000..bc2341f --- /dev/null +++ b/src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.css @@ -0,0 +1,251 @@ +.dynamic-grid { + &.dynamic-grid--bleed-bleed { + grid-column: bleed !important; + } + + &.dynamic-grid--bleed-screen { + grid-column: screen !important; + } + + .dynamic-grid-title { + text-align: center; + margin-top: 0; + } + + .tiles-container { + display: grid; + grid-gap: 24px; + grid-template-columns: repeat(3, 1fr); + grid-auto-rows: min-content; + grid-auto-flow: row dense; + + @container (min-width: 900px) { + grid-template-columns: repeat(4, 1fr); + } + + .tile { + overflow: hidden; + display: grid; + gap: 0; + + grid-template-columns: subgrid; + grid-template-rows: subgrid; + + color: var(--color-brand-text-fg); + text-decoration: none; + + .tile-content { + grid-row: 2/3; + background-color: var(--tile-bg-color); + color: var(--tile-fg-color); + width: 100%; + opacity: 0.9; + padding: 8px; + z-index: 1; + overflow: hidden; + bottom: 0; + box-sizing: border-box; + + .tile-content-wrapper { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 4; + line-height: 20px; + overflow: hidden; + + .tile-title { + font-weight: bold; + line-height: 20px; + margin: 10px 0; + } + + .tile-subtitle { + line-height: 20px; + margin: 0; + } + } + } + + .tile-image { + z-index: 0; + width: 100%; + height: 100%; + grid-row: 1/2; + + picture { + height: 100%; + width: 100% !important; + } + } + } + + .tile.square { + grid-column: span 1; + grid-row: span 2; + + .tile-content { + grid-row: 2/3; + } + + .tile-image--horizontal { + display: none; + } + + .tile-image--vertical { + display: none; + } + + .tile-image--square { + grid-row: 1/2; + picture img { + display: block !important; + } + } + } + + .tile.horizontal { + grid-column: span 2; + grid-row: span 2; + + .tile-content { + grid-column: 1/3; + } + + .tile-image--vertical { + display: none; + } + + .tile-image--square { + display: none; + } + + .tile-image--horizontal { + grid-column: 1/3; + picture img { + display: block !important; + } + } + } + + .tile.vertical { + grid-row: span 4; + grid-column: span 1; + + .tile-content { + grid-row: 4/5; + } + + .tile-image--horizontal { + display: none; + } + + .tile-image--square { + display: none; + } + + .tile-image--vertical { + grid-row: 1/4; + picture img { + display: block !important; + } + } + } + + .buttons-container { + margin-top: 36px; + display: flex; + justify-content: center; + flex-flow: row wrap; + column-gap: 18px; + row-gap: 16px; + + .button { + display: inline-block; + text-align: center; + padding: 8px 24px; + border: 1px solid var(--color-brand-text-fg); + color: var(--text-color); + min-width: 240px; + line-height: 23px; + font-size: 16px; + + &.accent { + background-color: var(--color-brand-accent); + --text-color: var(--color-brand-text-on-accent); + } + + &.accent2 { + background-color: var(--color-brand-accent2); + --text-color: var(--color-brand-text-on-accent2); + } + } + } + } + + @container (max-width: 950px) { + .tab-container { + .tiles-container { + grid-template-columns: repeat(2, 1fr); + + .tile.vertical { + grid-row: span 1; + grid-column: span 1; + + .tile-image--vertical { + display: none; + } + + .tile-image--horizontal { + display: none; + } + + .tile-image--square { + display: block; + + picture img { + display: block !important; + } + } + } + + .tile.horizontal { + grid-column: span 1; + } + } + } + } + + @container (max-width: 700px) { + .tiles-container { + grid-template-columns: 1fr; + max-width: 700px; + margin: 0 auto; + + .tile { + grid-column: span 1 !important; + grid-row: span 2 !important; + + .tile-content { + grid-row: 2/3 !important; + } + + .tile-image--vertical { + display: none; + } + + .tile-image--horizontal { + display: none; + } + + .tile-image--square { + display: block !important; + grid-row: 1/2 !important; + + picture img { + display: block !important; + } + } + } + } + } +} diff --git a/src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.jdd.tsx b/src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.jdd.tsx new file mode 100644 index 0000000..4f4e465 --- /dev/null +++ b/src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.jdd.tsx @@ -0,0 +1,112 @@ +import type { FlatTemplatable } from "tempstream"; +import { TempstreamJSX } from "tempstream"; +import type { ComponentToHTMLArgs, ExtractParsed, JDDContext } from "@sealcode/jdd"; +import { Component, ComponentArguments } from "@sealcode/jdd"; +import { getFgColorVariable } from "src/back/colors.js"; + +type ExtractArray = T extends Array ? X : never; + +const generate_id = (function* () { + while (true) { + for (let i = 1; i <= 10000; i++) { + yield i; + } + } +})(); + +const component_arguments = { + bleed: new ComponentArguments.Enum(["none", "bleed", "screen"]).setDefaultValue( + "none" + ), + tiles: new ComponentArguments.List( + new ComponentArguments.Structured({ + title: new ComponentArguments.ShortText(), + subtitle: new ComponentArguments.ShortText(), + url: new ComponentArguments.ShortText(), + photo: new ComponentArguments.Structured({ + image: new ComponentArguments.Image(), + alt: new ComponentArguments.ShortText(), + }), + shape: new ComponentArguments.Enum(["square", "horizontal", "vertical"]), + background: new ComponentArguments.Enum(["accent", "accent2", "text-bg"]), + }) + ), +} as const; + +export class DynamicGridV2 extends Component { + getArguments() { + return component_arguments; + } + + public image_sizes = { + square: { width: 700, height: 700 }, + horizontal: { width: 824, height: 400 }, + vertical: { width: 400, height: 824 }, + }; + + renderTile( + jdd_context: JDDContext, + tile: ExtractArray> + ) { + return ( + +
+
+

{tile.title}

+

{tile.subtitle}

+
+
+ + {(["square", "horizontal", "vertical"] as const).map((shape) => ( +
+ {!tile.photo + ? "" + : jdd_context.render_image(tile.photo.image, { + sizesAttr: + "(max-width: 730px) 100vw, (max-width: 980px) 50vw, 810px", + alt: tile.photo.alt, + container: { + ...this.image_sizes[shape], + objectFit: "cover", + }, + crop: this.image_sizes[shape], + imgStyle: "display: none;", + })} +
+ ))} +
+ ); + } + + toHTML( + { + args: { tiles, bleed }, + jdd_context, + classes, + index, + }: ComponentToHTMLArgs, + tab_style_when_active = `border-bottom-color: var(--color-brand-canvas); + border-top-color: var(--color-brand-accent-04); + background: var(--color-brand-canvas); + color: var(--color-brand-text-fg);` + ): FlatTemplatable { + const { value: id } = generate_id.next(); + return ( +
+
+ {tiles.map((tile) => this.renderTile(jdd_context, tile))} +
+
+ ); + } +}