fix and expand table styles. man do I ever love scroll animations!!!
This commit is contained in:
parent
41bd3463e7
commit
f21fa5e224
2 changed files with 109 additions and 34 deletions
|
@ -1,26 +1,29 @@
|
|||
.table {
|
||||
--shadow: hsla(0 0% 0% / .1) 0 .5em 2em;
|
||||
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--columns), minmax(0, auto));
|
||||
display: block grid;
|
||||
grid-template-columns: repeat(var(--columns), minmax(max-content, auto));
|
||||
align-content: start;
|
||||
padding-inline: 1px;
|
||||
margin-inline: -1px;
|
||||
overflow: auto;
|
||||
background-color: inherit;
|
||||
isolation: isolate;
|
||||
|
||||
block-size: 100%;
|
||||
|
||||
&.selectable {
|
||||
grid-template-columns: 2em repeat(calc(var(--columns) - 1), minmax(0, auto));
|
||||
}
|
||||
|
||||
& input[type="checkbox"] {
|
||||
margin: .1em;
|
||||
}
|
||||
|
||||
& .cell {
|
||||
display: grid;
|
||||
display: block grid;
|
||||
padding: var(--padding-m);
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radii-m);
|
||||
background: inherit;
|
||||
white-space: nowrap;
|
||||
|
||||
&:has(textarea:focus) {
|
||||
border-color: var(--info);
|
||||
|
@ -29,11 +32,32 @@
|
|||
& > span {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
position: sticky;
|
||||
inset-inline-start: calc(var(--padding-m) * var(--depth));
|
||||
padding-inline-start: calc(var(--padding-m) * (1 + var(--depth)));
|
||||
z-index: 1;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset-inline-start: 100%;
|
||||
inset-block-start: -2px;
|
||||
display: block;
|
||||
inline-size: 2em;
|
||||
block-size: calc(3px + 100%);
|
||||
background: linear-gradient(90deg, hsla(0 0% 0% / .05), transparent);
|
||||
animation: column-scroll-shadow linear both;
|
||||
animation-timeline: scroll(inline);
|
||||
animation-range: 0 2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& :is(.header, .main, .footer) {
|
||||
grid-column: span calc(2 + var(--columns));
|
||||
display: grid;
|
||||
display: block grid;
|
||||
grid-template-columns: subgrid;
|
||||
}
|
||||
|
||||
|
@ -41,35 +65,49 @@
|
|||
position: sticky;
|
||||
inset-block-start: 0;
|
||||
border-block-end: 1px solid var(--surface-300);
|
||||
background-color: inherit;
|
||||
z-index: 2;
|
||||
animation: header-scroll-shadow linear both;
|
||||
animation-timeline: scroll();
|
||||
animation-range: 0 2em;
|
||||
|
||||
& > aside {
|
||||
position: sticky;
|
||||
inset-inline-start: 0;
|
||||
background: inherit;
|
||||
padding: var(--padding-m);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
& .main {
|
||||
overflow: clip auto;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
& .row {
|
||||
--bg: var(--text);
|
||||
--alpha: 0;
|
||||
grid-column: span calc(2 + var(--columns));
|
||||
display: grid;
|
||||
display: block grid;
|
||||
grid-template-columns: subgrid;
|
||||
border: 1px solid transparent;
|
||||
background-color: color(from var(--bg) srgb r g b / var(--alpha));
|
||||
background-color: inherit;
|
||||
background-image: linear-gradient(0deg, oklch(from var(--info) l c h / var(--alpha)), oklch(from var(--info) l c h / var(--alpha)));
|
||||
|
||||
&:has(> .cell > :checked) {
|
||||
--bg: var(--info);
|
||||
&:has(> aside > :checked) {
|
||||
--alpha: .1;
|
||||
border-color: var(--bg);
|
||||
border-color: var(--info);
|
||||
|
||||
& span {
|
||||
font-variation-settings: 'GRAD' 1000;
|
||||
}
|
||||
|
||||
& + :has(> .cell> :checked) {
|
||||
/* Remove the top border when directly preceded by a selected row */
|
||||
& + :has(> aside > :checked) {
|
||||
border-block-start-color: transparent;
|
||||
}
|
||||
|
||||
&:has(+ .row > .cell > :checked) {
|
||||
/* Remove the top border when directly succeeded by a selected row */
|
||||
&:has(+ .row > aside > :checked) {
|
||||
border-block-end-color: transparent;
|
||||
}
|
||||
}
|
||||
|
@ -77,15 +115,25 @@
|
|||
&:hover {
|
||||
--alpha: .2 !important;
|
||||
}
|
||||
|
||||
& > aside {
|
||||
position: sticky;
|
||||
inset-inline-start: 0;
|
||||
background: inherit;
|
||||
padding: var(--padding-m);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
& details {
|
||||
display: contents;
|
||||
background-color: inherit;
|
||||
|
||||
&::details-content {
|
||||
grid-column: span calc(2 + var(--columns));
|
||||
display: grid;
|
||||
display: block grid;
|
||||
grid-template-columns: subgrid;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
&:not([open])::details-content {
|
||||
|
@ -93,15 +141,30 @@
|
|||
}
|
||||
|
||||
& > summary {
|
||||
position: sticky;
|
||||
inset-inline-start: 0;
|
||||
grid-column: 1;
|
||||
padding: .5em;
|
||||
padding-inline-start: calc(var(--depth) * 1em + .5em);
|
||||
|
||||
}
|
||||
|
||||
& > .row > .cell {
|
||||
padding-inline-start: calc(var(--depth) * 1em + var(--padding-m));
|
||||
}
|
||||
}
|
||||
|
||||
&.selectable {
|
||||
grid-template-columns: 2em repeat(calc(var(--columns) - 1), minmax(max-content, auto));
|
||||
|
||||
& .cell:first-of-type {
|
||||
inset-inline-start: calc(2em + var(--padding-m) * var(--depth));
|
||||
}
|
||||
|
||||
& details > summary {
|
||||
inset-inline-start: 2em;
|
||||
grid-column: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@property --depth {
|
||||
|
@ -109,3 +172,23 @@
|
|||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
@keyframes header-scroll-shadow {
|
||||
from {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
to {
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes column-scroll-shadow {
|
||||
from {
|
||||
background: linear-gradient(90deg, transparent, transparent);
|
||||
}
|
||||
|
||||
to {
|
||||
background: linear-gradient(90deg, hsla(0 0% 0% / .05), transparent);
|
||||
}
|
||||
}
|
|
@ -102,14 +102,14 @@ function Head<T extends Record<string, any>>(props: {}) {
|
|||
|
||||
return <header class={css.header}>
|
||||
<Show when={table.selectionMode() !== SelectionMode.None}>
|
||||
<div class={css.cell}>
|
||||
<aside>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={context.selection().length > 0 && context.selection().length === context.length()}
|
||||
indeterminate={context.selection().length !== 0 && context.selection().length !== context.length()}
|
||||
on:input={(e: InputEvent) => e.target.checked ? context.selectAll() : context.clear()}
|
||||
/>
|
||||
</div>
|
||||
</aside>
|
||||
</Show>
|
||||
|
||||
<For each={table.columns()}>{
|
||||
|
@ -137,15 +137,15 @@ function Row<T extends Record<string, any>>(props: { key: string, value: T, dept
|
|||
const values = createMemo(() => Object.entries(props.value));
|
||||
const isSelected = context.isSelected(props.key);
|
||||
|
||||
return <div class={css.row} use:selectable={{ value: props.value, key: props.key }}>
|
||||
return <div class={css.row} style={{ '--depth': props.depth }} use:selectable={{ value: props.value, key: props.key }}>
|
||||
<Show when={table.selectionMode() !== SelectionMode.None}>
|
||||
<div class={css.cell}>
|
||||
<aside>
|
||||
<input type="checkbox" checked={isSelected()} on:input={() => context.select([props.key])} on:pointerdown={e => e.stopPropagation()} />
|
||||
</div>
|
||||
</aside>
|
||||
</Show>
|
||||
|
||||
<For each={values()}>{
|
||||
([k, v]) => <div style={k === props.groupedBy ? { '--depth': props.depth } : {}} class={css.cell}>{table.cellRenderers()[k]?.({ value: v }) ?? v}</div>
|
||||
([k, v]) => <div class={css.cell}>{table.cellRenderers()[k]?.({ value: v }) ?? v}</div>
|
||||
}</For>
|
||||
</div>;
|
||||
};
|
||||
|
@ -153,16 +153,8 @@ function Row<T extends Record<string, any>>(props: { key: string, value: T, dept
|
|||
function Group<T extends Record<string, any>>(props: { key: string, groupedBy: keyof T, nodes: Node<T>[], depth: number }) {
|
||||
const table = useTable();
|
||||
|
||||
const gridColumn = createMemo(() => {
|
||||
const groupedBy = props.groupedBy;
|
||||
const columns = table.columns();
|
||||
const selectable = table.selectionMode() !== SelectionMode.None;
|
||||
|
||||
return columns.findIndex(({ id }) => id === groupedBy) + (selectable ? 2 : 1);
|
||||
});
|
||||
|
||||
return <details open>
|
||||
<summary style={{ '--depth': props.depth, 'grid-column-start': gridColumn() }}>{props.key}</summary>
|
||||
<summary style={{ '--depth': props.depth }}>{props.key}</summary>
|
||||
|
||||
<For each={props.nodes}>{
|
||||
node => <Node node={node} depth={props.depth + 1} groupedBy={props.groupedBy} />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue