@anydigital/blades 0.27.0-beta.8 → 0.28.0-alpha

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/assets/blades.css CHANGED
@@ -2,40 +2,43 @@
2
2
 
3
3
  /* Layout */
4
4
 
5
- /*
6
- <!--section:docs-->
7
-
8
- ### Document
9
- Extends https://github.com/picocss/pico/blob/main/scss/layout/_document.scss
5
+ /* Extends https://github.com/picocss/pico/blob/main/scss/layout/
6
+ <!--section:docs-intro-->
10
7
 
11
- Prevent horizontal overflow and scrolling, modern way:
8
+ Global styles:
12
9
  ```css */
13
10
 
14
11
  html {
12
+ /* Prevent horizontal overflow and scrolling, modern way. */
15
13
  overflow-x: clip;
16
14
  }
17
15
 
18
- /*```
16
+ body {
17
+ /* Ensure `body` takes at least the full height of the viewport (using dynamic viewport height for better mobile support). */
18
+ min-height: 100dvh;
19
+ }
19
20
 
20
- ### Landmarks
21
- Extends https://github.com/picocss/pico/blob/main/scss/layout/_landmarks.scss
21
+ /*```
22
+ <!--section:docs-->
22
23
 
23
- 1. Ensure `body` takes at least the full height of the viewport (using dynamic viewport height for better mobile support).
24
- 2. Make the `body` a flex container with column layout, and `main` to automatically fill available space. This is useful for creating sticky footers and full-height layouts.
24
+ ### Auto-columns
25
25
  ```css */
26
26
 
