@starci/grammar 0.4.5 → 0.4.6

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.
@@ -172,22 +172,37 @@
172
172
  min-width: 0;
173
173
  }
174
174
 
175
+ /*
176
+ * THE COLLAPSED FORM IS THE DEFAULT. Every two-column form lives INSIDE the container query.
177
+ *
178
+ * A container query adds no specificity, so while the expanded tracks were written outside it
179
+ * as attribute selectors, `[data-grammar-layout-rail-width="wide"]` (0,2,0) outranked the
180
+ * collapse (0,1,0) and the layout never collapsed at all: in a 358px container the primary
181
+ * track computed to 0px and the entire primary column vanished on a phone.
182
+ *
183
+ * Restating the collapse once per attribute value would repair today's three variants and break
184
+ * again on the fourth one somebody adds. The two ranges are made MUTUALLY EXCLUSIVE instead:
185
+ * the narrow form is what remains when the query does not match, so no selector inside the
186
+ * query - at any specificity, with any attribute invented later - can outrank it. It is also
187
+ * what a renderer without container queries gets, which is the safe half of the pair.
188
+ */
175
189
  .starci-core-primary-rail-layout {
176
190
  display: grid;
177
191
  min-width: 0;
178
- grid-template-columns: minmax(0, 1fr) minmax(16rem, 20rem);
179
- gap: var(--starci-core-region-gap, 1.5rem);
180
- }
181
-
182
- .starci-core-primary-rail-layout[data-grammar-layout-rail="absent"] {
183
192
  grid-template-columns: minmax(0, 1fr);
193
+ gap: var(--starci-core-region-gap, 1.5rem);
184
194
  }
185
195
 
186
- .starci-core-primary-rail-layout[data-grammar-layout-rail-width="compact"] { grid-template-columns: minmax(0, 1fr) minmax(14rem, 16rem); }
187
- .starci-core-primary-rail-layout[data-grammar-layout-rail-width="wide"] { grid-template-columns: minmax(0, 1fr) minmax(20rem, 24rem); }
188
196
  .starci-core-primary-rail-layout[data-grammar-layout-align="start"] { align-items: start; }
189
197
  .starci-core-primary-rail-layout[data-grammar-layout-align="stretch"] { align-items: stretch; }
190
198
 
199
+ /* The rail track is spelled once per width, and only where there is a rail to give it to. */
200
+ @container starci-core-primary-rail (min-width: 56.001rem) {
201
+ .starci-core-primary-rail-layout[data-grammar-layout-rail="present"] { grid-template-columns: minmax(0, 1fr) minmax(16rem, 20rem); }
202
+ .starci-core-primary-rail-layout[data-grammar-layout-rail="present"][data-grammar-layout-rail-width="compact"] { grid-template-columns: minmax(0, 1fr) minmax(14rem, 16rem); }
203
+ .starci-core-primary-rail-layout[data-grammar-layout-rail="present"][data-grammar-layout-rail-width="wide"] { grid-template-columns: minmax(0, 1fr) minmax(20rem, 24rem); }
204
+ }
205
+
191
206
  .starci-core-primary-region,
192
207
  .starci-core-rail-region {
193
208
  min-width: 0;
@@ -1167,11 +1182,13 @@
1167
1182
  }
1168
1183
 
1169
1184
  @container starci-core-primary-rail (max-width: 56rem) {
1170
- .starci-core-primary-rail-layout {
1171
- grid-template-columns: minmax(0, 1fr);
1172
- }
1173
-
1174
- /* Collapsed, the rail may lead - a filter or summary a reader needs before the content. */
1185
+ /*
1186
+ * The single column itself is the DEFAULT above, not an override here - see the note on
1187
+ * `.starci-core-primary-rail-layout`. This block owns only what is true of the collapsed
1188
+ * reading order, which has no counterpart outside the query to fight with.
1189
+ *
1190
+ * Collapsed, the rail may lead - a filter or summary a reader needs before the content.
1191
+ */
1175
1192
  .starci-core-primary-rail-layout[data-grammar-layout-collapsed-order="rail-first"] .starci-core-rail-region {
1176
1193
  order: -1;
1177
1194
  }
@@ -1293,6 +1310,30 @@
1293
1310
  gap: var(--starci-core-inline-gap, 0.5rem);
1294
1311
  }
1295
1312
 
