Skip to content
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
31 changes: 31 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# AGENTS Guide

## Project Overview

- **Name:** mlut website
- **Stack:** Eleventy, mlut, ejs, Sass, Javascript
- **Architecture:** SSG (Static site generation)

## Project Structure

- `src/` - editable sources
- `src/_includes/` - partials and reusable templates
- `src/_data/` - global Eleventy data
- `src/assets/` - styles, scripts, images, and other static assets
- `src/layouts/` - reusable generic layouts for pages
- `src/arts/` - pure CSS arts
- `dist/` - generated output

## Setup and commands

- **Install dependencies:** `npm i`
- **Build project:** `npm run build`
- **Start dev server:** `npm start`
- **Start mlut CLI in watch mode:** `npm run mlut`

## Working rules

- Always try to address the cause, not the effect
- Use modern vanilla JS with custom elements and without frameworks. See examples of components in `src/assets/script/`
- Use Atomic CSS aproach with mlut for writing styles
- Do not install new third-party packages without asking the user first
33 changes: 21 additions & 12 deletions src/_data/arts.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,61 @@
{
"artId":"ghost",
"bgColor":"Bgc-$artGhost",
"showInMain": true
"showInMain": true,
"size":"standard"
},
{
"artId":"flushed-emoji",
"bgColor":"Bgc-$artFlushedEmoji",
"showInMain": true
"showInMain": true,
"size":"standard"
},
{
"artId":"penrose-triangle",
"bgColor":"Bgc-$artPenroseTriangle",
"showInMain": true
"showInMain": true,
"size":"wide"
},
{
"artId":"exploding-head",
"bgColor":"Bgc-$artExplodingHead",
"showInMain": true
"showInMain": true,
"size":"wide"
},
{
"artId":"clown-emoji",
"bgColor":"Bgc-$artClownEmoji",
"showInMain": false
"showInMain": false,
"size":"standard"
},
{
"artId":"mushroom",
"bgColor":"Bgc-$artMushroom",
"showInMain": false
"showInMain": false,
"size":"tall"
},
{
"artId":"robot-hare",
"bgColor":"Bgc-$artRobotHare",
"showInMain": true
"showInMain": true,
"size":"tall"
},
{
"artId":"funny-cake",
"bgColor":"Bgc-$artFunnyCake",
"showInMain": false
"showInMain": false,
"size":"wide"
},
{
"artId":"cat",
"bgColor":"Bgc-$artCat",
"showInMain": false
"showInMain": false,
"size":"wide"
},
{
"artId":"corgi",
"bgColor":"Bgc-$artCorgi",
"showInMain": true
"showInMain": true,
"size":"wide"
}

]
]
86 changes: 77 additions & 9 deletions src/arts.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,91 @@ area: Arts
---
<%
const artsPageCSS = {
card:"W100p H20gg Tsd-$shortTs @:hv_Tsd-$longTs",
artWrapper:"-Sz100p Ov-h Plcc-c Plci-c D-f",
card:"D H20gg Bgc-$core800 Tsd-$shortTs @:hv_Tsd-$longTs",
button: "W12gg lg_W9gg Mxw50u xl_Mxw55u Ai-str"
};

// Grid spans are expressed as [columns, rows].
const tileSizes = {
standard: [1, 2],
wide: [2, 2],
tall: [1, 4]
};
const colsOnScreen = {
md: 2,
xl: 4,
};

const masonryItems = [
...it.arts,
{ artId: 'add-art', size: 'standard' }
];

// Represent every occupied grid cell with a stable row:column key.
const getCells = (row, column, width, height) => Array.from(
{ length: width * height },
(_, index) => `${row + Math.floor(index / width)}:${column + (index % width)}`
);

function getTileDimensions(size, columns) {
const [preferredWidth, height] = tileSizes[size] || tileSizes.standard;
const wideTileOnMdScreen = size === 'wide' && columns === colsOnScreen.md;
const width = wideTileOnMdScreen ? 1 : Math.min(preferredWidth, columns);

return { width, height };
}

