forked from vczb/sagu-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
262 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,3 +11,4 @@ rollup.config.* | |
node_modules/ | ||
docs-build/ | ||
.github | ||
.tool-versions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as placeholder } from './placeholder' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { css } from 'styled-components' | ||
import { theme } from './../styles' | ||
|
||
const placeholder = css` | ||
color: ${theme.colors.neutral.lighter}; | ||
background-image: linear-gradient( | ||
to right, | ||
currentColor 0%, | ||
${theme.colors.neutral.base} 20%, | ||
currentColor 40%, | ||
currentColor 100% | ||
); | ||
background-size: 80rem 14rem; | ||
animation: placeholder 1s linear infinite forwards; | ||
@keyframes placeholder { | ||
0% { | ||
background-position: -40rem 0; | ||
} | ||
100% { | ||
background-position: 40rem 0; | ||
} | ||
} | ||
` | ||
|
||
export default placeholder |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import React from 'react' | ||
export const Down = () => ( | ||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
<path | ||
opacity="0.3" | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="m8 9.491 3.403-3.308a.656.656 0 0 1 .909 0 .613.613 0 0 1 0 .884l-3.857 3.75a.656.656 0 0 1-.91 0l-3.857-3.75a.613.613 0 0 1 0-.884.656.656 0 0 1 .91 0L8 9.491Z" | ||
fill="currentColor" | ||
/> | ||
</svg> | ||
) | ||
|
||
export default Down |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import React from 'react' | ||
export const Up = () => ( | ||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
<path | ||
opacity="0.3" | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M8 6.509 4.597 9.817a.656.656 0 0 1-.909 0 .613.613 0 0 1 0-.884l3.857-3.75a.656.656 0 0 1 .91 0l3.857 3.75a.613.613 0 0 1 0 .884.656.656 0 0 1-.91 0L8 6.509Z" | ||
fill="currentColor" | ||
/> | ||
</svg> | ||
) | ||
|
||
export default Up |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { default as Down } from './Down' | ||
export { default as Up } from './Up' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
export * from './packages' | ||
export * from './styles' | ||
export * from './animations' | ||
export * from './icons' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import React, { useMemo, useState } from 'react' | ||
import { Down, Up } from '../../icons' | ||
import * as S from './styles' | ||
|
||
export type ImageProps = { | ||
url: string | ||
listOrder: number | ||
} | ||
|
||
export type SliderProps = { | ||
images: ImageProps[] | ||
size?: 'small' | 'large' | ||
loading?: boolean | ||
} | ||
|
||
const Slider = ({ images, size = 'small', loading }: SliderProps) => { | ||
const sortedImages = useMemo( | ||
() => images.slice().sort((a, b) => a.listOrder - b.listOrder), | ||
[images] | ||
) | ||
|
||
const [active, setActive] = useState(0) | ||
|
||
if (loading) return <S.Loading size={size} /> | ||
|
||
return ( | ||
<S.Figure size={size}> | ||
{sortedImages?.map(({ url, listOrder }, index) => ( | ||
<S.Image | ||
active={active === index} | ||
position={index - active} | ||
loading="lazy" | ||
key={index} | ||
src={url} | ||
alt={`Slider image ${listOrder}`} | ||
/> | ||
))} | ||
{sortedImages.length > 1 && ( | ||
<> | ||
<S.SlideButton | ||
disabled={active === 0} | ||
onClick={() => setActive(active - 1)} | ||
> | ||
<Up /> | ||
</S.SlideButton> | ||
<S.SlideButton | ||
disabled={active === sortedImages.length - 1} | ||
onClick={() => setActive(active + 1)} | ||
> | ||
<Down /> | ||
</S.SlideButton> | ||
</> | ||
)} | ||
</S.Figure> | ||
) | ||
} | ||
|
||
export default Slider |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
export const mock = [ | ||
{ | ||
url: 'https://picsum.photos/id/237/400/200', | ||
listOrder: 0 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/238/400/200', | ||
listOrder: 1 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/239/400/200', | ||
listOrder: 2 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/240/400/200', | ||
listOrder: 3 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/241/400/200', | ||
listOrder: 4 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/242/400/200', | ||
listOrder: 5 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/243/400/200', | ||
listOrder: 6 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/244/400/200', | ||
listOrder: 7 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/500/400/200', | ||
listOrder: 8 | ||
}, | ||
{ | ||
url: 'https://picsum.photos/id/501/400/200', | ||
listOrder: 9 | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react' | ||
import { Story, Meta } from '@storybook/react/types-6-0' | ||
import Slider, { SliderProps } from '.' | ||
import { mock } from './mock' | ||
|
||
export default { | ||
title: 'Slider', | ||
component: Slider, | ||
args: { | ||
images: mock | ||
} | ||
} as Meta | ||
|
||
export const Default: Story<SliderProps> = (args) => <Slider {...args} /> | ||
|
||
export const OneImageOnly: Story<SliderProps> = (args) => ( | ||
<Slider {...args} images={[mock[0]]} /> | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import styled, { css } from 'styled-components' | ||
import { placeholder } from '../../animations/' | ||
import { SliderProps } from '.' | ||
|
||
const figureModifiers = { | ||
small: () => css` | ||
max-width: 40rem; | ||
height: 20rem; | ||
`, | ||
large: () => css` | ||
max-width: 80rem; | ||
height: 40rem; | ||
` | ||
} | ||
|
||
export const Figure = styled.figure<Pick<SliderProps, 'size'>>` | ||
${({ size }) => css` | ||
position: relative; | ||
overflow: hidden; | ||
${!!size && figureModifiers[size]()} | ||
`} | ||
` | ||
|
||
export const Loading = styled.div<Pick<SliderProps, 'size'>>` | ||
${({ size }) => css` | ||
${!!size && figureModifiers[size]()} | ||
${placeholder} | ||
`} | ||
` | ||
|
||
export const Image = styled.img<{ active?: boolean; position: number }>` | ||
${({ theme, active, position }) => css` | ||
position: absolute; | ||
width: 100%; | ||
height: 100%; | ||
transition: transform ${theme.transitions.default}; | ||
transform: translateX(${active ? 0 : position * 100 + '%'}); | ||
object-fit: cover; | ||
border-radius: ${theme.border.mini}; | ||
${placeholder} | ||
`} | ||
` | ||
|
||
export const SlideButton = styled.button` | ||
${({ theme }) => css` | ||
position: absolute; | ||
top: 50%; | ||
transform: translateY(-50%) rotate(270deg); | ||
width: 2rem; | ||
height: 2rem; | ||
border-radius: 50%; | ||
background: ${theme.colors.neutral.lightest}; | ||
border: none; | ||
outline: none; | ||
cursor: pointer; | ||
color: ${theme.colors.primary.light}; | ||
transition: all ${theme.transitions.default}; | ||
opacity: 0.7; | ||
&:hover, | ||
&:focus { | ||
box-shadow: ${theme.shadows.focus}; | ||
opacity: 1; | ||
color: ${theme.colors.neutral.darkest}; | ||
} | ||
&:first-of-type { | ||
left: ${theme.spacings.xsmall}; | ||
} | ||
&:last-of-type { | ||
right: ${theme.spacings.xsmall}; | ||
} | ||
&:disabled { | ||
opacity: 0.2; | ||
cursor: default; | ||
} | ||
`} | ||
` |