diff --git a/src/stable/components/Event/Event.js b/src/stable/components/Event/Event.js new file mode 100644 index 00000000..43a6861f --- /dev/null +++ b/src/stable/components/Event/Event.js @@ -0,0 +1,93 @@ +import styles from '!!raw-loader!./event.css'; + +const template = document.createElement('template'); +template.innerHTML = ` + +
+
+
+
+
+
+
+ + + + + + +
+
+
+ + + +
+
+ + + + + + +
+
+ +
+
+
+
+ +`; + +class Event extends HTMLElement { + constructor() { + super(); + + // Create a shadow root + const shadow = this.attachShadow({ mode: 'open' }); + shadow.appendChild(template.content.cloneNode(true)); + } + connectedCallback() { + this.setupDatetime(); + } + + setupDatetime() { + // Get args.when (Date) + const dateInfo = this.getAttribute('datetime'); + const numFromString = Number(dateInfo); + const dateISO = new Date(numFromString).toISOString(); + // Month & Day + const dateFormat = new Date(dateISO).toLocaleDateString('en-DE', { + month: 'short', + day: 'numeric', + }); + const dateSpan = document.createElement('span'); + dateSpan.innerText = dateFormat + '\n'; + const eventDate = this.shadowRoot.querySelector('.event-date'); + eventDate.appendChild(dateSpan); + + // Year + const year = new Date(dateISO).toLocaleDateString('en-DE', { + year: 'numeric', + }); + const yearSpan = document.createElement('span'); + yearSpan.innerText = year; + const eventYear = this.shadowRoot.querySelector('.event-year'); + eventYear.appendChild(yearSpan); + + // Get Time + const locTime = new Date(dateISO).toLocaleTimeString('en-US', { + hour: '2-digit', + minute: '2-digit', + }); + const timeSpan = document.createElement('span'); + timeSpan.innerText = locTime; + const eventTime = this.shadowRoot.querySelector('.event-time'); + eventTime.appendChild(timeSpan); + } +} + +export default Event; diff --git a/src/stable/components/Event/cod-event.js b/src/stable/components/Event/cod-event.js new file mode 100644 index 00000000..5f7997d1 --- /dev/null +++ b/src/stable/components/Event/cod-event.js @@ -0,0 +1,2 @@ +import Event from './Event'; +customElements.define('cod-event', Event); diff --git a/src/stable/components/Event/event.css b/src/stable/components/Event/event.css new file mode 100644 index 00000000..feeb6ddd --- /dev/null +++ b/src/stable/components/Event/event.css @@ -0,0 +1,54 @@ +.event-container { + width: fit-content; + min-width: 340px; + display: flex; +} +.event-container .date-info { + background-color: #004445; + height: 75px; + justify-content: center; + text-align: center; + flex: 0; + color: white; + font-weight: lighter; + padding: 3px 20px; + line-height: normal; +} +.event-container .date-info .event-date { + color: white; + flex: 0; + font-weight: 900; + display: flex; +} +.event-container .event-info { + flex: 3; + padding: 5px 10px; +} +.event-container .event-info .event-title { + display: flex; +} +.event-container .event-info .event-title ::slotted(a) { + text-decoration: none !important; + border-bottom: 3px solid #279989 !important; + color: #000 !important; +} +.event-container .event-info .event-title svg { + top: 5px; + position: relative; +} +.event-container .event-info .event-title:hover svg { + transform: translate(5px, 0px); +} +.event-container .event-info .info-row { + display: flex; + margin-top: 10px; + flex-flow: row wrap; +} +.event-container .event-info .info-row .info-item { + flex-grow: 1; +} +.event-container .event-info .info-row .event-time { + font-weight: 900; +} + +/*# sourceMappingURL=event.css.map */ diff --git a/src/stable/components/Event/event.css.map b/src/stable/components/Event/event.css.map new file mode 100644 index 00000000..7e007c33 --- /dev/null +++ b/src/stable/components/Event/event.css.map @@ -0,0 +1 @@ +{"version":3,"sourceRoot":"","sources":["event.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;;AAEA;EACE;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE","file":"event.css"} \ No newline at end of file diff --git a/src/stable/components/Event/event.scss b/src/stable/components/Event/event.scss new file mode 100644 index 00000000..67ef25e8 --- /dev/null +++ b/src/stable/components/Event/event.scss @@ -0,0 +1,62 @@ +.event-container { + width: fit-content; + min-width: 340px; + display: flex; + + .date-info { + background-color: #004445; + height: 75px; + justify-content: center; + text-align: center; + flex: 0; + color: white; + font-weight: lighter; + padding: 3px 20px; + line-height: normal; + + .event-date { + color: white; + flex: 0; + font-weight: 900; + display: flex; + } + } + + .event-info { + flex: 3; + padding: 5px 10px; + + .event-title { + display: flex; + + ::slotted(a) { + text-decoration: none !important; + border-bottom: 3px solid #279989 !important; + color: #000 !important; + } + + svg { + top: 5px; + position: relative; + } + } + + .event-title:hover svg { + transform: translate(5px, 0px); + } + + .info-row { + display: flex; + margin-top: 10px; + flex-flow: row wrap; + + .info-item { + flex-grow: 1; + } + + .event-time { + font-weight: 900; + } + } + } +} diff --git a/src/stable/components/Tag/Tag.css b/src/stable/components/Tag/Tag.css index 46c95b74..b6c9667c 100644 --- a/src/stable/components/Tag/Tag.css +++ b/src/stable/components/Tag/Tag.css @@ -1,3 +1,8 @@ .tag-container { display: inline; + + ::slotted(a) { + text-decoration: none !important; + color: #000 !important; + } } diff --git a/src/stable/docs/Event.mdx b/src/stable/docs/Event.mdx new file mode 100644 index 00000000..ff2cee44 --- /dev/null +++ b/src/stable/docs/Event.mdx @@ -0,0 +1,84 @@ +import { + Meta, + Canvas, + Title, + Subtitle, + Description, + Primary, + Controls, + Stories, + Story, + Source, +} from '@storybook/blocks'; +import * as EventStories from '../stories/event.stories'; + +import '../../../.storybook/docs'; // Import all documentation components + + + +# Event + +
+ Event element will be used within Department pages to display Event + information +
+ +## Usage + + + + + +## + + + +## Slots + + + + +## HTML Attributes / JS Properties + + element."}, +])}> + + +## Events + + + + +## Methods + + + + +## Custom CSS Properties + + + + +## CSS Parts + + + + +## Dependencies + + + +## Accessibility + +event components are designed to be accessible by default. diff --git a/src/stable/stories/event.stories.js b/src/stable/stories/event.stories.js new file mode 100644 index 00000000..11200384 --- /dev/null +++ b/src/stable/stories/event.stories.js @@ -0,0 +1,115 @@ +import '../components/Event/cod-event'; +import '../components/Tag/cod-tag'; +import { html } from 'lit-html'; +import { expect } from '@storybook/test'; + +export default { + title: 'Components/Event', + argTypes: { + title: { control: 'text' }, + when: { control: 'date' }, + virutalEvent: { control: 'boolean' }, + location: { control: 'text' }, + tag: { control: 'text' }, + }, +}; + +const Template = (args) => { + const event = document.createElement('cod-event'); + + // Title + const title = document.createElement('a'); + title.setAttribute('href', 'https://www.example.com'); + title.slot = 'event-title'; + title.textContent = args.title; + event.appendChild(title); + + // Datetime + const eventDate = args.when; + event.setAttribute('datetime', eventDate); + + // Default Datetime + if (!args.when) { + const defaultDate = Date.now(); + event.setAttribute('datetime', defaultDate); + } + + // Location + const location = document.createElement('span'); + location.slot = 'event-location'; + + // Virtual Event + if (args.virutalEvent === true) { + location.textContent = 'Virtual Event'; + } else { + location.textContent = args.location; + } + event.appendChild(location); + + // Tag + const tagSpan = document.createElement('span'); + tagSpan.innerHTML = ` + ${args.tag} + `; + tagSpan.slot = 'event-tag'; + event.appendChild(tagSpan); + + return event; +}; + +export const Default = Template.bind({}); + +Default.args = { + title: 'DDOT Virtual Community Input Meeting', + location: 'Conference Room', + tag: 'Meeting', +}; + +export const TagLink = { + tags: ['!dev'], + render: () => { + return html` + + DDOT Virtual Community Input Meeting + Conference Room + Click Me + + `; + }, +}; + +export const Test = { + tags: ['!dev'], + render: () => { + return html` + DDOT Virtual Community Input MeetingConference Room + Meeting + + `; + }, + play: async ({ canvasElement }) => { + const event = canvasElement.querySelector('cod-event'); + const eventShadowRoot = event.shadowRoot; + const titleSlot = eventShadowRoot.querySelector('slot[name="event-title"]'); + + // Tests if title slot is empty + expect(titleSlot).not.toBeNull(); + + // Test if title is a link + const titleLink = titleSlot.assignedElements()[0]; + expect(titleLink.tagName).toBe('A'); + }, +};