27
- body {
28
- min-height: 100dvh;
27
+ .columns,
28
+ [data-is-toc] > ul,
29
+ [data-is-toc] > ol {
30
+ columns: 30ch auto; /* 2 cols max for 65ch container */
29
31
 
30
- display: flex;
31
- flex-direction: column;
32
- > main {
33
- flex-grow: 1;
32
+ /* Avoid breaking inside elements, such as nested lists */
33
+ > * {
34
+ break-inside: avoid;
34
35
  }
35
36
  }
36
37
 
37
38
  /*```
38
39
 
40
+ Table of contents (`[data-is-toc]`) has auto-columns by default.
41
+
39
42
  ### Jump to top
40
43
  ```css */
41
44
 
@@ -137,10 +140,14 @@ body {
137
140
  }
138
141
  }
139
142
 
140
- /*```<!--section:docs-->
143
+ /*```
144
+ <!--section:docs,summary-->
145
+
141
146
  Framework-agnostic utilities for breaking out images and figures beyond their container width.
142
147
 
143
- Use the `.breakout` class to allow elements to extend beyond their parent container:
148
+ Use the `.breakout` class to allow elements to extend beyond their parent container.
149
+
150
+ <!--section:docs-->
144
151
 
145
152
  ```html
146
153
  <div class="breakout">
@@ -149,12 +156,13 @@ Use the `.breakout` class to allow elements to extend beyond their parent contai
149
156
  ```
150
157
 
151
158
  The breakout container has `10%` inline padding and a max-width of `calc(10% + 65ch + 10%)`. The breakout utilities support images, pictures, figures, canvas, audio, video, tables, pre, iframe, and other media elements. Tables inside `.breakout` are specifically enhanced for horizontal scrolling and full-bleed mobile display. This is automatically included when you import the stylesheet.
159
+
152
160
  <!--section--> */
153
161
 
154
162
  /* Content */
155
163
 
156
164
  /* Extends https://github.com/picocss/pico/blob/main/scss/content/_typography.scss
157
- <!--section:docs-->
165
+ <!--section:docs-intro-->
158
166
 
159
167
  Global styles:
160
168
  ```css */
@@ -166,6 +174,8 @@ html {
166
174
  }
167
175
 
168
176
  body {
177
+ /* Evaluates the last ~4 lines of text blocks to prevent a single word from sitting on the final line. */
178
+ text-wrap: pretty;
169
179
  /* Enable global hyphenation */
170
180
  hyphens: auto;
171
181
  /* ... except for links and tables which are better (safer) without hyphenation */
@@ -176,6 +186,7 @@ body {
176
186
  }
177
187
 
178
188
  /*```
189
+ <!--section:docs-->
179
190
 
180
191
  ### Heading anchors
181
192
 
@@ -195,13 +206,14 @@ h6 {
195
206
  position: relative;
196
207
 
197
208
  [data-is-anchor] {
198
- visibility: hidden;
199
209
  position: absolute;
200
- top: 0;
201
210
  right: 100%;
211
+ top: 50%;
212
+ transform: translateY(-50%);
202
213
  padding-right: 0.2ch;
203
214
  color: silver;
204
215
  text-decoration: none;
216
+ visibility: hidden;
205
217
  }
206
218
  /* Avoid double-tap on touch devices */
207
219
  @media (hover: hover) {
@@ -249,14 +261,20 @@ ol {
249
261
  /* ⚠️ `data-marker` works only in Chrome and Firefox */
250
262
  content: attr(data-marker) " ";
251
263
  }
264
+ }
252
265
 
253
- /* Helper class to remove list styling at all */
254
- &.unlist {
255
- padding-inline-start: 0;
266
+ /*```
256
267
 
257
- > li {
258
- list-style: none;
259
- }
268
+ ### Unlist
269
+
270
+ Helper class to remove list styling at all:
271
+ ```css */
272
+
273
+ .unlist {
274
+ padding-inline-start: 0;
275
+
276
+ > li {
277
+ list-style: none;
260
278
  }
261
279
  }
262
280
 
@@ -268,24 +286,32 @@ ol {
268
286
  ```css */
269
287
 
270
288
  a {
271
- /* Helper to handle icons in links */
289
+ /* Use inline flex only if link contains an icon */
290
+ &:has(> i) {
291
+ display: inline-flex;
292
+ gap: 0.375ch; /* =3/8 */
293
+ overflow-y: clip; /* to work in pair with text-underline-offset in Safari */
294
+ }
272
295
  > i {
273
- display: inline-block;
274
296
  font-style: normal;
275
- }
276
-
277
- /* Helper for favicons in links */
278
- &[data-has-favicon] {
279
- display: inline-block;
297
+ float: left; /* ✅ Chrome ❌ Safari */
298
+ text-underline-offset: -2em; /* ❌ Chrome ✅ Safari - to clip it with overflow-y */
280
299
 
300
+ /* Favicons */
281
301
  > img {
282
- max-height: 1.25em;
283
- margin-top: calc(-0.25em / 2);
284
- margin-inline-end: 0.375ch; /* =3/8 */
302
+ height: 1.25em;
303
+ margin-block: calc(-0.25em / 2);
304
+ display: inline-block; /* for Tailwind CSS Typography */
305
+ }
285
306
 
286
- /* for tw-typography (.prose) */
287
- display: inline-block;
288
- margin-bottom: 0;
307
+ /* Font Awesome */
308
+ &[class^="fa-"],
309
+ &[class*=" fa-"] {
310
+ line-height: inherit;
311
+ --fa-width: auto;
312
+ }
313
+ &.fa-lg {
314
+ line-height: normal;
289
315
  }
290
316
  }
291
317
  }
@@ -293,23 +319,23 @@ a {
293
319
  /*```
294
320
  > **PRO-TIP** for 11ty: https://blades.ninja/build-awesome-11ty/processors/#auto-link-favicons
295
321
 
296
- <!--section:docs-->
322
+ <!--section:docs,summary-->
323
+
324
+ Use Blades' `<i>`-helper to wrap emojis, favicons, or simply drop Font Awesome icons inside links. It automatically handles sizing and alignment while preventing underline on icons.
297
325
 
298
- ### Link [fav]icons
326
+ <!--section:docs-->
299
327
 
300
- Wrap icons inside links using `<i>...&nbsp;</i>` helper to avoid underline. Compare:
328
+ Compare:
301
329
 
302
- <big class="grid">
303
- <article><a href="https://github.com/anydigital/blades"> 🥷 Blades</a></article>
304
- <article><a href="https://github.com/anydigital/blades"><i>🥷&nbsp;</i>Blades</a></article>
305
- </big>
330
+ | Without Blades <hr class="lg"> | With Blades' `<i>`-helper <hr class="lg"> | Clean HTML without `<span>ning` <hr class="x2"> |
331
+ | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
332
+ | [🥷 Link with emoji](#) | [<i>🥷</i> Link with emoji](#) | `<a><i>🥷</i> Text</a>` |
333
+ | [![](https://www.google.com/s2/favicons?domain=any.digital&sz=64) Multi-line link <br> with favicon](#) | [<i>![](https://www.google.com/s2/favicons?domain=any.digital&sz=64)</i> Multi-line link <br> with favicon](#) | `<a><i><img src="..."></i> Text</a>` |
334
+ | [<b class="fa-brands fa-github fa-lg"></b> Link with Font Awesome icon](#) | [<i class="fa-brands fa-github fa-lg"></i> Link with Font Awesome icon](#) | `<a><i class="fa-..."></i> Text</a>` |
306
335
 
307
- Use `data-has-favicon` helper attribute on plain-text links containing `<img>`-favicon for better alignment. Compare:
336
+ ---
308
337
 
309
- <big class="grid">
310
- <article><a href="https://github.com/anydigital/blades" ><img src="https://www.google.com/s2/favicons?domain=github.com&amp;sz=64">/anydigital/blades</a></article>
311
- <article><a href="https://github.com/anydigital/blades" data-has-favicon><img src="https://www.google.com/s2/favicons?domain=github.com&amp;sz=64">/anydigital/blades</a></article>
312
- </big>
338
+ [How we made it ↗ &nbsp;<small>(on Codepen)</small>](https://codepen.io/editor/anydigital/pen/019d2b94-5616-75dc-a23e-e111869d5237){role=button .outline}
313
339
 
314
340
  <!--section--> */
315
341
 
@@ -349,6 +375,9 @@ table {
349
375
  margin: 0;
350
376
  visibility: hidden;
351
377
 
378
+ &.lg {
379
+ width: 18ch;
380
+ }
352
381
  &.x2 {
353
382
  width: 24ch;
354
383
  }
@@ -357,8 +386,6 @@ table {
357
386
  }
358
387
 
359
388
  /*```
360
- ---
361
-
362
389
  ### Borderless table
363
390
 
364
391
  `<table class="borderless">` removes all default borders:
@@ -416,21 +443,24 @@ Soft-increase selector specificity trick:
416
443
 
417
444
  `table:not(.does-not-exist)` (inspired by postcss) is used here to increase specificity against selectors like `&:is(table, .table)`
418
445
 
419
- <!--section:docs-->
446
+ <!--section:docs,summary-->
447
+
448
+ `<table class="responsive">` allows a table to full-bleed and scroll on mobile.
420
449
 
421
- `<table class="responsive">` allows a table to full-bleed and scroll on mobile:
422
- <hr><div>
450
+ <!--section:docs-->
423
451
 
424
- | Term | Description <hr class="x2"> | Link |
425
- | --- | --- | --- |
452
+ | Term | Description <hr class="x2"> | Link |
453
+ | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
426
454
  | Responsive design | Approach to web design that aims to make web pages render well on a variety of devices and window or screen sizes from minimum to maximum display size to ensure usability and satisfaction. | https://en.wikipedia.org/wiki/Responsive_web_design |
427
455
 
428
456
  {.responsive}
429
- </div><hr>
457
+
458
+ ---
430
459
 
431
460
  Tables inside https://blades.ninja/css/breakout/ are responsive by default.
432
461
 
433
462
  Living examples:
463
+
434
464
  - https://any.digital/insights/ai-ide/
435
465
  - https://any.digital/insights/css-frameworks/
436
466
  - https://any.digital/insights/ssg/
@@ -487,28 +517,59 @@ code {
487
517
 
488
518
  /*``` <!--section--> */
489
519
 
490
- /* Utilities */
520
+ /* Forms */
491
521
 
492
- /*
522
+ /* Moved here from https://github.com/anydigital/float-label-css for easier maintenance
493
523
  <!--section:docs-->
494
524
 
495
- ### Auto-columns
525
+ First, we target either:
526
+ 1. `<label>` which `:has` inner form inputs (classless approach)
527
+ 2. or explicit `.has-float-label` class (alternative approach)
496
528
  ```css */
497
529
 
498
- .columns,
499
- [data-is-toc] > ul,
500
- [data-is-toc] > ol {
501
- columns: 30ch auto; /* 2 cols max for 65ch container */
502
-
503
- /* Avoid breaking inside elements, such as nested lists */
504
- > * {
505
- break-inside: avoid;
530
+ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
531
+ .has-float-label {
532
+ display: block;
533
+ position: relative;
534
+ /*
535
+ ```
536
+ Then, we define the default/fallback state (when the float label should be minimized):
537
+ ```css */
538
+ > span,
539
+ label {
540
+ position: absolute;
541
+ left: 0;
542
+ top: 0;
543
+ cursor: text;
544
+ font-size: 75%;
545
+ }
546
+ /*
547
+ ```
548
+ Finally, we detect if placeholder is shown, but not in focus. That means we can safely hide it, and enlarge the float label instead:
549
+ ```css */
550
+ *:placeholder-shown:not(:focus)::placeholder {
551
+ opacity: 0;
552
+ }
553
+ &:has(*:placeholder-shown:not(:focus)) {
554
+ > span,
555
+ label {
556
+ font-size: inherit;
557
+ opacity: 50%;
558
+ }
506
559
  }
507
560
  }
508
561
 
509
- /*```
562
+ /*
563
+ ```
564
+ The `:has(*:placeholder-shown:not(:focus))` trick allows this input state information to *propagate* to the parent level. This enables modern CSS to target inner float label (`<span>` or `<label>`) regardless of its position relative to the input field.
510
565
 
511
- Table of contents (`[data-is-toc]`) has auto-columns by default.
566
+ Historically, this was not possible: the float label had to be placed after the input field to be targeted using the `input:focus + label` selector.
567
+ <!--section--> */
568
+
569
+ /* Utilities */
570
+
571
+ /*
572
+ <!--section:docs-->
512
573
 
513
574
  ### Auto-dark
514
575
  ```css */
@@ -523,7 +584,7 @@ Table of contents (`[data-is-toc]`) has auto-columns by default.
523
584
 
524
585
  /*```
525
586
 
526
- ### Misc
587
+ ### Faded
527
588
  ```css */
528
589
 
529
590
  .faded {
@@ -533,6 +594,11 @@ Table of contents (`[data-is-toc]`) has auto-columns by default.
533
594
  }
534
595
  }
535
596
 
597
+ /*```
598
+
599
+ ### Invert
600
+ ```css */
601
+
536
602
  /* Extends https://tailwindcss.com/docs/filter-invert */
537
603
 
538
604
  .invert {
@@ -543,3 +609,147 @@ Table of contents (`[data-is-toc]`) has auto-columns by default.
543
609
  }
544
610
 
545
611
  /*``` <!--section--> */
612
+
613
+ /* <!--section:code-->
614
+ ```css */
615
+
616
+ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
617
+ .has-float-label {
618
+ /* Default/fallback state */
619
+ > span,
620
+ label {
621
+ padding-inline-start: calc(1rem + 1px); /* match Pico's padding + border */
622
+ padding-block-start: 0.25rem;
623
+ opacity: 75%;
624
+ transition: all 0.25s;
625
+ }
626
+ input,
627
+ textarea,
628
+ select {
629
+ margin-block-start: 0; /* reset Pico */
630
+ padding-inline-start: 1rem; /* match Pico */
631
+ padding-block: 1.125rem 0.375rem; /* match Pico's total: 2 x 0.75rem = 1.5rem */
632
+
633
+ &::placeholder {
634
+ opacity: 100%;
635
+ transition: all 0.25s;
636
+ }
637
+ }
638
+
639
+ /* Enlarged state */
640
+ &:has(*:placeholder-shown:not(:focus)) {
641
+ > span,
642
+ label {
643
+ padding-block: 0.75rem; /* match Pico */
644
+ }
645
+ }
646
+ }
647
+
648
+ body {
649
+ /* Make the `body` a flex container with column layout, and `main` to automatically fill available space. This is useful for creating sticky footers and full-height layouts. */
650
+ display: flex;
651
+ flex-direction: column;
652
+ > main {
653
+ flex-grow: 1;
654
+ }
655
+ }
656
+
657
+ a {
658
+ &:not([href^="#"]) {
659
+ text-decoration-thickness: 1px;
660
+ &:hover {
661
+ text-decoration-thickness: 2px;
662
+ }
663
+ }
664
+ }
665
+
666
+ h1 {
667
+ font-size: 2.5em; /* for pico.css & tw-typography */
668
+ margin-bottom: 1rem; /* for tw-typography */
669
+ }
670
+
671
+ /* Potential fix https://github.com/picocss/pico/blob/main/css/pico.css for the very first headings
672
+ :where(article, address, blockquote, dl, figure, form, ol, p, pre, table, ul) ~ :is(h1, h2, h3, h4, h5, h6) {
673
+ margin-top: var(--pico-typography-spacing-top);
674
+ }
675
+ h1,
676
+ h2,
677
+ h3,
678
+ h4,
679
+ h5,
680
+ h6 {
681
+ & ~ & {
682
+ margin-bottom: 2rem;
683
+ }
684
+ }
685
+ NOTE: be careful with wrapped headings, i.e. inside nav: https://blades.ninja/build-awesome-11ty/#usage
686
+ */
687
+
688
+ hr {
689
+ margin-block: 2em; /* for pico.css & tw-typography */
690
+ }
691
+
692
+ ul {
693
+ ul {
694
+ font-size: 87.5%;
695
+ }
696
+ }
697
+
698
+ pre {
699
+ small {
700
+ opacity: 75%;
701
+ font-weight: lighter;
702
+ }
703
+ }
704
+
705
+ table {
706
+ th {
707
+ vertical-align: bottom;
708
+ font-weight: bold;
709
+ }
710
+ td {
711
+ vertical-align: top;
712
+ }
713
+ pre {
714
+ margin-bottom: 0.25rem;
715
+ }
716
+ }
717
+
718
+ [data-jump-to="top"] {
719
+ > i {
720
+ display: inline-block;
721
+ padding: 0.25rem 0.375rem;
722
+ margin: 0.5rem;
723
+ font-size: 0.75rem;
724
+ color: black;
725
+ border-color: black;
726
+ }
727
+ }
728
+
729
+ [data-is-toc] {
730
+ font-size: 87.5%;
731
+
732
+ a {
733
+ text-decoration: none;
734
+ }
735
+ > ul > * > a {
736
+ font-weight: 500;
737
+ }
738
+ }
739
+
740
+ .breakout,
741
+ .breakout-all {
742
+ > img,
743
+ > figure {
744
+ margin-bottom: 1rem;
745
+ }
746
+ }
747
+
748
+ .faded {
749
+ a {
750
+ text-decoration-style: dotted;
751
+ }
752
+ }
753
+
754
+ /*```
755
+ <!--section--> */
@@ -1,3 +1,44 @@
1
+ /* <!--section:code-->
2
+ ```css */
3
+ label:has(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select),
4
+ .has-float-label {
5
+ /* Default/fallback state */
6
+ > span,
7
+ label {
8
+ padding-inline-start: calc(1rem + 1px); /* match Pico's padding + border */
9
+ padding-block-start: 0.25rem;
10
+ opacity: 75%;
11
+ transition: all 0.25s;
12
+ }
13
+ input,
14
+ textarea,
15
+ select {
16
+ margin-block-start: 0; /* reset Pico */
17
+ padding-inline-start: 1rem; /* match Pico */
18
+ padding-block: 1.125rem 0.375rem; /* match Pico's total: 2 x 0.75rem = 1.5rem */
19
+
20
+ &::placeholder {
21
+ opacity: 100%;
22
+ transition: all 0.25s;
23
+ }
24
+ }
25
+
26
+ /* Enlarged state */
27
+ &:has(*:placeholder-shown:not(:focus)) {
28
+ > span,
29
+ label {
30
+ padding-block: 0.75rem; /* match Pico */
31
+ }
32
+ }
33
+ }
34
+ body {
35
+ /* Make the `body` a flex container with column layout, and `main` to automatically fill available space. This is useful for creating sticky footers and full-height layouts. */
36
+ display: flex;
37
+ flex-direction: column;
38
+ > main {
39
+ flex-grow: 1;
40
+ }
41
+ }
1
42
  a {
2
43
  &:not([href^="#"]) {
3
44
  text-decoration-thickness: 1px;
@@ -6,29 +47,40 @@ a {
6
47
  }
7
48
  }
8
49
  }
9
-
10
50
  h1 {
11
51
  font-size: 2.5em; /* for pico.css & tw-typography */
12
52
  margin-bottom: 1rem; /* for tw-typography */
13
53
  }
14
-
54
+ /* Potential fix https://github.com/picocss/pico/blob/main/css/pico.css for the very first headings
55
+ :where(article, address, blockquote, dl, figure, form, ol, p, pre, table, ul) ~ :is(h1, h2, h3, h4, h5, h6) {
56
+ margin-top: var(--pico-typography-spacing-top);
57
+ }
58
+ h1,
59
+ h2,
60
+ h3,
61
+ h4,
62
+ h5,
63
+ h6 {
64
+ & ~ & {
65
+ margin-bottom: 2rem;
66
+ }
67
+ }
68
+ NOTE: be careful with wrapped headings, i.e. inside nav: https://blades.ninja/build-awesome-11ty/#usage
69
+ */
15
70
  hr {
16
71
  margin-block: 2em; /* for pico.css & tw-typography */
17
72
  }
18
-
19
73
  ul {
20
74
  ul {
21
75
  font-size: 87.5%;
22
76
  }
23
77
  }
24
-
25
78
  pre {
26
79
  small {
27
80
  opacity: 75%;
28
81
  font-weight: lighter;
29
82
  }
30
83
  }
31
-
32
84
  table {
33
85
  th {
34
86
  vertical-align: bottom;
@@ -41,18 +93,16 @@ table {
41
93
  margin-bottom: 0.25rem;
42
94
  }
43
95
  }
44
-
45
96
  [data-jump-to="top"] {
46
97
  > i {
47
98
  display: inline-block;
48
- padding: 0.25rem;
99
+ padding: 0.25rem 0.375rem;
49
100
  margin: 0.5rem;
50
101
  font-size: 0.75rem;
51
102
  color: black;
52
103
  border-color: black;
53
104
  }
54
105
  }
55
-
56
106
  [data-is-toc] {
57
107
  font-size: 87.5%;
58
108
 
@@ -63,7 +113,6 @@ table {
63
113
  font-weight: 500;
64
114
  }
65
115
  }
66
-
67
116
  .breakout,
68
117
  .breakout-all {
69
118
  > img,
@@ -71,9 +120,10 @@ table {
71
120
  margin-bottom: 1rem;
72
121
  }
73
122
  }
74
-
75
123
  .faded {
76
124
  a {
77
125
  text-decoration-style: dotted;
78
126
  }
79
127
  }
128
+ /*```
129
+ <!--section--> */
@@ -78,10 +78,14 @@
78
78
  }
79
79
  }
80
80
  }
81
- /*```<!--section:docs-->
81
+ /*```
82
+ <!--section:docs,summary-->
83
+
82
84
  Framework-agnostic utilities for breaking out images and figures beyond their container width.
83
85
 
84
- Use the `.breakout` class to allow elements to extend beyond their parent container:
86
+ Use the `.breakout` class to allow elements to extend beyond their parent container.
87
+
88
+ <!--section:docs-->
85
89
 
86
90
  ```html
87
91
  <div class="breakout">
@@ -90,4 +94,5 @@ Use the `.breakout` class to allow elements to extend beyond their parent contai
90
94
  ```
91
95
 
92
96
  The breakout container has `10%` inline padding and a max-width of `calc(10% + 65ch + 10%)`. The breakout utilities support images, pictures, figures, canvas, audio, video, tables, pre, iframe, and other media elements. Tables inside `.breakout` are specifically enhanced for horizontal scrolling and full-bleed mobile display. This is automatically included when you import the stylesheet.
97
+
93
98
  <!--section--> */