@semanticus/semanticus-css 1.2.0 → 2.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semanticus/semanticus-css",
3
- "version": "1.2.0",
3
+ "version": "2.0.0",
4
4
  "description": "lightweight CSS framework that prioritizes semantic HTML and ARIA-focused accessibility, with a small set of atomic utilities",
5
5
  "author": "Joao Goncalves",
6
6
  "style": "./dist/semanticus.css",
@@ -89,6 +89,7 @@
89
89
  "demo:server": "tsx --tsconfig scripts/tsconfig.json scripts/demo-server.ts",
90
90
  "test": "npx playwright test",
91
91
  "test:dev": "npx playwright test --ui",
92
+ "test:report": "npx playwright show-report --host 0.0.0.0",
92
93
  "test:update-snapshots": "npx playwright test -u",
93
94
  "kill-zombies": "sh -c 'PORT=${PORT:-4000}; pids=$(lsof -t -i :$PORT); if [ -n \"$pids\" ]; then echo \"Killing PIDs: $pids\"; kill -9 $pids; else echo \"No processes listening on port $PORT\"; fi'",
94
95
  "kill-playwright": "sh -c 'pgrep -af playwright | awk \"{print $1}\" | xargs -r kill -9 || true'",
@@ -41,4 +41,68 @@
41
41
  > :last-child:is(hgroup, h1, h2, h3, h4, h5, h6) {
42
42
  margin-bottom: 0;
43
43
  }
44
+
45
+ &:is(ul, [role="list"], [role="group"]) {
46
+ padding: 0;
47
+ border: none;
48
+
49
+ > * {
50
+ --color-background: transparent;
51
+ --card-item-fill: var(--color-background);
52
+ --border-color: color-mix(in srgb, light-dark(var(--color-slate-900), var(--color-zinc-350)), transparent 90%);
53
+
54
+ background: var(--card-item-fill);
55
+ color: var(--color-text);
56
+ margin: 0;
57
+ padding: var(--spacing);
58
+ border-radius: 0;
59
+ border: var(--border-size) solid var(--border-color);
60
+
61
+ &:first-child {
62
+ border-top-left-radius: var(--radius);
63
+ }
64
+
65
+ &:last-child {
66
+ border-bottom-right-radius: var(--radius);
67
+ }
68
+
69
+ &:is([aria-current]:not([aria-current="false"])) {
70
+ --card-item-fill: color-mix(in srgb, var(--color-background), var(--color-hover-effect) 15%);
71
+ }
72
+ }
73
+ }
74
+
75
+ &:is(ul, [role="list"]) {
76
+ display: flex;
77
+ flex-direction: column;
78
+
79
+ > * {
80
+ border-top: none;
81
+ list-style: none;
82
+
83
+ &:first-child {
84
+ border-top: var(--border-size) solid var(--border-color);
85
+ border-top-right-radius: var(--radius);
86
+ }
87
+
88
+ &:last-child {
89
+ border-bottom-left-radius: var(--radius);
90
+ }
91
+ }
92
+ }
93
+
94
+ &[role="group"] {
95
+ > * {
96
+ border-left: none;
97
+
98
+ &:first-child {
99
+ border-left: var(--border-size) solid var(--border-color);
100
+ border-bottom-left-radius: var(--radius);
101
+ }
102
+
103
+ &:last-child {
104
+ border-top-right-radius: var(--radius);
105
+ }
106
+ }
107
+ }
44
108
  }
