@agentic-design-kits/swiss-minimal 2026.1113.2 → 2026.1114.0

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 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, set like a split `Hero`: the text and a square image 50/50 from 768px, text first on phones. The `PostList` of the other posts follows it.
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
- - The image is cropped square (`.media--1x1`) and loads eagerly, like a hero's. A square or portrait original crops best.
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
 
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): text and a square image
3
- // 50/50 from 768px, stacked text first on phones. Put it where a Hero would go, before the
4
- // PostList of the other posts. Import the image so Astro knows its size; it is cropped square.
5
- // For something other than a raster image, such as an SVG that follows the theme, leave out
6
- // image and alt and fill the media slot instead.
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="post-feature">
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="media media--1x1"
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="(min-width: 768px) 50vw, 100vw"
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-100); font-weight: var(--weight-medium); line-height: 1.375;
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-100); font-weight: var(--weight-strong); letter-spacing: var(--label-tracking); text-transform: var(--label-case);
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-100); line-height: 1.375; color: var(--muted); }
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentic-design-kits/swiss-minimal",
3
- "version": "2026.1113.2",
3
+ "version": "2026.1114.0",
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",