Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[💅 design system] 이미지 갤러리 컴포넌트 생성 #55

Merged
merged 2 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions apps/web/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import {
Drawer,
Gallery,
Headers,
MyButton,
Text,
Expand Down Expand Up @@ -45,6 +46,30 @@ export default function Home() {
<div>:)</div>
</Drawer>
<MyButton onClick={open}>토글</MyButton>
<Container align="center">
<Gallery
urls={[
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
]}
/>
</Container>
<Container align="center">
<Gallery.Post
displayLeftOverImgCount={true}
urls={[
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
]}
/>
</Container>
</>
);
}
10 changes: 10 additions & 0 deletions apps/web/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ const nextConfig = {
sassOptions: {
includePaths: [path.join(__dirname, "styles")],
},
images: {
remotePatterns: [
{
protocol: "https",
hostname: "media.triple.guide",
port: "",
pathname: "/triple-cms/c_limit,f_auto,h_1024,w_1024/**",
},
],
},
};

export default nextConfig;
139 changes: 139 additions & 0 deletions packages/design-system/src/components/gallery/_gallery.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
@use "../../functions/" as *;
@use "../../mixins/" as *;
@use "sass:map";

$overlay-color: #fefefe;

.gallery {
display: grid;
gap: space("sm");
min-width: min(50vw, 36rem);
position: relative;

img {
width: 100%;
height: 100%;
position: relative !important;
z-index: z("base") !important;
}

.overlay {
filter: brightness(40%);
position: absolute;
}

.image-container {
position: relative;
display: inline-block;
cursor: pointer;

&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

&.post {
grid-column: span 2;
grid-row: span 1;
}
}

.display-leftover-img-count {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: $overlay-color;
z-index: z("default");
font-size: font-size(h3);
font-weight: bold;
}

@mixin gallery-template($i) {
@if ($i==4) {
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
.gallery-item {
&:nth-child(1) {
grid-column: span 3;
grid-row: span 3;
}
&:nth-child(2),
&:nth-child(3),
&:nth-child(4) {
grid-column: span 1;
grid-column: span 1;
}
}
} @else if($i==3) {
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 1fr);
.gallery-item {
&:nth-child(1) {
grid-column: span 2;
grid-row: span 2;
}
&:nth-child(2),
&:nth-child(3) {
grid-column: span 1;
grid-column: span 1;
}
}
} @else if($i==2) {
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(1, 1fr);
.gallery-item {
grid-column: span 1;
grid-row: span 1;
}
}
}
Comment on lines +56 to +94
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

모든 갤러리 컴포넌트는 1 - 4 개의 이미지/영상을 보여줄 때 공통으로 보여줄 스타일입니다.


@for $i from 1 through 5 {
&.gallery-img-length-#{$i}:not(.post) {
@if $i == 5 {
grid-template-columns: repeat(4, 1fr);
}
Comment on lines +97 to +100
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

카드 컴포넌트와 댓글 이외의 갤러리들은 다음과 같이 그려주기 위한 스타일링입니다.

image

@include gallery-template($i);

.gallery-item {
@if $i == 5 {
&:nth-child(1) {
grid-column: span 2;
grid-row: span 2;
}
&:nth-child(n + 2):nth-child(-n + 5) {
grid-column: span 1;
grid-row: span 1;
}
}
}
}
}

// Post gallery
&.post {
@for $i from 1 through 5 {
&.gallery-img-length-#{$i} {
@if $i == 5 {
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(2, 1fr);
.gallery-item {
&:nth-child(1),
&:nth-child(2) {
grid-column: span 3;
}
&:nth-child(n + 3):nth-child(-n + 5) {
grid-column: span 2;
}
}
}
Comment on lines +122 to +134
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

댓글에 첨부한 이미지(/영상 포함예정)들은 다음과 같이 그려주기 위한 스타일입니다.
image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지에 cover 같은거 적용해줘도 좋겠네요 ..! ㅋㅋㅋㅋ 비율이 ..!

Copy link
Collaborator Author

@Pyotato Pyotato Aug 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#62 (comment) 반영완료!

@include gallery-template($i);
}
}
}
}
112 changes: 112 additions & 0 deletions packages/design-system/src/components/gallery/_gallery.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import type { Meta, StoryObj } from "@storybook/react";
import { useEffect } from "react";
import { useAppTheme } from "../../hooks";
import Gallery from "./_gallery";

