diff --git a/src/UI/Components/Table.js b/src/UI/Components/Table.js new file mode 100644 index 00000000..865aa7c4 --- /dev/null +++ b/src/UI/Components/Table.js @@ -0,0 +1,83 @@ +import { Component, defineComponent } from "../../util/Component.js"; + +/** + * A table with a sticky header + */ +export default class Table extends Component { + static PROPERTIES = { + headings: { value: [] }, + scale: { value: '2pt' }, + rows: { value: [] }, + } + + static CSS = /*css*/` + table { + box-sizing: border-box; + border-collapse: collapse; + width: 100%; + } + + thead th { + box-shadow: 0 1px 4px -2px rgba(0,0,0,0.2); + backdrop-filter: blur(2px); + position: sticky; + z-index: 100; + padding: + calc(10 * var(--scale)) + calc(2.5 * var(--scale)) + calc(5 * var(--scale)) + calc(2.5 * var(--scale)); + top: 0; + background-color: hsla(0, 0%, 100%, 0.8); + text-align: left; + border-bottom: 1px solid #e0e0e0; + } + + thead th:not(:last-of-type) { + /* we set borders on this span because */ + /* borders fly away from sticky headers */ + border-right: 1px solid #e0e0e0; + } + + tbody > * { + border-bottom: 1px solid #e0e0e0; + padding: 0 calc(2.5 * var(--scale)); + vertical-align: middle; + } + `; + + create_template ({ template }) { + $(template).html(` + + + + + + + +
+ `); + } + + on_ready ({ listen }) { + listen('headings', headings => { + $(this.dom_).find('.headings') + .html(headings.map(heading => `${heading}`).join('')) + }); + + listen('scale', scale => { + $(this.dom_).css('--scale', scale); + }); + + listen('rows', rows => { + const tbody = $(this.dom_).find('tbody')[0]; + $(tbody).find('[slot=rows]').detach(); + for (const row of rows) { + row.setAttribute('slot', 'rows'); + row.attach(tbody); + } + }); + } +} + +defineComponent('c-table', Table);