function findFirstAvailableArea(occupied, columns, width, height) {
// Preserve the row-first, then column-first placement order.
for (let row = 1; ; row += 1) {
for (let column = 1; column <= columns - width + 1; column += 1) {
const cells = getCells(row, column, width, height);
const isAvailable = cells.every((cell) => !occupied.has(cell));

if (isAvailable) return { column, row, cells };
}
}
}

function setCtaLength(){
return it.arts.length % 2 != 0 ? 'md_W50p' : ''
function packMasonry(columns) {
const occupied = new Set();

return masonryItems.reduce((layout, item) => {
const { width, height } = getTileDimensions(item.size, columns);
const { column, row, cells } = findFirstAvailableArea(
occupied,
columns,
width,
height
);

cells.forEach((cell) => occupied.add(cell));
layout[item.artId] = { column, row, width, height };
return layout;
}, {});
}

// Save positions for the two responsive grid configurations.
const masonryLayouts = {
md: packMasonry(colsOnScreen.md),
xl: packMasonry(colsOnScreen.xl)
};

function getMasonryStyle(artId) {
// Serialize server-calculated positions as CSS custom properties.
return Object.entries(masonryLayouts).map(([breakpoint, layout]) => {
const { column, row, width, height } = layout[artId];
return `--masonry-column-${breakpoint}:${column}/span ${width};--masonry-row-${breakpoint}:${row}/span ${height};`;
}).join('');
}
%>
<section class="W100p Bgc-$core800 Pt-$headerH">
<div>
<h1 class="M0 Bgc-$core500 C-$accent900 Txa-c Fns7u P10u;0"> Pure CSS art</h1>

<div class="M-a W100p D-f Fld-r Flw-w Jc-c Ai-c">
<% it.arts.forEach((art, index) => {%>
<art-panel class="D Ps -Ctx W100p H20gg -Ts md_W50p" id="<%= art.artId %>">
<div class="M-a W100p D-g Gtc1fr md_Gtc-t2 xl_Gtc-t4 Gatr10gg Gatf-r;d Gap3u">
<% it.arts.forEach((art) => { %>
<art-panel class="D Ps -Ctx Gr-s2" id="<%= art.artId %>" size="<%= art.size %>" style="<%= getMasonryStyle(art.artId) %>">
<div class="-Sz100p Ov-h Plcc-c Plci-c D-f <%= art.bgColor %>">
<%- include(`./arts/${art.artId}.ejs`) %>
</div>
Expand All @@ -43,9 +111,9 @@ area: Arts
</div>
</div>
</art-panel>
<% }) %>
<% }); %>

<div class="<%= artsPageCSS.card %> <%= setCtaLength() %> -Ctx P3u">
<div class="<%= artsPageCSS.card %> arts-masonry-cta -Ctx P3u" style="<%= getMasonryStyle('add-art') %>">
<a href="https://github.com/mlutcss/website/fork" target="_blank"
class="-Sz100p Bd1u;d;$brand205 Bdc-$brand_a @:hv_Bdc-$brand205 @:hv_^:h_Bdc-$brand Bdrd5u Tsd-ih D-f Fld-c Jc-c Ai-c C-$brand Txd-n">
<svg class="M0;0;5u @:hv_O0.5 @:hv_^:h_O1 Tsd-ih H40p Stw2">
Expand Down
21 changes: 21 additions & 0 deletions src/assets/style/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,24 @@ html, .theme-dark {
@include light-theme;
}
}

art-panel[size],
.arts-masonry-cta {
min-width: 0;
}

@media (min-width: 768px) {
art-panel[size],
.arts-masonry-cta {
grid-column: var(--masonry-column-md);
grid-row: var(--masonry-row-md);
}
}

@media (min-width: 1200px) {
art-panel[size],
.arts-masonry-cta {
grid-column: var(--masonry-column-xl);
grid-row: var(--masonry-row-xl);
}
}