@agentic-design-kits/swiss-minimal 2026.1113.2 → 2026.1114.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +6 -4
- package/DESIGN.md +38 -1
- package/kit/astro/PostFeature.astro +14 -9
- package/kit/theme.css +26 -5
- package/package.json +1 -1
package/COMPONENTS.md
CHANGED
|
@@ -289,6 +289,7 @@ A row of outlined buttons that narrows a list to one category. One choice at a t
|
|
|
289
289
|
- Announce the result in a polite live region outside the accordion: `<p class="sr-only" aria-live="polite">Showing 5 Writing items</p>`.
|
|
290
290
|
- With `FavoriteStar`, add a **Favorites** chip after All, its count in `<span class="chip-count" data-favorites-count>0</span>`. It filters like a category, using the starred ids. When it shows nothing, say how to add some in a `muted` line under the accordion.
|
|
291
291
|
- Listen for `filter:reset` and go back to All (`JumpToCurrent` sends it when the current item is filtered out).
|
|
292
|
+
- A chip that can't be chosen right now takes `disabled`: it fades to 60% and doesn't fill on hover. Say why near the row.
|
|
292
293
|
|
|
293
294
|
## FavoriteStar
|
|
294
295
|
|
|
@@ -833,7 +834,7 @@ In Astro, `<PostList posts={posts} />`, each a `Post` (`title`, `href`, `date`,
|
|
|
833
834
|
|
|
834
835
|
## PostFeature
|
|
835
836
|
|
|
836
|
-
One post at the top of a blog's index,
|
|
837
|
+
One post at the top of a blog's index, in one of two layouts. **Split**, like a split `Hero`: the text and a square image 50/50 from 768px, text first on phones. **Wide**: the text across the full width, then the image under it at 16:9. The `PostList` of the other posts follows it.
|
|
837
838
|
|
|
838
839
|
**Markup.**
|
|
839
840
|
|
|
@@ -850,15 +851,15 @@ One post at the top of a blog's index, set like a split `Hero`: the text and a s
|
|
|
850
851
|
</article>
|
|
851
852
|
```
|
|
852
853
|
|
|
853
|
-
In Astro, `<PostFeature post={post} image={art} alt="What it shows" />`, with the same `Post` as `PostList` and an imported image. `label` (default "Featured") and `action` (default "Read post") change the two short labels; `level="h1"` when nothing else on the page is the `h1`.
|
|
854
|
+
In Astro, `<PostFeature post={post} image={art} alt="What it shows" />`, with the same `Post` as `PostList` and an imported image. The image's shape picks the layout: wide for a landscape image, split for a square or portrait one. `layout="wide"` or `layout="split"` overrides it. `label` (default "Featured") and `action` (default "Read post") change the two short labels; `level="h1"` when nothing else on the page is the `h1`.
|
|
854
855
|
|
|
855
856
|
- It takes a hero's place and space: `space-12` above, more from 768px. A page with a `PostFeature` has no `Hero` or `PageTitle`; give it an `h1` (visually hidden is fine) naming the page.
|
|
856
857
|
- The label is small, bold and `accent-text`; the title is bold and tight at `clamp(2.5rem, 5.5vw, 5rem)`, and underlines (3px) on hover.
|
|
857
858
|
- The primary button is the page's one main action. Its name adds the post's title, so it says where it goes.
|
|
858
|
-
-
|
|
859
|
+
- Split crops the image square (`.media--1x1`); wide crops it 16:9 (`.media--16x9`) and adds `post-feature--wide` to the article, which also gives the summary a longer measure. Either way it loads eagerly, like a hero's. Give wide a landscape original and split a square or portrait one, so the crop takes little.
|
|
859
860
|
- Only one per page. Don't repeat the featured post in the list below it.
|
|
860
861
|
|
|
861
|
-
**Other media.** `image` and `alt` are optional. To show something other than a raster image, such as an SVG that follows the theme, leave them out and fill the `media` slot: `<PostFeature post={post}><svg slot="media" …></svg></PostFeature>`. Keep it square, and give it its own text alternative if it says anything.
|
|
862
|
+
**Other media.** `image` and `alt` are optional. To show something other than a raster image, such as an SVG that follows the theme, leave them out and fill the `media` slot: `<PostFeature post={post}><svg slot="media" …></svg></PostFeature>`. Keep it square, or 16:9 with `layout="wide"`, and give it its own text alternative if it says anything.
|
|
862
863
|
|
|
863
864
|
## Pager
|
|
864
865
|
|
|
@@ -927,6 +928,7 @@ Long-form text from Markdown: `.post-body` styles the plain elements inside it,
|
|
|
927
928
|
- A quote is large and bold beside a 6px `accent` edge, the same edge as the active row. Keep quotes short; one or two per post.
|
|
928
929
|
- `hr` is a 2px `ink` rule. Images fill the measure, square, on `rule` until they load. A table has small uppercase headings over a 2px rule and 1px rules between rows.
|
|
929
930
|
- Code uses the kit's own `pre` and `code` styles.
|
|
931
|
+
- Markdown footnotes (`[^1]`) are numbered in `accent-text`, with no underline until hover; the notes sit at the end in 16px `muted` text under a 2px `ink` rule, each ending in an underlined `accent-text` arrow back to its number. A note about one word goes straight after it, mid-sentence and before any punctuation (`Overused Grotesk[^1], at two weights`); a note about a whole sentence goes after its full stop.
|
|
930
932
|
|
|
931
933
|
**Don't.** Set a whole paragraph in a quote to make it stand out, or add colored callout boxes.
|
|
932
934
|
|
package/DESIGN.md
CHANGED
|
@@ -74,6 +74,43 @@ One family, `--font-sans` (Overused Grotesk, falling back to Helvetica Neue, Hel
|
|
|
74
74
|
- Long labels that would otherwise be caps take `.prose-sentence`.
|
|
75
75
|
- Code is plain HTML, no class: inline `<code>` sits in the line with no tint behind it; a `<pre>` block is square with a 1px `rule` border and `space-4` padding, and scrolls sideways rather than wrapping (give a long one `tabindex="0"` so the keyboard can scroll it); `<kbd>` is outlined in `currentColor`, like the top-bar buttons. Terminal output and logs go on a dark block (`.pre--bar`), with commands in bold and errors in the accent; see CodeBlock in `COMPONENTS.md`. Monospace never goes beyond code: not for labels, numbers or headings.
|
|
76
76
|
|
|
77
|
+
### OpenType features
|
|
78
|
+
|
|
79
|
+
Overused Grotesk has alternate letters, boxed and circled figures and a few numeric features. The kit sets only tabular figures, in `.num`; everything else is off. The demo's Type and color page shows each one off and on.
|
|
80
|
+
|
|
81
|
+
| Feature | What it changes | Use |
|
|
82
|
+
| --- | --- | --- |
|
|
83
|
+
| `ss01` | Single-storey a | Site-wide, if the site wants a friendlier a |
|
|
84
|
+
| `ss02` | Bottom-curled l | Where l, I and 1 must be told apart: codes, names, tables |
|
|
85
|
+
| `ss03` | Round dots on i, j, umlauts and punctuation | Site-wide, if chosen |
|
|
86
|
+
| `ss04` | Spurless G | Site-wide, if chosen |
|
|
87
|
+
| `ss05` | Straight-legged R | Site-wide, if chosen |
|
|
88
|
+
| `ss06` | Alternative J | Site-wide, if chosen |
|
|
89
|
+
| `ss07` | Alternative y | Site-wide, if chosen |
|
|
90
|
+
| `ss08` | Arcless t | Site-wide, if chosen |
|
|
91
|
+
| `ss09` | Alternative asterisk | Site-wide, if chosen |
|
|
92
|
+
| `ss10` | u with no stem | Site-wide, if chosen |
|
|
93
|
+
| `ss11` | Serif I | With `ss02`, where I and l must be told apart |
|
|
94
|
+
| `cv01`, `cv02` | Figures in solid or outlined squares | Keys and step numbers only, never running text |
|
|
95
|
+
| `cv03`, `cv04` | Figures in solid or outlined circles | Keys and step numbers only, never running text |
|
|
96
|
+
| `cv05` | a with a spur | Site-wide, if chosen; works with `ss01` |
|
|
97
|
+
| `tnum` | Tabular figures | Through `.num`, on numbers that line up in a column |
|
|
98
|
+
| `zero` | Slashed zero | Where 0 and O could be confused: codes, IDs |
|
|
99
|
+
| `frac` | Fractions | On the fraction only |
|
|
100
|
+
| `sups`, `subs` | Superscript, subscript figures | On the figures only |
|
|
101
|
+
|
|
102
|
+
- **Choose alternates once.** Set a site's alternate letters on `body`, so a letter has one shape everywhere. Don't switch them word by word.
|
|
103
|
+
- **Prefer `font-variant-*`** where it exists: `font-variant-numeric: tabular-nums`, `slashed-zero` or `diagonal-fractions`, and `font-variant-position: super` or `sub`. These combine on their own. Stylistic sets and character variants have no such property, so they need `font-feature-settings`.
|
|
104
|
+
- **`font-feature-settings` replaces, it doesn't add.** Setting it on an element drops every feature it inherited. To let features stack, give each its own custom property and list them all in one rule:
|
|
105
|
+
|
|
106
|
+
```css
|
|
107
|
+
body { font-feature-settings: var(--ff-ss01, "ss01" 0), var(--ff-ss02, "ss02" 0), var(--ff-zero, "zero" 0); }
|
|
108
|
+
.codes { --ff-ss02: "ss02" 1; --ff-zero: "zero" 1; }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- **Features change looks, not text.** A screen reader reads, and copy and paste gives, the characters typed: a boxed 3 is still "3". Never let a box or circle carry meaning on its own.
|
|
112
|
+
- **Not available:** ligatures, case-sensitive forms, old-style figures and small caps; the font has none. `ss12` changes Bulgarian Cyrillic only. Don't use the slant axis (`slnt`): in this version of the font only some letters slant.
|
|
113
|
+
|
|
77
114
|
## Layout
|
|
78
115
|
|
|
79
116
|
- Content width `page-max` (88rem), centered in `.page`, with `gutter` side padding (1rem, 2rem from 640px).
|
|
@@ -89,7 +126,7 @@ One family, `--font-sans` (Overused Grotesk, falling back to Helvetica Neue, Hel
|
|
|
89
126
|
|
|
90
127
|
## Iconography
|
|
91
128
|
|
|
92
|
-
- **Type and CSS come first.** Draw UI chrome in CSS: the plus/minus is two bars (`.acc-icon`), the menu button is three bars (`.burger`). Use the font's own glyphs where they exist: "Site ↗" (the arrow at 1.3em of the label size), the ▲ / ▼ of a jump button.
|
|
129
|
+
- **Type and CSS come first.** Draw UI chrome in CSS: the plus/minus is two bars (`.acc-icon`), the menu button is three bars (`.burger`). Use the font's own glyphs where they exist: "Site ↗" (the arrow at 1.3em of the label size), the ▲ / ▼ of a jump button. Overused Grotesk has 22 arrows (← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↺ ↻ ⇄ ⇆ ⇋ ⇌ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕) and 23 shapes (▲ △ ▶ ▷ ▼ ▽ ◀ ◁ ■ □ ◆ ◇ ◊ ● ○ ◐ ◑ ◒ ◓ ◢ ◣ ◤ ◥), plus fractions, math signs, currency and typographic marks; the demo's Type and color page shows them all. Use one of these before reaching for an icon set, and give a glyph that acts as a control an `aria-label`, as screen readers read glyphs by their Unicode names.
|
|
93
130
|
- **An icon set is allowed for two things only:**
|
|
94
131
|
1. Third-party brand marks (YouTube, Spotify, Apple Music) where the mark is the clearest label. Use Simple Icons.
|
|
95
132
|
2. A few action icons with no good glyph, such as copy and remove. Use Material Symbols, outline style.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
// One post at the top of a blog's index (PostFeature in COMPONENTS.md)
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// image
|
|
2
|
+
// One post at the top of a blog's index (PostFeature in COMPONENTS.md), where a Hero would go,
|
|
3
|
+
// before the PostList of the other posts. Two layouts, picked by the image's shape unless
|
|
4
|
+
// `layout` says otherwise: a square or portrait image sits beside the text, 50/50 from 768px and
|
|
5
|
+
// cropped square; a landscape image goes under text that runs the full width, cropped 16:9.
|
|
6
|
+
// Import the image so Astro knows its size. For something other than a raster image, such as an
|
|
7
|
+
// SVG that follows the theme, leave out image and alt and fill the media slot instead.
|
|
7
8
|
import { Image } from 'astro:assets';
|
|
8
9
|
import type { ImageMetadata } from 'astro';
|
|
9
10
|
import type { Post } from './types';
|
|
@@ -18,8 +19,12 @@ interface Props {
|
|
|
18
19
|
/** The button's text. One or two words. */
|
|
19
20
|
action?: string;
|
|
20
21
|
level?: 'h1' | 'h2';
|
|
22
|
+
/** 'split': text beside a square image. 'wide': full-width text over a 16:9 image. By default,
|
|
23
|
+
* wide for a landscape image and split for any other. */
|
|
24
|
+
layout?: 'split' | 'wide';
|
|
21
25
|
}
|
|
22
26
|
const { post, image, alt, label = 'Featured', action = 'Read post', level: Title = 'h2' } = Astro.props;
|
|
27
|
+
const wide = (Astro.props.layout ?? (image && image.width > image.height ? 'wide' : 'split')) === 'wide';
|
|
23
28
|
|
|
24
29
|
// Dates are plain days, so format them in UTC or they can slip back a day.
|
|
25
30
|
const date = new Date(post.date).toLocaleDateString('en-US', {
|
|
@@ -30,7 +35,7 @@ const date = new Date(post.date).toLocaleDateString('en-US', {
|
|
|
30
35
|
});
|
|
31
36
|
---
|
|
32
37
|
|
|
33
|
-
<article class=
|
|
38
|
+
<article class:list={['post-feature', { 'post-feature--wide': wide }]}>
|
|
34
39
|
<div>
|
|
35
40
|
<p class="post-feature-label">{label}</p>
|
|
36
41
|
<Title class="post-feature-title">
|
|
@@ -46,11 +51,11 @@ const date = new Date(post.date).toLocaleDateString('en-US', {
|
|
|
46
51
|
{
|
|
47
52
|
image && (
|
|
48
53
|
<Image
|
|
49
|
-
class=
|
|
54
|
+
class:list={['media', wide ? 'media--16x9' : 'media--1x1']}
|
|
50
55
|
src={image}
|
|
51
56
|
alt={alt ?? ''}
|
|
52
|
-
widths={[480, 800, 1200, 1600].filter((w) => w <= image.width)}
|
|
53
|
-
sizes=
|
|
57
|
+
widths={[480, 800, 1200, 1600, 2000].filter((w) => w <= image.width)}
|
|
58
|
+
sizes={wide ? '(min-width: 88rem) 88rem, 100vw' : '(min-width: 768px) 50vw, 100vw'}
|
|
54
59
|
loading="eager"
|
|
55
60
|
fetchpriority="high"
|
|
56
61
|
/>
|
package/kit/theme.css
CHANGED
|
@@ -420,6 +420,8 @@ html[data-drawer-open] .topbar { --tb-bg: var(--bar); --tb-fg: var(--bar-ink); }
|
|
|
420
420
|
transition: background-color 150ms, color 150ms;
|
|
421
421
|
}
|
|
422
422
|
.chip:hover, .chip[aria-pressed="true"] { background: var(--ink); color: var(--paper); }
|
|
423
|
+
.chip:disabled { opacity: 0.6; } /* faded like a disabled .choice */
|
|
424
|
+
.chip:disabled:hover { background: transparent; color: var(--ink); } /* and it doesn't fill */
|
|
423
425
|
.chip-count { font-size: var(--size-100); font-variant-numeric: tabular-nums; opacity: 0.75; } /* how many items it shows */
|
|
424
426
|
.chip-group { display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
425
427
|
|
|
@@ -729,7 +731,7 @@ html[data-drawer-open] { overflow: hidden; } /* stop the page scrolling behind
|
|
|
729
731
|
.post-list > li:last-child { border-bottom: 0; }
|
|
730
732
|
@media (min-width: 640px) { .post-list > li { grid-template-columns: 10rem minmax(0, 1fr); } }
|
|
731
733
|
.post-list time {
|
|
732
|
-
font-size: var(--size-
|
|
734
|
+
font-size: var(--size-200); font-weight: var(--weight-medium); line-height: 1.375;
|
|
733
735
|
font-variant-numeric: tabular-nums; color: var(--muted);
|
|
734
736
|
}
|
|
735
737
|
@media (min-width: 640px) { .post-list time { padding-top: 0.5rem; } }
|
|
@@ -770,7 +772,7 @@ html[data-drawer-open] { overflow: hidden; } /* stop the page scrolling behind
|
|
|
770
772
|
|
|
771
773
|
/* ---------- Post feature: one post at the top of a blog's index ---------- */
|
|
772
774
|
/* Built like .hero--split: text and a square image 50/50 from 768px, stacked text first on
|
|
773
|
-
phones, with a hero's space around it. A small accent-text label, the title as a link, the
|
|
775
|
+
phones, with a hero's space around it (.post-feature--wide, below, stacks it at every width). A small accent-text label, the title as a link, the
|
|
774
776
|
summary in lead size, a meta line and the primary button. The image is cropped square. */
|
|
775
777
|
.post-feature { display: grid; gap: 2.5rem; padding: 3rem 0 4rem 0; }
|
|
776
778
|
@media (min-width: 768px) {
|
|
@@ -778,7 +780,7 @@ html[data-drawer-open] { overflow: hidden; } /* stop the page scrolling behind
|
|
|
778
780
|
}
|
|
779
781
|
.post-feature-label {
|
|
780
782
|
margin: 0;
|
|
781
|
-
font-size: var(--size-
|
|
783
|
+
font-size: var(--size-200); font-weight: var(--weight-strong); letter-spacing: var(--label-tracking); text-transform: var(--label-case);
|
|
782
784
|
color: var(--accent-text);
|
|
783
785
|
}
|
|
784
786
|
.post-feature-title {
|
|
@@ -789,8 +791,12 @@ html[data-drawer-open] { overflow: hidden; } /* stop the page scrolling behind
|
|
|
789
791
|
.post-feature-title a { color: inherit; text-decoration: none; }
|
|
790
792
|
.post-feature-title a:hover { text-decoration: underline; text-decoration-thickness: 3px; text-underline-offset: 0.12em; }
|
|
791
793
|
.post-feature-summary { margin: 1.5rem 0 0 0; max-width: 32rem; }
|
|
792
|
-
.post-feature-meta { margin: 1rem 0 0 0; font-size: var(--size-
|
|
794
|
+
.post-feature-meta { margin: 1rem 0 0 0; font-size: var(--size-200); line-height: 1.375; color: var(--muted); }
|
|
793
795
|
.post-feature .btn { margin-top: 2rem; text-decoration: none; }
|
|
796
|
+
/* Wide: the text runs the full width, the summary at a longer measure, and the image goes under
|
|
797
|
+
it cropped 16:9. For a landscape image. */
|
|
798
|
+
@media (min-width: 768px) { .post-feature--wide { grid-template-columns: minmax(0, 1fr); gap: 3.5rem; } }
|
|
799
|
+
.post-feature--wide .post-feature-summary { max-width: 48rem; }
|
|
794
800
|
|
|
795
801
|
/* ---------- Post header: the top of an article ---------- */
|
|
796
802
|
/* A small label back to the index, the title (between page-title and h2 in size, since titles
|
|
@@ -823,7 +829,7 @@ a.post-header-label:hover { color: var(--accent-text); text-decoration: underlin
|
|
|
823
829
|
|
|
824
830
|
/* ---------- Post body: long-form text from Markdown ---------- */
|
|
825
831
|
/* Markdown can't take classes, so this styles plain elements inside it: paragraphs, h2 and h3,
|
|
826
|
-
lists, quotes, rules, images, tables and code. A 42rem measure by default; a utility on the
|
|
832
|
+
lists, quotes, rules, images, tables, footnotes and code. A 42rem measure by default; a utility on the
|
|
827
833
|
same element changes it. An h2 has no rule over it: inside one article, space and size mark a
|
|
828
834
|
new part, and the thick rule is kept for sections of the page. A quote is set
|
|
829
835
|
large and bold beside a 6px accent edge, the same edge the active row has. */
|
|
@@ -861,6 +867,21 @@ a.post-header-label:hover { color: var(--accent-text); text-decoration: underlin
|
|
|
861
867
|
font-size: var(--size-100); font-weight: var(--weight-medium); letter-spacing: var(--label-tracking); text-transform: var(--label-case);
|
|
862
868
|
}
|
|
863
869
|
.post-body td { padding: 0.625rem 1rem 0.625rem 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
|
|
870
|
+
/* Markdown footnotes ([^1]). The number in the text is a superscript in the accent, with no
|
|
871
|
+
underline (it gets one on hover); line-height 0 keeps it from pushing its line down. The notes
|
|
872
|
+
are a part of their own at the end, so they start under a 2px rule, in small muted text; the
|
|
873
|
+
arrow back to the number is in the accent too, underlined, and turns ink on hover. A jump
|
|
874
|
+
to a note or back to its number stops clear of the top bar. */
|
|
875
|
+
.post-body sup { line-height: 0; }
|
|
876
|
+
.post-body [data-footnote-ref] { color: var(--accent-text); text-decoration: none; font-variant-numeric: tabular-nums; }
|
|
877
|
+
.post-body [data-footnote-ref]:hover { text-decoration: underline; }
|
|
878
|
+
.post-body .footnotes { margin-top: 3rem; font-size: var(--size-200); line-height: 1.375; color: var(--muted); }
|
|
879
|
+
.post-body .footnotes ol { margin: 0; padding: 0.75rem 0 0 1.5rem; border-top: 2px solid var(--ink); }
|
|
880
|
+
.post-body .footnotes p { margin: 0; }
|
|
881
|
+
.post-body .footnotes p + p { margin-top: 0.5rem; }
|
|
882
|
+
.post-body [data-footnote-backref] { margin-left: 0.25rem; color: var(--accent-text); }
|
|
883
|
+
.post-body [data-footnote-backref]:hover { color: var(--ink); }
|
|
884
|
+
.post-body :is([data-footnote-ref], .footnotes li) { scroll-margin-top: 5rem; }
|
|
864
885
|
|
|
865
886
|
/* ---------- Post nav: the previous and next posts, at the end of one ---------- */
|
|
866
887
|
/* A 2px rule, then two links: a small label over the post's title. Stacked on phones; side by
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentic-design-kits/swiss-minimal",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.1114.1",
|
|
4
4
|
"description": "A type-led design kit: plain CSS, a few small scripts and Astro components, for Tailwind v4 sites.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Danny Englander",
|