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

feature/back-to-top #353

Merged
merged 12 commits into from
Nov 20, 2023
1 change: 1 addition & 0 deletions src/components/_all.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import 'accordion/accordion';
@import 'back-to-top/back-to-top';
@import 'dialog/dialog';
@import 'breadcrumbs/breadcrumbs';
@import 'button/button';
Expand Down
2 changes: 2 additions & 0 deletions src/components/back-to-top/_back-to-top.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<button type="button" class="nsw-button nsw-button--dark nsw-button--flex nsw-back-to-top js-back-to-top">
</button>
38 changes: 38 additions & 0 deletions src/components/back-to-top/_back-to-top.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.nsw-back-to-top {
display: flex;
flex-direction: column-reverse;
position: fixed;
right: 1rem;
bottom: 1rem;
z-index: 10;
visibility: hidden;
opacity: 0;
transition: 0.2s;
text-decoration: none;

@include breakpoint('md') {
flex-direction: row;
}

&.active {
visibility: visible;
opacity: 1;
}

&.nsw-button {
padding: 1rem;
border: 0;

@include breakpoint('md') {
padding: 0.625rem 1.375rem;
}

.nsw-material-icons:last-child {
margin-left: 0;

@include breakpoint('md') {
letter-spacing: -0.25rem;
}
}
}
}
50 changes: 50 additions & 0 deletions src/components/back-to-top/_guidance.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Back to top
layout: blank-layout.hbs
---

<h2>Usage</h2>
<p>A back to top button provides an easy way to return to the top of the page, without having to manually scroll.</p>

<p>Use the back to top component when there is a lot of content on the page, such as articles, blogs, or listings.</p>

<h3>When to avoid</h3>

<p>Do not use:</p>

<ul>
<li>on pages that are short that have a minimum amount of scrolling</li>
<li>if there is already a way to return to the top of the page, such as a fixed in-page navigation menu</li>
<li>if the 'back to top' button creates confusion or adds unnecessary clutter</li>
</ul>

<h3>How this component works</h3>

<p>The back to top button appears when users want to scroll up, making it visible only when necessary.</p>

<p>On mobile and smaller screens, the icon turns into an upward chevron and the text becomes 'Top' below the icon to save space.</p>

<h3>Scrollable distance</h3>

<p>By default the back to top button appears when users start scrolling up, signaling an intention to return to the top. However, if you want the button to appear when users have scrolled down a certain distance you can use the <code>data-offset</code> attribute.</p>

