Skip to content

Commit

Permalink
[Feat] 모집직군 컴포넌트 (#264)
Browse files Browse the repository at this point in the history
* chore: position icon image

* chore: storybook static

* feat: 이미지 경로 상수화

* feat: create Positions
  • Loading branch information
kimyouknow authored Sep 17, 2023
1 parent ee9c83a commit 0caa195
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 0 deletions.
1 change: 1 addition & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ const config: StorybookConfig = {
options.presets!.push('@emotion/babel-preset-css-prop');
return options;
},
staticDirs: ['../public'],
};
export default config;
Binary file added public/images/position/aos.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/position/design.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/position/ios.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/position/server.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/position/web.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions src/components/Positions/Positions.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ComponentProps } from 'react';
import type { Meta, StoryObj } from '@storybook/react';

import { Positions } from './index';

const meta: Meta<typeof Positions> = {
title: 'components/Positions',
component: Positions,
args: {},
};

export default meta;

type Story = StoryObj<typeof Positions>;

const MOCK: Array<ComponentProps<typeof Positions.Item>> = [
{ type: 'design', title: 'UX/UI DESIGN', link: '' },
{ type: 'ios', title: 'IOS', link: '' },
{ type: 'aos', title: 'ANDROID', link: '' },
{ type: 'web', title: 'WEB', link: '' },
{ type: 'server', title: 'SERVER', link: '' },
];

export const Primary: Story = {
render: () => (
<Positions>
<Positions.Body>
{MOCK.map(({ ...info }) => (
<Positions.Item key={info.type} {...info} />
))}
</Positions.Body>
</Positions>
),
};
18 changes: 18 additions & 0 deletions src/components/Positions/PositionsBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { PropsWithChildren } from 'react';
import { css } from '@emotion/react';

interface PositionsBodyProps {}

export function PositionsBody({ children }: PropsWithChildren<PositionsBodyProps>) {
return <div css={layoutCss}>{children}</div>;
}

const layoutCss = css`
display: flex;
flex-wrap: wrap;
gap: 20px;
align-items: flex-start;
justify-content: center;
position: relative;
width: 960px; // TODO 전체 너비 상수화
`;
64 changes: 64 additions & 0 deletions src/components/Positions/PositionsItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import Image from 'next/image';
import Link from 'next/link';
import { css, Theme } from '@emotion/react';

import { ArrowIcon } from '~/components/Icons';
import { POSITION_BASE } from '~/constant/image';

type Position = 'aos' | 'design' | 'ios' | 'server' | 'web';

interface PositionsItemProps {
type: Position;
title: string;
link: string;
}

export function PositionsItem({ type, title, link }: PositionsItemProps) {
return (
<div css={layoutCss}>
<Image width={112} height={112} src={`${POSITION_BASE}/${type}.png`} alt={title} />
<h3 css={titleCss}>{title}</h3>
<Link href={link} target="_blank" css={linkCss}>
<span>자세히보기</span>
<ArrowIcon direction="right" css={arrowIconCss} />
</Link>
</div>
);
}

const layoutCss = (theme: Theme) => css`
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 36px 32px;
background-color: ${theme.colors.black400};
width: 306px;
height: 272px;
`;

const titleCss = (theme: Theme) => css`
${theme.typos.decimal.body1};
color: ${theme.colors.white};
margin-top: 28px;
`;

const linkCss = (theme: Theme) => css`
${theme.typos.pretendard.body1};
color: ${theme.colors.blue400};
display: flex;
align-items: center;
margin-top: 8px;
> svg {
margin-left: 4px;
}
`;

const arrowIconCss = (theme: Theme) => css`
width: 24px;
height: 24px;
> path {
stroke: ${theme.colors.blue400};
stroke-width: 4;
}
`;
7 changes: 7 additions & 0 deletions src/components/Positions/PositionsWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { PropsWithChildren } from 'react';

interface PositionsWrapperProps {}

export function PositionsWrapper({ children }: PropsWithChildren<PositionsWrapperProps>) {
return <div>{children}</div>;
}
8 changes: 8 additions & 0 deletions src/components/Positions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { PositionsBody } from '~/components/Positions/PositionsBody';
import { PositionsItem } from '~/components/Positions/PositionsItem';
import { PositionsWrapper } from '~/components/Positions/PositionsWrapper';

export const Positions = Object.assign(PositionsWrapper, {
Body: PositionsBody,
Item: PositionsItem,
});
1 change: 1 addition & 0 deletions src/constant/image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const POSITION_BASE = '/images/position';

0 comments on commit 0caa195

Please sign in to comment.