Skip to content

Commit

Permalink
Side Nav Improvements (#133)
Browse files Browse the repository at this point in the history
  • Loading branch information
colegoldsmith committed May 16, 2024
1 parent b466aa7 commit 1c82089
Show file tree
Hide file tree
Showing 17 changed files with 173 additions and 75 deletions.
2 changes: 1 addition & 1 deletion preview-src/ui-model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ site:
"items": [
{ "title": "Apache Pulsar Connector", "url": "#" },
{ "title": "CDC for Cassandra", "url": "#" },
{ "title": "K8ssandra", "url": "#" },
{ "title": "K8ssandra", "url": "https://docs.k8ssandra.io" },
{ "title": "Stargate", "url": "#" },
{ "title": "Starlight for JMS", "url": "#" },
{ "title": "Starlight for Kafka", "url": "#" },
Expand Down
22 changes: 7 additions & 15 deletions src/css/components/collapse.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
@layer components {
.collapse {
@apply !visible grid;
@apply !visible;
}

.collapse > .collapse-content {
@apply relative col-start-1 row-start-2 grid min-h-0;
@apply grid min-h-0 invisible;

grid-template-rows: 0fr;
transition: grid-template-rows 0.2s;
transition-property: grid-template-rows, visibility;
transition-duration: 0.2s;
transition-behavior: allow-discrete;

@media (prefers-reduced-motion: reduce) {
transition-property: none;
Expand All @@ -18,19 +20,9 @@
@apply overflow-hidden;
}

.collapse-title,
.collapse > input[type="checkbox"],
.collapse > input[type="radio"] {
@apply col-start-1 row-start-1;
}

.collapse > input[type="checkbox"],
.collapse > input[type="radio"] {
@apply cursor-pointer appearance-none opacity-0;
}
.collapse > .collapse-content.active {
@apply visible;

.collapse > input[type="checkbox"]:checked ~ .collapse-content,
.collapse > input[type="radio"]:checked ~ .collapse-content {
grid-template-rows: 1fr;
}
}
2 changes: 1 addition & 1 deletion src/css/vars/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
--ds-primary-soft-color: var(--ds-primary-200);
--ds-primary-soft-disabled-bg: var(--ds-primary-600);
--ds-primary-soft-disabled-color: var(--ds-primary-800);
--ds-primary-soft-hover-bg: var(--ds-primary-500);
--ds-primary-soft-hover-bg: var(--ds-primary-700);
--ds-primary-solid-active-bg: var(--ds-primary-600);
--ds-primary-solid-bg: var(--ds-primary-600);
--ds-primary-solid-color: var(--ds-common-white);
Expand Down
4 changes: 2 additions & 2 deletions src/css/vars/light.css
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@
--ds-primary-plain-color: var(--ds-primary-600);
--ds-primary-plain-disabled-color: var(--ds-primary-200);
--ds-primary-plain-hover-bg: var(--ds-primary-100);
--ds-primary-soft-active-bg: var(--ds-primary-300);
--ds-primary-soft-active-bg: var(--ds-primary-200);
--ds-primary-soft-bg: var(--ds-primary-0);
--ds-primary-soft-color: var(--ds-primary-600);
--ds-primary-soft-disabled-bg: var(--ds-primary-100);
--ds-primary-soft-disabled-color: var(--ds-primary-300);
--ds-primary-soft-hover-bg: var(--ds-primary-200);
--ds-primary-soft-hover-bg: var(--ds-primary-100);
--ds-primary-solid-active-bg: var(--ds-primary-700);
--ds-primary-solid-bg: var(--ds-primary-500);
--ds-primary-solid-color: var(--ds-common-white);
Expand Down
38 changes: 28 additions & 10 deletions src/helpers/global-nav-active.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,45 @@

module.exports = module.exports = (navItem, {
data: {
root: { page },
root: { page, site },
},
}) => {
const pageVersion = page.componentVersion?.version
const pageComponent = page.component?.name

const getIgnoredActiveComponents = (items) => {
return items.reduce((acc, item) => {
if (item.ignoreActiveComponent) {
acc[item.url] = item.component
}
if (item.items) {
acc = { ...acc, ...getIgnoredActiveComponents(item.items) }
}
return acc
}, {})
}

const ignoredActiveComponents = getIgnoredActiveComponents(site.keys.globalNav)

const matchesComponentAndVersion = (item) => {
if (pageVersion) {
return item.component === pageComponent && item.version === pageVersion
} else {
if (ignoredActiveComponents[page.url] === pageComponent && !item.ignoreActiveComponent) {
return false
}
if (item.ignoreActiveComponent) {
return item.url === page.url
}
if (item.component) {
if (item.version && pageVersion) {
return item.component === pageComponent && item.version === pageVersion
}
return item.component === pageComponent
}
}

if (navItem.component) {
return matchesComponentAndVersion(navItem)
return false
}

if (navItem.items) {
return navItem.items.some(matchesComponentAndVersion)
} else {
return matchesComponentAndVersion(navItem)
}

return false
}
5 changes: 5 additions & 0 deletions src/helpers/log-pretty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict'

module.exports = (obj) => {
return console.log(JSON.stringify(obj, null, 2))
}
6 changes: 6 additions & 0 deletions src/helpers/nav-id.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict'

module.exports = (level = 0, content) => {
if (!content) return
return `${level}-${content.replace(/\s+/g, '-').toLowerCase()}`
}
10 changes: 5 additions & 5 deletions src/js/01-nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
// Useful for pages with no nav links i.e. landing pages.
const sideNav = document.querySelector('#side-nav')
if (sideNav) {
const checkedInputs = sideNav.querySelectorAll('input[type="checkbox"]:checked, input[type="radio"]:checked')
if (!checkedInputs.length) {
const firstInput = sideNav.querySelector('input[type="checkbox"], input[type="radio"]')
if (firstInput) {
firstInput.checked = true
const activeCollapses = sideNav.querySelectorAll('.collapse > .collapse-content.active')
if (!activeCollapses.length) {
const firstCollapse = sideNav.querySelector('.collapse > .collapse-content')
if (firstCollapse) {
firstCollapse.classList.add('active')
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/js/02-on-this-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
headingsSelector.push(headingSelector.join('>'))
}
var headings = find(headingsSelector.join(','), article.parentNode)
if (!headings.length) return sidebar.querySelector('.toc-menu').classList.add('hidden')
if (!headings.length) return sidebar.classList.add('!hidden')

var lastActiveFragment
var links = {}
Expand Down
36 changes: 33 additions & 3 deletions src/js/09-dropdown.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
/**
* Dropdown Example
*
* Optional: data-trigger-type="hover" (default is "click")
* Optional: data-placement="right-start" (default is "bottom-start")
* Valid Placement Options:
* top, top-start, top-end,
* right, right-start, right-end,
* bottom, bottom-start, bottom-end,
* left, left-start, left-end
*
* <div class="dropdown" data-trigger-type="hover" data-placement="bottom-start">
* <button id="dropdown-1" class="dropdown-trigger" aria-haspopup="true">
* Show or Hide Content
* </button>
* <ul class="dropdown-content" role="menu" aria-orientation="vertical" aria-labelledby="dropdown-1">
* <li role="menuitem"><a href="#">Dropdown Item 1</a></li>
* <li role="menuitem"><a href="#">Dropdown Item 2</a></li>
* </ul>
* </div>
*/

;(function () {
'use strict'

Expand All @@ -11,12 +33,17 @@
})
}

const dropdownFn = (trigger, dropdown, triggerType = 'click') => {
const dropdownFn = (trigger, dropdown, triggerType = 'click', placement) => {
const update = () => {
computePosition(trigger, dropdown, {
strategy: 'fixed',
middleware: [
autoPlacement({ alignment: 'start', allowedPlacements: ['bottom', 'bottom-start', 'bottom-end'] }),
autoPlacement(
{
alignment: 'start',
allowedPlacements: placement ? [placement] : ['bottom', 'bottom-start', 'bottom-end'],
}
),
shift(),
],
}).then(({ x, y }) => {
Expand Down Expand Up @@ -68,6 +95,8 @@
}
}

trigger.ariaExpanded = false

if (triggerType === 'hover' && !isTouchDevice) {
trigger.addEventListener('mouseenter', show)
trigger.addEventListener('mouseenter', clearHideTimeout)
Expand All @@ -84,8 +113,9 @@
// Init all dropdowns
document.querySelectorAll('.dropdown').forEach((dropdown) => {
const triggerType = dropdown.dataset.triggerType
const placement = dropdown.dataset.placement
const trigger = dropdown.querySelector('.dropdown-trigger')
const content = dropdown.querySelector('.dropdown-content')
dropdownFn(trigger, content, triggerType)
dropdownFn(trigger, content, triggerType, placement)
})
})()
35 changes: 35 additions & 0 deletions src/js/10-collapse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Collapse Example
*
* <div class="collapse">
* <button id="collapse-button-1" class="collapse-trigger" aria-controls="collapse-content-1" >
* Show or Hide Content
* </button>
* <div id="collapse-content-1" class="collapse-content" aria-labelledby="collapse-button-1">
* <p>Collapse Content</p>
* </div>
* </div>
*/

;(function () {
'use strict'

const collapseFn = (trigger, collapse) => {
const toggle = (e) => {
e.stopPropagation()
e.preventDefault()
collapse.classList.toggle('active')
trigger.classList.toggle('active')
trigger.ariaExpanded = trigger.ariaExpanded !== 'true'
}
trigger.ariaExpanded = false
trigger.addEventListener('click', toggle)
}

// Init all collapses
document.querySelectorAll('.collapse').forEach((collapse) => {
const trigger = collapse.querySelector('.collapse-trigger')
const content = collapse.querySelector('.collapse-content')
collapseFn(trigger, content)
})
})()
14 changes: 8 additions & 6 deletions src/partials/global-nav.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,30 @@
{{#each this}}
{{#if ./url}}
<a
class="btn btn-plain btn-neutral {{#if (global-nav-active this)}}!color-primary nav-group-active{{/if}}"
class="btn btn-plain btn-neutral flex gap-1{{#if (global-nav-active this)}} !color-primary nav-group-active{{/if}}"
href="{{#if (eq ./urlType 'internal')}}{{{relativize ./url}}}{{else}}{{{./url}}}{{/if}}"
{{#if (eq ./urlType 'external')}}target="_blank"{{/if}}>
{{#if ./home}}<i class="material-icons text-xl mr-1.5">home</i>{{/if}}
{{#if ./home}}<i class="material-icons text-xl">home</i>{{/if}}
{{{./title}}}
</a>
{{#if ./home}}<div class="m-0.5 border-l h-6 w-[1px]"></div>{{/if}}
{{/if}}
{{#if ./items}}
<div class="dropdown" data-trigger-type="hover">
<button id="nav-dropdown-{{@index}}" class="group dropdown-trigger btn btn-plain btn-neutral {{#if (global-nav-active this)}}!color-primary nav-group-active{{/if}}" aria-haspopup="true" aria-expanded="false">
<button id="nav-dropdown-{{@index}}" class="group dropdown-trigger btn btn-plain btn-neutral flex gap-1{{#if (global-nav-active this)}} !color-primary nav-group-active{{/if}}" aria-haspopup="true" aria-expanded="false">
{{{./title}}}
<i class="material-icons text-lg text-tertiary motion-safe:transition-transform motion-safe:duration-300 motion-safe:ease-in-out ml-[0.15em] group-[.active]:rotate-180">expand_more</i>
<i class="material-icons text-lg text-tertiary motion-safe:transition-transform motion-safe:duration-300 motion-safe:ease-in-out group-[.active]:rotate-180">expand_more</i>
</button>
<ul class="dropdown-content py-2 bg-body border rounded w-52 z-[1]" role="menu" aria-orientation="vertical" aria-labelledby="nav-dropdown-{{@index}}">
{{#each ./items}}
<li>
<a
class="!no-underline w-full py-1 px-3 block transition-colors {{#if (global-nav-active this)}}color-primary font-bold{{/if}}"
class="!no-underline w-full py-1 px-3 transition-colors flex gap-1 items-center hover:bg-level1{{#if (global-nav-active this)}} color-primary font-bold{{/if}}"
{{#if (global-nav-active this)}}aria-current="page"{{/if}}
href="{{#if (eq urlType 'internal')}}{{{relativize url}}}{{else}}{{{url}}}{{/if}}"
{{#if (eq ./urlType 'external')}}target="_blank"{{/if}}>
{{#if (eq urlType 'external')}}target="_blank"{{/if}}>
{{{title}}}
{{#if (eq urlType 'external')}}<i class="material-icons text-sm text-tertiary">open_in_new</i>{{/if}}
</a>
</li>
{{/each}}
Expand Down
2 changes: 1 addition & 1 deletion src/partials/nav-secondary.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<ul class="bg-level1 sticky bottom-0 mt-auto flex flex-col py-3">
<ul class="bg-level1 sticky bottom-0 mt-auto flex flex-col pt-3 pb-5">
<li>
<a
class="text-body-small text-primary hover:bg-level2 flex rounded p-1 !no-underline transition-colors"
Expand Down
57 changes: 32 additions & 25 deletions src/partials/nav-tree.hbs
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
{{#if navigation.length}}
<ul>
<ul class="nav-list">
{{#each navigation}}
{{#if ./content}}
{{#if ./items.length}}
<li class="collapse" data-depth="{{or ../level 0}}">
<input type="checkbox" class="peer z-10 w-auto h-auto" {{#if (nav-tree-contains-url ./items @root.page.url)}} checked{{/if}} />
<div class="collapse-title rounded flex items-start py-1 px-2 peer-checked:[&_i]:rotate-180 peer-hover:bg-level2 transition-colors{{#if (greater (or ../level 0) 0)}} text-caption{{else}} text-overline py-2{{/if}}">
{{{./content}}}
<i class="material-icons text-lg text-tertiary motion-safe:transition-transform ml-[0.15em]">expand_more</i>
</div>
<div class="collapse-content ml-3 pl-2 border-l">
<li class="nav-item{{#if ./items.length}} collapse{{/if}}" data-depth="{{or ../level 0}}">
{{#if (and ./url (not ./items.length))}}
<a
class="nav-link !no-underline"
href="{{~#if (eq ./urlType 'internal')}}{{{relativize ./url}}}{{~else}}{{{./url}}}{{~/if}}"
{{#if (eq ./url @root.page.url)}} aria-current="page"{{/if}}
{{#if (eq ./urlType 'external')}} target="_blank"{{/if}}>
{{/if}}
{{#if ./items.length}}
<button
class="nav-item-toggle collapse-trigger w-full group{{#if (nav-tree-contains-url ./items @root.page.url)}} active{{/if}}"
aria-label="{{{./content}}}" aria-expanded="false" aria-controls="{{nav-id (increment (or ../level 0)) ./content}}">
{{/if}}
<span
class="nav-text flex items-center text-left gap-1 text-body-small text-primary rounded py-1 px-2 hover:bg-level2 transition-colors
{{~#if ./items.length}} text-caption{{~/if}}
{{~#if (eq (or ../level 0) 0)}}{{~#if ./items.length}} text-overline py-2{{~/if}}{{~/if}}
{{~#if (eq ./url @root.page.url)}} color-primary font-semibold{{~/if}}
{{~#if (greater (or ../level 0) 1)}} text-tertiary{{~/if}}">
{{{./content}}}
{{#if ./items.length}}
<i class="material-icons text-lg text-tertiary mr-auto self-start motion-safe:transition-transform motion-safe:duration-300 motion-safe:ease-in-out group-[.active]:rotate-180 group-hover:text-primary">expand_more</i>
{{/if}}
{{#if (eq ./urlType 'external')}}<i class="material-icons text-sm text-tertiary">open_in_new</i>{{/if}}
</span>
{{#if (and ./url (not ./items.length))}}
</a>
{{/if}}
{{#if ./items.length}}
</button>
<div id="{{nav-id (increment (or ../level 0)) ./content}}" class="collapse-content ml-3 pl-2 border-l{{#if (nav-tree-contains-url ./items @root.page.url)}} active{{/if}}">
{{> nav-tree navigation=./items level=(increment ../level)}}
</div>
</li>
{{else}}
<li data-depth="{{or ../level 0}}">
{{#if ./url}}
<a class="flex rounded !no-underline text-body-small text-primary py-1 px-2 hover:bg-level2 transition-colors
{{~#if (greater (or ../level 0) 1)}} text-tertiary{{~/if}}
{{~#if (eq ./url @root.page.url)}} text-link font-semibold{{~/if}}"
href="{{~#if (eq ./urlType 'internal')}}{{{relativize ./url}}}{{~else}}{{{./url}}}{{~/if}}">
{{{./content}}}
</a>
{{else}}
<span class="[&>a]:flex [&>a]:rounded [&>a]:!no-underline [&>a]:text-body-small [&>a]:text-primary [&>a]:py-1 [&>a]:px-2 [&>a:hover]:bg-level2">
{{{./content}}}
</span>
{{/if}}
</li>
{{> nav-tree navigation=./items level=(increment ../level)}}
{{/if}}
{{else}}
{{> nav-tree navigation=./items level=0}}
{{/if}}
Expand Down
5 changes: 4 additions & 1 deletion src/partials/nav.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
data-version="{{page.version}}"
{{~/if}}
id="side-nav"
class="h-full bg-level1 overflow-y-scroll flex flex-col w-[18.5rem] pt-4 px-2">
class="h-full bg-level1 overflow-y-scroll flex flex-col w-[18.5rem] px-2 pt-2">
{{> page-versions page=../page}}
{{#with @root.page.componentVersion}}
<a class="p-2 mb-1 text-h4 hover:bg-level2 rounded transition-colors !no-underline" href="{{{relativize ./url}}}">{{./title}}</a>
{{/with}}
{{> nav-tree navigation=this}}
{{> nav-secondary}}
</nav>
Expand Down
Loading

0 comments on commit 1c82089

Please sign in to comment.