{{#>_docs-code open=true}}
<button type="button" data-offset="400">
<!-- ... -->
</button>
{{/_docs-code}}

<h3>Scrollable element</h3>

<p>By default, the visibility of the back to top button is toggled by the scrolling on the window element. If you have a different scrollable element in your page, you can use the data-element attribute to pass the CSS selector of the scrollable element.</p>

<p>For example, if you have a <code>&lt;main class=&quot;main-element&quot;&gt;</code> with a <code>height: 100vh</code> and <code>overflow: auto</code>, you can set <code>data-element='.main-element'</code></p>

{{#>_docs-code open=true}}
<button type="button" data-element=".main-element">
<!-- ... -->
</button>
{{/_docs-code}}

<h2>Accessibility</h2>
<p>All components are responsive and meet WCAG 2.1 AA accessibility guidelines.</p>
128 changes: 128 additions & 0 deletions src/components/back-to-top/back-to-top.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
class BackTop {
constructor(element) {
this.element = element
this.dataElement = this.element.getAttribute('data-element')
this.scrollOffset = this.element.getAttribute('data-offset')
this.text = false
this.icon = false
this.scrollElement = this.dataElement ? document.querySelector(this.dataElement) : window
this.scrollPosition = 0
this.width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
this.height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
this.condition = false
}

init() {
this.createButton()

this.element.addEventListener('click', (event) => {
event.preventDefault()

if (!window.requestAnimationFrame) {
this.scrollElement.scrollTo(0, 0)
} else if (this.dataElement) {
this.scrollElement.scrollTo({ top: 0, behavior: 'smooth' })
} else {
window.scrollTo({ top: 0, behavior: 'smooth' })
}
})

this.checkBackToTop()

const debounceEvent = this.debounce(this.checkBackToTop)
this.scrollElement.addEventListener('scroll', () => { debounceEvent() })

const debounceResize = this.debounce(this.resizeHandler)
window.addEventListener('resize', () => { debounceResize() })
}

createButton() {
const textSpan = this.constructor.createElement('span')
const iconSpan = this.constructor.createElement('span', ['material-icons', 'nsw-material-icons'], {
title: 'Back to top',
focusable: 'false',
'aria-hidden': 'true',
})

this.element.append(textSpan, iconSpan)

this.text = this.element.querySelector('span:not(.material-icons)')
this.icon = this.element.querySelector('span.material-icons')

this.createButtonContent()
}

createButtonContent() {
if (this.width < 768) {
this.text.innerText = 'Top'
this.icon.innerText = 'keyboard_arrow_up'
} else {
this.text.innerText = 'Back to top'
this.icon.innerText = 'north'
}
}

checkBackToTop() {
let windowTop = this.scrollElement.scrollTop || document.documentElement.scrollTop
if (!this.dataElement) windowTop = window.scrollY || document.documentElement.scrollTop

const scroll = this.scrollPosition
this.scrollPosition = window.scrollY

if (this.scrollOffset && this.scrollOffset > 0) {
this.condition = windowTop >= this.scrollOffset
this.element.classList.toggle('active', this.condition)
} else {
this.condition = scroll > this.scrollPosition && this.scrollPosition > 200
this.element.classList.toggle('active', this.condition)
}
}

resizeHandler() {
const oldWidth = this.width
const oldHeight = this.height

this.width = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
this.height = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)

if (oldWidth !== this.width && oldHeight === this.height) {
this.createButtonContent()
}
}

debounce(fn, wait = 250) {
let timeout

return (...args) => {
const context = this

if (!window.requestAnimationFrame) {
clearTimeout(timeout)
timeout = setTimeout(() => fn.apply(context, args), wait)
} else {
if (timeout) {
window.cancelAnimationFrame(timeout)
}

timeout = window.requestAnimationFrame(() => {
fn.apply(context, args)
})
}
}
}

static createElement(tag, classes = [], attributes = {}) {
const element = document.createElement(tag)
if (classes.length > 0) {
element.classList.add(...classes)
}

Object.entries(attributes).forEach(([key, value]) => {
element.setAttribute(key, value)
})

return element
}
}

export default BackTop
15 changes: 15 additions & 0 deletions src/components/back-to-top/blank.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Back to top
width: narrow
page: true
model: json/back-to-top.json
---

{{#>_layout-container}}
<h1>Back to top</h1>
<p>⚠️ Scroll down and then up to reveal the Back to top button.</p>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consectetur, aspernatur. Sapiente dolorum neque modi ad repellendus, suscipit quia doloremque vero, veritatis aliquid nihil! Adipisci odit laudantium voluptas repellendus consequatur assumenda eveniet, molestias nobis tenetur? Quaerat ex illo ut cupiditate blanditiis qui atque vero fuga, consequatur velit perferendis rem reprehenderit tenetur, amet illum architecto, maxime dicta impedit iusto! Nobis, quam incidunt maxime at quia laudantium natus cum. Quis eveniet hic officiis animi doloremque, tenetur consequatur nihil eligendi nobis in ex voluptates harum, delectus dicta facilis, vero ea. Molestias dolorum, eius ipsa officia error iste illo voluptatum ipsum eaque. Quisquam quasi ab quibusdam cupiditate explicabo ad nobis aliquam, saepe, commodi molestiae error, quos quaerat ea! Ipsum minus velit quisquam omnis recusandae saepe! Dolore rerum tempore est veritatis minus modi facere, ipsam illo dicta, iusto beatae officia odio deserunt veniam dignissimos quos quia laudantium iure fugit eaque possimus suscipit? Magni saepe soluta nisi ipsa iusto deleniti tempora, explicabo commodi, at quam voluptatem voluptatum voluptas accusamus non id asperiores nobis aliquid excepturi? Delectus consectetur, animi aut illum at iusto? Est impedit iusto, praesentium porro eaque unde aspernatur aperiam. Veniam error, deleniti iusto aut a ullam voluptatem dignissimos quia! Maxime vitae reprehenderit quidem eligendi sit non est? Earum illum sequi odio. Beatae sit unde velit voluptatibus, ducimus officia, accusamus iusto voluptas atque necessitatibus, qui sunt delectus porro reiciendis quisquam hic autem illo magnam ipsa quod nobis odio dignissimos. Impedit ipsum tenetur deserunt quod odio labore, minus, sit voluptate corrupti nisi pariatur quae quaerat, necessitatibus est iste exercitationem quisquam quia voluptas rem? Eos voluptatibus nihil aut reprehenderit suscipit temporibus praesentium quod, animi debitis. Dolores exercitationem nesciunt ea eum voluptatibus quaerat! Expedita quae suscipit, corrupti repudiandae reiciendis autem totam ipsam dolor rem eius sed doloremque modi voluptates, quidem consequatur deserunt possimus ullam inventore voluptate nemo dolore error amet.</p>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Cum tempore dolorum mollitia. Accusamus dolor odit molestiae nostrum sunt consequatur quidem, nam magnam obcaecati? Fuga maxime sint, earum minima modi, nobis dicta nam ipsam consequatur neque dolorem temporibus fugit aspernatur porro corporis sequi est facilis quasi incidunt! Tempora possimus dignissimos laboriosam, repellat ratione dolore minima quo. Ab, corrupti delectus est, nihil cupiditate minus aspernatur asperiores alias molestiae necessitatibus voluptates exercitationem rerum natus! Cumque beatae ducimus, sunt ut eum nulla laboriosam libero molestias repudiandae, facilis unde eveniet odit. Doloribus totam, sunt corrupti molestias fugit quaerat dignissimos repellendus quas quae fuga nemo blanditiis aperiam obcaecati sapiente nisi animi suscipit eum mollitia maxime architecto molestiae necessitatibus ducimus vel? Dolorum, ratione cupiditate! Fuga placeat delectus eos quos nam excepturi aliquid incidunt deserunt quisquam possimus veritatis amet, recusandae explicabo beatae eligendi voluptatum ea ipsa aliquam perferendis provident illum harum! Optio ab excepturi sit corporis, deleniti ipsam laboriosam eveniet at quo amet dolore a quasi voluptates libero id nam doloribus rerum quas nulla mollitia ad aliquid dolorum voluptas. Similique itaque numquam eius est recusandae, nemo minus. Itaque expedita dolore aut exercitationem dolor illo molestias eveniet recusandae corrupti. Optio eveniet fugiat corrupti minima aspernatur a minus delectus vel.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Perferendis, tenetur quidem iste nisi accusantium dicta nostrum ratione officia, fuga ipsa fugit qui nemo quibusdam voluptatibus hic dolor quaerat ut sapiente magnam ullam nesciunt accusamus temporibus. Dolore doloremque dolorem quos ab ducimus debitis modi adipisci minus animi architecto odit quia voluptatem optio nulla eaque, neque suscipit accusamus dolorum enim! Quos dolor eos dolorem quibusdam debitis distinctio voluptas aperiam, ratione voluptatem omnis voluptates adipisci, praesentium temporibus dicta eius dolorum maiores quae doloremque? Error odio harum debitis atque, similique minima nobis voluptatibus sequi non consequatur cumque sint ratione accusamus deleniti maiores fugit animi repellat ullam, natus at quam excepturi tenetur cupiditate. Corporis tenetur possimus soluta praesentium maxime vero autem reprehenderit quia culpa unde velit cum sapiente eligendi laboriosam fugiat adipisci, architecto libero, reiciendis doloribus ratione tempora temporibus. Aliquid quibusdam, dolor officia temporibus repellendus nemo explicabo hic quod! Totam architecto officiis vitae nostrum quae deserunt, harum quasi cumque fuga delectus. Consequuntur deserunt alias, consectetur recusandae minima ducimus vitae in mollitia at, tempore blanditiis expedita modi repellendus, nam harum dolorem laudantium aliquam! Harum omnis eos perspiciatis quam mollitia. Voluptates quas nulla quasi ex accusantium soluta laudantium beatae commodi ullam expedita, sapiente enim totam quia? Iste, facere repudiandae ipsum fuga, enim quibusdam doloribus cumque odit atque repellat numquam nulla dolor molestiae laboriosam deleniti ab in omnis, soluta sed ex quae optio! Corporis provident reprehenderit, repellat obcaecati voluptatem consequuntur similique rem tempore eveniet delectus iste tenetur? Autem accusamus nisi voluptate earum atque molestias? Nemo cumque consequuntur ullam ex cum, fuga voluptas vero nihil laborum architecto, possimus incidunt natus autem nobis aliquam molestiae placeat provident ut delectus. Totam error unde obcaecati porro velit mollitia maxime iure, perferendis vitae placeat, officia, natus odio quam quo perspiciatis dicta nulla voluptates in expedita commodi non. Saepe tempora architecto quos dolor quis a impedit voluptates dignissimos, quia eaque placeat, sunt aperiam omnis vel aliquam? Mollitia voluptas exercitationem eveniet quos tempore quisquam provident, fuga hic harum asperiores aperiam magni dolores ex sint illum voluptatem delectus id earum beatae sequi esse at ratione quas. Rem, accusamus. Non, vel maxime quisquam magni culpa quidem repellat in dolorum nam vero asperiores voluptatibus laudantium ducimus quis quos expedita omnis a illum explicabo. Suscipit sint, delectus praesentium velit vel earum pariatur, adipisci perspiciatis animi illo porro nihil! Unde maxime a vel eligendi iure veniam rem. Nulla, vero! Sequi sit autem assumenda natus numquam in iste aliquam id cupiditate!</p>
{{>_back-to-top}}
{{/_layout-container}}
21 changes: 21 additions & 0 deletions src/components/back-to-top/index.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Back to top
width: narrow
tabs: true
directory: back-to-top
intro: A button that allows users to quickly return to the top of the page.
model: json/back-to-top.json
meta-description: A button that allows users to quickly return to the top of the page.
meta-index: true
---

{{#>_docs-example showcode=true separated=true}}
<p>⚠️ Scroll down and then up to reveal the Back to top button.</p>
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consectetur, aspernatur. Sapiente dolorum neque modi ad repellendus, suscipit quia doloremque vero, veritatis aliquid nihil! Adipisci odit laudantium voluptas repellendus consequatur assumenda eveniet, molestias nobis tenetur? Quaerat ex illo ut cupiditate blanditiis qui atque vero fuga, consequatur velit perferendis rem reprehenderit tenetur, amet illum architecto, maxime dicta impedit iusto! Nobis, quam incidunt maxime at quia laudantium natus cum. Quis eveniet hic officiis animi doloremque, tenetur consequatur nihil eligendi nobis in ex voluptates harum, delectus dicta facilis, vero ea. Molestias dolorum, eius ipsa officia error iste illo voluptatum ipsum eaque. Quisquam quasi ab quibusdam cupiditate explicabo ad nobis aliquam, saepe, commodi molestiae error, quos quaerat ea! Ipsum minus velit quisquam omnis recusandae saepe! Dolore rerum tempore est veritatis minus modi facere, ipsam illo dicta, iusto beatae officia odio deserunt veniam dignissimos quos quia laudantium iure fugit eaque possimus suscipit? Magni saepe soluta nisi ipsa iusto deleniti tempora, explicabo commodi, at quam voluptatem voluptatum voluptas accusamus non id asperiores nobis aliquid excepturi? Delectus consectetur, animi aut illum at iusto? Est impedit iusto, praesentium porro eaque unde aspernatur aperiam. Veniam error, deleniti iusto aut a ullam voluptatem dignissimos quia! Maxime vitae reprehenderit quidem eligendi sit non est? Earum illum sequi odio. Beatae sit unde velit voluptatibus, ducimus officia, accusamus iusto voluptas atque necessitatibus, qui sunt delectus porro reiciendis quisquam hic autem illo magnam ipsa quod nobis odio dignissimos. Impedit ipsum tenetur deserunt quod odio labore, minus, sit voluptate corrupti nisi pariatur quae quaerat, necessitatibus est iste exercitationem quisquam quia voluptas rem? Eos voluptatibus nihil aut reprehenderit suscipit temporibus praesentium quod, animi debitis. Dolores exercitationem nesciunt ea eum voluptatibus quaerat! Expedita quae suscipit, corrupti repudiandae reiciendis autem totam ipsam dolor rem eius sed doloremque modi voluptates, quidem consequatur deserunt possimus ullam inventore voluptate nemo dolore error amet.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Perferendis, tenetur quidem iste nisi accusantium dicta nostrum ratione officia, fuga ipsa fugit qui nemo quibusdam voluptatibus hic dolor quaerat ut sapiente magnam ullam nesciunt accusamus temporibus. Dolore doloremque dolorem quos ab ducimus debitis modi adipisci minus animi architecto odit quia voluptatem optio nulla eaque, neque suscipit accusamus dolorum enim! Quos dolor eos dolorem quibusdam debitis distinctio voluptas aperiam, ratione voluptatem omnis voluptates adipisci, praesentium temporibus dicta eius dolorum maiores quae doloremque? Error odio harum debitis atque, similique minima nobis voluptatibus sequi non consequatur cumque sint ratione accusamus deleniti maiores fugit animi repellat ullam, natus at quam excepturi tenetur cupiditate. Corporis tenetur possimus soluta praesentium maxime vero autem reprehenderit quia culpa unde velit cum sapiente eligendi laboriosam fugiat adipisci, architecto libero, reiciendis doloribus ratione tempora temporibus. Aliquid quibusdam, dolor officia temporibus repellendus nemo explicabo hic quod! Totam architecto officiis vitae nostrum quae deserunt, harum quasi cumque fuga delectus. Consequuntur deserunt alias, consectetur recusandae minima ducimus vitae in mollitia at, tempore blanditiis expedita modi repellendus, nam harum dolorem laudantium aliquam! Harum omnis eos perspiciatis quam mollitia. Voluptates quas nulla quasi ex accusantium soluta laudantium beatae commodi ullam expedita, sapiente enim totam quia? Iste, facere repudiandae ipsum fuga, enim quibusdam doloribus cumque odit atque repellat numquam nulla dolor molestiae laboriosam deleniti ab in omnis, soluta sed ex quae optio! Corporis provident reprehenderit, repellat obcaecati voluptatem consequuntur similique rem tempore eveniet delectus iste tenetur? Autem accusamus nisi voluptate earum atque molestias? Nemo cumque consequuntur ullam ex cum, fuga voluptas vero nihil laborum architecto, possimus incidunt natus autem nobis aliquam molestiae placeat provident ut delectus. Totam error unde obcaecati porro velit mollitia maxime iure, perferendis vitae placeat, officia, natus odio quam quo perspiciatis dicta nulla voluptates in expedita commodi non. Saepe tempora architecto quos dolor quis a impedit voluptates dignissimos, quia eaque placeat, sunt aperiam omnis vel aliquam? Mollitia voluptas exercitationem eveniet quos tempore quisquam provident, fuga hic harum asperiores aperiam magni dolores ex sint illum voluptatem delectus id earum beatae sequi esse at ratione quas. Rem, accusamus. Non, vel maxime quisquam magni culpa quidem repellat in dolorum nam vero asperiores voluptatibus laudantium ducimus quis quos expedita omnis a illum explicabo. Suscipit sint, delectus praesentium velit vel earum pariatur, adipisci perspiciatis animi illo porro nihil! Unde maxime a vel eligendi iure veniam rem. Nulla, vero! Sequi sit autem assumenda natus numquam in iste aliquam id cupiditate!</p>
{{>_back-to-top model}}
{{/_docs-example}}

{{#>_docs-code open=true}}
{{>_back-to-top model}}
{{/_docs-code}}
1 change: 1 addition & 0 deletions src/components/back-to-top/json/back-to-top.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Loading
Loading