diff --git a/apps/admin/package.json b/apps/admin/package.json index 6f141f5c..468e85d2 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -17,6 +17,7 @@ "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@hookform/resolvers": "^4.1.0", + "@repo/pointer-design-system": "workspace:*", "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", "@tanstack/react-router": "^1.98.4", diff --git a/apps/admin/src/styles/globals.css b/apps/admin/src/styles/globals.css index d55abaf0..e8a1706b 100644 --- a/apps/admin/src/styles/globals.css +++ b/apps/admin/src/styles/globals.css @@ -1,132 +1,11 @@ -@import 'tailwindcss'; +@import '@repo/pointer-design-system/global-styles'; -/* ========================= */ -/* FONT STYLES */ -/* ========================= */ -@font-face { - font-family: 'Pretendard'; - font-style: normal; - font-display: swap; - font-weight: 100 900; - src: url('/fonts/PretendardVariable.woff2') format('woff2-variations'); -} - -/* ========================= */ -/* THEME STYLES */ -/* ========================= */ -@theme { - /* fonts */ - --font-pretendard: Pretendard, sans-serif; - - /* Black & White */ - --color-black: #000000; - --color-white: #ffffff; - - /* Gray Scale */ - --color-lightgray500: #c8cad4; - --color-lightgray400: #dfe2e7; - --color-lightgray300: #edeef2; - --color-lightgray200: #f3f5fb; - --color-lightgray100: #f8f9fc; - - --color-midgray200: #6b6f77; - --color-midgray100: #9fa4ae; - - --color-darkgray200: #222224; - --color-darkgray100: #3e3f45; - - --color-background: #f7f7f7; - - /* Colors */ - --color-green: #0fb700; - --color-lightgreen: #e7f6e5; - --color-red: #d20000; - --color-lightred: #fce4e4; - --color-blue: #3a67ee; - --color-lightblue: #ecf0fb; -} - -/* ========================= */ -/* BASE STYLES */ -/* ========================= */ @layer base { html { - font-size: 62.5%; - font-family: var(--font-pretendard); - overscroll-behavior: none; - background-color: var(--color-background); min-width: 144rem; } body { - width: 100%; - min-height: 100dvh; - font-family: var(--font-pretendard); - scroll-behavior: smooth; overflow-x: auto; } - - p { - word-break: keep-all; - white-space: pre-line; - } - - a { - text-decoration: none; - } - - button { - cursor: pointer; - } - - input:disabled { - cursor: not-allowed; - } - - select { - background: #fff; - } - - ::-webkit-scrollbar { - display: none; - } -} - -/* ========================= */ -/* TYPOGRAPHY STYLES */ -/* ========================= */ -@layer components { - /* Bold font styles */ - .font-bold-32 { - @apply font-pretendard text-[3.2rem] leading-[150%] font-bold; - } - .font-bold-24 { - @apply font-pretendard text-[2.4rem] leading-[150%] font-bold; - } - .font-bold-20 { - @apply font-pretendard text-[2.0rem] leading-[150%] font-bold; - } - .font-bold-18 { - @apply font-pretendard text-[1.8rem] leading-[150%] font-bold; - } - .font-bold-14 { - @apply font-pretendard text-[1.4rem] leading-[150%] font-bold; - } - - /* Medium font styles */ - .font-medium-24 { - @apply font-pretendard text-[2.4rem] leading-[150%] font-medium; - } - .font-medium-18 { - @apply font-pretendard text-[1.8rem] leading-[150%] font-medium; - } - .font-medium-16 { - @apply font-pretendard text-[1.6rem] leading-[150%] font-medium; - } - .font-medium-14 { - @apply font-pretendard text-[1.4rem] leading-[150%] font-medium; - } - .font-medium-12 { - @apply font-pretendard text-[1.2rem] leading-[150%] font-medium; - } } diff --git a/apps/service/eslint.config.mjs b/apps/service/eslint.config.mjs index 6a3704e4..98ae8b4d 100644 --- a/apps/service/eslint.config.mjs +++ b/apps/service/eslint.config.mjs @@ -11,7 +11,7 @@ const compat = new FlatCompat({ }); /** @type {import("eslint").FlatConfig[]} */ -export default [ +const config = [ ...baseConfig, ...compat.extends('next/core-web-vitals'), { @@ -21,3 +21,5 @@ export default [ }, }, ]; + +export default config; diff --git a/apps/service/package.json b/apps/service/package.json index 14ba5313..2f7d408b 100644 --- a/apps/service/package.json +++ b/apps/service/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@next/third-parties": "^15.2.4", + "@repo/pointer-design-system": "workspace:*", "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", "dayjs": "^1.11.13", diff --git a/apps/service/src/styles/globals.css b/apps/service/src/styles/globals.css index 6141f2ea..2295c84c 100644 --- a/apps/service/src/styles/globals.css +++ b/apps/service/src/styles/globals.css @@ -1,146 +1,19 @@ -@import 'tailwindcss'; +@import '@repo/pointer-design-system/global-styles'; -/* ========================= */ -/* FONT STYLES */ -/* ========================= */ -@font-face { - font-family: 'Pretendard'; - font-style: normal; - font-display: swap; - font-weight: 100 900; - src: url('/fonts/PretendardVariable.woff2') format('woff2-variations'); -} - -/* ========================= */ -/* THEME STYLES */ -/* ========================= */ @theme { /* breakpoints */ --breakpoint-sm: 431px; --breakpoint-md: 769px; --breakpoint-lg: 1367px; - - /* fonts */ - --font-pretendard: Pretendard, sans-serif; - - /* Black & White */ - --color-black: #000000; - --color-white: #ffffff; - - /* Gray Scale */ - --color-lightgray500: #c6cad4; - --color-lightgray400: #dfe2e7; - --color-lightgray300: #edeef2; - --color-lightgray200: #f3f5fb; - --color-lightgray100: #f8f9fc; - - --color-midgray200: #6b6f77; - --color-midgray100: #9fa4ae; - - --color-darkgray200: #222224; - --color-darkgray100: #3e3f45; - - --color-background: #f7f7f7; - - /* Colors */ - --color-main: #617af9; - --color-sub1: #c5ceff; - --color-sub2: #e9ebf8; - --color-green: #0fb700; - --color-lightgreen: #e7f6e5; - --color-red: #d20000; - --color-lightred: #fce4e4; - --color-blue: #3a67ee; - --color-lightblue: #ecf0fb; - --color-yellow: #e59c00; - --color-lightyellow: #fff4cc; } -/* ========================= */ -/* BASE STYLES */ -/* ========================= */ @layer base { html { - font-size: 62.5%; - font-family: var(--font-pretendard); - overscroll-behavior: none; - background-color: var(--color-background); min-width: 375px; } body { - width: 100%; - min-height: 100dvh; - font-family: var(--font-pretendard); - scroll-behavior: smooth; max-width: 768px; margin: 0 auto; } - - p { - word-break: keep-all; - white-space: pre-line; - } - - a { - text-decoration: none; - } - - button { - cursor: pointer; - } - - input:disabled { - cursor: not-allowed; - } - - select { - background: #fff; - } - - ::-webkit-scrollbar { - display: none; - } -} - -/* ========================= */ -/* TYPOGRAPHY STYLES */ -/* ========================= */ -@layer components { - /* Bold font styles */ - .font-bold-32 { - @apply font-pretendard text-[3.2rem] leading-[150%] font-bold; - } - .font-bold-24 { - @apply font-pretendard text-[2.4rem] leading-[150%] font-bold; - } - .font-bold-20 { - @apply font-pretendard text-[2.0rem] leading-[150%] font-bold; - } - .font-bold-18 { - @apply font-pretendard text-[1.8rem] leading-[150%] font-bold; - } - .font-bold-16 { - @apply font-pretendard text-[1.6rem] leading-[150%] font-bold; - } - .font-bold-14 { - @apply font-pretendard text-[1.4rem] leading-[150%] font-bold; - } - - /* Medium font styles */ - .font-medium-24 { - @apply font-pretendard text-[2.4rem] leading-[150%] font-medium; - } - .font-medium-18 { - @apply font-pretendard text-[1.8rem] leading-[150%] font-medium; - } - .font-medium-16 { - @apply font-pretendard text-[1.6rem] leading-[150%] font-medium; - } - .font-medium-14 { - @apply font-pretendard text-[1.4rem] leading-[150%] font-medium; - } - .font-medium-12 { - @apply font-pretendard text-[1.2rem] leading-[150%] font-medium; - } } diff --git a/packages/ui/eslint.config.mjs b/packages/pointer-design-system/eslint.config.mjs similarity index 100% rename from packages/ui/eslint.config.mjs rename to packages/pointer-design-system/eslint.config.mjs diff --git a/packages/ui/package.json b/packages/pointer-design-system/package.json similarity index 61% rename from packages/ui/package.json rename to packages/pointer-design-system/package.json index 747e66f1..4a797433 100644 --- a/packages/ui/package.json +++ b/packages/pointer-design-system/package.json @@ -1,11 +1,10 @@ { - "name": "@repo/ui", - "version": "0.0.0", - "private": true, + "name": "@repo/pointer-design-system", + "version": "1.0.0", + "main": "index.js", "exports": { - "./button": "./src/button.tsx", - "./card": "./src/card.tsx", - "./code": "./src/code.tsx" + "./components": "./src/components/index.ts", + "./global-styles": "./src/styles/globals.css" }, "scripts": { "lint": "eslint . --max-warnings 0", @@ -16,9 +15,9 @@ "@repo/eslint-config": "workspace:*", "@repo/typescript-config": "workspace:*", "@turbo/gen": "^1.12.4", - "@types/node": "^20.11.24", - "@types/react": "18.3.0", - "@types/react-dom": "18.3.1", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", "typescript": "5.5.4" }, "dependencies": { diff --git a/packages/pointer-design-system/src/components/Divider.tsx b/packages/pointer-design-system/src/components/Divider.tsx new file mode 100644 index 00000000..1ec71acb --- /dev/null +++ b/packages/pointer-design-system/src/components/Divider.tsx @@ -0,0 +1,5 @@ +const Divider = () => { + return
; +}; + +export default Divider; diff --git a/packages/pointer-design-system/src/components/PortalModal.tsx b/packages/pointer-design-system/src/components/PortalModal.tsx new file mode 100644 index 00000000..02a64590 --- /dev/null +++ b/packages/pointer-design-system/src/components/PortalModal.tsx @@ -0,0 +1,42 @@ +'use client'; +import { useEffect } from 'react'; +import { createPortal } from 'react-dom'; + +interface PortalModalProps { + isOpen: boolean; + onClose: () => void; + children: React.ReactNode; +} + +const portalElement = + typeof window !== 'undefined' && (document.getElementById('modal') as HTMLElement); + +const PortalModal = ({ isOpen, onClose, children = null }: PortalModalProps) => { + useEffect(() => { + if (isOpen) { + document.body.style.overflow = 'hidden'; + } else { + document.body.style.overflow = ''; + } + + return () => { + document.body.style.overflow = ''; + }; + }, [isOpen]); + + if (!isOpen || !portalElement) return null; + + return createPortal( +
+
+
e.stopPropagation()}> + {children} +
+
, + portalElement + ); +}; + +export default PortalModal; diff --git a/packages/pointer-design-system/src/components/button.tsx b/packages/pointer-design-system/src/components/button.tsx new file mode 100644 index 00000000..8399c8c0 --- /dev/null +++ b/packages/pointer-design-system/src/components/button.tsx @@ -0,0 +1,35 @@ +import { ButtonHTMLAttributes } from 'react'; + +interface ButtonProps extends ButtonHTMLAttributes { + variant?: 'blue' | 'light'; + disabled?: boolean; + children: React.ReactNode; +} + +const Button = ({ + variant = 'blue', + disabled = false, + children, + className, + ...props +}: ButtonProps) => { + const baseStyles = + 'w-full h-[5.6rem] min-w-fit rounded-[16px] font-medium-16 flex items-center justify-center gap-[1.6rem] px-[1rem]'; + + const variantStyles = { + blue: 'bg-main text-white', + light: 'bg-white text-main border border-main', + disabled: 'bg-lightgray300 text-lightgray500', + }; + + return ( + + ); +}; + +export default Button; diff --git a/packages/pointer-design-system/src/components/index.ts b/packages/pointer-design-system/src/components/index.ts new file mode 100644 index 00000000..4b15f5f4 --- /dev/null +++ b/packages/pointer-design-system/src/components/index.ts @@ -0,0 +1,5 @@ +import Button from './Button'; +import PortalModal from './PortalModal'; +import Divider from './Divider'; + +export { Button, PortalModal, Divider }; diff --git a/packages/pointer-design-system/src/styles/globals.css b/packages/pointer-design-system/src/styles/globals.css new file mode 100644 index 00000000..ddb04c4f --- /dev/null +++ b/packages/pointer-design-system/src/styles/globals.css @@ -0,0 +1,138 @@ +@import 'tailwindcss'; + +/* ========================= */ +/* FONT STYLES */ +/* ========================= */ +@font-face { + font-family: 'Pretendard'; + font-style: normal; + font-display: swap; + font-weight: 100 900; + src: url('/fonts/PretendardVariable.woff2') format('woff2-variations'); +} + +/* ========================= */ +/* THEME STYLES */ +/* ========================= */ +@theme { + /* fonts */ + --font-pretendard: Pretendard, sans-serif; + + /* Black & White */ + --color-black: #000000; + --color-white: #ffffff; + + /* Gray Scale */ + --color-lightgray500: #c6cad4; + --color-lightgray400: #dfe2e7; + --color-lightgray300: #edeef2; + --color-lightgray200: #f3f5fb; + --color-lightgray100: #f8f9fc; + + --color-midgray200: #6b6f77; + --color-midgray100: #9fa4ae; + + --color-darkgray200: #222224; + --color-darkgray100: #3e3f45; + + --color-background: #f7f7f7; + + /* Colors */ + --color-main: #617af9; + --color-sub1: #c5ceff; + --color-sub2: #e9ebf8; + --color-green: #0fb700; + --color-lightgreen: #e7f6e5; + --color-red: #d20000; + --color-lightred: #fce4e4; + --color-blue: #3a67ee; + --color-lightblue: #ecf0fb; + --color-yellow: #e59c00; + --color-lightyellow: #fff4cc; +} + +/* ========================= */ +/* BASE STYLES */ +/* ========================= */ +@layer base { + html { + font-size: 62.5%; + font-family: var(--font-pretendard); + overscroll-behavior: none; + background-color: var(--color-background); + } + + body { + width: 100%; + min-height: 100dvh; + font-family: var(--font-pretendard); + scroll-behavior: smooth; + } + + p { + word-break: keep-all; + white-space: pre-line; + } + + a { + text-decoration: none; + } + + button { + cursor: pointer; + } + + input:disabled { + cursor: not-allowed; + } + + select { + background: #fff; + } + + ::-webkit-scrollbar { + display: none; + } +} + +/* ========================= */ +/* TYPOGRAPHY STYLES */ +/* ========================= */ +@layer components { + /* Bold font styles */ + .font-bold-32 { + @apply font-pretendard text-[3.2rem] leading-[150%] font-bold; + } + .font-bold-24 { + @apply font-pretendard text-[2.4rem] leading-[150%] font-bold; + } + .font-bold-20 { + @apply font-pretendard text-[2.0rem] leading-[150%] font-bold; + } + .font-bold-18 { + @apply font-pretendard text-[1.8rem] leading-[150%] font-bold; + } + .font-bold-16 { + @apply font-pretendard text-[1.6rem] leading-[150%] font-bold; + } + .font-bold-14 { + @apply font-pretendard text-[1.4rem] leading-[150%] font-bold; + } + + /* Medium font styles */ + .font-medium-24 { + @apply font-pretendard text-[2.4rem] leading-[150%] font-medium; + } + .font-medium-18 { + @apply font-pretendard text-[1.8rem] leading-[150%] font-medium; + } + .font-medium-16 { + @apply font-pretendard text-[1.6rem] leading-[150%] font-medium; + } + .font-medium-14 { + @apply font-pretendard text-[1.4rem] leading-[150%] font-medium; + } + .font-medium-12 { + @apply font-pretendard text-[1.2rem] leading-[150%] font-medium; + } +} diff --git a/packages/ui/tsconfig.json b/packages/pointer-design-system/tsconfig.json similarity index 100% rename from packages/ui/tsconfig.json rename to packages/pointer-design-system/tsconfig.json diff --git a/packages/ui/src/button.tsx b/packages/ui/src/button.tsx deleted file mode 100644 index 7b117d23..00000000 --- a/packages/ui/src/button.tsx +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; - -import { ReactNode } from 'react'; - -interface ButtonProps { - children: ReactNode; - className?: string; - appName: string; -} - -export const Button = ({ children, className, appName }: ButtonProps) => { - return ( - - ); -}; diff --git a/packages/ui/src/card.tsx b/packages/ui/src/card.tsx deleted file mode 100644 index 124e8e2c..00000000 --- a/packages/ui/src/card.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { type JSX } from 'react'; - -export function Card({ - className, - title, - children, - href, -}: { - className?: string; - title: string; - children: React.ReactNode; - href: string; -}): JSX.Element { - return ( - -

- {title} -> -

-

{children}

-
- ); -} diff --git a/packages/ui/src/code.tsx b/packages/ui/src/code.tsx deleted file mode 100644 index ba44df8b..00000000 --- a/packages/ui/src/code.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { type JSX } from 'react'; - -export function Code({ - children, - className, -}: { - children: React.ReactNode; - className?: string; -}): JSX.Element { - return {children}; -} diff --git a/packages/ui/turbo/generators/config.ts b/packages/ui/turbo/generators/config.ts deleted file mode 100644 index 58c565f0..00000000 --- a/packages/ui/turbo/generators/config.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { PlopTypes } from '@turbo/gen'; - -// Learn more about Turborepo Generators at https://turbo.build/repo/docs/core-concepts/monorepos/code-generation - -export default function generator(plop: PlopTypes.NodePlopAPI): void { - // A simple generator to add a new React component to the internal UI library - plop.setGenerator('react-component', { - description: 'Adds a new react component', - prompts: [ - { - type: 'input', - name: 'name', - message: 'What is the name of the component?', - }, - ], - actions: [ - { - type: 'add', - path: 'src/{{kebabCase name}}.tsx', - templateFile: 'templates/component.hbs', - }, - { - type: 'append', - path: 'package.json', - pattern: /"exports": {(?)/g, - template: ' "./{{kebabCase name}}": "./src/{{kebabCase name}}.tsx",', - }, - ], - }); -} diff --git a/packages/ui/turbo/generators/templates/component.hbs b/packages/ui/turbo/generators/templates/component.hbs deleted file mode 100644 index 5a3ace46..00000000 --- a/packages/ui/turbo/generators/templates/component.hbs +++ /dev/null @@ -1,8 +0,0 @@ -export const -{{pascalCase name}} -= ({ children }: { children: React.ReactNode }) => { return ( -
-

