diff --git a/preview-src/ui-model.yml b/preview-src/ui-model.yml index 8a45c132..1a9df8dd 100644 --- a/preview-src/ui-model.yml +++ b/preview-src/ui-model.yml @@ -8,19 +8,102 @@ site: homeUrl: &home_url http://localhost:5252 components: - &component - name: datastax - title: PREVIEW Datastax Docs - url: '#' + name: xyz + title: &component_title Preview Docs + url: /xyz/6.0/index.html versions: - - &latest_version - url: *home_url - version: 'latest' - displayVersion: 'latest' - latestVersion: *latest_version + - &latest_version_xyz + url: /xyz/6.0/index.html + version: '6.0' + displayVersion: '6.0' + - &component_version + title: *component_title + url: '#' + version: '5.2' + displayVersion: '5.2' + - url: '#' + version: '5.1' + displayVersion: '5.1' + - url: '#' + version: '5.0' + displayVersion: '5.0' + latestVersion: *latest_version_xyz + keys: + globalNav: | + [ + { + "title": "Docs Home", + "url": "#", + "home": true + }, + { + "title": "Astra DB", + "items": [ + { "title": "Serverless", "url": "#" }, + { "title": "Dedicated", "url": "#" }, + { "title": "CLI", "url": "#" } + ] + }, + { + "title": "RAGStack", + "url": "#" + }, + { + "title": "DSE", + "items": [ + { "title": "Mission Control", "url": "#" }, + { "title": "DSE 6.8", "url": "#" }, + { "title": "DSE 5.1", "url": "#" }, + { "title": "CLI", "url": "#" } + ] + }, + { + "title": "Streaming", + "items": [ + { "title": "Astra Streaming", "url": "#" }, + { "title": "Luna Streaming", "url": "#" } + ] + }, + { + "title": "Open Source", + "items": [ + { "title": "Apache Pulsar Connector", "url": "#" }, + { "title": "CDC for Cassandra", "url": "#" }, + { "title": "K8ssandra", "url": "#" }, + { "title": "Stargate", "url": "#" }, + { "title": "Starlight for JMS", "url": "#" }, + { "title": "Starlight for Kafka", "url": "#" }, + { "title": "Starlight for Rabbit MQ", "url": "#" } + ] + } + ] page: - src: - component: *component - version: *latest_version + url: *home_url + home: true + title: Brand’s Hardware & Software Requirements + component: *component + componentVersion: *component_version + version: '5.2' + displayVersion: '5.2' + module: ROOT + relativeSrcPath: index.adoc + editUrl: http://example.com/project-xyz/blob/main/index.adoc + origin: + private: false + versions: + - version: '6.0' + displayVersion: '6.0' + url: '#' + - version: '5.2' + displayVersion: '5.2' + url: '#' + - version: '5.1' + displayVersion: '5.1' + url: '#' + - version: '5.0' + displayVersion: '5.0' + missing: true + url: '#' navigation: - content: Page Templates items: diff --git a/src/css/asciidoc/doc.css b/src/css/asciidoc/doc.css index 8c9910d4..075dac68 100644 --- a/src/css/asciidoc/doc.css +++ b/src/css/asciidoc/doc.css @@ -40,7 +40,7 @@ .doc h4 { @apply text-h4; color: var(--ds-text-tertiary); - margin: calc(32/var(--rem-base)*1rem) 0 0; + margin: calc(32 / var(--rem-base) * 1rem) 0 0; } .doc h5 { @@ -63,12 +63,12 @@ .doc h2:not(.discrete) { border-bottom: 1px solid var(--ds-divider); - margin: calc(80/var(--rem-base)*1rem) 0 0; + margin: calc(80 / var(--rem-base) * 1rem) 0 0; padding: 0 0 calc(16 / var(--rem-base) * 1rem); } .doc h3:not(.discrete) { - margin: calc(64/var(--rem-base)*1rem) 0 0; + margin: calc(64 / var(--rem-base) * 1rem) 0 0; } .doc h4:not(.discrete) { @@ -85,7 +85,7 @@ justify-content: flex-end; align-items: center; gap: var(--ds-space-h); - scroll-margin-top: 6rem; + scroll-margin-top: 9rem; } .doc h1 .anchor, diff --git a/src/css/color.css b/src/css/color.css index 6f318611..740c0c19 100644 --- a/src/css/color.css +++ b/src/css/color.css @@ -11,7 +11,12 @@ color: var(--ds-text-tertiary); } - .text-link { + .text-inverse { + color: var(--ds-text-inverse); + } + + .text-link, + .color-primary { color: var(--ds-primary-main); } diff --git a/src/css/components/btn.css b/src/css/components/btn.css index 6e435d97..58730d69 100644 --- a/src/css/components/btn.css +++ b/src/css/components/btn.css @@ -15,6 +15,10 @@ @apply bg-[var(--ds-primary-solid-bg)] text-[var(--ds-primary-solid-color)] hover:bg-[var(--ds-primary-solid-hover-bg)] hover:text-[var(--ds-primary-solid-color)] active:bg-[var(--ds-primary-solid-active-bg)] disabled:bg-[var(--ds-primary-solid-disabled-bg)] disabled:text-[var(--ds-primary-solid-disabled-color)]; } + .btn-primary.btn-soft { + @apply bg-[var(--ds-primary-soft-bg)] text-[var(--ds-primary-soft-color)] hover:bg-[var(--ds-primary-soft-hover-bg)] hover:text-[var(--ds-primary-soft-color)] active:bg-[var(--ds-primary-soft-active-bg)] disabled:bg-[var(--ds-primary-soft-disabled-bg)] disabled:text-[var(--ds-primary-soft-disabled-color)]; + } + .btn-neutral.btn-outlined { @apply border-[var(--ds-neutral-outlined-border)] text-[var(--ds-neutral-outlined-color)] hover:border-[var(--ds-neutral-outlined-hover-border)] hover:bg-[var(--ds-neutral-outlined-hover-bg)] hover:text-[var(--ds-neutral-outlined-color)] active:border-[var(--ds-neutral-outlined-active-border)] active:bg-[var(--ds-neutral-outlined-active-bg)] disabled:border-[var(--ds-neutral-outlined-disabled-border)] disabled:text-[var(--ds-neutral-outlined-disabled-color)]; } @@ -31,6 +35,10 @@ @apply h-10 w-10 p-0; } + .btn-small { + @apply h-8 px-2 py-1; + } + .btn-leading-icon { @apply mr-2 flex; } diff --git a/src/css/components/dropdown.css b/src/css/components/dropdown.css new file mode 100644 index 00000000..954b0d30 --- /dev/null +++ b/src/css/components/dropdown.css @@ -0,0 +1,15 @@ +@layer components { + .dropdown .dropdown-content { + @apply invisible fixed left-0 top-0 origin-top scale-95 transform opacity-0 motion-safe:transition motion-safe:duration-300 motion-safe:ease-in-out; + + /* Shadow-100 */ + box-shadow: + 0px 4px 5px 0px rgba(10, 10, 10, 0.08), + 0px 1px 10px 0px rgba(10, 10, 10, 0.08), + 0px 2px 4px 0px rgba(32, 41, 58, 0.14); + } + + .dropdown .dropdown-content.active { + @apply visible scale-100 opacity-100; + } +} diff --git a/src/css/global-nav.css b/src/css/global-nav.css new file mode 100644 index 00000000..b10059be --- /dev/null +++ b/src/css/global-nav.css @@ -0,0 +1,32 @@ +.global-nav > .scroll-btn-left, +.global-nav > .scroll-btn-right { + @apply invisible absolute opacity-0 motion-safe:transition-all; + + &.active { + @apply visible opacity-100; + } +} + +.global-nav > .scroll-btn-left { + @apply left-0 rounded-tl py-3 pl-2 pr-4; +} + +.global-nav > .scroll-btn-right { + @apply right-0 rounded-tr py-3 pl-4 pr-2; +} + +html[data-theme="light"] .global-nav > .scroll-btn-left { + background: linear-gradient(to left, rgba(255, 255, 255, 0), rgb(255, 255, 255), rgb(255, 255, 255) 50%); +} + +html[data-theme="dark"] .global-nav > .scroll-btn-left { + background: linear-gradient(to left, rgba(9, 9, 9, 0), rgb(9, 9, 9), rgb(9, 9, 9) 50%); +} + +html[data-theme="light"] .global-nav > .scroll-btn-right { + background: linear-gradient(to right, rgba(255, 255, 255, 0), rgb(255, 255, 255), rgb(255, 255, 255) 50%); +} + +html[data-theme="dark"] .global-nav > .scroll-btn-right { + background: linear-gradient(to right, rgba(9, 9, 9, 0), rgb(9, 9, 9), rgb(9, 9, 9) 50%); +} \ No newline at end of file diff --git a/src/css/site.css b/src/css/site.css index b710a1c5..fcdfe489 100644 --- a/src/css/site.css +++ b/src/css/site.css @@ -10,6 +10,7 @@ @import "components/input.css"; @import "components/drawer.css"; @import "components/collapse.css"; +@import "components/dropdown.css"; @import "typeface/typeface-material-icons-outlined.css"; @import "typeface/typeface-roboto-flex.css"; @import "typeface/typeface-sora.css"; @@ -23,6 +24,7 @@ @import "highlight.css"; @import "print.css"; @import "docsearch.css"; +@import "global-nav.css"; @tailwind base; @tailwind components; diff --git a/src/css/vars/light.css b/src/css/vars/light.css index 11e013b4..3840271c 100644 --- a/src/css/vars/light.css +++ b/src/css/vars/light.css @@ -3,8 +3,8 @@ --ds-focus-visible: var(--ds-neutral-900); --ds-background-body: var(--ds-common-white); --ds-background-level1: var(--ds-neutral-0); - --ds-background-level2: var(--ds-neutral-50); - --ds-background-level3: var(--ds-neutral-100); + --ds-background-level2: var(--ds-neutral-100); + --ds-background-level3: var(--ds-neutral-300); --ds-background-surface: var(--ds-common-white); --ds-background-tooltip: var(--ds-neutral-900); --ds-background-backdrop: rgba(0, 0, 0, 0.6); @@ -42,10 +42,10 @@ --ds-neutral-outlined-disabled-color: var(--ds-neutral-300); --ds-neutral-outlined-hover-bg: var(--ds-neutral-0); --ds-neutral-outlined-hover-border: var(--ds-neutral-900); - --ds-neutral-plain-active-bg: var(--ds-neutral-200); + --ds-neutral-plain-active-bg: var(--ds-neutral-100); --ds-neutral-plain-color: var(--ds-neutral-900); --ds-neutral-plain-disabled-color: var(--ds-neutral-200); - --ds-neutral-plain-hover-bg: var(--ds-neutral-100); + --ds-neutral-plain-hover-bg: var(--ds-neutral-0); --ds-neutral-soft-active-bg: var(--ds-neutral-300); --ds-neutral-soft-bg: var(--ds-neutral-0); --ds-neutral-soft-color: var(--ds-neutral-900); diff --git a/src/css/vars/vars.css b/src/css/vars/vars.css index 63439ca5..db294d1c 100644 --- a/src/css/vars/vars.css +++ b/src/css/vars/vars.css @@ -41,7 +41,6 @@ --ds-neutral-200: #ced0d2; --ds-neutral-300: #a6aaae; --ds-neutral-400: #898d91; - --ds-neutral-50: #edeeee; --ds-neutral-500: #6b6f73; --ds-neutral-600: #5a5d60; --ds-neutral-700: #494a4d; diff --git a/src/helpers/global-nav-active.js b/src/helpers/global-nav-active.js new file mode 100644 index 00000000..ed05385b --- /dev/null +++ b/src/helpers/global-nav-active.js @@ -0,0 +1,28 @@ +'use strict' + +module.exports = module.exports = (navItem, { + data: { + root: { page }, + }, +}) => { + const pageVersion = page.componentVersion?.version + const pageComponent = page.component?.name + + const matchesComponentAndVersion = (item) => { + if (pageVersion) { + return item.component === pageComponent && item.version === pageVersion + } else { + return item.component === pageComponent + } + } + + if (navItem.component) { + return matchesComponentAndVersion(navItem) + } + + if (navItem.items) { + return navItem.items.some(matchesComponentAndVersion) + } + + return false +} diff --git a/src/helpers/global-nav.js b/src/helpers/global-nav.js new file mode 100644 index 00000000..8d5d1b6d --- /dev/null +++ b/src/helpers/global-nav.js @@ -0,0 +1,44 @@ +'use strict' + +const mapNavList = (list, contentCatalog) => { + return list.map((item) => { + if (item.xref) { + const page = contentCatalog.resolvePage(item.xref) + if (page) item.url = page.pub.url + if (page?.src?.component) { + item.component = page.src.component + } + if (page?.src?.version) { + item.version = page.src.version + } + item.urlType = 'internal' + delete item.xref + } + if (item.url && item.url.startsWith('http')) item.urlType = 'external' + if (item.items) { + item.items = mapNavList(item.items, contentCatalog) + } + return item + }) +} + +module.exports = ({ + data: { + root: { + contentCatalog = { resolvePage: () => undefined, getComponent: () => undefined }, + site, + }, + }, +}) => { + let globalNav = site?.keys?.globalNav + + if (!globalNav) return [] + if (globalNav._compiled) return globalNav + + globalNav = mapNavList(JSON.parse(globalNav), contentCatalog) + + globalNav._compiled = true + + site.keys.globalNav = globalNav + return globalNav +} diff --git a/src/helpers/isLast.js b/src/helpers/is-last.js similarity index 100% rename from src/helpers/isLast.js rename to src/helpers/is-last.js diff --git a/src/helpers/navTreeContainsUrl.js b/src/helpers/nav-tree-contains-url.js similarity index 100% rename from src/helpers/navTreeContainsUrl.js rename to src/helpers/nav-tree-contains-url.js diff --git a/src/js/01-nav.js b/src/js/01-nav.js index 11025d7a..027a3dcc 100644 --- a/src/js/01-nav.js +++ b/src/js/01-nav.js @@ -27,4 +27,51 @@ } } } + + // Top Global Nav horizontal scrolling + const globalNav = document.querySelector('.global-nav') + if (globalNav) { + const scrollLeftButton = document.createElement('button') + scrollLeftButton.className = 'scroll-btn-left' + const leftIcon = document.createElement('i') + leftIcon.className = 'material-icons' + leftIcon.textContent = 'chevron_left' + scrollLeftButton.appendChild(leftIcon) + globalNav.appendChild(scrollLeftButton) + + const scrollRightButton = document.createElement('button') + scrollRightButton.className = 'scroll-btn-right' + const rightIcon = document.createElement('i') + rightIcon.className = 'material-icons' + rightIcon.textContent = 'chevron_right' + scrollRightButton.appendChild(rightIcon) + globalNav.appendChild(scrollRightButton) + + // Function to check scroll and show/hide buttons + const checkScroll = () => { + scrollLeftButton.classList.toggle('active', globalNav.scrollLeft > 0) + scrollRightButton.classList.toggle('active', + globalNav.scrollWidth > (globalNav.clientWidth + globalNav.scrollLeft + 1)) + } + + // Check scroll initially + checkScroll() + + // Check scroll whenever the tablist is resized + // eslint-disable-next-line no-undef + const resizeObserver = new ResizeObserver(checkScroll) + resizeObserver.observe(globalNav) + + // Check scroll whenever the block is scrolled + globalNav.addEventListener('scroll', checkScroll) + + // Scroll when buttons are clicked + scrollLeftButton.addEventListener('click', () => { + globalNav.scrollLeft -= 200 + }) + + scrollRightButton.addEventListener('click', () => { + globalNav.scrollLeft += 200 + }) + } })() diff --git a/src/js/09-dropdown.js b/src/js/09-dropdown.js new file mode 100644 index 00000000..a2998f62 --- /dev/null +++ b/src/js/09-dropdown.js @@ -0,0 +1,91 @@ +;(function () { + 'use strict' + + const { computePosition, autoPlacement, shift } = window.FloatingUIDOM + const isTouchDevice = window.matchMedia('(pointer: coarse)').matches + + const hideAllDropdowns = () => { + document.querySelectorAll('.dropdown').forEach((dropdown) => { + dropdown.querySelector('.dropdown-trigger').classList.remove('active') + dropdown.querySelector('.dropdown-content').classList.remove('active') + }) + } + + const dropdownFn = (trigger, dropdown, triggerType = 'click') => { + const update = () => { + computePosition(trigger, dropdown, { + strategy: 'fixed', + middleware: [ + autoPlacement({ alignment: 'start', allowedPlacements: ['bottom', 'bottom-start', 'bottom-end'] }), + shift(), + ], + }).then(({ x, y }) => { + dropdown.style.left = `${x}px` + dropdown.style.top = `${y}px` + }) + } + + const show = () => { + hideAllDropdowns() + dropdown.classList.add('active') + trigger.classList.add('active') + trigger.ariaExpanded = true + update() + } + + const hide = () => { + dropdown.classList.remove('active') + trigger.classList.remove('active') + trigger.ariaExpanded = false + } + + let hideTimeoutId = null + + const hideTimeout = () => { + hideTimeoutId = setTimeout(hide, 400) + } + + const clearHideTimeout = () => { + clearTimeout(hideTimeoutId) + } + + const toggle = () => { + dropdown.classList.toggle('active') + trigger.classList.toggle('active') + trigger.ariaExpanded = trigger.ariaExpanded !== 'true' + update() + } + + const clickOutside = (event) => { + if (event.target !== trigger && !trigger.contains(event.target)) { + hide() + } + } + + const blur = (event) => { + if (event.target !== dropdown && !dropdown.contains(event.target)) { + hide() + } + } + + if (triggerType === 'hover' && !isTouchDevice) { + trigger.addEventListener('mouseenter', show) + trigger.addEventListener('mouseenter', clearHideTimeout) + trigger.addEventListener('mouseleave', hideTimeout) + dropdown.addEventListener('mouseenter', clearHideTimeout) + dropdown.addEventListener('mouseleave', hideTimeout) + } + + trigger.addEventListener('click', toggle) + document.body.addEventListener('click', clickOutside) + dropdown.addEventListener('blur', blur) + } + + // Init all dropdowns + document.querySelectorAll('.dropdown').forEach((dropdown) => { + const triggerType = dropdown.dataset.triggerType + const trigger = dropdown.querySelector('.dropdown-trigger') + const content = dropdown.querySelector('.dropdown-content') + dropdownFn(trigger, content, triggerType) + }) +})() diff --git a/src/partials/body-end-scripts.hbs b/src/partials/body-end-scripts.hbs index 34a6f026..a0057a9f 100644 --- a/src/partials/body-end-scripts.hbs +++ b/src/partials/body-end-scripts.hbs @@ -1,3 +1,5 @@ + + diff --git a/src/partials/body.hbs b/src/partials/body.hbs index a79d94f4..1b7db69c 100644 --- a/src/partials/body.hbs +++ b/src/partials/body.hbs @@ -2,10 +2,10 @@ {{> navbar}}
-
+
{{> main}}
-
+
{{> nav}}
diff --git a/src/partials/breadcrumbs.hbs b/src/partials/breadcrumbs.hbs index 13628f84..5f46ccd5 100644 --- a/src/partials/breadcrumbs.hbs +++ b/src/partials/breadcrumbs.hbs @@ -9,7 +9,7 @@ {{/with}} {{#each page.breadcrumbs}} {{#if (and ./url (eq ./urlType 'internal'))}} - {{#if (isLast this ../page.breadcrumbs)}} + {{#if (is-last this ../page.breadcrumbs)}}
  • {{{./content}}}
  • {{else}}
  • - +
    {{{./content}}} expand_more @@ -16,7 +16,7 @@ {{else}}
  • {{#if ./url}} - diff --git a/src/partials/nav.hbs b/src/partials/nav.hbs index 4ca7958f..79f3b1cd 100644 --- a/src/partials/nav.hbs +++ b/src/partials/nav.hbs @@ -1,8 +1,13 @@ {{#with page.navigation}} -
  • {{/unless}}