From 63beb8dcb01f3d94fbf545bccef73495ecb07ab1 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 13 Jun 2024 11:54:50 -0300 Subject: content, client, css: quick description expand/collapse --- .../dependencies/generateGroupGalleryPage.js | 7 +- .../dependencies/generateQuickDescription.js | 120 +++++++++++++++------ src/static/css/site.css | 45 +++++++- src/static/js/client.js | 66 ++++++++++++ src/strings-default.yaml | 8 ++ 5 files changed, 205 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/content/dependencies/generateGroupGalleryPage.js b/src/content/dependencies/generateGroupGalleryPage.js index 6f23710d..34c789b3 100644 --- a/src/content/dependencies/generateGroupGalleryPage.js +++ b/src/content/dependencies/generateGroupGalleryPage.js @@ -13,7 +13,6 @@ export default { 'generateQuickDescription', 'image', 'linkAlbum', - 'linkGroup', 'linkListing', ], @@ -60,9 +59,6 @@ export default { relations.quickDescription = relation('generateQuickDescription', group); - relations.quickDescriptionInfoLink = - relation('linkGroup', group); - relations.coverGrid = relation('generateCoverGrid'); @@ -136,8 +132,7 @@ export default { image.slot('path', path)), }), - relations.quickDescription - .slot('infoPageLink', relations.quickDescriptionInfoLink), + relations.quickDescription, html.tag('p', {class: 'quick-info'}, language.$('groupGalleryPage.infoLine', { diff --git a/src/content/dependencies/generateQuickDescription.js b/src/content/dependencies/generateQuickDescription.js index 3dadfbcf..f555af28 100644 --- a/src/content/dependencies/generateQuickDescription.js +++ b/src/content/dependencies/generateQuickDescription.js @@ -2,40 +2,92 @@ export default { contentDependencies: ['transformContent'], extraDependencies: ['html', 'language'], - relations: (relation, thing) => - ({description: - (thing.descriptionShort || thing.description - ? relation('transformContent', - thing.descriptionShort ?? thing.description) - : null)}), - - data: (thing) => - ({hasLongerDescription: - thing.description && - thing.descriptionShort && - thing.descriptionShort !== thing.description}), - - slots: { - infoPageLink: { - type: 'html', - mutable: true, - }, - }, - - generate: (data, relations, slots, {html, language}) => - html.tag('p', {class: 'quick-info'}, - {[html.joinChildren]: html.tag('br')}, - {[html.onlyIfContent]: true}, - - [ - relations.description?.slot('mode', 'inline'), + query: (thing) => ({ + hasDescription: + !!thing.description, + + hasLongerDescription: + thing.description && + thing.descriptionShort && + thing.descriptionShort !== thing.description, + }), + + relations: (relation, query, thing) => ({ + description: + (query.hasLongerDescription || !thing.description + ? null + : relation('transformContent', thing.description)), + + descriptionShort: + (query.hasLongerDescription + ? relation('transformContent', thing.descriptionShort) + : null), + + descriptionLong: + (query.hasLongerDescription + ? relation('transformContent', thing.description) + : null), + }), + + data: (query) => ({ + hasDescription: query.hasDescription, + hasLongerDescription: query.hasLongerDescription, + }), + + generate(data, relations, {html, language}) { + const prefix = 'misc.quickDescription'; + + const wrapExpandCollapseLink = (expandCollapse, content) => + html.tag('a', {class: `${expandCollapse}-link`}, + {href: '#'}, + content); + + const actionsWhenCollapsed = + (data.hasLongerDescription + ? language.$(prefix, 'expandDescription', { + expand: + wrapExpandCollapseLink('expand', + language.$(prefix, 'expandDescription.expand')), + }) + : null); + + const actionsWhenExpanded = + (data.hasLongerDescription + ? language.$(prefix, 'collapseDescription', { + collapse: + wrapExpandCollapseLink('collapse', + language.$(prefix, 'collapseDescription.collapse')), + }) + : null); + + const wrapActions = (attributes, children) => + html.tag('p', {class: 'quick-description-actions'}, + {[html.onlyIfContent]: true}, + attributes, + + children); + + const wrapContent = (attributes, content) => + html.tag('div', {class: 'description-content'}, + {[html.onlyIfContent]: true}, + attributes, + + content?.slot('mode', 'multiline')); + + return ( + html.tag('div', {class: 'quick-description'}, + {[html.onlyIfContent]: true}, data.hasLongerDescription && - slots.infoPageLink && - language.$('misc.quickDescription.moreInfo', { - link: - slots.infoPageLink - .slot('content', language.$('misc.quickDescription.moreInfo.link')), - }), - ]), + {class: 'collapsed'}, + + [ + wrapContent(null, relations.description), + wrapContent({class: 'short'}, relations.descriptionShort), + wrapContent({class: 'long'}, relations.descriptionLong), + + wrapActions({class: 'when-collapsed'}, actionsWhenCollapsed), + wrapActions({class: 'when-expanded'}, actionsWhenExpanded), + ])); + } }; diff --git a/src/static/css/site.css b/src/static/css/site.css index e297993c..173c7910 100644 --- a/src/static/css/site.css +++ b/src/static/css/site.css @@ -1258,10 +1258,53 @@ ul.quick-info li:not(:last-child)::after { font-weight: 800; } -.carousel-container + .quick-info { +.carousel-container + .quick-info, +.carousel-container + .quick-description { margin-top: 25px; } +.quick-description { + margin-left: 8%; + margin-right: 8%; + padding-left: 4%; + padding-right: 4%; + padding-top: 0.25em; + padding-bottom: 0.5em; + border-left: 1px solid var(--dim-color); + border-right: 1px solid var(--dim-color); + line-height: 1.25em; +} + +.quick-description p { + text-align: center; +} + +.quick-description .description-content.long hr ~ p { + text-align: left; +} + +.quick-description > .description-content :first-child { + margin-top: 0; +} + +.quick-description > .quick-description-actions, +.quick-description.has-content-only .description-content :last-child { + margin-bottom: 0; +} + +.quick-description:not(.collapsed) .description-content.short, +.quick-description:not(.collapsed) .quick-description-actions.when-collapsed, +.quick-description:not(.expanded) .description-content.long, +.quick-description:not(.expanded) .quick-description-actions.when-expanded { + display: none; +} + +.quick-description .quick-description-actions .expand-link, +.quick-description .quick-description-actions .collapse-link { + text-decoration: underline; + text-decoration-style: dotted; +} + #intro-menu { margin: 24px 0; padding: 10px; diff --git a/src/static/js/client.js b/src/static/js/client.js index 68b1a013..935a9d87 100644 --- a/src/static/js/client.js +++ b/src/static/js/client.js @@ -3524,6 +3524,72 @@ clientSteps.getPageReferences.push(getArtistExternalLinkTooltipPageReferences); clientSteps.addInternalListeners.push(addArtistExternalLinkTooltipInternalListeners); clientSteps.addPageListeners.push(addArtistExternalLinkTooltipPageListeners); +// Quick description -------------------------------------- + +const quickDescriptionInfo = initInfo('quickDescriptionInfo', { + quickDescriptionContainers: null, + + quickDescriptionsAreExpandable: null, + + expandDescriptionLinks: null, + collapseDescriptionLinks: null, +}); + +function getQuickDescriptionReferences() { + const info = quickDescriptionInfo; + + info.quickDescriptionContainers = + Array.from(document.querySelectorAll('#content .quick-description')); + + info.quickDescriptionsAreExpandable = + info.quickDescriptionContainers + .map(container => + container.querySelector('.quick-description-actions.when-expanded')); + + info.expandDescriptionLinks = + info.quickDescriptionContainers + .map(container => + container.querySelector('.quick-description-actions .expand-link')); + + info.collapseDescriptionLinks = + info.quickDescriptionContainers + .map(container => + container.querySelector('.quick-description-actions .collapse-link')); +} + +function addQuickDescriptionListeners() { + const info = quickDescriptionInfo; + + for (const { + isExpandable, + container, + expandLink, + collapseLink, + } of stitchArrays({ + isExpandable: info.quickDescriptionsAreExpandable, + container: info.quickDescriptionContainers, + expandLink: info.expandDescriptionLinks, + collapseLink: info.collapseDescriptionLinks, + })) { + if (!isExpandable) continue; + + expandLink.addEventListener('click', event => { + event.preventDefault(); + container.classList.add('expanded'); + container.classList.remove('collapsed'); + }); + + collapseLink.addEventListener('click', event => { + event.preventDefault(); + container.classList.add('collapsed'); + container.classList.remove('expanded'); + }); + } +} + +clientSteps.getPageReferences.push(getQuickDescriptionReferences); +clientSteps.addPageListeners.push(addQuickDescriptionListeners); + // Internal search functionality -------------------------- const wikiSearchInfo = initInfo('wikiSearchInfo', { diff --git a/src/strings-default.yaml b/src/strings-default.yaml index c9152434..96ec36ad 100644 --- a/src/strings-default.yaml +++ b/src/strings-default.yaml @@ -630,6 +630,14 @@ misc: _: "({LINK})" link: "More info..." + expandDescription: + _: "({EXPAND})" + expand: "Expand description..." + + collapseDescription: + _: "({COLLAPSE})" + collapse: "Collapse description" + # nav: # Generic navigational elements. These usually only appear in the # wiki's nav bar, at the top of the page. -- cgit 1.3.0-6-gf8a5