diff options
Diffstat (limited to 'src/content/dependencies/generatePageLayout.js')
-rw-r--r-- | src/content/dependencies/generatePageLayout.js | 128 |
1 files changed, 113 insertions, 15 deletions
diff --git a/src/content/dependencies/generatePageLayout.js b/src/content/dependencies/generatePageLayout.js index 98b2d350..1ea5ce24 100644 --- a/src/content/dependencies/generatePageLayout.js +++ b/src/content/dependencies/generatePageLayout.js @@ -29,6 +29,47 @@ export default { transformMultiline, wikiInfo, }) { + const sidebarSlots = side => ({ + // Content is a flat HTML array. It'll generate one sidebar section + // if specified. + [side + 'Content']: {type: 'html'}, + + // Multiple is an array of {content: (HTML)} objects. Each of these + // will generate one sidebar section. + [side + 'Multiple']: { + validate: v => + v.arrayOf( + v.validateProperties({ + content: v.isHTML, + })), + }, + + // Sticky mode controls which sidebar section(s), if any, follow the + // scroll position, "sticking" to the top of the browser viewport. + // + // 'last' - last or only sidebar box is sticky + // 'column' - entire column, incl. multiple boxes from top, is sticky + // 'none' - sidebar not sticky at all, stays at top of page + // + // Note: This doesn't affect the content of any sidebar section, only + // the whole section's containing box (or the sidebar column as a whole). + [side + 'StickyMode']: { + validate: v => v.is('last', 'column', 'static'), + }, + + // Collapsing sidebars disappear when the viewport is sufficiently + // thin. (This is the default.) Override as false to make the sidebar + // stay visible in thinner viewports, where the page layout will be + // reflowed so the sidebar is as wide as the screen and appears below + // nav, above the main content. + [side + 'Collapse']: {type: 'boolean', default: true}, + + // Wide sidebars generally take up more horizontal space in the normal + // page layout, and should be used if the content of the sidebar has + // a greater than typical focus compared to main content. + [side + 'Wide']: {type: 'boolean', defualt: false}, + }); + return html.template({ annotation: 'generatePageLayout', @@ -36,15 +77,8 @@ export default { title: {type: 'html'}, cover: {type: 'html'}, - mainContent: {type: 'html'}, - footerContent: {type: 'html'}, socialEmbed: {type: 'html'}, - headingMode: { - validate: v => v.is('sticky', 'static'), - default: 'static', - }, - styleRules: { validate: v => v.arrayOf(v.isString), default: [], @@ -54,6 +88,24 @@ export default { validate: v => v.arrayOf(v.isString), default: [], }, + + // Main + + mainContent: {type: 'html'}, + + headingMode: { + validate: v => v.is('sticky', 'static'), + default: 'static', + }, + + // Sidebars + + ...sidebarSlots('leftSidebar'), + ...sidebarSlots('rightSidebar'), + + // Nav & Footer + + footerContent: {type: 'html'}, }, content(slots) { @@ -114,6 +166,52 @@ export default { relations.footerLocalizationLinks, ]); + const generateSidebarHTML = (side, id) => { + const content = slots[side + 'Content']; + const multiple = slots[side + 'Multiple']; + const stickyMode = slots[side + 'StickyMode']; + const wide = slots[side + 'Wide']; + const collapse = slots[side + 'Collapse']; + + let sidebarClasses = []; + let sidebarContent = html.blank(); + + if (!html.isBlank(content)) { + sidebarClasses = ['sidebar']; + sidebarContent = content; + } else if (multiple) { + sidebarClasses = ['sidebar-multiple']; + sidebarContent = + multiple + .filter(Boolean) + .map(({content}) => + html.tag('div', + { + [html.onlyIfContent]: true, + class: 'sidebar', + }, + content)); + } + + return html.tag('div', + { + [html.onlyIfContent]: true, + id, + class: [ + 'sidebar-column', + wide && 'wide', + !collapse && 'no-hide', + stickyMode !== 'static' && `sticky-${stickyMode}`, + ...sidebarClasses, + ], + }, + sidebarContent); + } + + const sidebarLeftHTML = generateSidebarHTML('leftSidebar', 'sidebar-left'); + const sidebarRightHTML = generateSidebarHTML('rightSidebar', 'sidebar-right'); + const collapseSidebars = slots.leftSidebarCollapse && slots.rightSidebarCollapse; + const layoutHTML = [ // navHTML, // banner.position === 'top' && bannerHTML, @@ -122,18 +220,18 @@ export default { { class: [ 'layout-columns', - // !collapseSidebars && 'vertical-when-thin', - // (sidebarLeftHTML || sidebarRightHTML) && 'has-one-sidebar', - // (sidebarLeftHTML && sidebarRightHTML) && 'has-two-sidebars', - // !(sidebarLeftHTML || sidebarRightHTML) && 'has-zero-sidebars', - // sidebarLeftHTML && 'has-sidebar-left', - // sidebarRightHTML && 'has-sidebar-right', + !collapseSidebars && 'vertical-when-thin', + (sidebarLeftHTML || sidebarRightHTML) && 'has-one-sidebar', + (sidebarLeftHTML && sidebarRightHTML) && 'has-two-sidebars', + !(sidebarLeftHTML || sidebarRightHTML) && 'has-zero-sidebars', + sidebarLeftHTML && 'has-sidebar-left', + sidebarRightHTML && 'has-sidebar-right', ], }, [ - // sidebarLeftHTML, + sidebarLeftHTML, mainHTML, - // sidebarRightHTML, + sidebarRightHTML, ]), // banner.position === 'bottom' && bannerHTML, footerHTML, |