Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Implement marquee component (#71)
Browse files Browse the repository at this point in the history
* Create the basic for marquee (sc2156)

* Finish marquee creation (sc2156)

* Format Marquee stories file (sc2156)

* Add functionality to slide when mouse is over (sc2156)

* Improve names on stories (sc2156)

* Export Marquee (sc2156)

* Remove left padding on Marquee (sc2156)

* Remove global variation addition (sc2156)
  • Loading branch information
guerrato authored Mar 18, 2022
1 parent f6824a3 commit 3273ca1
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 0 deletions.
95 changes: 95 additions & 0 deletions src/lib/components/common/Marquee/Marquee.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Story } from '@storybook/react'
import React, { useState } from 'react'
import { Marquee, MarqueeProps } from '.'
import { Icon, IconData, IconName } from '../../icons'

export default {
title: 'Components/Common/Marquee',
component: Marquee,
parameters: {
layout: 'fullscreen'
}
}

const icons = Object.keys(IconData).map((key) => (
<div style={{ display: 'flex' }}>
<Icon key={key} icon={key as IconName} size="large" color="white" />
&nbsp;
<p>{key}</p>
</div>
))

const longLorem = (
<p style={{ color: '#f1c3c3', whiteSpace: 'nowrap' }}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin feugiat bibendum vehicula. Cras
et eros vitae velit commodo volutpat ac eget ex. Donec sed felis scelerisque, scelerisque nisl
non, maximus nunc.
</p>
)

const shortLorem = (
<p style={{ color: '#f1c3c3', whiteSpace: 'nowrap' }}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
)

const DefaultTemplate = (args: MarqueeProps) => {
return <Marquee {...args} />
}

const BoxTemplate = (args: MarqueeProps) => {
const [slide, setSlide] = useState<boolean>(args.slide && false)
return (
<div
style={{
position: 'relative',
width: '300px',
height: '50px',
backgroundColor: 'black',
display: 'flex',
alignItems: 'center'
}}
onMouseEnter={() => setSlide(true)}
onMouseLeave={() => setSlide(false)}
>
<Marquee {...args} slide={slide} />
</div>
)
}

export const Default: Story<MarqueeProps> = DefaultTemplate.bind({})
Default.args = {
children: <div style={{ color: 'white', display: 'flex', gap: '32px' }}>{icons}</div>,
duration: 120
}

export const ShortText: Story<MarqueeProps> = DefaultTemplate.bind({})
ShortText.args = {
children: shortLorem,
duration: 15
}

export const LongText: Story<MarqueeProps> = DefaultTemplate.bind({})
LongText.args = {
children: longLorem,
duration: 25
}

export const ShortTextInBox: Story<MarqueeProps> = BoxTemplate.bind({})
ShortTextInBox.args = {
children: shortLorem,
duration: 15
}

export const LongTextInBox: Story<MarqueeProps> = BoxTemplate.bind({})
LongTextInBox.args = {
children: longLorem,
duration: 25
}

export const SlideWhenMouseover: Story<MarqueeProps> = BoxTemplate.bind({})
SlideWhenMouseover.args = {
children: shortLorem,
duration: 15,
slide: true
}
94 changes: 94 additions & 0 deletions src/lib/components/common/Marquee/Marquee.styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import styled, { keyframes } from 'styled-components'

export type MarqueeStyles = {
duration: number
width?: string
}

const slideMainWhenStart = (props) => {
return keyframes`
0% {
transform: 0px;
}
100% {
transform: translateX(-100%);
}
`
}

const slideMainForever = (props) => {
return keyframes`
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-100%);
}
`
}

const slideFakeForever = (props) => {
return keyframes`
0% {
transform: translateX(0);
}
100% {
transform: translateX(-200%);
}
`
}

export const Track = styled.div<MarqueeStyles>`
--duration: ${(props) => props.duration}s;
box-sizing: border-box;
width: ${(props) => props.width || '100%'};
overflow: hidden;
* {
margin: 0;
padding: 0;
}
`

export const Roller = styled.div.attrs((props) => ({
'aria-hidden': true
}))`
display: block;
width: max-content;
min-width: 200%;
`

export const MainContent = styled.div`
display: inline-block;
box-sizing: border-box;
margin: 0;
padding: 0 20px 0 0;
width: fit-content;
min-width: 50%;
&.slide {
animation-name: ${slideMainWhenStart}, ${slideMainForever};
animation-duration: var(--duration), calc(var(--duration) * 2);
animation-delay: 0s, var(--duration);
animation-timing-function: linear, linear;
animation-iteration-count: 1, infinite;
}
`

export const FakeContent = styled.div`
display: inline-block;
box-sizing: border-box;
margin: 0;
padding: 0 20px 0 0;
width: fit-content;
min-width: 50%;
&.slide {
animation-name: ${slideFakeForever};
animation-duration: calc(var(--duration) * 2);
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-delay: 0;
}
`
20 changes: 20 additions & 0 deletions src/lib/components/common/Marquee/Marquee.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { ReactNode } from 'react'
import { FakeContent, MainContent, MarqueeStyles, Roller, Track } from './Marquee.styles'

export type MarqueeProps = MarqueeStyles & {
children: ReactNode
slide?: boolean
}

export const Marquee = (props: MarqueeProps) => {
const { slide = true } = props

return (
<Track {...props}>
<Roller>
<MainContent className={slide && 'slide'}>{props.children}</MainContent>
<FakeContent className={slide && 'slide'}>{props.children}</FakeContent>
</Roller>
</Track>
)
}
1 change: 1 addition & 0 deletions src/lib/components/common/Marquee/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Marquee'
1 change: 1 addition & 0 deletions src/lib/components/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './AspectRatio'
export * from './Tooltip'
export * from './Modal'
export * from './Toast'
export * from './Marquee'

0 comments on commit 3273ca1

Please sign in to comment.