@@ -0,0 +1,95 @@
1
+ /*!
2
+ * Content Grid
3
+ *
4
+ * A CSS Grid layout pattern that eliminates the need for container/wrapper divs.
5
+ * Inspired by Kevin Powell's content grid technique (https://www.youtube.com/watch?v=c13gpBrnGEw)
6
+ * and the original idea from Stephanie Eckles (smolcss.dev) and Ryan Mulligan.
7
+ *
8
+ * The grid provides three width levels for direct children:
9
+ * - content (default) — constrained to the content max-width
10
+ * - .breakout — wider than content, narrower than full-width
11
+ * - .full-width — edge-to-edge spanning the entire viewport
12
+ *
13
+ * .full-width elements also create a nested grid with the same column structure,
14
+ * so their children follow the same content / breakout / full-width rules.
15
+ */
16
+
17
+ .content-grid {
18
+ --content-grid-padding-inline: var(--spacing);
19
+ --content-grid-content-max-width: 70ch;
20
+ --content-grid-breakout-max-width: 90ch;
21
+
22
+ /* Internal computed value */
23
+ --content-grid-breakout-size: max(
24
+ 0px,
25
+ calc(
26
+ (var(--content-grid-breakout-max-width) - var(--content-grid-content-max-width)) / 2
27
+ )
28
+ );
29
+
30
+ display: grid;
31
+ grid-template-columns:
32
+ [full-width-start]
33
+ minmax(var(--content-grid-padding-inline), 1fr)
34
+ [breakout-start]
35
+ minmax(0px, var(--content-grid-breakout-size))
36
+ [content-start]
37
+ min(
38
+ var(--content-grid-content-max-width),
39
+ 100% - var(--content-grid-padding-inline) * 2
40
+ )
41
+ [content-end]
42
+ minmax(0px, var(--content-grid-breakout-size))
43
+ [breakout-end]
44
+ minmax(var(--content-grid-padding-inline), 1fr)
45
+ [full-width-end];
46
+ }
47
+
48
+ /* ── Default placement: all direct children → content column ── */
49
+ .content-grid > :not(.breakout, .full-width) {
50
+ grid-column: content;
51
+ }
52
+
53
+ /* ── Breakout: spans the breakout area (wider than content) ── */
54
+ .content-grid > .breakout {
55
+ grid-column: breakout;
56
+ }
57
+
58
+ /* ── Full-width: spans edge-to-edge, becomes a nested content grid ── */
59
+ .content-grid > .full-width {
60
+ grid-column: full-width;
61
+ display: grid;
62
+ grid-template-columns: inherit;
63
+ }
64
+
65
+ /* Children of any .full-width (at any nesting depth) follow the same rules */
66
+ .content-grid .full-width > :not(.breakout, .full-width) {
67
+ grid-column: content;
68
+ }
69
+
70
+ .content-grid .full-width > .breakout {
71
+ grid-column: breakout;
72
+ }
73
+
74
+ /* ── Nested full-width: spans edge-to-edge within any .full-width ancestor ── */
75
+ /*
76
+ * Instead of inheriting the full 5-track template (which starts with a gutter
77
+ * column), we define a single centered content-width column. This ensures that
78
+ * auto-placed items — including bare text nodes, which CSS selectors cannot
79
+ * target — land in the content column rather than the first gutter track.
80
+ *
81
+ * Trade-off: .breakout and .full-width children inside a nested .full-width
82
+ * will not span wider than the content column (graceful degradation).
83
+ */
84
+ .content-grid .full-width > .full-width {
85
+ grid-column: full-width;
86
+ display: grid;
87
+ grid-template-columns:
88
+ [full-width-start breakout-start content-start]
89
+ min(
90
+ var(--content-grid-content-max-width),
91
+ 100% - var(--content-grid-padding-inline) * 2
92
+ )
93
+ [content-end breakout-end full-width-end];
94
+ justify-content: center;
95
+ }
@@ -1,4 +1,4 @@
1
- [role="toolbar"] {
1
+ .grid {
2
2
  grid-column-gap: var(--spacing);
3
3
  grid-row-gap: var(--spacing);
4
4
  display: grid;
@@ -2,8 +2,8 @@
2
2
  [class^="icon-"],
3
3
  [class*=" icon-"] {
4
4
  display: inline-block;
5
- width: 1em;
6
- height: 1em;
5
+ min-width: 1em;
6
+ min-height: 1em;
7
7
  margin: 0;
8
8
  padding: 0;
9
9
  border: none;
@@ -14,7 +14,6 @@
14
14
  mask-size: contain;
15
15
  mask-repeat: no-repeat;
16
16
  vertical-align: -.199em;
17
- align-self: center;
18
17
  color: inherit;
19
18
  }
20
19
 
@@ -1,5 +1,6 @@
1
1
  @import "./_card.css";
2
- @import "./_card-list.css";
3
2
  @import "./_container.css";
3
+ @import "./_grid.css";
4
4
  @import "./_icons.css";
5
+ @import "./_content-grid.css";
5
6
  @import "./_sidebar.css";
package/src/index.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Semanticus CSS v1.2.0 (https://semanticus.design/)
2
+ * Semanticus CSS v2.0.0 (https://semanticus.design/)
3
3
  *
4
4
  * A ARIA-centric, semantic HTML — enhanced with components and variants and utilities
5
5
  *
@@ -6,8 +6,4 @@
6
6
  background-color: var(--color-background);
7
7
  height: unset;
8
8
  margin: unset;
9
-
10
- &:popover-open {
11
- display: block !important;
12
- }
13
9
  }
@@ -18,6 +18,7 @@
18
18
  margin-bottom: 0;
19
19
 
20
20
  &:not(:first-child) {
21
+ /* when a button is next to an input that has a border */
21
22
  margin-left: calc(var(--border-size) * -1);
22
23
  border-top-left-radius: 0;
23
24
  border-bottom-left-radius: 0;
@@ -8,6 +8,31 @@
8
8
  --alert-size: var(--border-size);
9
9
 
10
10
  color: var(--color-text);
11
+ display: grid;
12
+ grid-template-columns: 1fr;
13
+ gap: calc(var(--nav-link-gap) * 1.5);
14
+ align-items: start;
15
+
16
+ &:empty {
17
+ display: none;
18
+ }
19
+
20
+ &:has(> :nth-child(2):last-child) {
21
+ grid-template-columns: 1fr auto;
22
+
23
+ &:has(> :first-child:empty) {
24
+ display: none;
25
+ }
26
+ }
27
+
28
+ &:has(> :nth-child(3):last-child) {
29
+ grid-template-columns: auto 1fr auto;
30
+
31
+ &:has(> :nth-child(2):empty) {
32
+ display: none;
33
+ }
34
+ }
35
+
11
36
  padding: var(--spacing);
12
37
  margin-bottom: var(--spacing);
13
38
  border-radius: var(--radius);
@@ -20,6 +45,16 @@
20
45
  --alert-size: calc(var(--border-size) * 4);
21
46
  }
22
47
 
48
+ > * {
49
+ margin: 0 !important;
50
+ }
51
+
52
+ [class^="icon-"],
53
+ [class*=" icon-"] {
54
+ position: relative;
55
+ top: 4px;
56
+ }
57
+
23
58
  /* Opening animation using @starting-style (Chrome 117+, Firefox 129+, Safari 17.4+) */
24
59
  /* Gracefully degrades to instant appearance in unsupported browsers */
25
60
  transition: opacity 0.2s ease-in-out, top 0.2s ease-in-out, right 0.2s ease-in-out, left 0.2s ease-in-out, bottom 0.2s ease-in-out;
@@ -34,7 +69,7 @@
34
69
  margin: var(--spacing);
35
70
 
36
71
  &:popover-open {
37
- display: flex;
72
+ display: grid;
38
73
  }
39
74
 
40
75
  &[data-placement="top-start"] {
@@ -4,7 +4,6 @@ summary {
4
4
 
5
5
  details {
6
6
  display: block;
7
- margin-bottom: var(--spacing);
8
7
 
9
8
  & summary {
10
9
  line-height: 1rem;
@@ -5,7 +5,6 @@
5
5
  @import "./attributes/_role-group.css";
6
6
  @import "./attributes/_role-search.css";
7
7
  @import "./attributes/_role-status-alert.css";
8
- @import "./attributes/_role-toolbar.css";
9
8
  @import "./attributes/_role-tooltip.css";
10
9
 
11
10
  @import "./elements/_abbr.css";
@@ -1,60 +0,0 @@
1
- .card-list {
2
- border: none;
3
- display: flex;
4
- flex-direction: column;
5
- padding: 0;
6
- list-style: none;
7
-
8
- > * {
9
- --color-background: transparent;
10
- --card-fill: var(--color-background);
11
- --border-color: color-mix(in srgb, light-dark(var(--color-slate-900), var(--color-zinc-350)), transparent 90%);
12
-
13
- background: var(--card-fill);
14
- border-bottom: var(--border-size) solid var(--border-color);
15
- border-inline: var(--border-size) solid var(--border-color);
16
- color: var(--color-text);
17
- margin: 0;
18
- padding: var(--spacing);
19
- list-style: none;
20
-
21
- &:first-child {
22
- border-top: var(--border-size) solid var(--border-color);
23
- border-top-left-radius: var(--radius);
24
- border-top-right-radius: var(--radius);
25
- }
26
-
27
- &:last-child {
28
- border-bottom-left-radius: var(--radius);
29
- border-bottom-right-radius: var(--radius);
30
- }
31
-
32
- &:is([aria-current]:not([aria-current="false"])) {
33
- --card-fill: color-mix(in srgb, var(--color-background), var(--color-hover-effect) 15%);
34
- }
35
- }
36
-
37
- nav & {
38
- gap: 0;
39
- flex-direction: row;
40
-
41
- > * {
42
- flex: 1 1 0;
43
- text-align: center;
44
- border-top: var(--border-size) solid var(--border-color);
45
- border-left: none;
46
- white-space: nowrap;
47
-
48
- &:first-child {
49
- border-left: var(--border-size) solid var(--border-color);
50
- border-bottom-left-radius: var(--radius);
51
- border-top-right-radius: 0;
52
- }
53
-
54
- &:last-child {
55
- border-top-right-radius: var(--radius);
56
- border-bottom-left-radius: 0;
57
- }
58
- }
59
- }
60
- }