Dynamic Grid V2
This commit is contained in:
parent
2dd85a6db6
commit
daeaea5488
251
src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.css
Normal file
251
src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.css
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
112
src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.jdd.tsx
Normal file
112
src/back/jdd-components/dynamic-grid-v2/dynamic-grid-v2.jdd.tsx
Normal file
@ -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> = T extends Array<infer X> ? 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<typeof component_arguments> {
|
||||
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<ExtractParsed<typeof component_arguments.tiles>>
|
||||
) {
|
||||
return (
|
||||
<a
|
||||
href={[tile.url]}
|
||||
class={["tile", tile.shape]}
|
||||
style={[
|
||||
`--tile-bg-color: var(--color-brand-${tile.background})`,
|
||||
`--tile-fg-color: var(${getFgColorVariable("brand-" + tile.background)})`,
|
||||
].join(";")}
|
||||
>
|
||||
<div class="tile-content">
|
||||
<div class="tile-content-wrapper">
|
||||
<h3 class="tile-title">{tile.title}</h3>
|
||||
<p class="tile-subtitle">{tile.subtitle}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{(["square", "horizontal", "vertical"] as const).map((shape) => (
|
||||
<div class={["tile-image", `tile-image--${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;",
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
toHTML(
|
||||
{
|
||||
args: { tiles, bleed },
|
||||
jdd_context,
|
||||
classes,
|
||||
index,
|
||||
}: ComponentToHTMLArgs<typeof component_arguments>,
|
||||
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 (
|
||||
<div
|
||||
class={["dynamic-grid", `dynamic-grid--bleed-${bleed}`, ...classes]}
|
||||
style={`--jdd-index: ${index}`}
|
||||
>
|
||||
<div class="tiles-container">
|
||||
{tiles.map((tile) => this.renderTile(jdd_context, tile))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user