diff --git a/package-lock.json b/package-lock.json index 9b7df474..21c09ad5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12261,4 +12261,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/components/bs5/backToTop/backToTop.data.json b/src/components/bs5/backToTop/backToTop.data.json new file mode 100644 index 00000000..cdea53aa --- /dev/null +++ b/src/components/bs5/backToTop/backToTop.data.json @@ -0,0 +1,5 @@ +{ + "hide_back_to_top": false, + "has_icon": true, + "min_page_height": 0 +} \ No newline at end of file diff --git a/src/components/bs5/backToTop/backToTop.functions.js b/src/components/bs5/backToTop/backToTop.functions.js new file mode 100644 index 00000000..0e237a1c --- /dev/null +++ b/src/components/bs5/backToTop/backToTop.functions.js @@ -0,0 +1,20 @@ +export function backToTop() { + let backToTop = document.getElementById("backToTop"); + + if (backToTop) { + let minHightValue = backToTop.getAttribute("data-min-page-height"); // .dataset.minPageHeight; + let minScreenHight = parseInt(window.innerHeight * minHightValue); + let backToTopPos = backToTop.getBoundingClientRect().top; + + if (backToTopPos <= minScreenHight) { + backToTop.classList.add("hide"); + } else { + backToTop.classList.remove("hide"); + backToTop.addEventListener("click", function () { + document.body.scrollTop = 0; // For Safari + document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera + event.preventDefault(); + }); + } + } +} diff --git a/src/components/bs5/backToTop/backToTop.hbs b/src/components/bs5/backToTop/backToTop.hbs new file mode 100644 index 00000000..19a23120 --- /dev/null +++ b/src/components/bs5/backToTop/backToTop.hbs @@ -0,0 +1,12 @@ +{{#unless hide_back_to_top}} +
+{{/unless}} \ No newline at end of file diff --git a/src/components/bs5/backToTop/backToTop.js b/src/components/bs5/backToTop/backToTop.js new file mode 100644 index 00000000..1725b7f3 --- /dev/null +++ b/src/components/bs5/backToTop/backToTop.js @@ -0,0 +1,12 @@ +import Component from '../../../js/QGDSComponent.js' +import template from "./backToTop.hbs?raw"; + +export class BackToTop { + // Use the global Component class to create a new instance of the Blockquote component. + // A data object, containing the Handlebars placeholder replacement strings, should be provided as an argument. + + constructor( data = {} ) { + return new Component(template, data); + } + +} diff --git a/src/components/bs5/backToTop/backToTop.mdx b/src/components/bs5/backToTop/backToTop.mdx new file mode 100644 index 00000000..31d26b8a --- /dev/null +++ b/src/components/bs5/backToTop/backToTop.mdx @@ -0,0 +1,15 @@ +import { Canvas, Meta, Story } from "@storybook/blocks" +import * as BackToTopStories from "./backToTop.stories" + + + +# Back to Top + + +## Design resources + +- [Component library (Figma)](https://www.figma.com/design/qKsxl3ogIlBp7dafgxXuCA/QGDS-UI-kit?node-id=23167-395564&t=Hc9l3zmwhJe3tqyn-0) +- [Master component file (Figma)](https://www.figma.com/design/qKsxl3ogIlBp7dafgxXuCA/QGDS-UI-kit?node-id=11056-321317&p=f&t=k3rhuWqQX2wN7QZo-0) +- [Design System website](https://www.designsystem.qld.gov.au/components/back-to-top) diff --git a/src/components/bs5/backToTop/backToTop.scss b/src/components/bs5/backToTop/backToTop.scss new file mode 100644 index 00000000..0c8716f1 --- /dev/null +++ b/src/components/bs5/backToTop/backToTop.scss @@ -0,0 +1,76 @@ + +//-------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Widgets +//-------------------------------------------------------------------------------------------------------------------------------------------------------------- + +.qld__widgets { + display: flex; + align-items: baseline; + flex-direction: row; + position: relative; + z-index: 1; + &.fixed { + position: fixed; + bottom:0.75rem; + right: 0.75rem; + z-index: 10; + } +} + +.qld__widgets + .qld__footer { + @include media-breakpoint-up(xl) { + padding-block-end: 4rem; + } +} + +.qld__btn--back-to-top { + --btn-background-colour: var(--#{$prefix}color-default-color-light-background-default-shade); + --btn-background-colour-hover: var(--#{$prefix}color-default-color-light-background-alt-shade); + --btn-font-colour: var(--#{$prefix}color-default-color-light-action-primary); + --btn-font-colour-hover: var(--#{$prefix}color-default-color-light-action-primary); + --btn-border: 0px; //This is to allow borders added to btn + --btn-border-colour: var(--btn-background-colour); + + margin-block-start: 0.5rem; + margin-inline-start: auto; + background-color: var(--btn-background-colour); + border: var(--btn-border) solid var(--btn-border-colour); + color: var(--btn-font-colour); + padding: calc(0.75rem - var(--btn-border)); + border-radius: 0.25rem; + display: flex; + gap: 0.5rem; + text-decoration: none; + + svg { + height: 1.5rem; + width: 1.5rem; + display: inline-block; + color: var(--#{$prefix}color-default-color-light-action-secondary); + } + &:hover, &:focus { + box-shadow: 0px 1px 2px rgba(0, 0, 0, .2), 0px 1px 3px 1px rgba(0, 0, 0, .1); + } + &:hover, + &:focus, + &:active { + text-decoration: underline; + background-color: var(--btn-background-colour-hover); + color: var(--btn-font-colour-hover); + text-decoration-color: var(--btn-font-colour-hover); + border-color: var(--btn-border-colour); + svg { + color: var(--#{$prefix}color-default-color-light-action-secondary-hover); + } + } + &.hide { + display: none; + width: 0; + height: 0; + } +} +@media print { + .qld__widgets { + display: none !important; + } +} \ No newline at end of file diff --git a/src/components/bs5/backToTop/backToTop.stories.js b/src/components/bs5/backToTop/backToTop.stories.js new file mode 100644 index 00000000..90ae8684 --- /dev/null +++ b/src/components/bs5/backToTop/backToTop.stories.js @@ -0,0 +1,56 @@ +/** + * @file bactToTop.stories.js + * @description Storybook configuration file for the BackToTop component. + * @module backToTop.stories + */ + +import { BackToTop } from './backToTop.js'; +import defaultdata from './backToTop.data.json'; + +export default { + tags: ["autodocs"], + title: "3. Components/Widgets (Back to Top)", + render: (args) => new BackToTop(args).html, + args: defaultdata, + argTypes: { + hide_back_to_top: { + control: 'boolean', + }, + has_icon: { + control: 'boolean', + }, + min_page_height: { + name: "Minimum Page Height", + description: 'Sets the minimum page height before the back to top button is displayed. This might be tricky to observe, as you will need to set the pages height using CSS to see the effect.', + control: { + type: 'range', + min: 0, + max: 4, + step: 1, + }, + }, + }, + + + /** + * Additional parameters for the story. + * + * @type {Object} + * @property {Object} design - Configuration for the design parameter. + * @property {string} design.name - Name of the design parameter. + * @property {string} design.type - Type of the design parameter. + * @property {string} design.url - URL of the design parameter. + */ + parameters: { + design: { + name: "QGDS Figma Reference", + type: "figma", + url: "https://www.figma.com/design/qKsxl3ogIlBp7dafgxXuCA/QGDS-UI-kit?node-id=23167-395564&t=VORt8BOjhLPGSoci-0", + }, + }, +}; + +/** + * Default backToTop story + */ +export const Default = {}; diff --git a/src/components/bs5/backToTop/manifest.json b/src/components/bs5/backToTop/manifest.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/src/components/bs5/backToTop/manifest.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/css/main.scss b/src/css/main.scss index 82c0bc9f..5e67e223 100644 --- a/src/css/main.scss +++ b/src/css/main.scss @@ -78,6 +78,7 @@ $enable-dark-mode: true; // 9. QLD Design System components (bootstrap overrides and custom). Please maintain naming consistency. @import "../components/bs5/accordion/accordion"; +@import "../components/bs5/backToTop/backToTop"; @import "../components/bs5/banner/banner"; @import "../components/bs5/blockquote/blockquote"; @import "../components/bs5/breadcrumbs/breadcrumbs"; diff --git a/src/js/handlebars.partials.js b/src/js/handlebars.partials.js index 848357da..0b820e5a 100644 --- a/src/js/handlebars.partials.js +++ b/src/js/handlebars.partials.js @@ -2,6 +2,7 @@ /** THIS IS A GENERATED FILE **/ import accordion from "../components/bs5/accordion/accordion.hbs?raw"; +import backToTop from "../components/bs5/backToTop/backToTop.hbs?raw"; import banner from "../components/bs5/banner/banner.hbs?raw"; import blockquote from "../components/bs5/blockquote/blockquote.hbs?raw"; import breadcrumbs from "../components/bs5/breadcrumbs/breadcrumbs.hbs?raw"; @@ -50,6 +51,7 @@ import video from "../components/bs5/video/video.hbs?raw"; */ export default function handlebarsPartials(handlebars) { handlebars.registerPartial("accordion", accordion); + handlebars.registerPartial("backToTop", backToTop); handlebars.registerPartial("banner", banner); handlebars.registerPartial("blockquote", blockquote); handlebars.registerPartial("breadcrumbs", breadcrumbs); diff --git a/src/js/qld.bootstrap.js b/src/js/qld.bootstrap.js index dbe16f6f..63cefb65 100644 --- a/src/js/qld.bootstrap.js +++ b/src/js/qld.bootstrap.js @@ -10,6 +10,7 @@ import { positionQuickExit, initQuickexit } from "./../components/bs5/quickexit/ import { displayFeedbackForm } from "./../components/bs5/footer/footer.functions"; import { toggleSearch } from "./../components/bs5/header/header.functions"; import { showSuggestions, submitSearchForm } from "./../components/bs5/searchInput/search.functions"; +import { backToTop } from "./../components/bs5/backToTop/backToTop.functions"; window.addEventListener("scroll", positionQuickExit, true); window.addEventListener("resize", positionQuickExit, true); @@ -18,6 +19,7 @@ window.addEventListener("keydown", initQuickexit, true); window.addEventListener("DOMContentLoaded", () => { (() => { + backToTop(); // Footer FormIO Action // Note: This is added here, as there is an issue with breadcrumbShorten() function. // Will move this once that issue is fixed.