Skip to content
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
61 changes: 61 additions & 0 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: 'Chromatic Deployment'

run-name: Storybook deployment by ${{ github.actor }}

on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- '**/*.stories.tsx'
- '**/*.stories.ts'
- '**/*.stories.jsx'
- '**/*.stories.js'
- 'src/components/**'

jobs:
chromatic:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip-build') }}
name: Run Chromatic Deployment
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
outputs:
status: ${{ job.status }}

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false

- name: Set up Node.js version
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'

- name: Install dependencies
run: pnpm install

- name: Run Chromatic
id: chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
buildScriptName: build-storybook
onlyChanged: true

- name: Comment PR
uses: thollander/actions-comment-pull-request@v1
if: ${{ github.event_name == 'pull_request' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
message: '스토리북 URL 확인하기 - ${{ steps.chromatic.outputs.storybookUrl }}'
34 changes: 26 additions & 8 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,35 @@ import type { StorybookConfig } from '@storybook/nextjs';

const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@chromatic-com/storybook',
'@storybook/addon-docs',
'@storybook/addon-onboarding',
'@storybook/addon-a11y',
'@storybook/addon-vitest',
],
addons: ['@storybook/addon-onboarding', '@chromatic-com/storybook', '@storybook/addon-a11y'],
framework: {
name: '@storybook/nextjs',
options: {},
},
staticDirs: ['../public'],
webpackFinal: async (config) => {
if (!config.module || !config.module.rules) {
return config;
}

config.module.rules = [
...config.module.rules.map((rule) => {
if (!rule || rule === '...') {
return rule;
}

if (rule.test && /svg/.test(String(rule.test))) {
return { ...rule, exclude: /\.svg$/i };
}

return rule;
}),
{
test: /\.svg$/,
use: ['@svgr/webpack'],
},
];

return config;
},
};
export default config;
8 changes: 1 addition & 7 deletions .storybook/preview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Preview } from '@storybook/nextjs';
import '../src/styles/globals.css';

const preview: Preview = {
parameters: {
Expand All @@ -8,13 +9,6 @@ const preview: Preview = {
date: /Date$/i,
},
},

a11y: {
// 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely
test: 'todo',
},
},
};

Expand Down
7 changes: 0 additions & 7 deletions .storybook/vitest.setup.ts

This file was deleted.

3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"files.eol": "\n",
"files.insertFinalNewline": true,
"typescript.preferences.importModuleSpecifier": "non-relative",
"javascript.updateImportsOnFileMove.enabled": "always"
"javascript.updateImportsOnFileMove.enabled": "always",
"css.lint.unknownAtRules": "ignore"
}
21 changes: 5 additions & 16 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,14 @@ const nextConfig: NextConfig = {
typeof rule.test === 'object' && rule.test instanceof RegExp && rule.test?.test?.('.svg')
);

if (!fileLoaderRule) {
throw new Error('File loader rule not found');
}

config.module.rules.push(
{
...fileLoaderRule,
test: /\.svg$/i,
resourceQuery: /url/,
},
{
if (fileLoaderRule) {
config.module.rules.push({
test: /\.svg$/i,
issuer: fileLoaderRule.issuer,
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] },
use: ['@svgr/webpack'],
}
);
});

fileLoaderRule.exclude = /\.svg$/i;
fileLoaderRule.exclude = /\.svg$/i;
}