{{pascalCase name}} Component

- {children} -
-); }; \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f3bc2e4..5c60ca42 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,6 +62,9 @@ importers: '@hookform/resolvers': specifier: ^4.1.0 version: 4.1.0(react-hook-form@7.54.2(react@19.0.0)) + '@repo/pointer-design-system': + specifier: workspace:* + version: link:../../packages/pointer-design-system '@tanstack/react-query': specifier: ^5.66.0 version: 5.66.0(react@19.0.0) @@ -168,6 +171,9 @@ importers: '@next/third-parties': specifier: ^15.2.4 version: 15.2.4(next@15.1.4(@babel/core@7.26.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0) + '@repo/pointer-design-system': + specifier: workspace:* + version: link:../../packages/pointer-design-system '@tanstack/react-query': specifier: ^5.66.0 version: 5.66.0(react@19.0.0) @@ -263,9 +269,7 @@ importers: specifier: ^8.15.0 version: 8.22.0(eslint@9.19.0(jiti@2.4.2))(typescript@5.6.3) - packages/typescript-config: {} - - packages/ui: + packages/pointer-design-system: dependencies: react: specifier: ^19.0.0 @@ -284,18 +288,20 @@ importers: specifier: ^1.12.4 version: 1.13.4(@swc/core@1.10.12(@swc/helpers@0.5.15))(@types/node@20.17.16)(typescript@5.5.4) '@types/node': - specifier: ^20.11.24 + specifier: ^20 version: 20.17.16 '@types/react': - specifier: 18.3.0 - version: 18.3.0 + specifier: ^19 + version: 19.0.8 '@types/react-dom': - specifier: 18.3.1 - version: 18.3.1 + specifier: ^19 + version: 19.0.3(@types/react@19.0.8) typescript: specifier: 5.5.4 version: 5.5.4 + packages/typescript-config: {} + packages: '@alloc/quick-lru@5.2.0': @@ -1959,20 +1965,11 @@ packages: '@types/node@20.17.16': resolution: {integrity: sha512-vOTpLduLkZXePLxHiHsBLp98mHGnl8RptV4YAO3HfKO5UHjDvySGbxKtpYfy8Sx5+WKcgc45qNreJJRVM3L6mw==} - '@types/prop-types@15.7.14': - resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} - - '@types/react-dom@18.3.1': - resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} - '@types/react-dom@19.0.3': resolution: {integrity: sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==} peerDependencies: '@types/react': ^19.0.0 - '@types/react@18.3.0': - resolution: {integrity: sha512-DiUcKjzE6soLyln8NNZmyhcQjVv+WsUIFSqetMN0p8927OztKT4VTfFTqsbAi5oAGIcgOmOajlfBqyptDDjZRw==} - '@types/react@19.0.8': resolution: {integrity: sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==} @@ -6319,21 +6316,10 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/prop-types@15.7.14': {} - - '@types/react-dom@18.3.1': - dependencies: - '@types/react': 19.0.8 - '@types/react-dom@19.0.3(@types/react@19.0.8)': dependencies: '@types/react': 19.0.8 - '@types/react@18.3.0': - dependencies: - '@types/prop-types': 15.7.14 - csstype: 3.1.3 - '@types/react@19.0.8': dependencies: csstype: 3.1.3