Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Side Nav Improvements #133

Merged
merged 11 commits into from
May 16, 2024
Merged
Changes from all 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
2 changes: 1 addition & 1 deletion preview-src/ui-model.yml
Original file line number Diff line number Diff line change
@@ -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": "#" },
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;
@@ -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
@@ -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);
4 changes: 2 additions & 2 deletions src/css/vars/light.css
Original file line number Diff line number Diff line change
@@ -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);
38 changes: 28 additions & 10 deletions src/helpers/global-nav-active.js
Original file line number Diff line number Diff line change
@@ -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
@@ -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')
}
}
}
2 changes: 1 addition & 1 deletion src/js/02-on-this-page.js
Original file line number Diff line number Diff line change
@@ -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 = {}
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'

@@ -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 }) => {
@@ -68,6 +95,8 @@
}
}

trigger.ariaExpanded = false

if (triggerType === 'hover' && !isTouchDevice) {
trigger.addEventListener('mouseenter', show)
trigger.addEventListener('mouseenter', clearHideTimeout)
@@ -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
@@ -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}}
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"
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}}
5 changes: 4 additions & 1 deletion src/partials/nav.hbs
Original file line number Diff line number Diff line change
@@ -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>
6 changes: 3 additions & 3 deletions src/partials/page-versions.hbs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{{#with page.versions}}
<div class="dropdown mb-2">
<div class="dropdown my-2">
<button id="page-version-dropdown" title="Show other versions of page" class="group dropdown-trigger btn btn-soft btn-primary btn-small" aria-haspopup="true" aria-expanded="false">
Version: <span class="font-bold ml-1">{{@root.page.componentVersion.displayVersion}}{{#if (eq @root.page.component.latest.version @root.page.componentVersion.version)}} (Latest){{/if}}</span>
<i class="material-icons text-lg color-primary motion-safe:transition-transform motion-safe:duration-300 motion-safe:ease-in-out ml-[0.15em] group-[.active]:rotate-180">expand_more</i>
</button>
<ul class="dropdown-content py-2 bg-body border rounded w-32 z-50" role="menu" aria-orientation="vertical" aria-labelledby="page-version-dropdown">
<ul class="dropdown-content py-2 bg-body border rounded w-32 z-40" role="menu" aria-orientation="vertical" aria-labelledby="page-version-dropdown">
{{#each this}}
<li>
<a
class="!no-underline w-full py-1 px-3 block transition-colors
class="!no-underline w-full py-1 px-3 block hover:bg-level1 transition-colors
{{~#if (eq ./version @root.page.version)}} font-bold color-primary{{/if~}}"
href="{{{relativize ./url}}}">
{{./displayVersion}}{{#if (eq @root.page.component.latest.version ./version)}} (Latest){{/if}}
2 changes: 1 addition & 1 deletion src/partials/toc.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{#unless (or (eq page.layout 'full') (eq page.layout 'landing'))}}
<aside
class="toc sidebar peer sticky hidden h-[calc(100vh-10rem)] mb-[14rem] w-[20rem] xl:flex xl:flex-col xl:col-start-2 {{#if site.keys.globalNav}}top-[9rem]{{else}}top-[6rem]{{/if}}"
class="toc sidebar peer sticky hidden h-[min(100%,calc(100vh-10rem))] mb-[14rem] w-[20rem] xl:flex xl:flex-col xl:col-start-2{{#if site.keys.globalNav}} top-[9rem]{{else}} top-[6rem]{{/if}}"
data-title="{{{or page.attributes.toctitle 'Contents'}}}"
data-levels="{{{or page.attributes.toclevels 2}}}"
>