Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions src/stable/components/Linktray/Linktray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
const template = document.createElement('template');
template.innerHTML = `
<style>
.linktray-container {
background: #f2f2f2;
border-left: 5px solid #feb70d;
padding: 20px 10px;

ul {
list-style-type: none;
display: grid;
margin: 0 auto;
gap: 1rem;
margin: 1rem -2rem;
@media (min-width: 600px) {
grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 900px) {
grid-template-columns: repeat(3, 1fr);
}
a {
font-size: 18px;
font-weight: 600;
text-decoration: none !important;
color: #000 !important;
}

svg {
top: 3px;
position: relative;
}
}
#tray-links :hover svg {
transform: translate(3px, 0px);
}
}
</style>
<div class='linktray-container'>
<span class='tray-title'>
<slot name="tray-title"></slot>
</span>
<ul id="tray-links">
<slot name="tray-link"></slot>
</span>
</ul>

`;

class Linktray extends HTMLElement {
constructor() {
super();

// Create a shadow root
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(template.content.cloneNode(true));
}

connectedCallback() {
this._fetchLinks();
}

_fetchLinks() {
const linkSlot = this.shadowRoot.querySelector('slot[name="tray-link"]');

linkSlot.addEventListener('slotchange', () => {
const elements = linkSlot.assignedElements();

elements.forEach((element) => {
const li = document.createElement('li');

// append element to li
li.appendChild(element);

// append Chevron
const chevron = document.createElement('span');
chevron.classList.add('chevron');
chevron.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708"/>
</svg> `;
li.appendChild(chevron);

// place li at the at the top of ul
const trayLinks = this.shadowRoot.querySelector('#tray-links');
trayLinks.insertBefore(li, trayLinks.children[0]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't quite right. This is taking the slotted a elements, moving them out of the light DOM slot, and moving them into the shadow DOM (and out of the slot).

Notice how there's nothing inside the <slot name=tray-link> slot:

image

We want the slotted elements to remain in the light DOM slot, but wrapped in li elements.

To keep the elements in the light DOM, we need to add the slot=link-tray attribute to the li tag created, and then append the li elements to the element cod-linktray instead of appending to an element in the shadowRoot like '#tray-links.

You can see an example of how this is done at lines 88-94 for the section navigation component:

// Wrap the 'a' element in an 'li'
const li = document.createElement('li');
li.classList.add('nav-item');
li.setAttribute('slot', 'nav-items');
element.removeAttribute('slot');
element.parentNode.insertBefore(li, element);
li.appendChild(element);

Notice how the resulting HTML looks for the section navigation with the li elements inside the <slot name=nav-items>:

image

});
});
}
}

export { Linktray as default };
2 changes: 2 additions & 0 deletions src/stable/components/Linktray/cod-linktray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Linktray from './Linktray';
customElements.define('cod-linktray', Linktray);
53 changes: 53 additions & 0 deletions src/stable/stories/linktray.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import '../../stable/components/Linktray/cod-linktray';
import { html } from 'lit-html';

export default {
tags: ['stable'],
title: 'Components/Linktray',
};

export const Linktray = {
tags: ['autodocs'],
render: () => html`
<style>
.linktray [slot='tray-title'] { font-size: 20px; font-weight: 700;}

}
</style>
<cod-linktray class="linktray">
<span slot="tray-title"> More from Mayor's Office </span>

<a slot="tray-link" href="https://www.example.com">State of the city</a>
<a slot="tray-link" href="https://www.example.com">Properties</a>
<a slot="tray-link" href="https://www.example.com">Special Events</a>
<a slot="tray-link" href="https://www.example.com">Correspondence</a>
<a slot="tray-link" href="https://www.example.com"
>Renew Detroit Home Repair Program</a
>
<a slot="tray-link" href="https://www.example.com"
>Michigan State Fair Grounds Development</a
>
<a slot="tray-link" href="https://www.example.com"
>Detroit Neighborhood Initiatve</a
>
<a slot="tray-link" href="https://www.example.com">LEAN</a>
<a slot="tray-link" href="https://www.example.com"
>Detroit Opportunities</a
>
<a slot="tray-link" href="https://www.example.com">Mayor's Help Desk</a>
<a slot="tray-link" href="https://www.example.com">Executive Orders</a>
</cod-linktray>
`,
};

// Slots ----- tray title ---- links
// target tray body to resize ------ mobile 1 column ---- DT 3 col
// Grid 2 body size options - V or H
// child depts, related dept, More from this dept (Depts / More)
// Col, if more than 10? links
// grid-template-columns: repeat(auto-fit,minmax(132px, 1fr));
// grid-template-columns: 1fr 1fr 1fr;
// grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));

// https://www.w3schools.com/css/css3_flexbox_responsive.asp
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement
Loading