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
+
+
+
+
+
+
+
+ Save & Close
+ Save
+ Cancel
+
+
+
+
+
+
+ Order - Visual
+
+
+
+
+
+
+ One
+ Two
+ Three
+ Four
+ Five
+
+
+
+
+
+
+ Order - Visual & Keyboard
+
+
+
+
+
+
+ One
+ Two
+ Three
+ Four
+ Five
+
+
+
+
+
+
+ Order - Non-Interactive
+
+
+
+
+
+
+ One
+ Two
+ Three
+ Four
+ Five
+
+
+
+
+
+
+ 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);