Author: Adam Argyle [atom@argyleink.com]
Hash: c6a81a6db2320428d0961b86ad44a3c3a1567f4d
Timestamp: Fri, 06 Oct 2023 22:49:25 +0000 (11 months ago)

+676 -1 +/-4 browse
migration
1diff --git a/package.json b/package.json
2index 9e58cda..390f603 100644
3--- a/package.json
4+++ b/package.json
5 @@ -60,6 +60,9 @@
6 "./postcss/buttons": "./src/extra/buttons.css",
7 "./postcss/buttons/light": "./src/extra/buttons.light.css",
8 "./postcss/buttons/dark": "./src/extra/buttons.dark.css",
9+ "./inputs": "./inputs.min.css",
10+ "./inputs/range-handler": "./src/extra/inputs.range.js",
11+ "./postcss/inputs": "./src/extra/inputs.css",
12 "./animations": "./animations.min.css",
13 "./aspects": "./aspects.min.css",
14 "./blue": "./blue.min.css",
15 @@ -199,6 +202,7 @@
16 "lib:buttons": "postcss src/extra/buttons.css -o buttons.min.css",
17 "lib:buttons:light": "postcss src/extra/buttons.light.css -o buttons.light.min.css",
18 "lib:buttons:dark": "postcss src/extra/buttons.dark.css -o buttons.dark.min.css",
19+ "lib:inputs": "postcss src/extra/inputs.css -o inputs.min.css",
20 "lib:animations": "postcss src/props.animations.css -o animations.min.css",
21 "lib:aspects": "postcss src/props.aspects.css -o aspects.min.css",
22 "lib:borders": "postcss src/props.borders.css -o borders.min.css",
23 diff --git a/src/extra/buttons.css b/src/extra/buttons.css
24index 2598022..116007c 100644
25--- a/src/extra/buttons.css
26+++ b/src/extra/buttons.css
27 @@ -133,7 +133,6 @@
28 cursor: initial;
29 align-self: flex-start;
30 border-radius: var(--radius-2);
31- border: var(--border-size-1) solid var(--surface-2);
32 box-shadow: var(--inner-shadow-4);
33 color: var(--text-2);
34 }
35 diff --git a/src/extra/inputs.css b/src/extra/inputs.css
36new file mode 100644
37index 0000000..a2d9c22
38--- /dev/null
39+++ b/src/extra/inputs.css
40 @@ -0,0 +1,666 @@
41+ @import "../props.media.css";
42+
43+ :root {
44+ --icon-error: url(https://api.iconify.design/ic:baseline-error.svg?color=%23ff6b6b);
45+ --icon-search: url(https://api.iconify.design/ic:search.svg?color=%23adb5bd);
46+ --icon-email: url(https://api.iconify.design/ic:email.svg?color=%23adb5bd);
47+ --icon-url: url(https://api.iconify.design/ic:link.svg?color=%23adb5bd);
48+ --icon-user: url(https://api.iconify.design/ic:person.svg?color=%23adb5bd);
49+ --icon-user-editing: url(https://api.iconify.design/ic:person-outline.svg?color=%23adb5bd);
50+ --icon-tel: url(https://api.iconify.design/ic:phone.svg?color=%23adb5bd);
51+ --icon-tel-editing: url(https://api.iconify.design/ic:phone-in-talk.svg?color=%23adb5bd);
52+ --icon-password: url(https://api.iconify.design/ic:baseline-lock.svg?color=%23adb5bd);
53+ --icon-password-editing: url(https://api.iconify.design/ic:baseline-lock-open.svg?color=%23adb5bd);
54+ --icon-no-edit: url(https://api.iconify.design/ic:baseline-edit-off.svg?color=%23adb5bd);
55+ --icon-arrow-down: url(https://api.iconify.design/ic:keyboard-arrow-down.svg?color=%23adb5bd);
56+ --icon-arrow-up: url(https://api.iconify.design/ic:keyboard-arrow-up.svg?color=%23adb5bd);
57+ }
58+
59+ @keyframes drop-zone {
60+ from { box-shadow: 0 0 0 0 var(--link) }
61+ to { box-shadow: 0 0 0 25px #0000 }
62+ }
63+
64+ /* preload icons that switch upon editing, so they dont flash blank */
65+ :where(body)::after {
66+ content: var(--icon-tel-editing) var(--icon-password-editing) var(--icon-user-editing) var(--icon-arrow-up);
67+ opacity: 0;
68+ position: absolute;
69+ z-index: -1;
70+ }
71+
72+ /* fieldset counts errors and places required dots */
73+ :where(fieldset) {
74+ max-inline-size: max-content;
75+ display: grid;
76+ gap: var(--size-2);
77+ counter-reset: errors;
78+ border-color: var(--surface-2);
79+ box-shadow: var(--shadow-3);
80+ padding-inline: var(--size-4);
81+ padding-block: var(--size-2) var(--size-3);
82+ transition: box-shadow .4s var(--ease-out-4);
83+
84+ &:where(:focus-within) {
85+ box-shadow: var(--shadow-6);
86+ }
87+
88+ &:where(:focus-within) > :where(legend) {
89+ color: var(--link);
90+ }
91+
92+ & > :where(div:has(:placeholder-shown:required, :not(:placeholder-shown):invalid, :not([placeholder]):required)) > label {
93+ position: relative;
94+
95+ &::after {
96+ content: "required";
97+ position: absolute;
98+ margin-block-start: .5ex;
99+ margin-inline-start: 1ex;
100+ text-indent: -200vw;
101+ inline-size: 6px;
102+ block-size: 6px;
103+ border-radius: var(--radius-round);
104+ background-color: var(--red-4);
105+ box-shadow: 0 0 var(--size-2) var(--red-4);
106+ }
107+ }
108+
109+ &:where(:has(:not(:placeholder-shown):invalid)) :where(legend)::after {
110+ text-transform: initial;
111+ color: var(--red-5);
112+ content: " (" counter(errors) " errors)";
113+ }
114+
115+ &:where(:has(:not(:placeholder-shown):invalid)) {
116+ counter-increment: errors;
117+ }
118+
119+ & > :where(div) {
120+ display: grid;
121+ grid-auto-columns: 1fr;
122+ gap: var(--size-2) var(--size-3);
123+ align-items: center;
124+
125+ @media (width > 720px) {
126+ grid-template-columns: var(--size-content-1) auto;
127+ }
128+
129+ & > :where(label) {
130+ justify-self: start;
131+ }
132+ }
133+
134+ & > :where(footer) {
135+ display: flex;
136+ flex-wrap: wrap;
137+ justify-content: space-between;
138+ gap: var(--size-3);
139+ margin-block-start: var(--size-6);
140+
141+ & > :where(menu:only-child) {
142+ margin-inline-start: auto;
143+ }
144+ }
145+
146+ & > :where(ul) {
147+ padding: 0;
148+ margin: 0;
149+ list-style-type: none;
150+ display: grid;
151+ gap: var(--size-2);
152+
153+ & > :where(li) {
154+ padding: 0;
155+
156+ & > :where(label) {
157+ display: inline-flex;
158+ align-items: baseline;
159+ gap: var(--size-4);
160+ max-inline-size: var(--size-content-1);
161+
162+ & > :where(input) {
163+ margin-inline-start: 0;
164+ flex-shrink: 0;
165+ }
166+ }
167+ }
168+ }
169+ }
170+
171+ :where(legend) {
172+ display: inline-flex;
173+ gap: var(--size-2);
174+ align-items: center;
175+ min-block-size: 3ch;
176+ border: 1px solid var(--surface-2);
177+ padding-inline: 1.5ch;
178+ border-radius: var(--radius-round);
179+ text-transform: uppercase;
180+ letter-spacing: var(--font-letterspacing-3);
181+ font-size: var(--font-size-0);
182+ font-weight: var(--font-weight-6);
183+ margin-inline-start: -2px;
184+ color: var(--text-2);
185+
186+ @media (prefers-color-scheme: light) {
187+ background: white;
188+ }
189+ }
190+
191+ :where(input:not(
192+ button,
193+ [type="button"],
194+ [type="file"],
195+ [type="number"],
196+ [type="range"],
197+ [type="color"],
198+ [type="checkbox"],
199+ [type="radio"]
200+ )) {
201+ /* todo: touch-callout */
202+ line-height: 2.5;
203+ padding-block: 0;
204+ padding-inline: 1.75ch;
205+ transition:
206+ background-color .5s var(--ease-3),
207+ outline-offset 145ms var(--ease-2);
208+
209+ &:where(:placeholder-shown) {
210+ text-overflow: ellipsis;
211+ }
212+
213+ @media (prefers-reduced-motion: no-preference) {
214+ &:where(:not(:placeholder-shown)):where(:invalid:not(:focus)) {
215+ animation: var(--animation-shake-x);
216+ animation-duration: .4s;
217+ }
218+ }
219+ }
220+
221+ :where(input:not(
222+ button,
223+ input[type="button"],
224+ input[type="range"],
225+ input[type="color"],
226+ input[type="checkbox"],
227+ input[type="radio"]
228+ ), textarea) {
229+ box-shadow: var(--shadow-2), 0 0 1px 1px var(--surface-2);
230+
231+ @media (prefers-color-scheme: dark) {
232+ box-shadow:
233+ var(--inner-shadow-2),
234+ 0 1px 0px 0px var(--dark-surface) inset,
235+ 0 -.5px 0px 0px var(--surface-2) inset;
236+ }
237+ }
238+
239+ :where(input:is(
240+ [type=text],
241+ [type=password],
242+ [type=url],
243+ [type=email],
244+ [type=tel]
245+ )) {
246+ padding-inline-end: 3.5ch;
247+ }
248+
249+ :where(input:is(
250+ [type=text],
251+ [type=password],
252+ [type=url],
253+ [type=email],
254+ [type=tel],
255+ [type=search]
256+ )) {
257+ flex-shrink: 1;
258+ min-inline-size: 5ch;
259+ max-inline-size: 100%;
260+ }
261+
262+ :where(input, textarea) {
263+ --dark-surface: var(--gray-11);
264+ }
265+
266+ :where([readonly]:focus) {
267+ outline: none;
268+ }
269+
270+ :where(input:not(
271+ button,
272+ [disabled],
273+ [readonly],
274+ [type="file"],
275+ [type="button"],
276+ [type="submit"],
277+ [type="reset"],
278+ [type="checkbox"],
279+ [type="radio"]),
280+ textarea,
281+ select) {
282+ color: var(--text-1);
283+
284+ @media (prefers-color-scheme: light) {
285+ background-color: white;
286+ }
287+
288+ &:where(:hover, :focus-within) {
289+ @media (prefers-color-scheme: dark) {
290+ background-color: var(--dark-surface);
291+ }
292+ }
293+
294+ &:where(:not(:placeholder-shown, :not([placeholder])):invalid ){
295+ background-image: var(--icon-error);
296+ background-position: calc(100% - 1.5ch) center;
297+ }
298+
299+ &:where(:not(:focus-within):not(:placeholder-shown):invalid) {
300+ text-decoration: underline wavy var(--red-6);
301+
302+ @media (prefers-color-scheme: dark) {
303+ text-decoration: underline wavy var(--red-4);
304+ }
305+ }
306+ }
307+
308+ :where(
309+ input[readonly],
310+ input[disabled]
311+ ) {
312+ cursor: not-allowed;
313+ }
314+
315+ :where([disabled]) {
316+ opacity: .5;
317+ box-shadow: none;
318+ cursor: auto;
319+ }
320+
321+ :where(input[type="file"]) {
322+
323+ @media (prefers-color-scheme: light) {
324+ box-shadow: none;
325+ }
326+
327+ &:where(.dropping) {
328+ outline: 2px dashed var(--link);
329+
330+ @media (prefers-reduced-motion: no-preference) {
331+ animation: drop-zone 1.5s var(--ease-out-5) infinite;
332+ }
333+ }
334+ }
335+
336+ :where(input[type=file])::-webkit-file-upload-button, :where(input[type=file])::file-selector-button {
337+ margin: var(--size-3);
338+ }
339+
340+ @media (prefers-color-scheme: dark) {
341+ :where(input[type=file])::-webkit-file-upload-button,
342+ :where(input[type=file])::file-selector-button {
343+ border-color: transparent;
344+ }
345+ }
346+
347+ :where(input[type="number"]) {
348+ padding-block: .75ch;
349+ padding-inline: 1.75ch .75ch;
350+ min-inline-size: 10ch;
351+ }
352+
353+ ::placeholder {
354+ color: var(--gray-5);
355+ font-style: italic;
356+
357+ @media (prefers-color-scheme: dark) {
358+ color: var(--surface-4);
359+ }
360+ }
361+
362+ ::-moz-placeholder {
363+ opacity: 1;
364+ }
365+
366+ :where(search) {
367+ & > :where(form) {
368+ display: grid;
369+ gap: var(--size-3);
370+ grid-template-columns: minmax(20ch, 1fr) auto;
371+
372+ & > :where(label) {
373+ grid-column: span 2;
374+ }
375+ }
376+ }
377+
378+ :where(input[type="search"]) {
379+ background-image: var(--icon-search);
380+ background-position: 1.5ch center;
381+ padding-inline: 4ch 1.25ch;
382+ border-radius: var(--radius-round);
383+
384+ &::-webkit-search-cancel-button {
385+ margin-right: -5px;
386+ padding: .1ch;
387+ }
388+
389+ &:where([list]):placeholder-shown {
390+ background-image:
391+ var(--icon-search),
392+ var(--icon-arrow-down);
393+ background-position: 1.5ch center, calc(100% - 1.25ch) center;
394+ background-size: auto, 2.25ch;
395+
396+ &:focus {
397+ background-image:
398+ var(--icon-search),
399+ var(--icon-arrow-up);
400+ }
401+ }
402+
403+ &::-webkit-calendar-picker-indicator {
404+ color: transparent;
405+ }
406+ }
407+
408+ :where(input[type="text"][list]) {
409+ background-image: var(--icon-arrow-down);
410+ background-position: calc(100% - 1.25ch) center;
411+ background-size: 2.25ch;
412+
413+ &:focus {
414+ background-image: var(--icon-arrow-up);
415+ }
416+
417+ &::-webkit-calendar-picker-indicator {
418+ color: transparent;
419+ }
420+ }
421+
422+ :where(input[type="password"]) {
423+ background-image: var(--icon-password);
424+ background-position: calc(100% - 1.5ch) center;
425+
426+ &:focus {
427+ background-image: var(--icon-password-editing);
428+ }
429+ }
430+
431+ :where(input[type="email"]) {
432+ background-image: var(--icon-email);
433+ background-position: calc(100% - 1.5ch) center;
434+ }
435+
436+ :where(input[readonly]) {
437+ background-image: var(--icon-no-edit);
438+ background-position: calc(100% - 1.5ch) center;
439+ }
440+
441+ :where(input[type="url"]) {
442+ background-image: var(--icon-url);
443+ background-position: calc(100% - 1.5ch) center;
444+ }
445+
446+ :where(input[type="tel"]) {
447+ background-image: var(--icon-tel);
448+ background-position: calc(100% - 1.5ch) center;
449+
450+ &:focus {
451+ background-image: var(--icon-tel-editing);
452+ }
453+ }
454+
455+ :where(input:where([name*="username"],[id*="username"])) {
456+ background-image: var(--icon-user);
457+ background-position: calc(100% - 1.5ch) center;
458+ background-size: 1.75ch;
459+
460+ &:focus {
461+ background-image: var(--icon-user-editing);
462+ }
463+ }
464+
465+ :where(input[type="color"]) {
466+ appearance: none;
467+ background: none;
468+ border: none;
469+ padding: 0;
470+ inline-size: var(--size-8);
471+ block-size: var(--size-8);
472+ border-radius: var(--radius-round);
473+ overflow: hidden;
474+ box-shadow: var(--shadow-5);
475+
476+ &::-webkit-color-swatch {
477+ border: none;
478+ }
479+
480+ &::-webkit-color-swatch-wrapper {
481+ padding: 0;
482+ }
483+ }
484+
485+ :where(textarea) {
486+ transition: background-color .5s var(--ease-3);
487+ }
488+
489+ :where(select) {
490+ --_bg-light: #fff;
491+ --_bg-dark: var(--surface-3);
492+ --_bg: var(--_bg-light);
493+ background-color: var(--_bg);
494+ box-shadow: var(--shadow-3), 0 1px var(--surface-3);
495+
496+ appearance: none;
497+ background-image: var(--icon-arrow-down);
498+ background-position: calc(100% - 1ch) center;
499+ background-size: 3ex;
500+ padding-block: 0.75ch;
501+ padding-inline: 1.75ch 3ch;
502+ line-height: 1.5;
503+
504+ &:where(:hover, :focus) {
505+ /* add button hover */
506+ background-color: var(--_bg);
507+ }
508+
509+ &:where(:hover, :focus) {
510+ background-image: var(--icon-arrow-up);
511+ }
512+
513+ @media (prefers-color-scheme: dark) {
514+ --_bg: var(--_bg-dark);
515+ }
516+ }
517+
518+ :where(
519+ input[type="checkbox"],
520+ input[type="radio"]
521+ ) {
522+ aspect-ratio: 1;
523+ box-shadow: var(--shadow-6);
524+ transform-style: preserve-3d;
525+ cursor: pointer;
526+
527+ --isLTR: 1;
528+ --isRTL: -1;
529+
530+ &:dir(rtl) {
531+ --isLTR: -1;
532+ --isRTL: 1;
533+ }
534+
535+ &:hover::before {
536+ --thumb-scale: 1;
537+ }
538+
539+ @media (hover: none) {
540+ inline-size: 1.5rem;
541+ block-size: 1.5rem;
542+ }
543+
544+ &::before {
545+ --thumb-scale: .01;
546+ --thumb-highlight-size: 225%;
547+
548+ content: "";
549+ inline-size: var(--thumb-highlight-size);
550+ block-size: var(--thumb-highlight-size);
551+ clip-path: circle(50%);
552+ position: absolute;
553+ inset-block-start: 50%;
554+ inset-inline-start: 50%;
555+ background: hsl(0 0% 50% / 20%);
556+ transform-origin: center center;
557+ transform:
558+ translateX(calc(var(--isRTL) * 50%))
559+ translateY(-50%)
560+ translateZ(-1px)
561+ scale(var(--thumb-scale))
562+ ;
563+ will-change: transform;
564+
565+ @media (prefers-reduced-motion: no-preference) {
566+ transition: transform .2s ease;
567+ }
568+ }
569+ }
570+
571+ input[type="range"] {
572+ --track-height: .5ex;
573+ --track-fill: 0%;
574+ /* --_track-fill: calc(100% * attr(value number, 0) / attr(max number, 100)); */
575+ --track-color: var(--dark-surface);
576+ --thumb-size: 3ex;
577+ --thumb-offset: -1.25ex;
578+ --thumb-highlight-color: lch(100 0 0 / 20%);
579+ --thumb-highlight-size: 0px;
580+
581+ @media (prefers-color-scheme: light) {
582+ --thumb-highlight-color: lch(0 0 0 / 20%);
583+ --track-color: var(--surface-2);
584+ }
585+
586+ display: block;
587+ inline-size: 100%;
588+ margin: 1ex 0;
589+ appearance: none;
590+ background: transparent;
591+ outline-offset: 5px;
592+
593+ @media (hover: none) {
594+ --thumb-size: 30px;
595+ --thumb-offset: -14px;
596+ }
597+
598+ &::-webkit-slider-runnable-track {
599+ appearance: none;
600+ block-size: var(--track-height);
601+ border-radius: 5ex;
602+ box-shadow: var(--inner-shadow-2);
603+ background:
604+ linear-gradient(
605+ to right,
606+ transparent var(--track-fill),
607+ var(--track-color) 0%
608+ ),
609+ var(--link);
610+ }
611+
612+ &::-moz-range-track {
613+ appearance: none;
614+ block-size: var(--track-height);
615+ border-radius: 5ex;
616+ box-shadow: var(--inner-shadow-2);
617+ background:
618+ linear-gradient(
619+ to right,
620+ transparent var(--track-fill),
621+ var(--track-color) 0%
622+ ),
623+ var(--link);
624+ }
625+
626+ &::-webkit-slider-thumb {
627+ appearance: none;
628+ cursor: ew-resize;
629+ border: 3px solid var(--surface-1);
630+ block-size: var(--thumb-size);
631+ inline-size: var(--thumb-size);
632+ margin-block-start: var(--thumb-offset);
633+ border-radius: 50%;
634+ background: var(--link);
635+ box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
636+
637+ @media (prefers-reduced-motion: no-preference) {
638+ & {
639+ transition: box-shadow .1s ease;
640+ }
641+ }
642+
643+ .fieldset-item:focus-within & {
644+ border-color: var(--surface-2);
645+ }
646+ }
647+
648+ &::-moz-range-thumb {
649+ appearance: none;
650+ cursor: ew-resize;
651+ border: 3px solid var(--surface-1);
652+ block-size: var(--thumb-size);
653+ inline-size: var(--thumb-size);
654+ margin-block-start: var(--thumb-offset);
655+ border-radius: 50%;
656+ background: var(--link);
657+ box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
658+
659+ @media (prefers-reduced-motion: no-preference) {
660+ & {
661+ transition: box-shadow .1s ease;
662+ }
663+ }
664+
665+ .fieldset-item:focus-within & {
666+ border-color: var(--surface-2);
667+ }
668+ }
669+
670+ &:where(:hover,:active) {
671+ --thumb-highlight-size: 10px;
672+ }
673+ }
674+
675+ @media (pointer: coarse) {
676+ :where(
677+ input[type="checkbox"],
678+ input[type="radio"]
679+ ) {
680+ inline-size: var(--size-4);
681+ block-size: var(--size-4);
682+ }
683+ }
684+
685+ :where(input):-webkit-autofill,
686+ :where(input):-webkit-autofill:hover,
687+ :where(input):-webkit-autofill:focus,
688+ :where(textarea):-webkit-autofill,
689+ :where(textarea):-webkit-autofill:hover,
690+ :where(textarea):-webkit-autofill:focus,
691+ :where(select):-webkit-autofill,
692+ :where(select):-webkit-autofill:hover,
693+ :where(select):-webkit-autofill:focus,
694+ :where(input):autofill,
695+ :where(input):autofill:hover,
696+ :where(input):autofill:focus,
697+ :where(textarea):autofill,
698+ :where(textarea):autofill:hover,
699+ :where(textarea):autofill:focus,
700+ :where(select):autofill,
701+ :where(select):autofill:hover,
702+ :where(select):autofill:focus {
703+ -webkit-text-fill-color: var(--text-1);
704+ -webkit-box-shadow: 0 0 0px 1e5px var(--gray-11) inset;
705+ transition: background-color 5000s ease-in-out 0s;
706+ }
707\ No newline at end of file
708 diff --git a/src/extra/inputs.range.js b/src/extra/inputs.range.js
709new file mode 100644
710index 0000000..5e06d2f
711--- /dev/null
712+++ b/src/extra/inputs.range.js
713 @@ -0,0 +1,6 @@
714+ export const rangeToPercent = range => {
715+ const max = range.getAttribute('max') || 100
716+ const percent = range.value / max * 100
717+
718+ range.style.setProperty('--track-fill', `${parseInt(percent)}%`)
719+ }
720\ No newline at end of file