From aa3d9f73bba95aa123ec87938b4718ed84eda6b2 Mon Sep 17 00:00:00 2001 From: Max Morgan Date: Thu, 7 Mar 2024 15:17:12 -0500 Subject: [PATCH 1/2] Introduce unordered list component --- .../atoms/UnorderedList/UnorderedList.css | 8 ++++ .../atoms/UnorderedList/UnorderedList.js | 41 +++++++++++++++++++ src/components/atoms/UnorderedList/cod-ul.js | 2 + src/stories/unorderedlist.stories.js | 21 ++++++++++ 4 files changed, 72 insertions(+) create mode 100644 src/components/atoms/UnorderedList/UnorderedList.css create mode 100644 src/components/atoms/UnorderedList/UnorderedList.js create mode 100644 src/components/atoms/UnorderedList/cod-ul.js create mode 100644 src/stories/unorderedlist.stories.js diff --git a/src/components/atoms/UnorderedList/UnorderedList.css b/src/components/atoms/UnorderedList/UnorderedList.css new file mode 100644 index 00000000..6885adc6 --- /dev/null +++ b/src/components/atoms/UnorderedList/UnorderedList.css @@ -0,0 +1,8 @@ +ul { + color: grey; +} + +::slotted(li) { + color: blue; + list-style-type: none; +} diff --git a/src/components/atoms/UnorderedList/UnorderedList.js b/src/components/atoms/UnorderedList/UnorderedList.js new file mode 100644 index 00000000..9b7bad26 --- /dev/null +++ b/src/components/atoms/UnorderedList/UnorderedList.js @@ -0,0 +1,41 @@ +import styles from '!!raw-loader!./UnorderedList.css'; +import varStyles from '!!raw-loader!../../../shared/variables.css'; +import bootstrapStyles from '!!raw-loader!../../../shared/themed-bootstrap.css'; + +const template = document.createElement('template'); +template.innerHTML = ` + +`; + +class UnorderedList extends HTMLElement { + static observedAttributes = []; + + constructor() { + // Always call super first in constructor + super(); + // Create a shadow root + const shadow = this.attachShadow({ mode: 'open' }); + shadow.appendChild(template.content.cloneNode(true)); + + // Add styles + const bootStyles = document.createElement('style'); + bootStyles.textContent = bootstrapStyles; + const variableStyles = document.createElement('style'); + variableStyles.textContent = varStyles; + const itemStyles = document.createElement('style'); + itemStyles.textContent = styles; + shadow.appendChild(bootStyles); + shadow.appendChild(variableStyles); + shadow.appendChild(itemStyles); + } + + connectedCallback() { + this.getAttribute('icon'); + // TODO: Handle icon attribute and append icon in front of list elements. + } +} + +export { UnorderedList as default }; \ No newline at end of file diff --git a/src/components/atoms/UnorderedList/cod-ul.js b/src/components/atoms/UnorderedList/cod-ul.js new file mode 100644 index 00000000..4a114555 --- /dev/null +++ b/src/components/atoms/UnorderedList/cod-ul.js @@ -0,0 +1,2 @@ +import UnorderedList from './UnorderedList'; +customElements.define('cod-ul', UnorderedList); \ No newline at end of file diff --git a/src/stories/unorderedlist.stories.js b/src/stories/unorderedlist.stories.js new file mode 100644 index 00000000..3eae3e7d --- /dev/null +++ b/src/stories/unorderedlist.stories.js @@ -0,0 +1,21 @@ +import { html } from 'lit-html'; +import '../components/atoms/UnorderedList/cod-ul'; + +export default { + title: 'Components/Atoms/UnorderedList', + argTypes: { + }, +}; + +export const Default = () => html` +
+

To be implemented

+ +
  • + Item 1 +
    • Inner element
    +
  • +
  • Item 2
  • +
    +
    `; + From cec80414897be2d882ca63ff2b5583ceeb370c46 Mon Sep 17 00:00:00 2001 From: Max Morgan Date: Mon, 11 Mar 2024 14:47:37 -0400 Subject: [PATCH 2/2] Implement icon on unordered list --- .../atoms/UnorderedList/UnorderedList.css | 5 -- .../atoms/UnorderedList/UnorderedList.js | 14 +++- src/stories/unorderedlist.stories.js | 81 ++++++++++++++++--- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/components/atoms/UnorderedList/UnorderedList.css b/src/components/atoms/UnorderedList/UnorderedList.css index 6885adc6..c4609a1e 100644 --- a/src/components/atoms/UnorderedList/UnorderedList.css +++ b/src/components/atoms/UnorderedList/UnorderedList.css @@ -1,8 +1,3 @@ -ul { - color: grey; -} - ::slotted(li) { - color: blue; list-style-type: none; } diff --git a/src/components/atoms/UnorderedList/UnorderedList.js b/src/components/atoms/UnorderedList/UnorderedList.js index 9b7bad26..4a9e31a7 100644 --- a/src/components/atoms/UnorderedList/UnorderedList.js +++ b/src/components/atoms/UnorderedList/UnorderedList.js @@ -33,8 +33,18 @@ class UnorderedList extends HTMLElement { } connectedCallback() { - this.getAttribute('icon'); - // TODO: Handle icon attribute and append icon in front of list elements. + const icon = this.getAttribute('icon'); + // TODO: Move this logic into the slotchange event (to avoid the global queryselector). + const listItems = document.querySelectorAll('li[slot="list-item"]'); + listItems.forEach((listItem) => { + if (listItem.querySelector('cod-icon') !== null) { + return; + } + const codIcon = document.createElement('cod-icon'); + codIcon.setAttribute('data-icon', icon); + codIcon.setAttribute('data-size', 'small'); + listItem.prepend(codIcon); + }); } } diff --git a/src/stories/unorderedlist.stories.js b/src/stories/unorderedlist.stories.js index 3eae3e7d..a1f93426 100644 --- a/src/stories/unorderedlist.stories.js +++ b/src/stories/unorderedlist.stories.js @@ -1,21 +1,80 @@ import { html } from 'lit-html'; +import '../components/atoms/Icon/cod-icon'; import '../components/atoms/UnorderedList/cod-ul'; export default { title: 'Components/Atoms/UnorderedList', argTypes: { + icon: { + description: 'Determines the icon used in the list in place of a list bullet.', + control: { type: 'select' }, + options: [ + 'chevron-right', + 'chevron-right-circle', + 'chevron-right-circle-fill', + 'chevron-left', + 'chevron-left-circle', + 'chevron-left-circle-fill', + 'chevron-up', + 'chevron-up-circle', + 'chevron-up-circle-fill', + 'chevron-down', + 'chevron-down-circle', + 'chevron-down-circle-fill', + 'house', + 'house-fill', + 'exclamation-circle', + 'exclamation-circle-fill', + 'exclamation-triangle', + 'check-circle', + 'check-circle-fill', + 'calendar', + 'calendar-fill', + 'calendar-date', + 'calendar-date-fill', + 'newspaper', + 'building', + 'building-fill', + 'buildings', + 'buildings-fill', + 'currency-dollar', + 'file-earmark', + 'list-task', + 'journals', + ].sort(), + }, + }, + args: { + icon: 'list-task', }, }; -export const Default = () => html` -
    -

    To be implemented

    - -
  • - Item 1 -
    • Inner element
    -
  • -
  • Item 2
  • -
    -
    `; +export const Default = (args) => { + const codList = document.createElement('cod-ul'); + codList.setAttribute('icon', args.icon); + ['Item 1', 'Item 2', 'Item 3'].forEach((innerText) => { + const listItem = document.createElement('li'); + listItem.innerText = innerText; + listItem.setAttribute('slot', 'list-item'); + codList.appendChild(listItem); + + // Create an inner element to demo style + // change for inner list items. + const innerList = document.createElement('ul'); + const innerListItem = document.createElement('li'); + innerListItem.innerText = 'Inner list'; + innerList.appendChild(innerListItem); + listItem.appendChild(innerList); + }); + return codList; +} +// export const StaticIcon = () => html` +// +//
  • +// Item 1 +//
    • Inner element
    +//
  • +//
  • Item 2
  • +//
    +// `; \ No newline at end of file