1313
+ /*
1314
+ * THE BAND'S OWN CONTROLS MEET THE 44px TOUCH FLOOR.
1315
+ *
1316
+ * Every pressable in the two action slots was the vendor button's own height - 2.25rem on
1317
+ * desktop and 2.5rem compact - so the language menu, the cart, the account button, the compact
1318
+ * drawer trigger and the field-shaped search trigger all sat under the floor, on the surface a
1319
+ * reader is most likely to touch. It is a MINIMUM, not a size: `min-inline-size` and
1320
+ * `min-block-size` are properties the vendor's rules never set, so the glyph, the label, the
1321
+ * paint and the corner are all untouched and no `!important` is owed to the components layer.
1322
+ *
1323
+ * The band does NOT grow. The primary row is 4rem with a 0.5rem block inset on each side, so
1324
+ * 44px is 4px short of the 3rem it already offers a control, and `--starci-core-band-height`
1325
+ * stays `calc(4rem + 1px)`. The floor is spelled on the pressable, never on the slot: a slot
1326
+ * with a min-height would pad a row that has nothing in it.
1327
+ *
1328
+ * The feature layer is deliberately out of scope - its tabs are a Tabs branch, and a tab's
1329
+ * target is that branch's to answer.
1330
+ */
1331
+ .starci-core-navigation-feature-nav-actions :where(button, [role="button"], a[href]),
1332
+ .starci-core-navigation-feature-nav-compact-navigation :where(button, [role="button"], a[href]) {
1333
+ min-inline-size: 44px;
1334
+ min-block-size: 44px;
1335
+ }
1336
+
1296
1337
  .starci-core-navigation-feature-nav-feature {
1297
1338
  width: 100%;
1298
1339
  padding-inline: 0.75rem;
@@ -1450,16 +1491,26 @@
1450
1491
  display: none;
1451
1492
  }
1452
1493
 
1494
+ /*
1495
+ * THE COLLAPSED FORM IS THE DEFAULT here too, for the reason recorded on
1496
+ * `.starci-core-primary-rail-layout`: every multi-track form lives INSIDE a container query, so
1497
+ * the stacked one cannot be outranked by an attribute selector written outside it. Before this,
1498
+ * the two-track rule for `[navigation="present"][rail="present"]` (0,3,0) in the 72rem query
1499
+ * beat the collapse group's bare class (0,1,0), and the leading four-track rule (0,4,0) beat
1500
+ * every collapse rule there is, so a shell carrying a navigation and a rail never stacked.
1501
+ *
1502
+ * The tiers are mutually exclusive ranges, narrowest first:
1503
+ * default one column, one row per region
1504
+ * > 56rem the regions take their own tracks
1505
+ * > 72rem a navigation AND a rail stand beside the primary at the same time
1506
+ */
1453
1507
  .starci-core-workspace-shell-layout {
1454
1508
  --starci-core-workspace-navigation-track: minmax(14rem, var(--starci-core-workspace-navigation-width, 18rem));
1455
1509
  --starci-core-workspace-rail-track: minmax(16rem, var(--starci-core-rail-standard, 20rem));
1456
1510
  display: grid;
1457
1511
  min-width: 0;
1458
- grid-template-areas: "navigation primary rail";
1459
- grid-template-columns:
1460
- var(--starci-core-workspace-navigation-track)
1461
- minmax(0, 1fr)
1462
- var(--starci-core-workspace-rail-track);
1512
+ grid-template-areas: "navigation" "primary" "rail";
1513
+ grid-template-columns: minmax(0, 1fr);
1463
1514
  gap: var(--starci-core-region-gap, 1.5rem);
1464
1515
  }
1465
1516
 
@@ -1467,25 +1518,22 @@
1467
1518
  --starci-core-workspace-navigation-track: max-content;
1468
1519
  }
1469
1520
 
1470
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="present"] {
1471
- grid-template-areas: "primary rail";
1472
- grid-template-columns: minmax(0, 1fr) var(--starci-core-workspace-rail-track);
1521
+ /* Stacked, an absent region leaves no row behind - an empty one would still take a gap. */
1522
+ .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"] {
1523
+ grid-template-areas: "primary" "rail";
1473
1524
  }
1474
1525
 
