const categories = [ { id: 'typography', name: 'Typography', description: 'HTML, being a markup language, has abundantly clear semantics for basic typography. Water.css leaves those semantics untouched.', snippets: [ { id: 'copy', name: 'Headings and copy', code: `

Heading 1

This is a paragraph that could contain long-form text. Heck, here's a link. This is important, this is normal, and this is emphasized!

This is another paragraph that could contain long-form text.

Heading 2

You probably get the idea by now!

Heading 3

Heading 4

Heading 5
Heading 6
` }, { id: 'quotes', name: 'Quotes', code: `
"The HTML blockquote Element (or HTML Block Quotation Element) indicates that the enclosed text is an extended quotation. Usually, this is rendered visually by indentation (see Notes for how to change it). A URL for the source of the quotation may be given using the cite attribute, while a text representation of the source can be given using the <cite> cite element."

Did you know HTML supports inline quotes? I didn't, until I read that the <q> HTML element indicates that the enclosed text is a short inline quotation .

` }, { id: 'lists', name: 'Lists', code: `
  1. Ordered list item 1
  2. Ordered list item 2
  3. Ordered list item 3
Unordered lists
Represents an unordered list of items, typically rendered as a bulleted list
Ordered lists
Represents an ordered list of items, typically rendered as a numbered list
Description lists
Encloses a list of groups of terms and descriptions
Not commonly used, but still nifty
` }, { id: 'code-etc', name: 'Code samples, keyboard shortcuts, oh my', code: `

Below is some code. If you select it, you can copy using Ctrl-C. Did you know that alert(1) can show an alert in JavaScript?

// This logs a message to the console and check out the scrollbar.
console.log('Hello, world!')

HTML also has elements for variables and sample output: Hello, world!

` } ] }, { id: 'forms', name: 'Form controls', description: 'Water.css provides a set of styles for form controls, including text inputs, select boxes, buttons, and more.', snippets: [ { id: 'text-inputs', name: 'Text inputs', code: `
` }, { id: 'buttons', name: 'Buttons', code: `
` }, { id: 'assorted-inputs', name: 'Assorted other controls', code: `
Choose a Doe
` }, { id: 'dialogs', name: 'Dialogs', caniuse: 'https://caniuse.com/dialog', code: `
This is a sample dialog

What is your favorite pet animal?

`, realCode: `
` } ] }, { id: 'misc', name: 'Miscellaneous', description: 'Styles are also provided for various other elements that don\'t strictly fit into the other categories. These include tables, dialogs, and images.', snippets: [ { id: 'tables', name: 'Tables', code: `
Name Quantity Price
Godzilla 2 $299.99
Mozilla 10 $100,000.00
Quesadilla 1 $2.22
` }, { id: 'details', name: 'Summary/details', caniuse: 'https://caniuse.com/details', code: `
Some summary/details can't hurt!

Lorem ipsum dolor sit blah blah.

` }, { id: 'rules-etc', name: 'Rules, images, and addresses', code: `

Here's a horizontal rule and image because I don't know where else to put them.

Example kitten

Addresses are also styled to be awesome!

john.doe@example.com
778-330-2389
666-666-6666
` } ] } ] const tocContainer = document.getElementById('toc') for (const category of categories) { const li = document.createElement('li') const a = document.createElement('a') a.href = `#${category.id}` a.innerText = category.name li.appendChild(a) const ul = document.createElement('ul') for (const snippet of category.snippets) { const li = document.createElement('li') const a = document.createElement('a') a.href = `#${snippet.id}` a.innerText = snippet.name li.appendChild(a) ul.appendChild(li) } li.appendChild(ul) tocContainer.appendChild(li) } const demosContainer = document.getElementById('demos') let first = true for (const category of categories) { const h2 = document.createElement('h2') h2.id = category.id h2.innerText = category.name demosContainer.appendChild(h2) const p = document.createElement('p') p.innerText = category.description demosContainer.appendChild(p) for (const snippet of category.snippets) { const h3 = document.createElement('h3') h3.id = snippet.id h3.innerText = snippet.name demosContainer.appendChild(h3) if (snippet.caniuse) { const p = document.createElement('p') p.innerText = '⚠️ This may not be supported in all browsers. ' const a = document.createElement('a') a.href = snippet.caniuse a.target = '_blank' a.rel = 'noopener noreferrer' a.innerText = 'See caniuse for more info.' p.appendChild(a) demosContainer.appendChild(p) } const pre = document.createElement('pre') const code = document.createElement('code') code.innerText = snippet.code.trim() pre.style.position = 'relative' pre.appendChild(code) const button = document.createElement('button') button.innerText = 'Copy' button.className = 'snippet-copy' let timeout = null button.addEventListener('click', () => { navigator.clipboard.writeText(snippet.code.trim()) button.innerText = 'Copied!' clearTimeout(timeout) timeout = setTimeout(() => { button.innerText = 'Copy' }, 1000) }) pre.appendChild(button) demosContainer.appendChild(pre) const details = document.createElement('details') details.id = `${snippet.id}-details` details.innerHTML = snippet.realCode || snippet.code // Execute any scripts in the HTML. Array.from(details.querySelectorAll('script')).forEach((oldScript) => { const newScript = document.createElement('script') for (const { name, value } of oldScript.attributes) { newScript.setAttribute(name, value) } newScript.appendChild(document.createTextNode(oldScript.innerHTML)) oldScript.parentNode.replaceChild(newScript, oldScript) }) const summary = document.createElement('summary') summary.innerText = 'Show output' details.prepend(summary) demosContainer.appendChild(details) if (first) { details.open = true first = false let firstToggle = true details.addEventListener('toggle', () => { if (!details.open || firstToggle) return firstToggle = false history.pushState({}, '', '#' + snippet.id) }) } else { details.addEventListener('toggle', () => { if (!details.open) return history.pushState({}, '', '#' + snippet.id) }) } } } const hashChange = () => { const details = document.getElementById(`${window.location.hash.slice(1)}-details`) if (!details) return details.open = true } window.addEventListener('hashchange', hashChange, false) hashChange() // Dialog demo scripting. document.getElementById('dialog-trigger').addEventListener('click', () => { document.getElementById('dialog-result').innerText = '' document.getElementById('dialog').showModal() }) document.getElementById('dialog').addEventListener('close', (event) => { document.getElementById('dialog-result').innerText = `Your answer: ${event.target.returnValue}` })