Removes hardcoded data from render context, allowing more dynamic renderer implementation Changes include: - Decoupling data retrieval from render context - Simplifying renderer interface - Supporting more flexible data traversal strategies Prepares for more modular and adaptable rendering approach
5.1 KiB
5.1 KiB
Selvfølgelig—her er en opdateret, selvstændig .md-spec, som understøtter variable antal resources per team, dynamisk kolonnebredde, ingen inline layout-styles, pipeline‐rendering i grupper, og CSS-controlling via custom properties.
Kopier → gem som fx:
grid-render-pipeline-dynamic-columns.md
# Grid Render Pipeline — Dynamic Columns Spec
Denne specifikation beskriver en generisk render-pipeline til at bygge et
dynamisk CSS Grid layout, hvor hver "gruppe" (teams, resources, dates) har sin
egen renderer og pipeline-styring. Layoutet understøtter **variable antal
resources pr. team** og beregner automatisk antal kolonner. Ingen inline-styles
til positionering anvendes.
---
## ✨ Formål
- Ét globalt CSS Grid.
- Variabelt antal resources pr. team → dynamisk antal kolonner.
- CSS-grid auto-placerer rækker.
- Ingen inline styling af layout (ingen `element.style.gridRow = ...`).
- CSS custom properties bruges til at definere dynamiske spænder.
- Renderere har ens interface og bindes i pipeline.
- `pipeline.run(ctx)` executer alle renderers i rækkefølge.
- Hver renderer kan hente sin egen data (API, async osv.).
---
## 🧩 Data Model
```ts
type DateString = string;
interface Resource {
id: string;
name: string;
dates: DateString[];
}
interface Team {
id: string;
name: string;
resources: Resource[];
}
🧠 Context
interface RenderContext {
grid: HTMLElement; // root grid container
teams: Team[]; // data
}
grid er HTML-elementet med display:grid, og teams er data.
🎨 CSS Layout
Grid kolonner bestemmes dynamisk via CSS variablen --total-cols.
.grid {
display: grid;
grid-template-columns: repeat(var(--total-cols), minmax(0, 1fr));
gap: 6px 10px;
}
.cell {
font-size: 0.9rem;
}
Teams (øverste række)
Hver team-header spænder antal resources for team'et:
.team-header {
grid-column: span var(--team-cols, 1);
font-weight: 700;
border-bottom: 1px solid #ccc;
padding: 4px 2px;
}
Resources (2. række)
.resource-cell {
padding: 4px 2px;
background: #f5f5f5;
border-radius: 4px;
text-align: center;
font-weight: 600;
}
Dates (3. række)
.dates-cell { padding: 2px 0; }
.dates-list {
display: flex;
flex-wrap: wrap;
gap: 4px;
justify-content: center;
}
.date-pill {
padding: 3px 6px;
background: #e3e3e3;
border-radius: 4px;
font-size: 0.8rem;
}
🔧 Beregning af kolonner
Total cols = sum(resources.length for all teams)
const totalCols = ctx.teams.reduce((sum, t) => sum + t.resources.length, 0);
ctx.grid.style.setProperty('--total-cols', totalCols.toString());
For hvert team defineres hvor mange kolonner det spænder:
cell.style.setProperty('--team-cols', team.resources.length.toString());
Bemærk: vi bruger kun CSS vars til layoutparametre – ikke inline grid-row/grid-column.
⚙ Renderer Interface
interface Renderer {
id: string;
next: Renderer | null;
render(ctx: RenderContext): void;
}
Factory
function createRenderer(id: string, fn: (ctx: RenderContext) => void): Renderer {
return {
id,
next: null,
render(ctx) {
fn(ctx);
if (this.next) this.next.render(ctx);
}
};
}
🧱 De tre render-lag (grupper)
Teams
- Appender én
.team-headerper team. - Sætter
--team-cols.
Resources
- Appender én
.resource-cellper resource. - Foregår i teams-orden → CSS auto-row sørger for næste række.
Dates
- Appender én
.dates-cellper resource. - Hver celle indeholder flere
.date-pill.
Append-rækkefølge giver 3 rækker automatisk:
- teams, 2) resources, 3) dates.
🔗 Pipeline
function buildPipeline(renderers: Renderer[]) {
for (let i = 0; i < renderers.length - 1; i++) {
renderers[i].next = renderers[i + 1];
}
const first = renderers[0] ?? null;
return {
run(ctx: RenderContext) {
if (first) first.render(ctx);
}
};
}
Brug
const pipeline = buildPipeline([
teamsRenderer,
resourcesRenderer,
datesRenderer
]);
pipeline.run(ctx);
🚀 Kørsel
// 1) beregn total kolonner
const totalCols = ctx.teams.reduce((sum, t) => sum + t.resources.length, 0);
ctx.grid.style.setProperty('--total-cols', totalCols);
// 2) pipeline
pipeline.run(ctx);
CSS klarer resten.
🧽 Principper
- Ingen inline style-positionering.
- CSS Grid owner layout.
- JS owner data & rækkefølge.
- Renderers er udskiftelige og genbrugelige.
- Append i grupper = rækker automatisk.
- CSS vars styrer spans dynamisk.
✔ TL;DR
- Grid-cols bestemmes ud fra data.
- Team-header
span = resources.length. - Append rækkefølge = rækker.
- Renderere i pipeline.
- Ingen koordinater, ingen inline layout-styles.
---