1475
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="present"] {
1476
- grid-template-areas: "rail rule primary";
1477
- grid-template-columns: var(--starci-core-workspace-rail-track) 1px minmax(0, 1fr);
1478
- column-gap: 0;
1526
+ .starci-core-workspace-shell-layout[data-grammar-workspace-rail="absent"] {
1527
+ grid-template-areas: "navigation" "primary";
1479
1528
  }
1480
1529
 
1481
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="present"] {
1482
- grid-template-areas: "navigation rail rule primary";
1483
- grid-template-columns:
1484
- var(--starci-core-workspace-navigation-track)
1485
- var(--starci-core-workspace-rail-track)
1486
- 1px
1487
- minmax(0, 1fr);
1488
- column-gap: 0;
1530
+ .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="absent"] {
1531
+ grid-template-areas: "primary";
1532
+ }
1533
+
1534
+ /* A leading rail keeps its precedence in the reading order once the tracks are gone. */
1535
+ .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="present"] {
1536
+ grid-template-areas: "rail" "primary";
1489
1537
  }
1490
1538
 
1491
1539
  .starci-core-workspace-shell-leading-rule {
@@ -1497,22 +1545,61 @@
1497
1545
  background: var(--separator, var(--starci-core-separator, GrayText));
1498
1546
  }
1499
1547
 
1500
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"] .starci-core-workspace-shell-leading-rule {
1501
- display: block;
1502
- }
1548
+ @container starci-core-workspace-shell (min-width: 56.001rem) {
1549
+ .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="present"] {
1550
+ grid-template-areas: "navigation primary" "navigation rail";
1551
+ grid-template-columns: var(--starci-core-workspace-navigation-track) minmax(0, 1fr);
1552
+ }
1503
1553
 
1504
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"] .starci-core-workspace-shell-primary {
1505
- padding-inline-start: var(--starci-core-workspace-leading-seam, 2rem);
1506
- }
1554
+ .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="present"] {
1555
+ grid-template-areas: "primary rail";
1556
+ grid-template-columns: minmax(0, 1fr) var(--starci-core-workspace-rail-track);
1557
+ }
1558
+
1559
+ .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="absent"] {
1560
+ grid-template-areas: "navigation primary";
1561
+ grid-template-columns: var(--starci-core-workspace-navigation-track) minmax(0, 1fr);
1562
+ }
1563
+
1564
+ .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="absent"] {
1565
+ grid-template-areas: "primary";
1566
+ grid-template-columns: minmax(0, 1fr);
1567
+ }
1568
+
1569
+ .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="present"] {
1570
+ grid-template-areas: "rail rule primary";
1571
+ grid-template-columns: var(--starci-core-workspace-rail-track) 1px minmax(0, 1fr);
1572
+ column-gap: 0;
1573
+ }
1574
+
1575
+ .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="present"] {
1576
+ grid-template-areas: "navigation rail rule primary";
1577
+ grid-template-columns:
1578
+ var(--starci-core-workspace-navigation-track)
1579
+ var(--starci-core-workspace-rail-track)
1580
+ 1px
1581
+ minmax(0, 1fr);
1582
+ column-gap: 0;
1583
+ }
1584
+
1585
+ /* The seam and its rule belong to the side-by-side form, so they arrive with the tracks. */
1586
+ .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"] .starci-core-workspace-shell-leading-rule {
1587
+ display: block;
1588
+ }
1507
1589
 
1508
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="absent"] {
1509
- grid-template-areas: "navigation primary";
1510
- grid-template-columns: var(--starci-core-workspace-navigation-track) minmax(0, 1fr);
1590
+ .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"] .starci-core-workspace-shell-primary {
1591
+ padding-inline-start: var(--starci-core-workspace-leading-seam, 2rem);
1592
+ }
1511
1593
  }
1512
1594
 
1513
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="absent"] {
1514
- grid-template-areas: "primary";
1515
- grid-template-columns: minmax(0, 1fr);
1595
+ @container starci-core-workspace-shell (min-width: 72.001rem) {
1596
+ .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="present"] {
1597
+ grid-template-areas: "navigation primary rail";
1598
+ grid-template-columns:
1599
+ var(--starci-core-workspace-navigation-track)
1600
+ minmax(0, 1fr)
1601
+ var(--starci-core-workspace-rail-track);
1602
+ }
1516
1603
  }
1517
1604
 
