npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@uniai-fe/uds-primitives

v0.0.17

Published

UNIAI Design System; Primitives Components Package

Downloads

1,815

Readme

@uniai-fe/uds-primitives

@uniai-fe/uds-foundation 토큰 위에 Radix UI 컴포넌트를 얇게 감싼 기초 UI 컴포넌트 컬렉션입니다. Next.js 등 React 런타임에서 바로 import해 버튼·입력·네비게이션 등 공통 요소를 일관된 스타일로 사용할 수 있습니다. Templates(@uniai-fe/uds-templates) 패키지에서 사용하는 Phone Input/Email Verification Input/OneTimeCode Input 등의 인증 시나리오 컴포넌트도 이곳에서 제공합니다.

설치

pnpm add @uniai-fe/uds-foundation @uniai-fe/util-functions @uniai-fe/uds-primitives

Peer Dependencies

@uniai-fe/uds-primitives는 디자인 토큰과 유틸리티 로직을 공유하기 위해 다음 패키지를 같이 설치해야 합니다.

  • @uniai-fe/uds-foundation@^0.0.1
  • @uniai-fe/util-functions@^0.2.3
  • react@>=19, react-dom@>=19
  • react-hook-form@>=7

peer dependency가 빠져 있을 경우 앱 번들 시점에 에러가 발생하니, 위 목록을 프로젝트 package.json에 명시해 주세요.

// next.config.ts
const nextConfig = {
  transpilePackages: ["@uniai-fe/uds-foundation", "@uniai-fe/uds-primitives"],
};
export default nextConfig;

앱 루트에서 foundation CSS를 1회 import 하면 모든 primitives가 토큰을 공유합니다.

import "@uniai-fe/uds-foundation/css";

사용 예시

import { Button } from "@uniai-fe/uds-primitives";

export default function Page() {
  return (
    <Button.Default scale="solid-medium" priority="primary">
      확인
    </Button.Default>
  );
}

Link/Anchor로 사용하기

import Link from "next/link";
import { Button } from "@uniai-fe/uds-primitives";

function LinkButton() {
  return (
    <Button.Default
      as={Link}
      href="/dashboard"
      scale="outlined-medium"
      priority="secondary"
    >
      대시보드로 이동
    </Button.Default>
  );
}

Button 역할 클래스 & Props 미리보기

  • 기본 클래스: .button (padding/height/radius/타이포/커서 담당)
  • 슬롯: button-label, button-icon, button-left, button-right, button-loading
  • Modifier: button-scale-*, button-fill-*, button-priority-*, button-state-*, button-size-*, button-block, button-icon-left/right
  • 차기 리팩토링에서는 디자인 관련 props를 scale(레이아웃/spacing 집합)과 priority(color set) 두 축으로 단순화하고, 나머지는 상태/slot 위주의 역할 props만 남긴다. 자세한 계획은 docs/CONTEXT-BUTTON.md에서 확인할 수 있다.
  • loading 상태는 readonly와 동일하게 잠기며 hover/pressed 반응을 막는다. anchor 등 커스텀 요소도 aria-disabled="true"를 통해 동일한 스타일을 적용받는다.

TextButton / RoundButton 템플릿

Button 객체는 템플릿별 컴포넌트를 포함한다.

import { Button } from "@uniai-fe/uds-primitives";

function Templates() {
  return (
    <>
      <Button.Text priority="secondary" size="medium">
        링크 스타일
      </Button.Text>

      <Button.Rounded aria-label="추가" size="small">
        <span aria-hidden="true">+</span>
      </Button.Rounded>
    </>
  );
}
  • TextButton(Button.Text)은 size="small|medium|large" + priority="secondary|tertiary"만 허용한다.
  • RoundButton(Button.Rounded)은 size만 지정하면 되고 priority는 기본 Button과 동일하게 primary|secondary|tertiary를 사용한다.
  • 템플릿별 클래스를 추가로 노출한다: .button-template-text, .button-template-text-size-*, .button-template-round, .button-template-round-size-*.
  • 스토리북 primitives/Button Story에서 solid/outlined/텍스트/라운드 4가지 카테고리를 한 번에 확인할 수 있다.

스타일 내보내기

@uniai-fe/uds-primitives/styles 엔트리를 import하면 foundation CSS, theme override, 컴포넌트 SCSS가 한 번에 로드된다.

@use "@uniai-fe/uds-primitives/styles";

Next.js/webpack 환경에서 Sass를 사용하지 않는 경우에는 ESM import로 @uniai-fe/uds-primitives/css를 불러오면 된다. 이 CSS에는 foundation 토큰과 primitives 스타일이 이미 번들링되어 있다.

import "@uniai-fe/uds-primitives/css";

컴포넌트 단위로 필요한 스타일만 선택해 불러오려면 각 경로(components/{name}/index.scss)를 직접 import하면 된다.

