Skip to content

Commit

Permalink
Add back to top component
Browse files Browse the repository at this point in the history
  • Loading branch information
albinazs committed Jul 24, 2023
1 parent da80fd6 commit a783a74
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 5 deletions.
2 changes: 1 addition & 1 deletion dist/css/explorer-1.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/js/explorer-1.min.js

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,29 @@ <h2 class="text-h3">Heading</h2>
Maintained by DesignLab
</p>
</div>
<div id="BackToTop" class="BlockBackToTop">
<button
class="BaseButton text-contrast-none inline-block -primary -compact fixed bottom-10 right-10 z-60"
>
<span class="label block">
<svg
class="IconDropdown"
width="12"
height="8"
viewBox="0 0 12 8"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
focusable="false"
>
<path
d="M.343 2L1.757.586 6 4.828 10.243.586 11.657 2 6 7.657.343 2z"
fill="currentColor"
></path>
</svg>
<span class="label-text">Back to top</span>
</span>
</button>
</div>
<script type="module" src="./js/scripts.js"></script>
</body>
</html>
29 changes: 29 additions & 0 deletions src/js/components/_BlockBackToTop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
**
** Back To Top button for scrolling to the top
**
*/

document.addEventListener('DOMContentLoaded', () => {
const backToTopBtn = document
.getElementById('BackToTop')
.querySelector('button')
const alwaysVisible = backToTopBtn.classList.contains('always-visible')
const threshold = 300

const onScroll = () => {
if (!alwaysVisible) {
showBackToTop = window.scrollY > threshold
showBackToTop
? (backToTopBtn.style.display = 'block')
: (backToTopBtn.style.display = 'none')
}
}

const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' })
}

window.addEventListener('scroll', onScroll)
backToTopBtn.addEventListener('click', scrollToTop)
})
1 change: 1 addition & 0 deletions src/js/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ require('./vendors/_swiper.js')
require('./components/_HeroMedia.js')
require('./components/_BlockAccordion.js')
require('./components/_HeaderInternal.js')
require('./components/_BlockBackToTop.js')
1 change: 1 addition & 0 deletions src/scss/_components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@import 'components/BaseImageCaption';
@import 'components/BaseImagePlaceholder';
@import 'components/BasePlaceholder';
@import 'components/BlockBackToTop';
@import 'components/BlockImageCarousel';
@import 'components/BlockImageCarouselItem';
@import 'components/BlockImageGallery';
Expand Down
25 changes: 25 additions & 0 deletions src/scss/components/_BlockBackToTop.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.BlockBackToTop {
> button {
@apply hidden;

&.always-visible {
@apply block;
}
}

.IconDropdown {
@apply transform rotate-180 text-sm;

@screen sm {
@apply mr-2;
}
}

.label-text {
@apply hidden;

@screen sm {
@apply block;
}
}
}
5 changes: 5 additions & 0 deletions storybook/stories/_docs/overview_blocks.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ Reserved for the top of the page. Learn more about our heroes on the [heroes ove
canvasClass: 'sbdocs-inline-height',
fullWidth: true,
},
{
heading: 'BlockBackToTop',
description: 'Allows users to scroll back to the top of the page',
storyId: 'components-blocks-blockbacktotop--default',
},
]}
/>

Expand Down
14 changes: 11 additions & 3 deletions storybook/stories/components/BaseButton/BaseButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IconSocialInstagramTemplate } from '../Icons/IconSocialInstagram'
import { IconSocialYoutubeTemplate } from '../Icons/IconSocialYoutube'
import { IconExpandTemplate } from '../Icons/IconExpand'
import { IconExternalTemplate } from '../Icons/IconExternal'
import { IconDropdownTemplate } from '../Icons/IconDropdown'

export const BaseButtonTemplate = ({
label,
Expand All @@ -17,11 +18,13 @@ export const BaseButtonTemplate = ({
compact,
disabled,
icon,
iconBefore,
iconOnly,
cssClass,
fancybox,
target,
}) => {
if (iconBefore == undefined) iconBefore = false
if (iconOnly == undefined) iconOnly = false
fancybox = fancybox ? fancybox : ''
let iconTemplate = ''
Expand All @@ -35,6 +38,7 @@ export const BaseButtonTemplate = ({
else if (icon == 'instagram') iconTemplate = IconSocialInstagramTemplate({})
else if (icon == 'youtube') iconTemplate = IconSocialYoutubeTemplate({})
else if (icon == 'external') iconTemplate = IconExternalTemplate({})
else if (icon == 'dropdown') iconTemplate = IconDropdownTemplate({})
else if (caret) iconTemplate = IconCaretTemplate({})

// setup classnames
Expand All @@ -51,6 +55,10 @@ export const BaseButtonTemplate = ({
label = ''
}

const content = iconBefore
? `${iconTemplate}<span class="label-text">${label}</span>`
: `<span class="label-text">${label}</span>${iconTemplate}`

if (disabled) {
return `
<button
Expand All @@ -60,7 +68,7 @@ export const BaseButtonTemplate = ({
}
>
<span class="label block">
${label}${iconTemplate}
${content}
</span>
</button>
`
Expand All @@ -81,7 +89,7 @@ export const BaseButtonTemplate = ({
}
>
<span class="label block">
${label}${iconTemplate}
${content}
</span>
</a>
`
Expand All @@ -96,7 +104,7 @@ export const BaseButtonTemplate = ({
} ${fancybox}
>
<span class="label block">
${label}${iconTemplate}
${content}
</span>
</button>
`
Expand Down
12 changes: 12 additions & 0 deletions storybook/stories/components/BaseButton/BaseButton.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,23 @@ export default {
'twitter',
'instagram',
'youtube',
'dropdown',
],
},
table: {
defaultValue: { summary: 'none' },
},
},
iconBefore: {
type: 'boolean',
description: 'If the icon should be positioned before the text.',
control: {
type: 'boolean',
},
table: {
defaultValue: { summary: 'false' },
},
},
iconOnly: {
type: 'boolean',
description: 'If the button will only include an icon and no text.',
Expand Down Expand Up @@ -127,6 +138,7 @@ Primary_Button.args = {
compact: false,
disabled: false,
icon: null,
iconBefore: false,
iconOnly: false,
}
export const Primary_Internal_Button = BaseButtonTemplate.bind({})
Expand Down
14 changes: 14 additions & 0 deletions storybook/stories/components/BlockBackToTop/BlockBackToTop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BaseButtonTemplate } from '../BaseButton/BaseButton'

export const BlockBackToTopTemplate = ({ alwaysVisible }) => {
return `<div id="BackToTop" class="BlockBackToTop">
${BaseButtonTemplate({
variant: 'primary',
cssClass: `z-60 ${alwaysVisible ? 'always-visible' : ''}`,
compact: true,
icon: 'dropdown',
iconBefore: true,
label: 'Back to top',
})}
</div>`
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { BlockBackToTopTemplate } from './BlockBackToTop.js'

export default {
title: 'Components/Blocks/BlockBackToTop',
argTypes: {
alwaysVisible: {
type: 'boolean',
description: 'Toggles visibility based on the scrolling position.',
},
},
parameters: {
viewMode: 'docs',
docs: {
description: {
component: 'Allows users to scroll back to the top of the page',
},
},
},
}

export const Default = BlockBackToTopTemplate.bind({})
Default.storyName = 'BlockBackToTop'
Default.args = { alwaysVisible: true }

0 comments on commit a783a74

Please sign in to comment.