@browser.style/data-entry
Version:
Dynamic data entry form component with JSON schema validation and internationalization support
570 lines (509 loc) • 13.1 kB
CSS
@import url('../icon/index.css');
@layer bs-component {
:where(data-entry) {
--_bdc: var(--ButtonBorder);
--_bgc: var(--CanvasGray);
--_bdrs: var(--input-bdrs);
--_bdw: var(--input-bdw);
--_lblw: 75px;
--_pb: .6ch;
--_pi: 1.2ch;
--_rg: 1lh;
display: grid;
& *:not(ui-icon) {
font-size: clamp(0.8125rem, 0.7091rem + 0.5172vw, 1rem);
}
/* === PARTS === */
[part~=autosuggest],
[part~=datamapper] {
--_bdrs: 0;
&:not([form]) {
display: contents;
& [part~="row"]:first-of-type { border-block-start-width: 0; }
}
&[form] {
border: var(--_bdw) solid var(--_bdc);
border-radius: var(--input-bdrs);
margin-block-end: 1ch;
label { display: contents; }
span { display: none; }
}
}
[part~=datamapper] {
[part~="filewrap"] {
align-items: center;
display: flex;
justify-content: space-between;
padding-inline: var(--_pi);
}
[part~="processed"] {
color: var(--ColorInfo);
font-size: small;
white-space: nowrap;
}
[type="file"] {
--button-p: 3px 6px;
font-size: small;
width: fit-content;
}
abbr {
color: var(--ColorError);
margin-inline: .25ch 1ch;
text-decoration: none;
}
}
[part~=close] {
background-color: #0000;
border-color: var(--_bdc);
margin-inline-end: auto;
}
[part~=delete] {
--input-check-bg: var(--CanvasGray);
--input-check-bga: var(--CanvasText);
--icon: url('./assets/svg/cross.svg');
}
/* === Details === */
[part~=array-details] {
summary label { column-gap: 0; }
summary {
& [part~=value] {
align-items: center;
column-gap: 1ch;
display: flex;
font-weight: 400;
text-wrap: nowrap;
}
& output {
display: flex;
flex: 1;
font-style: normal;
gap: 2ch;
justify-content: space-between;
pointer-events: none;
text-wrap: balance;
& > :first-child { flex: 1; }
}
& label {
margin-inline-start: auto;
}
}
details:has(summary input[type=checkbox]:not(:checked)) {
background: color-mix(in srgb, var(--ColorError), var(--Canvas) 80%);
color: var(--GrayText);
text-decoration: line-through;
summary input[type=checkbox] {
background-color: var(--ColorError);
--input-check-bdc: var(--ColorError);
--input-check-bga: #FFF;
}
input:not([type=checkbox]) { background-color: #0000; }
}
details:not(:first-of-type):not(:last-of-type) summary {
border-block-start-width: 0;
border-radius: 0;
}
details:first-of-type:not(:only-of-type) summary {
border-end-start-radius: 0;
border-end-end-radius: 0;
}
details:last-of-type:not(:only-of-type) summary {
border-block-start-width: 0;
border-start-start-radius: 0;
border-start-end-radius: 0;
}
&[open] {
background-color: light-dark(hsl(211, 100%, 90%), hsl(211, 60%, 90%));
& input:not([type=checkbox]) { background-color: #0000; }
}
label:first-of-type { --_bdrs: 0; }
}
fieldset[part~=array-details] {
/* === Array has no children, add border to legend and padding to (optional) nav */
&:not(:has(details)) {
& > legend {
border-block-end: var(--_bdw) solid var(--_bdc);
}
}
/* === No nav-element was found, hide */
&:not(:has(details, nav)) {
display: none;
}
}
[part~=array-link] {
a {
color: inherit;
}
[part~=value] {
padding-inline: var(--_pi);
}
}
/* === Array Unit === */
fieldset[part~=array-unit] {
border-color: var(--_bdc);
border-style: solid;
border-width: 0 var(--_bdw) var(--_bdw);
font-variant-numeric: tabular-nums;
grid-template-columns: var(--_lblw) 1fr 9ch 9ch min-content;
&:not(:first-of-type):not(:last-of-type) {
border-radius: 0;
[part~=row] input[part=input] { border-radius: 0; }
}
&:first-of-type {
border-block-start-width: var(--_bdw);
&:not(:last-of-type) {
border-end-start-radius: 0;
border-end-end-radius: 0;
input[part=input] { border-radius: calc(var(--_bdrs) - var(--_bdw)) 0 0 0; }
}
}
&:last-of-type {
&:not(:first-of-type) {
border-start-start-radius: 0;
border-start-end-radius: 0;
input[part=input] { border-radius: 0 0 0 calc(var(--_bdrs) - var(--_bdw)); }
}
}
& > label {
grid-template-columns: 1fr;
margin-inline: var(--_pi);
place-self: center;
}
label[part=row] { display: contents; }
output {
display: contents;
& > span {
border-inline-start: var(--_bdw) solid var(--_bdc);
padding: var(--_pb) var(--_pi);
place-content: center;
&:not(:first-of-type) {
text-align: end;
}
&:not(:only-of-type):last-of-type {
border-inline-end: var(--_bdw) solid var(--_bdc);
}
}
}
span[part=label] { display: none; }
}
[part~=fieldset] {
border: 0;
gap: 0;
padding: 0;
}
/* TODO part form and part content */
[part~=form],
[part~=footer] {
display: grid;
row-gap: calc(var(--_rg) / 3);
[part~=nav] {
row-gap: calc(var(--_rg) / 3);
}
}
[part~=main-nav] {
background-color: Canvas;
display: flex;
flex-wrap: wrap;
gap: .75ch;
padding-block: .75ch;
position: sticky;
top: 0;
z-index: 10;
a {
background: var(--_bgc);
border-radius: var(--_bdrs);
color: inherit;
font-size: small;
padding: .5ch 1ch;
text-decoration: none;
&.visible {
/* --_bgc: hotpink; */
&.active {
--_bgc: var(--AccentColor);
color: var(--AccentColorText);
}
}
}
}
[part~=main] {
display: grid;
row-gap: var(--_rg);
}
[part~=title] {
font-size: 150%;
font-weight: 700;
line-height: 1.3;
}
@supports (animation-timeline: scroll()) {
[part~=main-nav] {
animation: scroll-shadow linear both;
animation-timeline: scroll();
animation-range: 0ex 5ex;
}
}
@media (min-width: 600px) {
--_lblw: 125px;
}
/* ARRAY GRID */
[part~=array-grid] {
fieldset {
border: 0;
border-radius: 0;
padding: 0;
row-gap: 0;
}
@media (max-width: 599px) {
margin-block-start: var(--_rg);
fieldset {
&:not(:last-of-type) {
margin-block-end: var(--_rg);
}
}
}
@media (min-width: 600px) {
& {
--_bdrs: 0;
background: var(--_bdc);
margin-block-start: var(--_rg);
padding: var(--_bdw);
position: relative;
row-gap: var(--_bdw);
}
legend {
inset-block-start: calc(0lh - var(--_rg));
position: absolute;
}
label[part~=row] {
border: 0;
grid-template-columns: unset;
row-gap: 0;
span {
border: 0;
border-radius: inherit ;
}
}
fieldset {
column-gap: var(--_bdw);
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
/* Only show the labels from first row */
&:nth-of-type(n+2) label > span { display: none; }
/* Hide UI Icons */
& :is(input, select, textarea) { --icon: none; }
&:first-of-type label {
span { border-bottom: var(--_bdc) solid var(--_bdw); }
&:first-of-type { border-start-start-radius: var(--input-bdrs); }
&:last-of-type { border-start-end-radius: var(--input-bdrs); }
}
&:last-of-type label {
&:first-of-type { border-end-start-radius: var(--input-bdrs); }
&:last-of-type { border-end-end-radius: var(--input-bdrs); }
& input { border-radius: inherit ;}
}
}
}
}
[part~=input]:not([type=checkbox],[type=radio]),
[part~=select],
[part~=textarea] {
block-size: 100%;
border: 0;
border-radius: 0;
font-family: inherit;
padding-block: var(--_pb);
&::-webkit-inner-spin-button{ display: none; }
}
[part~=label] {
align-items: center;
background-color: var(--_bgc);
border-inline-end: var(--_bdw) solid var(--_bdc);
column-gap: 1ch;
display: block;
font-weight: 500;
height: 100%;
overflow: hidden;
padding: var(--_pb) var(--_pi);
text-overflow: ellipsis;
white-space: nowrap;
summary & { display: flex;}
}
[part~=legend] {
font-weight: 700;
width: 100%;
}
[part~=media] {
gap: var(--_pi);
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
label {
border-width: var(--_bdw);
border-radius: var(--_bdrs);
grid-template-columns: 1fr;
padding: var(--_pi);
img {
aspect-ratio: 1 / 1;
grid-area: 1 / 1;
height: 100%;
object-fit: contain;
place-self: center;
user-drag: none;
-webkit-user-drag: none;
width: 100%;
}
input {
grid-area: 1 / 1;
place-self: end;
}
&:has(input:not(:checked)) {
background: color-mix(in srgb, var(--ColorError), var(--Canvas) 80%);
img { opacity: .25; }
input {
background-color: var(--ColorError);
--input-check-bdc: var(--ColorError);
--input-check-bga: #FFF;
}
}
}
}
[part~=micro] {
background: #0000;
color: var(--LinkText);
font-family: inherit;
font-size: x-small;
padding: 0;
}
[part~=nav] {
column-gap: 1ch;
display: flex;
flex-wrap: wrap;
justify-content: end;
padding-block-start: .33lh;
[part~=link] {
font-size: x-small;
font-weight: 500;
&[part~=action] {
background: var(--ButtonFace);
color: inherit;
padding: .25ch 1ch;
border-radius: 2px;
text-decoration: none;
}
}
&[part~=actions] { padding-block-start: 0; }
[popovertarget] { cursor: pointer; }
}
[part~=richtext] {
--ui-richtext-active-bg: var(--AccentColor);
--ui-richtext-active-c: var(--AccentColorText);
padding: var(--_pi);
&::part(toolbar) {
padding-block-end: var(--_pb);
}
}
[part~=row] {
align-items: center;
border-block-width: 0 var(--_bdw);
border-inline-width: var(--_bdw);
border-color: var(--_bdc);
border-style: solid;
display: grid;
grid-template-columns: var(--_lblw) 1fr;
user-select: none;
&[part~=action] {
grid-template-columns: var(--_lblw) 1fr min-content;
& > button {
font-size: small;
margin-inline-end: var(--_pb);
padding: .25ch .75ch;
}
}
abbr { margin: 0; }
&:first-of-type:not(div) {
border-block-start-width: var(--_bdw);
border-start-start-radius: var(--_bdrs);
border-start-end-radius: var(--_bdrs);
& > *:first-child { border-start-start-radius: var(--_bdrs); }
& > *:last-child { border-start-end-radius: calc(var(--_bdrs) - var(--_bdw)); }
}
&:last-of-type:not(div) {
border-end-start-radius: var(--_bdrs);
border-end-end-radius: var(--_bdrs);
& > *:first-child { border-end-start-radius: var(--_bdrs); }
& > *:last-child { border-end-end-radius: calc(var(--_bdrs) - var(--_bdw)); }
}
&:is(summary) {
[part~=value] {
padding-inline: var(--_pi);
}
[open] & {
border-block-end-width: 0;;
border-end-start-radius: 0;
border-end-end-radius: 0;
& + fieldset label:first-of-type {
border-start-start-radius: 0;
border-start-end-radius: 0;
}
}
&::-webkit-details-marker { display: none; }
}
[part~=link] {
padding-inline: var(--_pi);
}
}
[part~=textarea] {
textarea {
field-sizing: content;
min-block-size: 2.4lh;
resize: vertical;
}
}
[part~=toolbar] {
margin-block-start: .5lh;
}
/* WIP */
[data-lastpass-icon-root] { display: none; }
div[popover] {
border: var(--_bdw) solid var(--_bdc);
border-radius: var(--_bdrs);
box-shadow: 0px 25px 50px -12px color-mix(in srgb, CanvasText 25%, transparent);
inset-block: anchor(bottom) auto;
inset-inline: auto anchor(right);
min-inline-size: 20rem;
padding: 2ch;
position-anchor: var(--_pa);
position-try-fallbacks: flip-block;
text-wrap: nowrap;
&::backdrop { background: light-dark(#0002, #000A); }
[dir=rtl] & { inset-inline: auto anchor(left); }
nav { margin-block-start: 1ch; }
}
[popovertarget] {
anchor-name: var(--_an);
}
/* Focus */
:is(input:not([type=checkbox], [type=radio]), select, summary, textarea):focus-visible,
input[type=date]:focus-within,
label:has([type=checkbox], [type=radio]):focus-within,
ui-richtext:focus-within {
background-color: var(--CanvasGray);
outline: 2px solid var(--AccentColor);
outline-offset: -2px;
& * { outline: none; }
}
label:has([type=checkbox], [type=radio]):focus-within + label:not(:has([part=img])),
[part~="array-details"]:has(summary:focus-visible) + [part~="array-details"] summary [part~="label"]
{
clip-path: inset(2px 0 0 0);
}
label:has([part~=delete]):focus-within { outline-offset: 2px; }
[part~=media] label:focus-within { outline-offset: -2px; }
/* details:not([open]):focus-within + details */
}
}
/* TODO */
.mie-auto { margin-inline-end: auto; }
@keyframes scroll-shadow {
from {
box-shadow: none;
}
to {
box-shadow: 0px .8em .4em -.4em var(--_bdc);
}
}