@use "@uniai-fe/uds-primitives/button/index.scss";
@use "@uniai-fe/uds-primitives/navigation/index.scss";

ThemeProvider는 CSS를 import하지 않으므로 위 styles 엔트리를 앱 루트에서 1회만 로드하면 중복 없이 토큰 매핑이 적용된다.

Next.js 통합 예시

Next.js 15(app router 기준)에서 primitives를 사용하는 최소 구성 예시는 다음과 같다.

// next.config.ts
const nextConfig = {
  transpilePackages: ["@uniai-fe/uds-foundation", "@uniai-fe/uds-primitives"],
  sassOptions: {
    // monorepo가 아니어도 node_modules 경로를 자동 탐색하지만,
    // 필요 시 디자인 토큰 경로를 명시해 두면 빌드 환경 차이를 줄일 수 있다.
    includePaths: ["./node_modules"],
  },
};
export default nextConfig;
/* app/globals.scss */
@use "@uniai-fe/uds-primitives/styles";
// app/layout.tsx
import type { ReactNode } from "react";
import "@uniai-fe/uds-primitives/styles";
import { ThemeProvider } from "@uniai-fe/uds-primitives";

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="ko">
      <body>
        <ThemeProvider>{children}</ThemeProvider>
      </body>
    </html>
  );
}

위 예시는 ThemeProvider가 CSS를 다시 import하지 않는 현재 구조를 기준으로 하므로, globals.scss 또는 루트에서 styles/css 엔트리를 반드시 한 번 로드해야 한다. Sass 기반 프로젝트는 @use "@uniai-fe/uds-primitives/styles";, CSS-only 프로젝트는 import "@uniai-fe/uds-primitives/css";를 사용한다.

모든 컴포넌트는 .component 클래스 + CSS 변수 기반으로 override가 가능하며, 버튼처럼 Slot(left/right/icon 등)을 제공하는 항목은 CONTEXT-*.md 문서에 상세 API를 기록했습니다. 불필요한 data-* attribute는 제거했고, 상태 표시는 :disabled, [aria-busy="true"] 같은 표준 attribute만 사용합니다.

구조

src/components/{category}/
  markup/   // 컴포넌트 구현
  types/    // 외부 노출 타입
  styles/   // SCSS (foundation 토큰 기반)
  hooks/    // 카테고리 전용 훅
  • 배럴(components/{category}/index.tsx)은 항상 import "./index.scss"를 포함합니다.
  • 스타일은 foundation CSS 변수만 사용하며, .button.button-priority-* / .button.button-fill-* 클래스 조합으로 상태를 분기합니다.

스크립트

  • pnpm module:lint
  • pnpm module:typecheck
  • pnpm module:build

루트에서는 pnpm --filter @uniai-fe/uds-primitives <command>로 실행할 수 있습니다.

문서

  • CONTEXT.mdCONTEXT-*.md: 각 컴포넌트의 상태/진행/디자인 근거
  • CONTEXT-INPUT.md: Phone/Email/OneTimeCode 등 인증 입력 시나리오 규칙을 포함하며, templates CONTEXT-SIGNUP*.md와 항상 동기화해야 한다.
  • RADIX-SIZE-GUIDE.md: primitives 사이즈 체계와 Radix 매핑 규칙

Signup 인증 입력 컴포넌트

  • PhoneInput: 기본은 마스킹된 전화번호 입력만 제공한다. onRequestCode(optional)를 주입하면 인증요청 버튼이 우측 right 슬롯에 노출된다. Step1 User Info에서는 단순 입력만 필요하므로 optional props를 생략한다.
  • EmailInput: 이메일 입력 + 인증요청 버튼 + countdown + OneTimeCode 입력을 하나로 묶는다. countdownText, codeVisible, codeLength, codeLabel, codeHelper, codeState, onCodeComplete로 Step2 Verify & Agreement 상태를 제어한다.
  • AuthCodeInput: length 지정형 OneTimeCode grid. EmailInput 내부에서 사용하지만 서비스 앱도 직접 import할 수 있다.
  • 변경 시에는 다음 문서를 함께 업데이트한다: packages/design/primitives/docs/CONTEXT-INPUT.md, packages/design/templates/docs/CONTEXT-SIGNUP.md, CONTEXT-SIGNUP-FLOW.md, packages/design/templates/docs/STORYBOOK.md, apps/design-storybook/src/stories/templates/auth/AuthSignup.stories.tsx.
  • 컨벤션: 모든 컴포넌트/스토리/문서는 slot/prefix/suffix 용어를 사용하지 않고, 레이아웃 기준(header/body/footer, 2단 구조는 upper/lower)과 util* 키워드를 사용한다. 인터랙션 함수는 on* 접두사를 사용하고, JSDoc @param은 depth 전체를 풀어 쓴다.

필요한 컨텍스트를 확인한 뒤 컴포넌트를 import해 사용하면 됩니다.