const meta: Meta<typeof Gallery> = {
title: "tripie-ui/Gallery/Default",
component: Gallery,
tags: ["autodocs"],
decorators: [
(story, context) => {
const { mode, setMode } = useAppTheme();
const selectedTheme = context.globals.theme || mode;

useEffect(() => {
setMode(selectedTheme);
}, [selectedTheme]);

return <div className={`${context.globals.theme}`}>{story()}</div>;
},
],
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
name: "Default",
args: {
urls: [
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
],
},
};

export const ImageCount2: Story = {
name: "ImageCount2",
args: {
urls: [
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
],
},
};

export const ImageCount3: Story = {
name: "ImageCount3",
args: {
urls: [
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
],
},
};

export const ImageCount4: Story = {
name: "ImageCount4",
args: {
urls: [
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
],
},
};

export const MaxImage5: Story = {
name: "MaxImage5",
args: {
urls: [
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
],
},
};

export const OverMaxImageWithCount: Story = {
name: "OverMaxImageWithCount - displayLeftOverImgCount",
args: {
displayLeftOverImgCount: true,
urls: [
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
],
},
};

export const OverMaxImageWithoutCount: Story = {
name: "OverMaxImageWithout Count",
args: {
displayLeftOverImgCount: false,
urls: [
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
"https://media.triple.guide/triple-cms/c_limit,f_auto,h_1024,w_1024/f4208212-7c76-4d0b-9872-9651faa1a735.jpeg",
],
},
};
71 changes: 71 additions & 0 deletions packages/design-system/src/components/gallery/_gallery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import classNames from "classnames/bind";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

얘 파일명은 왜 _gallery 인가용 ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

index.ts 를 맨 아래에 배치하고 싶어서 파일명들 앞에 다 _를 붙여줬습니당😅

import Image from "next/image";
import Style from "./_gallery.module.scss";

const MAX_IMAGE_COUNT = 5;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gallery 이미지에서 MAX_IMAGE_COUNT 를 정해버리는건 조금 어색한 것 같아요 ..!
보통 외부에서 넣어주거나 넣어주는 이미지 갯수에따라 알아서 조절되는게 좋을 것 같은데 ..!


export type GalleryProps = {
urls: string[];
displayLeftOverImgCount?: boolean;
variant?: "default" | "post";
} & Omit<React.ComponentProps<"div">, "children">;

const cx = classNames.bind(Style);
const DEFAULT_IMG_SIZE_PX = 1024;

const Gallery = ({
urls,
className,
displayLeftOverImgCount = false,
variant = "default",
...props
}: GalleryProps) => {
const totalImgUrlCount = urls.length;
const displayedImages = urls.slice(0, MAX_IMAGE_COUNT);

return (
<div
className={cx(
"gallery",
variant,
`gallery-img-length-${displayedImages.length}`
)}
{...props}
>
{displayedImages.map((url, index) =>
displayLeftOverImgCount && index === 4 ? (
<div className={cx("image-container", variant)}>
<span className={cx("display-leftover-img-count", variant)}>
+{totalImgUrlCount - MAX_IMAGE_COUNT}
</span>
<Image
src={url}
alt={url}
width={DEFAULT_IMG_SIZE_PX}
height={DEFAULT_IMG_SIZE_PX}
className={cx("gallery-item", "overlay", variant)}
key={url + index}
/>
</div>
) : (
<Image
src={url}
alt={url}
width={DEFAULT_IMG_SIZE_PX}
height={DEFAULT_IMG_SIZE_PX}
className={cx("gallery-item", variant)}
key={url + index}
/>
)
)}
Comment on lines +41 to +60
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

갤러리로 보여줄 요소가 이미지가 아닌 영상일 가능성도 있어서
#54#56 에서 만들어서 확장자명에 따라 보여줄 컴포넌트로 대체할 거 같습니당

</div>
);
};

const PostGallery = (props: Omit<GalleryProps, "variant">) => (
<Gallery {...props} variant="post" />
);

Gallery.Post = PostGallery;

export default Gallery;
Loading
Loading