1518
1605
  .starci-core-workspace-shell-layout[data-grammar-workspace-rail-width="compact"] {
@@ -1847,62 +1934,16 @@
1847
1934
  }
1848
1935
 
1849
1936
  @container starci-core-workspace-shell (max-width: 72rem) {
1850
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="present"] {
1851
- grid-template-areas: "navigation primary" "navigation rail";
1852
- grid-template-columns: var(--starci-core-workspace-navigation-track) minmax(0, 1fr);
1853
- }
1854
-
1855
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="present"] {
1856
- grid-template-areas: "navigation rail rule primary";
1857
- grid-template-columns:
1858
- var(--starci-core-workspace-navigation-track)
1859
- var(--starci-core-workspace-rail-track)
1860
- 1px
1861
- minmax(0, 1fr);
1862
- }
1863
-
1864
1937
  .starci-core-workspace-shell-rail .starci-core-rail {
1865
1938
  max-width: none;
1866
1939
  }
1867
1940
  }
1868
1941
 
1942
+ /*
1943
+ * Every grid template this shell can take now lives in the two `min-width` tiers above. What
1944
+ * stays here is the behaviour of a STACKED rail, which no rule outside the query contradicts.
1945
+ */
1869
1946
  @container starci-core-workspace-shell (max-width: 56rem) {
1870
- .starci-core-workspace-shell-layout,
1871
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="present"],
1872
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="absent"],
1873
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="absent"] {
1874
- grid-template-areas: "navigation" "primary" "rail";
1875
- grid-template-columns: minmax(0, 1fr);
1876
- }
1877
-
1878
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="present"] {
1879
- grid-template-areas: "rail" "primary";
1880
- }
1881
-
1882
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"] {
1883
- grid-template-areas: "primary" "rail";
1884
- }
1885
-
1886
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"][data-grammar-workspace-navigation="absent"] {
1887
- grid-template-areas: "rail" "primary";
1888
- }
1889
-
1890
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"] .starci-core-workspace-shell-leading-rule {
1891
- display: none;
1892
- }
1893
-
1894
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail-position="leading"] .starci-core-workspace-shell-primary {
1895
- padding-inline-start: 0;
1896
- }
1897
-
1898
- .starci-core-workspace-shell-layout[data-grammar-workspace-rail="absent"] {
1899
- grid-template-areas: "navigation" "primary";
1900
- }
1901
-
1902
- .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="absent"][data-grammar-workspace-rail="absent"] {
1903
- grid-template-areas: "primary";
1904
- }
1905
-
1906
1947
  .starci-core-workspace-shell-rail .starci-core-rail-frame {
1907
1948
  position: static;
1908
1949
  max-height: none;
@@ -2006,12 +2047,26 @@
2006
2047
  */
2007
2048
 
2008
2049
  /* --- Surface card: the card, its label row and its content shell are HeroUI `Card` parts. --- */
2050
+ /*
2051
+ * THE CARD'S OUTER BOX IS ITS BOUNDARY, exactly as the list's and the accordion's are.
2052
+ *
2053
+ * `SurfaceCard` is the only one of the three whose root is a HeroUI `Card`, and the vendor's
2054
+ * `.card` carries a 1rem padding of its own. That inset moved the card's visible surface AND
2055
+ * its label a further 16px inward, so a padded `SurfaceCard` and an unpadded
2056
+ * `SurfaceAccordionCard` standing in one column disagreed by 16px at both edges - two members
2057
+ * of one family drawing the same boundary in two places. The label row and the content shell
2058
+ * were already given `padding: 0 !important` here for the same reason; the root was missed.
2059
+ *
2060
+ * The card keeps its inset where the contract puts it: `PADDING-4` is claimed by the CONTENT
2061
+ * REGION inside the surface, which is where the reader's copy is held off the boundary.
2062
+ */
2009
2063
  .starci-core-surface-card {
2010
2064
  display: flex !important;
2011
2065
  width: 100% !important;
2012
2066
  min-width: 0;
2013
2067
  flex-direction: column !important;
2014
2068
  gap: var(--starci-core-section-gap, 0.75rem) !important;
2069
+ padding: 0 !important;
2015
2070
  }
2016
2071
 
2017
2072
  .starci-core-surface-label {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starci/grammar",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "Reusable StarCi React components, compositions, and packaged visual DNA.",
5
5
  "keywords": [
6
6
  "starci",
@@ -55,7 +55,7 @@
55
55
  "scripts": {
56
56
  "build": "node scripts/clean.mjs && tsc -p tsconfig.build.json && node scripts/copy-css.mjs",
57
57
  "typecheck": "tsc -p tsconfig.build.json --noEmit",
58
- "test": "npm run build && node --test src/common/index.test.mjs src/core/index.test.mjs src/package-boundary.test.mjs && vitest run --config vitest.config.ts src/shipped-geometry.spec.ts src/core/shipped-claims.spec.tsx src/common/conformance.spec.ts src/common/styles.spec.ts src/core/family.spec.tsx src/core/styles.spec.ts src/core/surface-card-family.spec.tsx src/core/scrollable-surfaces.spec.tsx src/core/primitive/Badge/index.spec.tsx src/core/primitive/Button/index.spec.tsx src/core/primitive/Divider/index.spec.tsx src/core/primitive/Heading/index.spec.tsx src/core/primitive/Icon/index.spec.tsx src/core/primitive/IconButton/index.spec.tsx src/core/primitive/IconTile/index.spec.tsx src/core/primitive/Input/index.spec.tsx src/core/primitive/PressableField/index.spec.tsx src/core/primitive/Progress/index.spec.tsx src/core/primitive/Text/index.spec.tsx src/core/primitive/TextAction/index.spec.tsx src/core/primitive/Label/index.spec.tsx src/core/primitive/RankArtwork/index.spec.tsx src/core/composite/EmptyNotice/index.spec.tsx src/core/branch/Tabs/index.spec.tsx src/core/branch/Subnav/index.spec.tsx src/core/branch/Tooltip/index.spec.tsx src/core/composition/NavigationFeatureNav/index.spec.tsx src/core/composition/NavigationFeatureNav/styles.spec.ts src/core/composition/Sidebar/index.spec.tsx src/core/composition/Sidebar/styles.spec.ts src/core/composition/WorkspaceShell/index.spec.tsx src/core/composition/ChatWorkspace/index.spec.tsx src/heritage/index.spec.tsx src/heritage/styles.spec.ts src/offset-pop/index.spec.tsx src/offset-pop/render.spec.tsx src/offset-pop/styles.spec.ts",
58
+ "test": "npm run build && node --test src/common/index.test.mjs src/core/index.test.mjs src/package-boundary.test.mjs && vitest run --config vitest.config.ts src/shipped-geometry.spec.ts src/core/shipped-claims.spec.tsx src/common/conformance.spec.ts src/common/styles.spec.ts src/core/family.spec.tsx src/core/styles.spec.ts src/core/surface-card-family.spec.tsx src/core/scrollable-surfaces.spec.tsx src/core/primitive/Badge/index.spec.tsx src/core/primitive/Button/index.spec.tsx src/core/primitive/Divider/index.spec.tsx src/core/primitive/Heading/index.spec.tsx src/core/primitive/Icon/index.spec.tsx src/core/primitive/IconButton/index.spec.tsx src/core/primitive/IconTile/index.spec.tsx src/core/primitive/Input/index.spec.tsx src/core/primitive/PressableField/index.spec.tsx src/core/primitive/Progress/index.spec.tsx src/core/primitive/Text/index.spec.tsx src/core/primitive/TextAction/index.spec.tsx src/core/primitive/Label/index.spec.tsx src/core/primitive/RankArtwork/index.spec.tsx src/core/composite/EmptyNotice/index.spec.tsx src/core/branch/Tabs/index.spec.tsx src/core/branch/Subnav/index.spec.tsx src/core/branch/Tooltip/index.spec.tsx src/core/composition/NavigationFeatureNav/index.spec.tsx src/core/composition/NavigationFeatureNav/styles.spec.ts src/core/composition/Sidebar/index.spec.tsx src/core/composition/Sidebar/styles.spec.ts src/core/composition/collapse.spec.tsx src/core/composition/WorkspaceShell/index.spec.tsx src/core/composition/ChatWorkspace/index.spec.tsx src/heritage/index.spec.tsx src/heritage/styles.spec.ts src/offset-pop/index.spec.tsx src/offset-pop/render.spec.tsx src/offset-pop/styles.spec.ts",
59
59
  "prepack": "npm run typecheck && npm test"
60
60
  },
61
61
  "engines": {