diff --git a/.storybook/main.ts b/.storybook/main.ts index 2ee8a26b..6c316c09 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -7,6 +7,7 @@ const config: StorybookConfig = { '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-onboarding', + 'storybook-addon-next', '@storybook/addon-interactions', '@storybook/addon-styling', ], @@ -14,6 +15,7 @@ const config: StorybookConfig = { name: '@storybook/nextjs', options: { nextConfigPath: path.resolve(__dirname, '../next.config.js') }, }, + staticDirs: ['../public'], docs: { autodocs: 'tag', }, diff --git a/package.json b/package.json index 06e5fad7..c53b81cc 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "next-sitemap": "^3.1.54", "prettier": "^2.8.4", "storybook": "^7.4.0", + "storybook-addon-next": "^1.8.0", "typescript": "4.9.5" } } diff --git a/public/images/project/13-1.png b/public/images/project/13-1.png new file mode 100644 index 00000000..f5a76ac0 Binary files /dev/null and b/public/images/project/13-1.png differ diff --git a/public/images/session/orientation.png b/public/images/session/orientation.png new file mode 100644 index 00000000..4311207e Binary files /dev/null and b/public/images/session/orientation.png differ diff --git a/src/components/Thumbnail/Thumbnail.stories.tsx b/src/components/Thumbnail/Thumbnail.stories.tsx new file mode 100644 index 00000000..0c5127d9 --- /dev/null +++ b/src/components/Thumbnail/Thumbnail.stories.tsx @@ -0,0 +1,39 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import { Meta } from '@storybook/react'; + +import { Thumbnail } from './index'; + +const meta: Meta = { + title: 'components/Thumbnail', +}; + +export default meta; +const PROJECT_DUMMY_IMG = '/images/project/13-1.png'; +const SESSION_DUMMY_IMG = '/images/session/orientation.png'; + +export const Project = { + render: () => ( + + ), +}; + +export const Session = { + render: () => ( + + ), +}; diff --git a/src/components/Thumbnail/Thumbnail.tsx b/src/components/Thumbnail/Thumbnail.tsx new file mode 100644 index 00000000..293960a1 --- /dev/null +++ b/src/components/Thumbnail/Thumbnail.tsx @@ -0,0 +1,173 @@ +import Image from 'next/image'; +import { css } from '@emotion/react'; +import { m, Variants } from 'framer-motion'; + +import { ArrowIcon } from '~/components/Icons'; +import { colors } from '~/styles/colors'; + +type Link = { + type: 'Behance' | 'Github' | 'Web' | 'App'; + href: string; +}; + +type ThumbnailProps = { + title: string; + subTitle: string; + img: string; + description: string; + links?: Link[]; +}; + +const defaultEasing = [0.6, -0.05, 0.01, 0.99]; + +export function Thumbnail({ title, subTitle, img, description, links }: ThumbnailProps) { + return ( + + + {title} + + + + + {title} + + + {subTitle} + + + + {links && ( + + {links.map(link => ( + + + {link.type} + + + + + + ))} + + )} + + + ); +} + +const articleCss = css` + position: relative; + width: 312px; + height: 208px; + padding: 24px; + margin-top: 100px; +`; + +const imageCss = css` + position: absolute; + top: 0; + left: 0; + object-fit: cover; + z-index: -1; + width: 100%; + height: 100%; +`; + +const contentsCss = css` + display: flex; + flex-direction: column; + height: 100%; + justify-content: space-between; +`; + +const linkContainerCss = css` + display: flex; + gap: 12px; + align-items: center; +`; + +const linkWrapperCss = css` + display: flex; + align-items: center; +`; + +const linkCss = css` + color: ${colors.blue400}; + font-weight: 500; + font-size: 1rem; + line-height: 22px; + letter-spacing: -0.16px; + margin-right: 2px; +`; + +const titleCss = css` + position: relative; + font-weight: 700; + font-size: 1.25rem; + line-height: 30px; + color: ${colors.white}; + z-index: 10; +`; + +const subTitleCss = css` + position: relative; + font-weight: 500; + font-size: 1rem; + line-height: 22px; + color: ${colors.gray100}; + z-index: 10; +`; + +const descriptionCss = css` + position: relative; + font-weight: 500; + font-size: 1rem; + line-height: 22px; + color: ${colors.white}; + z-index: 10; + letter-spacing: -0.16px; + white-space: pre-wrap; +`; + +const textVariants: Variants = { + default: { opacity: 0 }, + hover: { + opacity: 1, + transition: { + duration: 0.3, + ease: defaultEasing, + }, + }, +}; + +const articleVariants: Variants = { + default: { background: 'transparent' }, + hover: { + background: 'rgba(19, 28, 40, 0.5)', + transition: { + duration: 0.3, + ease: defaultEasing, + }, + }, +}; + +const imageVariants: Variants = { + default: { filter: 'blur(0px)' }, + hover: { + filter: 'blur(7px)', + transition: { + duration: 0.3, + ease: defaultEasing, + }, + }, +}; diff --git a/src/components/Thumbnail/index.ts b/src/components/Thumbnail/index.ts new file mode 100644 index 00000000..9a19e45c --- /dev/null +++ b/src/components/Thumbnail/index.ts @@ -0,0 +1 @@ +export { Thumbnail } from './Thumbnail'; diff --git a/yarn.lock b/yarn.lock index f86fe6a9..a8de7c83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7860,7 +7860,7 @@ loader-utils@^2.0.0, loader-utils@^2.0.4: emojis-list "^3.0.0" json5 "^2.1.2" -loader-utils@^3.2.0: +loader-utils@^3.2.0, loader-utils@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== @@ -9722,7 +9722,7 @@ sass-loader@^12.4.0: klona "^2.0.4" neo-async "^2.6.2" -sass-loader@^13.2.2: +sass-loader@^13.2.0, sass-loader@^13.2.2: version "13.3.2" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-13.3.2.tgz#460022de27aec772480f03de17f5ba88fa7e18c6" integrity sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg== @@ -10054,6 +10054,20 @@ store2@^2.14.2: resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.2.tgz#56138d200f9fe5f582ad63bc2704dbc0e4a45068" integrity sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w== +storybook-addon-next@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/storybook-addon-next/-/storybook-addon-next-1.8.0.tgz#e37d5c851dd10a46a0d3aca170c49ba100e51e06" + integrity sha512-hCDRkgTllb9Qz14u+oafnhUbKMWZ/YKgcVBHDc9ilbsd9I3bHqBwpldfTelL/ahfo2jDqPnCQVnQkXV8U+fr2Q== + dependencies: + image-size "^1.0.0" + loader-utils "^3.2.1" + postcss-loader "^7.0.2" + resolve-url-loader "^5.0.0" + sass-loader "^13.2.0" + semver "^7.3.8" + tsconfig-paths "^4.1.2" + tsconfig-paths-webpack-plugin "^4.0.0" + storybook@^7.4.0: version "7.4.0" resolved "https://registry.yarnpkg.com/storybook/-/storybook-7.4.0.tgz#f1b64222e3d474bc6e258eb7e48c675685829873" @@ -10504,7 +10518,7 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tsconfig-paths-webpack-plugin@^4.0.1: +tsconfig-paths-webpack-plugin@^4.0.0, tsconfig-paths-webpack-plugin@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz#3c6892c5e7319c146eee1e7302ed9e6f2be4f763" integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==