diff --git a/src/lib/components/common/Marquee/Marquee.stories.tsx b/src/lib/components/common/Marquee/Marquee.stories.tsx
new file mode 100644
index 00000000..7bfc2ef6
--- /dev/null
+++ b/src/lib/components/common/Marquee/Marquee.stories.tsx
@@ -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) => (
+
+))
+
+const longLorem = (
+
+ 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.
+
+)
+
+const shortLorem = (
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+)
+
+const DefaultTemplate = (args: MarqueeProps) => {
+ return
+}
+
+const BoxTemplate = (args: MarqueeProps) => {
+ const [slide, setSlide] = useState(args.slide && false)
+ return (
+ setSlide(true)}
+ onMouseLeave={() => setSlide(false)}
+ >
+
+
+ )
+}
+
+export const Default: Story = DefaultTemplate.bind({})
+Default.args = {
+ children: {icons}
,
+ duration: 120
+}
+
+export const ShortText: Story = DefaultTemplate.bind({})
+ShortText.args = {
+ children: shortLorem,
+ duration: 15
+}
+
+export const LongText: Story = DefaultTemplate.bind({})
+LongText.args = {
+ children: longLorem,
+ duration: 25
+}
+
+export const ShortTextInBox: Story = BoxTemplate.bind({})
+ShortTextInBox.args = {
+ children: shortLorem,
+ duration: 15
+}
+
+export const LongTextInBox: Story = BoxTemplate.bind({})
+LongTextInBox.args = {
+ children: longLorem,
+ duration: 25
+}
+
+export const SlideWhenMouseover: Story = BoxTemplate.bind({})
+SlideWhenMouseover.args = {
+ children: shortLorem,
+ duration: 15,
+ slide: true
+}
diff --git a/src/lib/components/common/Marquee/Marquee.styles.tsx b/src/lib/components/common/Marquee/Marquee.styles.tsx
new file mode 100644
index 00000000..90431eec
--- /dev/null
+++ b/src/lib/components/common/Marquee/Marquee.styles.tsx
@@ -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`
+ --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;
+ }
+`
diff --git a/src/lib/components/common/Marquee/Marquee.tsx b/src/lib/components/common/Marquee/Marquee.tsx
new file mode 100644
index 00000000..7f1dc6ba
--- /dev/null
+++ b/src/lib/components/common/Marquee/Marquee.tsx
@@ -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 (
+
+ )
+}
diff --git a/src/lib/components/common/Marquee/index.tsx b/src/lib/components/common/Marquee/index.tsx
new file mode 100644
index 00000000..394b437f
--- /dev/null
+++ b/src/lib/components/common/Marquee/index.tsx
@@ -0,0 +1 @@
+export * from './Marquee'
diff --git a/src/lib/components/common/index.ts b/src/lib/components/common/index.ts
index e083d590..edefd5ec 100644
--- a/src/lib/components/common/index.ts
+++ b/src/lib/components/common/index.ts
@@ -2,3 +2,4 @@ export * from './AspectRatio'
export * from './Tooltip'
export * from './Modal'
export * from './Toast'
+export * from './Marquee'