Container, Columns, Grid, Divider, Image, Link, Typography and Kbd were built from utility classes and class: conditionals. That works only where Tailwind is present, and every variant cost a dozen conditional lines -- Divider spent eleven of them saying which token to paint the rule. They now carry wire-* classes with a local style block, and variants are data attributes the style block selects on. Divider went from eleven conditionals to five rules, and Typography lost thirteen. Behaviour is preserved rather than improved on. Container keeps columns and gap even though a container is not really a grid, because applications depend on them, and its columns default stays 2: the redesign contract test caught that changing it would silently reflow every Container already published. Additive only: Grid gains minItemWidth for an auto-fit track, Divider gains dashed and dotted variants, Image gains fit, and Link gains underline. Verified in a browser rather than by eye, since the pane cannot screenshot: track counts match the declared columns at desktop and collapse correctly below each breakpoint. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
139 lines
3.2 KiB
Plaintext
139 lines
3.2 KiB
Plaintext
// Grid -- an equal-track grid that collapses on small screens.
|
|
//
|
|
// <Grid columns={3} gap="lg">...</Grid>
|
|
//
|
|
// Pass minItemWidth to let the browser decide the count instead: the track
|
|
// list becomes auto-fit, which reflows continuously rather than at fixed
|
|
// breakpoints and suits card decks whose item count is not known.
|
|
//
|
|
// NOTE: the style block uses /* */ comments only -- // is not a CSS comment
|
|
// and silently swallows the rule that follows it.
|
|
component Grid {
|
|
props {
|
|
size: string = "default"
|
|
color: string = "primary"
|
|
columns: number = 2
|
|
gap: string = "md"
|
|
maxWidth: string = "xl"
|
|
// When set, the count is derived from the available width instead of the
|
|
// columns prop. Accepts any CSS length.
|
|
minItemWidth: string = ""
|
|
class: string = ""
|
|
}
|
|
|
|
functions {
|
|
shared function columnCount() {
|
|
var value = Number(columns)
|
|
if (!value || value < 1) {
|
|
return 1
|
|
}
|
|
return Math.min(6, value)
|
|
}
|
|
|
|
shared function autoTrack() {
|
|
return minItemWidth ? "repeat(auto-fit, minmax(" + minItemWidth + ", 1fr))" : ""
|
|
}
|
|
}
|
|
|
|
view {
|
|
<div
|
|
{...attrs}
|
|
data-ui-component="Grid"
|
|
class='wire-grid {class}'
|
|
data-size='{size}'
|
|
data-color='{color}'
|
|
data-gap='{gap}'
|
|
data-max-width='{maxWidth}'
|
|
data-columns='{columnCount()}'
|
|
data-auto='{minItemWidth ? "true" : "false"}'
|
|
style='--grid-auto-track:{autoTrack()};'
|
|
>
|
|
<slot></slot>
|
|
</div>
|
|
}
|
|
|
|
style {
|
|
.wire-grid {
|
|
--grid-gap: 1.25rem;
|
|
display: grid;
|
|
width: 100%;
|
|
min-width: 0;
|
|
gap: var(--grid-gap);
|
|
grid-template-columns: 1fr;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.wire-grid[data-size="compact"] {
|
|
align-items: start;
|
|
}
|
|
|
|
.wire-grid[data-max-width="md"] {
|
|
max-width: 48rem;
|
|
}
|
|
|
|
.wire-grid[data-max-width="lg"] {
|
|
max-width: 64rem;
|
|
}
|
|
|
|
.wire-grid[data-max-width="xl"] {
|
|
max-width: 80rem;
|
|
}
|
|
|
|
.wire-grid[data-max-width="2xl"] {
|
|
max-width: 96rem;
|
|
}
|
|
|
|
.wire-grid[data-max-width="full"] {
|
|
max-width: none;
|
|
}
|
|
|
|
.wire-grid[data-gap="xs"] {
|
|
--grid-gap: 0.5rem;
|
|
}
|
|
|
|
.wire-grid[data-gap="sm"] {
|
|
--grid-gap: 0.75rem;
|
|
}
|
|
|
|
.wire-grid[data-gap="lg"] {
|
|
--grid-gap: 2rem;
|
|
}
|
|
|
|
.wire-grid[data-gap="xl"] {
|
|
--grid-gap: 2.5rem;
|
|
}
|
|
|
|
/*
|
|
* auto-fit needs no breakpoints, so it wins over the fixed counts below
|
|
* and applies at every width.
|
|
*/
|
|
.wire-grid[data-auto="true"] {
|
|
grid-template-columns: var(--grid-auto-track);
|
|
}
|
|
|
|
@media (min-width: 640px) {
|
|
.wire-grid[data-auto="false"]:not([data-columns="1"]) {
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1024px) {
|
|
.wire-grid[data-auto="false"][data-columns="3"] {
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
}
|
|
|
|
.wire-grid[data-auto="false"][data-columns="4"] {
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
}
|
|
|
|
.wire-grid[data-auto="false"][data-columns="5"] {
|
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
}
|
|
|
|
.wire-grid[data-auto="false"][data-columns="6"] {
|
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
}
|
|
}
|
|
}
|
|
}
|