@anydigital/blades 0.27.0-alpha.10

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.
@@ -0,0 +1,322 @@
1
+ /**
2
+ * @anydigital/blades
3
+ * Framework-agnostic CSS utility helpers
4
+ */
5
+
6
+ html {
7
+ /* Prevent horizontal overflow and scrolling, modern way */
8
+ overflow-x: clip;
9
+
10
+ /* Font smoothing */
11
+ -webkit-font-smoothing: antialiased;
12
+ -moz-osx-font-smoothing: grayscale;
13
+ }
14
+
15
+ body {
16
+ /* Ensures body takes at least the full height of the viewport (using dynamic viewport height for better mobile support) */
17
+ min-height: 100dvh;
18
+
19
+ /* Make the body a flex container with column layout; main fills space */
20
+ display: flex;
21
+ flex-direction: column;
22
+ > main {
23
+ flex-grow: 1;
24
+ }
25
+
26
+ /* Hyphenation */
27
+ hyphens: auto;
28
+ /* Links and tables are better (safer) without hyphenation */
29
+ a,
30
+ table {
31
+ hyphens: none;
32
+ }
33
+ }
34
+
35
+ pre {
36
+ padding: 1rem 1.5rem;
37
+ padding-inline-end: 2rem;
38
+
39
+ code {
40
+ padding: 0;
41
+ }
42
+
43
+ @media screen and (max-width: 767px) {
44
+ border-radius: 0;
45
+ }
46
+ }
47
+
48
+ small {
49
+ [role="button"] {
50
+ padding: 0.75em 1em;
51
+ font-size: inherit;
52
+ }
53
+ }
54
+
55
+ /* Breakout CSS - Framework-agnostic utilities for breaking out images and figures */
56
+
57
+ .breakout,
58
+ .breakout-all {
59
+ /* Prepare the container for breakout elements */
60
+ padding-inline: 10%;
61
+ max-width: calc(10% + 65ch + 10%);
62
+
63
+ /* Breakout direct children only */
64
+ & > * {
65
+ &:is(
66
+ table,
67
+ pre,
68
+ figure, video, iframe, canvas,
69
+ img, picture,
70
+ /* Custom utility classes for other tags that need to be broken out */
71
+ .breakout-item,
72
+ .breakout-item-max
73
+ ) {
74
+ width: fit-content;
75
+ min-width: 100%;
76
+ max-width: 125%;
77
+ margin-left: 50%;
78
+ transform: translateX(-50%);
79
+ }
80
+
81
+ /* Respect img/picture min-width */
82
+ &:is(img, picture) {
83
+ min-width: auto;
84
+ }
85
+
86
+ /* <!--section:responsive-table-without-wrapper-->
87
+ ### Responsive tables without wrapper
88
+ ```css */
89
+ &:is(table):not(.does-not-exist) {
90
+ /* Let them full-bleed */
91
+ width: max-content;
92
+ min-width: auto;
93
+ max-width: 100vw;
94
+ padding-inline: 7.5%;
95
+
96
+ /* Let them scroll */
97
+ display: block;
98
+ overflow-x: auto;
99
+ -webkit-overflow-scrolling: touch; /* Smooth scroll for iOS */
100
+
101
+ th,
102
+ td {
103
+ padding-inline-start: 0;
104
+ }
105
+ }
106
+ /*```
107
+ #### Soft-increase selector specificity
108
+ `&:is(table):not(.does-not-exist)` trick (inspired by postcss) is used here to increase specificity against selectors like `&:is(table, .table)`
109
+ <!--section--> */
110
+
111
+ /* Max out the width of the element */
112
+ &.breakout-item-max {
113
+ width: 125% !important; /* !important is for cases like figure.breakout-item-max @TODO */
114
+ }
115
+ }
116
+ }
117
+
118
+ .breakout-all > * {
119
+ &:is(h2, h3, h4, hr):not([class]) {
120
+ position: relative;
121
+
122
+ &::before {
123
+ content: "";
124
+ display: block;
125
+ position: absolute;
126
+ background: gray;
127
+ opacity: 12.5%;
128
+ }
129
+ }
130
+
131
+ &:is(h2, h3, h4):not([class]) {
132
+ &::before {
133
+ width: 10em;
134
+ right: 100%;
135
+ margin-right: 0.8ch;
136
+ height: 0.25em;
137
+ top: 50%;
138
+ transform: translateY(-50%);
139
+ background: linear-gradient(to left, gray, transparent);
140
+ }
141
+
142
+ /* @TODO: add to tricks-wiki why `*` works here, but `&` fails */
143
+ &:where(hr + *) {
144
+ &::before {
145
+ display: none !important;
146
+ }
147
+ }
148
+ }
149
+ &:is(hr) {
150
+ height: 0.5rem;
151
+ border: none;
152
+ overflow: visible;
153
+
154
+ &::before {
155
+ width: 100vw;
156
+ left: 50%;
157
+ height: 100%;
158
+ transform: translateX(-50%);
159
+ }
160
+ }
161
+ }
162
+
163
+ /* Prism.js */
164
+
165
+ .token.treeview-part {
166
+ .entry-line {
167
+ width: 2.5em !important;
168
+ opacity: 25%;
169
+ }
170
+ .entry-name:last-child {
171
+ opacity: 50%;
172
+
173
+ &::before {
174
+ display: none !important;
175
+ }
176
+ }
177
+ }
178
+
179
+ table {
180
+ /* Workaround to widen particular columns @TODO: add to tricks-wiki */
181
+ th {
182
+ hr {
183
+ width: 12ch; /* min ~65/12 = ~5 cols */
184
+ height: 0;
185
+ margin: 0;
186
+ visibility: hidden;
187
+ }
188
+ }
189
+ }
190
+
191
+ table.borderless {
192
+ th,
193
+ td {
194
+ border: none;
195
+ }
196
+ }
197
+
198
+ /* Header anchors @TODO: add to tricks-wiki */
199
+
200
+ h1,
201
+ h2,
202
+ h3,
203
+ h4,
204
+ h5,
205
+ h6 {
206
+ position: relative;
207
+
208
+ [data-is-anchor] {
209
+ visibility: hidden;
210
+ position: absolute;
211
+ top: 0;
212
+ right: 100%;
213
+ padding-right: 0.2ch;
214
+ color: silver;
215
+ text-decoration: none;
216
+ }
217
+ &:hover {
218
+ [data-is-anchor] {
219
+ visibility: visible;
220
+ }
221
+ }
222
+ }
223
+
224
+ /* Helper to handle icons in links */
225
+
226
+ a > i {
227
+ display: inline-block;
228
+ margin-inline-end: 0.375ch; /* =3/8 */
229
+ font-style: normal;
230
+ }
231
+
232
+ /* Favicons in links @TODO: add to tricks-wiki */
233
+
234
+ a[data-has-favicon] {
235
+ display: inline-block;
236
+
237
+ > img {
238
+ max-height: 1.25em;
239
+ margin-top: calc(-0.25em / 2);
240
+ margin-inline-end: 0.375ch; /* =3/8 */
241
+
242
+ /* for tw-typography (.prose) */
243
+ display: inline-block;
244
+ margin-bottom: 0;
245
+ }
246
+ }
247
+
248
+ code[data-caption] {
249
+ &::before {
250
+ content: attr(data-caption);
251
+ display: block;
252
+ margin-bottom: 1rem;
253
+ opacity: 50%;
254
+ font-style: italic;
255
+ }
256
+ }
257
+
258
+ /* Tailwind tricks */
259
+
260
+ .invert {
261
+ /* Fix the scrollbar color when inverted */
262
+ ::-webkit-scrollbar {
263
+ filter: invert(1) !important;
264
+ }
265
+ }
266
+
267
+ /* Jump to top trick */
268
+
269
+ [data-jump-to="top"] {
270
+ position: fixed;
271
+ bottom: 0;
272
+ right: 0;
273
+ padding-top: 50vh;
274
+ opacity: 25%;
275
+
276
+ &:hover {
277
+ opacity: 75%;
278
+ }
279
+ }
280
+
281
+ /* Table of contents */
282
+
283
+ [data-is-toc] {
284
+ font-size: 87.5%;
285
+
286
+ a {
287
+ text-decoration: none;
288
+ }
289
+ > ul {
290
+ columns: 30ch auto; /* 2 cols max for 65ch container */
291
+ }
292
+ }
293
+
294
+ /* @TODO: to TRICKS */
295
+
296
+ .columns {
297
+ columns: 20ch auto; /* 3 cols max for 65ch container */
298
+ }
299
+
300
+ /* @TODO: to TRICKS */
301
+
302
+ ul,
303
+ ol {
304
+ li[data-marker]::marker {
305
+ content: attr(data-marker) " ";
306
+ }
307
+ }
308
+
309
+ .faded {
310
+ opacity: 50%;
311
+ &:hover {
312
+ opacity: 87.5%;
313
+ }
314
+ }
315
+
316
+ @media (prefers-color-scheme: dark) {
317
+ :root:not([data-theme="light"]) {
318
+ .dark-auto {
319
+ filter: invert(100%) hue-rotate(180deg);
320
+ }
321
+ }
322
+ }
@@ -0,0 +1,74 @@
1
+ a {
2
+ &:not([href^="#"]) {
3
+ text-decoration-thickness: 1px;
4
+ &:hover {
5
+ text-decoration-thickness: 2px;
6
+ }
7
+ }
8
+ }
9
+
10
+ h1 {
11
+ font-size: 2.5em; /* for pico.css & tw-typography */
12
+ margin-bottom: 1rem; /* for tw-typography */
13
+ }
14
+
15
+ hr {
16
+ margin-block: 2em; /* for pico.css & tw-typography */
17
+ }
18
+
19
+ ul {
20
+ ul {
21
+ font-size: 87.5%;
22
+ }
23
+ }
24
+
25
+ pre {
26
+ small {
27
+ opacity: 75%;
28
+ font-weight: lighter;
29
+ }
30
+ }
31
+
32
+ table {
33
+ th {
34
+ vertical-align: bottom;
35
+ font-weight: bold;
36
+ }
37
+ td {
38
+ vertical-align: top;
39
+ }
40
+ pre {
41
+ margin-bottom: 0.25rem;
42
+ }
43
+ }
44
+
45
+ [data-jump-to="top"] {
46
+ > i {
47
+ display: inline-block;
48
+ padding: 0.25rem;
49
+ margin: 0.5rem;
50
+ font-size: 0.75rem;
51
+ color: black;
52
+ border-color: black;
53
+ }
54
+ }
55
+
56
+ [data-is-toc] {
57
+ > ul > * > a {
58
+ font-weight: 500;
59
+ }
60
+ }
61
+
62
+ .breakout,
63
+ .breakout-all {
64
+ > img,
65
+ > figure {
66
+ margin-bottom: 1rem;
67
+ }
68
+ }
69
+
70
+ .faded {
71
+ a {
72
+ text-decoration-style: dotted;
73
+ }
74
+ }
@@ -0,0 +1,107 @@
1
+ /* Breakout CSS - Framework-agnostic utilities for breaking out images and figures */
2
+
3
+ .breakout,
4
+ .breakout-all {
5
+ /* Prepare the container for breakout elements */
6
+ padding-inline: 10%;
7
+ max-width: calc(10% + 65ch + 10%);
8
+
9
+ /* Breakout direct children only */
10
+ & > * {
11
+ &:is(
12
+ table,
13
+ pre,
14
+ figure, video, iframe, canvas,
15
+ img, picture,
16
+ /* Custom utility classes for other tags that need to be broken out */
17
+ .breakout-item,
18
+ .breakout-item-max
19
+ ) {
20
+ width: fit-content;
21
+ min-width: 100%;
22
+ max-width: 125%;
23
+ margin-left: 50%;
24
+ transform: translateX(-50%);
25
+ }
26
+
27
+ /* Respect img/picture min-width */
28
+ &:is(img, picture) {
29
+ min-width: auto;
30
+ }
31
+
32
+ /* <!--section:responsive-table-without-wrapper-->
33
+ ### Responsive tables without wrapper
34
+ ```css */
35
+ &:is(table):not(.does-not-exist) {
36
+ /* Let them full-bleed */
37
+ width: max-content;
38
+ min-width: auto;
39
+ max-width: 100vw;
40
+ padding-inline: 7.5%;
41
+
42
+ /* Let them scroll */
43
+ display: block;
44
+ overflow-x: auto;
45
+ -webkit-overflow-scrolling: touch; /* Smooth scroll for iOS */
46
+
47
+ th,
48
+ td {
49
+ padding-inline-start: 0;
50
+ }
51
+ }
52
+ /*```
53
+ #### Soft-increase selector specificity
54
+ `&:is(table):not(.does-not-exist)` trick (inspired by postcss) is used here to increase specificity against selectors like `&:is(table, .table)`
55
+ <!--section--> */
56
+
57
+ /* Max out the width of the element */
58
+ &.breakout-item-max {
59
+ width: 125% !important; /* !important is for cases like figure.breakout-item-max @TODO */
60
+ }
61
+ }
62
+ }
63
+
64
+ .breakout-all > * {
65
+ &:is(h2, h3, h4, hr):not([class]) {
66
+ position: relative;
67
+
68
+ &::before {
69
+ content: "";
70
+ display: block;
71
+ position: absolute;
72
+ background: gray;
73
+ opacity: 12.5%;
74
+ }
75
+ }
76
+
77
+ &:is(h2, h3, h4):not([class]) {
78
+ &::before {
79
+ width: 10em;
80
+ right: 100%;
81
+ margin-right: 0.8ch;
82
+ height: 0.25em;
83
+ top: 50%;
84
+ transform: translateY(-50%);
85
+ background: linear-gradient(to left, gray, transparent);
86
+ }
87
+
88
+ /* @TODO: add to tricks-wiki why `*` works here, but `&` fails */
89
+ &:where(hr + *) {
90
+ &::before {
91
+ display: none !important;
92
+ }
93
+ }
94
+ }
95
+ &:is(hr) {
96
+ height: 0.5rem;
97
+ border: none;
98
+ overflow: visible;
99
+
100
+ &::before {
101
+ width: 100vw;
102
+ left: 50%;
103
+ height: 100%;
104
+ transform: translateX(-50%);
105
+ }
106
+ }
107
+ }
package/blades.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "blades"
5
+ spec.version = "0.27.0-alpha.10"
6
+ spec.authors = ["Anton Staroverov"]
7
+
8
+ spec.summary = "Framework-agnostic CSS utilities and single-file Liquid 'blades' for modern web development."
9
+ spec.homepage = "https://github.com/anydigital/blades"
10
+ spec.license = "MIT"
11
+
12
+ spec.files = Dir.glob("{_includes,assets}/**/*")
13
+ # puts "spec.files: #{spec.files.inspect}"
14
+
15
+ spec.add_runtime_dependency "jekyll", ">= 3.5", "< 5.0"
16
+ end
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@anydigital/blades",
3
+ "version": "0.27.0-alpha.10",
4
+ "description": "Framework-agnostic CSS utilities and single-file Liquid 'blades' for modern web development.",
5
+ "style": "./src/blades.css",
6
+ "exports": {
7
+ ".": "./src/blades.css",
8
+ "./theme": "./src/blades.theme.css",
9
+ "./unreduce-motion": "./src/_unreduce-motion.css",
10
+ "./dist": "./dist/blades.css"
11
+ },
12
+ "scripts": {
13
+ "postcss": "postcss './src/!(_)*.css' --dir ./assets",
14
+ "build": "npm run postcss -- --no-map",
15
+ "start": "npm run postcss -- --watch",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/anydigital/blades.git"
21
+ },
22
+ "keywords": [
23
+ "css",
24
+ "utilities",
25
+ "helpers",
26
+ "atomic",
27
+ "cdn"
28
+ ],
29
+ "author": "Anton Staroverov",
30
+ "license": "MIT",
31
+ "devDependencies": {
32
+ "postcss": "^8.4.33",
33
+ "postcss-cli": "^11.0.0",
34
+ "postcss-import": "^16.1.1",
35
+ "prettier-plugin-jinja-template": "^2.1.0"
36
+ }
37
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ plugins: {
3
+ "postcss-import": {},
4
+ },
5
+ };
@@ -0,0 +1,48 @@
1
+ html {
2
+ /* Prevent horizontal overflow and scrolling, modern way */
3
+ overflow-x: clip;
4
+
5
+ /* Font smoothing */
6
+ -webkit-font-smoothing: antialiased;
7
+ -moz-osx-font-smoothing: grayscale;
8
+ }
9
+
10
+ body {
11
+ /* Ensures body takes at least the full height of the viewport (using dynamic viewport height for better mobile support) */
12
+ min-height: 100dvh;
13
+
14
+ /* Make the body a flex container with column layout; main fills space */
15
+ display: flex;
16
+ flex-direction: column;
17
+ > main {
18
+ flex-grow: 1;
19
+ }
20
+
21
+ /* Hyphenation */
22
+ hyphens: auto;
23
+ /* Links and tables are better (safer) without hyphenation */
24
+ a,
25
+ table {
26
+ hyphens: none;
27
+ }
28
+ }
29
+
30
+ pre {
31
+ padding: 1rem 1.5rem;
32
+ padding-inline-end: 2rem;
33
+
34
+ code {
35
+ padding: 0;
36
+ }
37
+
38
+ @media screen and (max-width: 767px) {
39
+ border-radius: 0;
40
+ }
41
+ }
42
+
43
+ small {
44
+ [role="button"] {
45
+ padding: 0.75em 1em;
46
+ font-size: inherit;
47
+ }
48
+ }
package/src/_prism.css ADDED
@@ -0,0 +1,14 @@
1
+ /* Prism.js */
2
+ .token.treeview-part {
3
+ .entry-line {
4
+ width: 2.5em !important;
5
+ opacity: 25%;
6
+ }
7
+ .entry-name:last-child {
8
+ opacity: 50%;
9
+
10
+ &::before {
11
+ display: none !important;
12
+ }
13
+ }
14
+ }