return config;
},
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"prettier": "prettier --write .",
"prepare": "husky",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
"build-storybook": "storybook build",
"chromatic": "npx chromatic"
},
"lint-staged": {
"*.{js,ts,tsx,jsx}": [
Expand Down Expand Up @@ -43,6 +44,7 @@
"@types/webpack": "^5.28.5",
"@vitest/browser": "^3.2.4",
"@vitest/coverage-v8": "^3.2.4",
"chromatic": "^13.3.3",
"eslint": "^9",
"eslint-config-next": "15.5.4",
"eslint-config-prettier": "^10.1.8",
Expand Down
17 changes: 17 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 3 additions & 8 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { Metadata } from 'next';
import localFont from 'next/font/local';
import './globals.css';
import '@/styles/globals.css';

const pretendard = localFont({
src: [{ path: '../assets/fonts/PretendardVariable.woff2', style: 'normal', weight: '100 900' }],
variable: '--font-family-sans',
display: 'swap',
fallback: ['system-ui', 'Arial', 'sans-serif'],
});
Expand All @@ -14,13 +13,9 @@ export const metadata: Metadata = {
description: '함께 모으는 우리만의 기록, 공유 가계부 MOA',
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko" className={pretendard.variable}>
<html lang="ko" className={pretendard.className}>
<body className="antialiased">
<div className="drop-shadow-brand bg-bg flex h-dvh justify-center md:drop-shadow-none">
<div className="w-full max-w-[var(--layout-width)]">{children}</div>
Expand Down
36 changes: 36 additions & 0 deletions src/components/Button/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const BUTTON_BASE_STYLES =
'inline-flex items-center justify-center font-semibold transition-colors disabled:opacity-50 disabled:cursor-not-allowed';

export const BUTTON_BORDER_RADIUS = {
xs: 'rounded-[var(--rounded-sm)]',
sm: 'rounded-[var(--rounded-sm)]',
md: 'rounded-[var(--rounded-md)]',
lg: 'rounded-[var(--rounded-md)]',
xl: 'rounded-[var(--rounded-md)]',
} as const;

export const BUTTON_VARIANTS = {
primary:
'bg-[var(--color-green-normal)] text-white hover:bg-[var(--color-green-normal-hover)] active:bg-[var(--color-green-normal-active)]',
back: 'bg-[var(--color-green-dark)] text-white hover:bg-[var(--color-green-dark-hover)] active:bg-[var(--color-green-dark-active)]',
cancel:
'bg-[var(--color-grey-light)] text-white hover:bg-[var(--color-grey-light-hover)] active:bg-[var(--color-grey-light-active)]',
outline:
'bg-[var(--color-green-light)] !text-[var(--color-green-normal)] border border-[var(--color-green-normal)] hover:bg-[var(--color-green-light-hover)] active:bg-[var(--color-green-light-active)]',
text: 'text-[var(--color-green-darker)] hover:text-[var(--color-green-darker-hover)] active:text-[var(--color-green-darker-active)] font-medium',
underline:
'text-[var(--color-grey-normal)] hover:text-[var(--color-grey-normal-hover)] active:text-[var(--color-grey-normal-active)] font-medium underline decoration-[var(--color-grey-normal)] underline-offset-[4px]',
} as const;

export const BUTTON_TEXT_SIZES = {
text: 'text-xs-custom',
underline: 'text-sm-custom',
} as const;

export const BUTTON_SIZES = {
xs: 'h-8 w-[100px] max-w-full text-base-custom',
sm: 'h-8 w-[200px] max-w-full text-base-custom',
md: 'h-10 w-[72px] max-w-full text-lg-custom',
lg: 'h-10 w-[228px] max-w-full text-lg-custom',
xl: 'h-10 w-[300px] max-w-full text-lg-custom',
} as const;
105 changes: 105 additions & 0 deletions src/components/Button/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import type { Meta, StoryObj } from '@storybook/nextjs';
import { Button } from './index';

const meta = {
title: 'Components/Button',
component: Button,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta<typeof Button>;

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

export const Primary: Story = {
args: {
children: '입력 완료',
variant: 'primary',
},
};

export const Back: Story = {
args: {
children: '이전',
variant: 'back',
},
};

export const Cancel: Story = {
args: {
children: '취소',
variant: 'cancel',
},
};

export const Outline: Story = {
args: {
children: '새 가계부 만들기',
variant: 'outline',
},
};

export const Text: Story = {
args: {
children: '건너뛰기',
variant: 'text',
},
};

export const Underline: Story = {
args: {
children: '건너뛰기',
variant: 'underline',
},
};

export const SizeXS: Story = {
args: {
children: 'XS',
size: 'xs',
},
};

export const SizeSM: Story = {
args: {
children: '다음',
size: 'sm',
},
};

export const SizeMD: Story = {
args: {
children: '확인',
size: 'md',
},
};

export const SizeLG: Story = {
args: {
children: '확인',
size: 'lg',
},
};

export const SizeXL: Story = {
args: {
children: '입력 완료',
size: 'xl',
},
};

export const Loading: Story = {
args: {
children: '입력 완료',
isLoading: true,
},
};

export const Disabled: Story = {
args: {
children: '입력 완료',
disabled: true,
},
};
Loading