diff --git a/components/order/demo/order-demo.js b/components/order/demo/order-demo.js new file mode 100644 index 00000000000..23ef364322b --- /dev/null +++ b/components/order/demo/order-demo.js @@ -0,0 +1,31 @@ +import '../order.js'; +import '../../button/button.js'; +import { css, html, LitElement } from 'lit'; + +/** + * A container element that can order its contents separately for keyboard users, screenreader users, and visually + * @slot content - Slot for primary content + */ +class OrderDemo extends LitElement { + + static get properties() { + return { + num: { type: Number }, + visualOrder: { type: String, attribute: 'visual-order' }, + keyboardOrder: { type: String, attribute: 'keyboard-order' }, + extra: { type: Boolean } + } + } + + render() { + return html` + ${Array(this.num).fill(0).map((item, idx) => { + return html`${idx + 1}` + })} + ${this.extra ? html`Extra Button` : null} + `; + } + +} + +customElements.define('d2l-order-demo', OrderDemo); diff --git a/components/order/demo/order.html b/components/order/demo/order.html new file mode 100644 index 00000000000..304baf1d023 --- /dev/null +++ b/components/order/demo/order.html @@ -0,0 +1,119 @@ + + + + + + + + + + + + + +

Order - Real-World

+ + + + + + + +

Order - Visual

+ + + + + + + +

Order - Visual & Keyboard

+ + + + + + + +

Order - Non-Interactive

+ + + + + + + +

Order - Toggle Extra Button

+ + Toggle Extra Button + + + + + + + + +
+ + diff --git a/components/order/order-item.js b/components/order/order-item.js new file mode 100644 index 00000000000..a3d2af59e92 --- /dev/null +++ b/components/order/order-item.js @@ -0,0 +1,17 @@ +import { css, html, LitElement } from 'lit'; + +/** + * A container element that can order its contents separately for keyboard users, screenreader users, and visually + * @slot content - Slot for primary content + */ +class OrderItem extends LitElement { + + static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }; + + render() { + return html``; + } + +} + +customElements.define('d2l-order-item', OrderItem); diff --git a/components/order/order.js b/components/order/order.js new file mode 100644 index 00000000000..0cbf405d778 --- /dev/null +++ b/components/order/order.js @@ -0,0 +1,73 @@ +import './order-item.js'; +import { css, html, LitElement } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; + +/** + * A container element that can order its contents separately for keyboard users, screenreader users, and visually. + * @slot content - Slot for primary content + */ +class Order extends LitElement { + + static get properties() { + return { + /** + * Specifies the order in which elements should be navigable by keyboard. + * This should almost never be set, allowing keyboard order to match the visual order. + * @type {array} + * @default {visualOrder} + */ + keyboardOrder: { type: Array, attribute: 'keyboard-order' }, + /** + * Specifies the order in which elements should appear visually + * @type {array} + */ + visualOrder: { type: Array, attribute: 'visual-order' }, + }; + } + + static get styles() { + return css` + :host { + display: flex; + align-items: center; + } + `; + } + + constructor() { + super(); + this.visualOrder = Array(this.childElementCount).fill(0).map((_, idx) => idx + 1); + } + + render() { + return html` + ${[...this.children].map((child, idx) => { + + child.slot = `item-${idx + 1}`; + const orderIdx = this.visualOrder.indexOf(idx + 1) + 1; + const styles = { order: orderIdx || idx + 1 }; + const tabindex = child.focus && (this.keyboardOrder?.indexOf(idx + 1) + 1 || orderIdx); + + return html` + + + + `; + })} + + `; + } + + #handleSlotChangeAdd(e) { + if (e.target.assignedElements().length) this.requestUpdate(); + } + + #handleSlotChangeRemove(e) { + if (!e.target.assignedElements().length) this.requestUpdate(); + } + +} + +customElements.define('d2l-order', Order);