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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bnvsrnd/brand-assets

v1.4.0

Published

BNV Solutions design tokens & components

Readme

brand-assets

비앤브이솔루션(BNV Solutions) 공식 디자인 시스템 단일 진본. Figma에서 디자인하고, 코드에서 바로 쓸 수 있도록 토큰화해서 자동 빌드합니다.

운영 브랜치는 main. Tokens Studio가 tokens.json을 push하면 GitHub Actions가 자동으로 CSS/TS를 빌드해서 다시 commit합니다.


현재 상태

✅ Foundation Tokens 완성

| 카테고리 | 내용 | |---|---| | Color (Primitive) | Brand 10단계 + Gray, Success, Warning, Danger, Info(Sky) (각 10단계) + White/Black | | Color (Semantic) | Background, Text, Border, Action, Status (Success/Warning/Danger/Info/Neutral) — Light/Dark 자동 매핑 | | Typography | 15개 Text Styles (Display, Heading 1-4, Body, Label + Default/Small Semibold, Caption, Overline) | | Spacing | 14단계 (space-0 0px ~ space-13 96px), 4px 베이스 | | Radius | 7단계 (radius-none ~ radius-full) | | Elevation | 4단계 shadow (Sm/Md/Lg/Xl) | | Icon Size | 5단계 (Xs 12 / Sm 16 / Md 20 / Lg 24 / Xl 32) |

🎉 코어 컴포넌트 20/20 완성 (Figma + React + Demo)

| 그룹 | 컴포넌트 | |---|---| | Form (7) | Button · Input · Checkbox · Radio · Toggle · Textarea · Select | | Display (5) | Badge · Avatar · Card · Search · Divider | | Overlay (4) | Modal · Drawer · Toast · Tooltip | | Navigation (2) | Tabs · Menu | | Feedback (2) | Spinner · Alert |

🔧 접근성

  • Portal (Modal · Drawer · ToastContainer · Tooltip) — 부모 transform/overflow 영향 없음
  • Focus Trap + Body Scroll Lock (Modal · Drawer)
  • Keyboard Navigation (Tabs ←→, Menu ↓↑, Select)
  • Animation API (Modal · Drawer · Toast) — animation prop + CSS 변수 + Exit animation
  • prefers-reduced-motion 대응
  • ARIA roles: dialog, tab, tabpanel, menu, menuitem, listbox, option, switch, alert, tooltip, status, separator

🧪 Unit Tests

  • Vitest + Testing Library
  • 68 tests across 20 components
  • npm test / npm run test:watch / npm run test:coverage

사용 방법

1단계: 설치

npm install @bnvsrnd/brand-assets

peer dependency: React 18+ (React 19 권장). 이 단계는 파일을 node_modules/에 다운로드만 합니다. 아직 화면엔 적용되지 않음.

2단계: 글로벌 CSS에 한 번만 import

프로젝트의 글로벌 CSS 파일 한 곳 또는 entry 파일에서:

// app/layout.tsx (Next.js) 또는 main.tsx (Vite)
import '@bnvsrnd/brand-assets/tokens/light.css';
import '@bnvsrnd/brand-assets/tokens/dark.css';
import '@bnvsrnd/brand-assets/styles.css';  // 컴포넌트도 쓸 경우

또는 CSS 파일에서:

/* src/styles/globals.css */
@import '@bnvsrnd/brand-assets/tokens/light.css';
@import '@bnvsrnd/brand-assets/tokens/dark.css';
@import '@bnvsrnd/brand-assets/styles.css';

한 번만 import하면 프로젝트 전체에서 토큰 + 모든 컴포넌트 사용 가능. 페이지/컴포넌트마다 따로 import 불필요.

3단계: 컴포넌트에서 토큰 사용

.button {
  background: var(--action-primary-default);
  color: var(--action-primary-text);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-md);
  font: var(--label-default);
}
.button:hover {
  background: var(--action-primary-hover);
}

다크 모드 토글

<html data-theme="dark">

→ 모든 semantic 토큰이 자동으로 dark 매핑으로 전환됩니다.

토큰 둘러보기

전체 토큰 시각화: demo/index.html 브라우저로 열기 (Dark 토글 포함).

Per-product Brand 색 override (필수 인지)

BNV는 여러 제품을 운영하고 각 제품의 brand 색이 다릅니다 (코딩 플랫폼=퍼플, 수학 플랫폼=민트, BNV 메인=블루 …). 이 패키지의 --brand-* 토큰은 BNV 기본값이며, 각 제품은 brand 10단계만 override해서 자신의 색을 입힙니다.

의도된 토큰 분류

| 분류 | 토큰 | Override 가능? | |---|---|---| | 구조 (모든 제품 공통) | --gray-*, --space-*, --radius-*, --elevation-*, typography | ❌ 절대 금지 | | Brand (제품별) | --brand-50 ~ --brand-900 | ✅ 권장 | | Semantic | --action-primary-*, --status-*, --text-*, --background-* | ❌ brand-*만 바꾸면 자동 따라옴 |

Override 방법

// entry 파일
import '@bnvsrnd/brand-assets/tokens/light.css';
import '@bnvsrnd/brand-assets/tokens/dark.css';
import '@bnvsrnd/brand-assets/styles.css';
import './brand-override.css';   // ← 가장 마지막!
/* coding-platform/src/brand-override.css — Purple 예시 */
:root {
  --brand-50:  #faf5ff;
  --brand-100: #f3e8ff;
  --brand-200: #e9d5ff;
  --brand-300: #d8b4fe;
  --brand-400: #c084fc;
  --brand-500: #a855f7;
  --brand-600: #9333ea;
  --brand-700: #7e22ce;
  --brand-800: #6b21a8;
  --brand-900: #581c87;
}
[data-theme='dark'] {
  --brand-50: #581c87;
  --brand-100: #6b21a8;
  --brand-200: #7e22ce;
  --brand-300: #9333ea;
  --brand-400: #a855f7;
  --brand-500: #c084fc;
  --brand-600: #d8b4fe;
  --brand-700: #e9d5ff;
  --brand-800: #f3e8ff;
  --brand-900: #faf5ff;
}

→ 모든 컴포넌트(Button, Badge, Progress, Modal focus ring 등)가 자동으로 그 제품의 brand 색을 따라옵니다. 컴포넌트 코드 변경 0줄.

10단계 색 생성 도구

hex 하나만 정하면 자동 생성:

Tailwind 프로젝트와 통합

Tailwind config가 CSS 변수를 참조하도록 설정하면 bg-brand-600 같은 유틸리티도 자동으로 그 제품의 brand 색을 따라옵니다:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: {
          50: 'var(--brand-50)',
          100: 'var(--brand-100)',
          200: 'var(--brand-200)',
          300: 'var(--brand-300)',
          400: 'var(--brand-400)',
          500: 'var(--brand-500)',
          600: 'var(--brand-600)',
          700: 'var(--brand-700)',
          800: 'var(--brand-800)',
          900: 'var(--brand-900)',
          DEFAULT: 'var(--brand-500)',
        },
        // Semantic도 동일 패턴으로 매핑하면 다크 모드 자동 대응
        surface: 'var(--background-surface)',
        ink: 'var(--text-primary)',
        line: 'var(--border-default)',
      },
      borderRadius: {
        sm: 'var(--radius-sm)',
        md: 'var(--radius-md)',
        lg: 'var(--radius-lg)',
        full: 'var(--radius-full)',
      },
    },
  },
};

이제 className="bg-brand-600 rounded-lg"가 그 제품의 brand 색 + 우리 시스템 토큰 값으로 렌더됩니다.


React 컴포넌트 사용

위 2단계의 글로벌 import만 돼있으면, 어디서든 컴포넌트 import만으로 동작.

컴포넌트 카탈로그

import {
  // Form (7)
  Button, Input, Checkbox, Radio, Toggle, Textarea, Select,
  // Display (5)
  Badge, Avatar, Card, Search, Divider,
  // Overlay (4)
  Modal, Drawer, Toast, ToastContainer, Tooltip,
  // Navigation (2)
  Tabs, Menu,
  // Feedback (2)
  Spinner, Alert,
} from '@bnvsrnd/brand-assets';

빠른 예시

Button

<Button variant="primary" size="md">저장</Button>
<Button variant="secondary" disabled>취소</Button>

Input / Textarea

<Input label="이메일" helperText="[email protected]" />
<Textarea label="메모" maxLength={500} />

Checkbox / Radio / Toggle

<Checkbox defaultChecked>동의합니다</Checkbox>
<Radio name="plan" value="pro">Pro</Radio>
<Toggle defaultChecked>다크 모드</Toggle>

Select

<Select
  label="카테고리"
  options={[
    { value: 'design', label: '디자인' },
    { value: 'dev', label: '개발' },
  ]}
  onChange={(v) => setCat(v)}
/>

Badge / Avatar

<Badge color="success">완료</Badge>
<Avatar src="/profile.jpg" alt="홍길동" />
<Avatar initials="HG" size="lg" />

Card

<Card variant="elevated">
  <Card.Title>Title</Card.Title>
  <Card.Body>본문</Card.Body>
  <Card.Footer>
    <Button>확인</Button>
  </Card.Footer>
</Card>

Modal / Drawer

<Modal open={open} onClose={() => setOpen(false)}>
  <Modal.Header>제목</Modal.Header>
  <Modal.Body>본문</Modal.Body>
  <Modal.Footer><Button>확인</Button></Modal.Footer>
</Modal>

<Drawer open={open} onClose={...} position="right">
  <Drawer.Header>필터</Drawer.Header>
  <Drawer.Body>...</Drawer.Body>
  <Drawer.Footer>...</Drawer.Footer>
</Drawer>

Toast

<ToastContainer position="top-right">
  {toasts.map((t) => (
    <Toast key={t.id} type={t.type} onClose={() => remove(t.id)}>
      {t.message}
    </Toast>
  ))}
</ToastContainer>

Tooltip

<Tooltip content="설정" position="bottom">
  <button>⚙️</button>
</Tooltip>

Tabs / Menu

<Tabs defaultValue="all">
  <Tabs.List>
    <Tabs.Trigger value="all">전체</Tabs.Trigger>
    <Tabs.Trigger value="active">활성</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Content value="all">...</Tabs.Content>
</Tabs>

<Menu>
  <Menu.Item shortcut="Cmd+E">편집</Menu.Item>
  <Menu.Divider />
  <Menu.Item type="destructive">삭제</Menu.Item>
</Menu>

Spinner / Alert

<Spinner size="md">Loading...</Spinner>

<Alert severity="warning" title="저장되지 않은 변경사항"
  action={{ label: '저장', onClick: save }}
  onClose={() => setOpen(false)}>
  이 화면을 떠나면 변경사항이 사라집니다.
</Alert>

접근성

모든 컴포넌트는 다음을 자동으로 처리합니다:

  • ARIA 역할 + 속성
  • 키보드 네비게이션 (Tabs · Menu · Select · Modal · Drawer)
  • Focus trap + body scroll lock (Modal · Drawer)
  • Portal 렌더링 (Modal · Drawer · Toast · Tooltip)
  • prefers-reduced-motion 대응

상세 props/타입은 IDE의 IntelliSense (TypeScript) 또는 dist/index.d.ts 참조.

데모 페이지

demo/index.html을 브라우저로 열면 모든 컴포넌트의 인터랙티브 카탈로그 + 다크 토글을 볼 수 있습니다.


파이프라인

Figma Variables / Text Styles / Effect Styles
       ↓ Tokens Studio plugin (Sync + Push 버튼)
tokens.json (main)
       ↓ GitHub Actions 자동 실행
build/css/, build/ts/ 자동 commit
       ↓ npm install
자사 제품 (DuoCodi, DuoAcademy) / B2B 외주

상세 셋업: docs/tokens-setup.md


폴더 구조

brand-assets/
├── tokens.json              # ⭐ Source of truth (Tokens Studio 출력, W3C DTCG)
├── src/                     # ⭐ React 컴포넌트 소스
│   ├── index.ts             # public API
│   └── components/Button/   # Button.tsx + Button.css
├── build/                   # 자동 생성 (CSS 토큰)
│   ├── css/light.css, dark.css
│   └── ts/*.ts, *.d.ts
├── dist/                    # 자동 생성 (컴파일된 컴포넌트, tsup 출력)
│   ├── index.js (ESM), index.cjs (CJS)
│   ├── index.d.ts
│   └── index.css            # 모든 컴포넌트 CSS 통합본
├── demo/index.html          # 토큰 시각화 (Dark 토글)
├── scripts/build-tokens.mjs # Style Dictionary 빌드
├── tsup.config.ts           # 컴포넌트 빌드 설정
├── .github/workflows/       # 자동 빌드 워크플로우
├── docs/                    # 셋업 가이드
├── logos/                   # 로고 (예정)
└── icons/                   # 아이콘 (예정)

로컬에서 빌드 (수동)

GitHub Actions가 자동 빌드하지만, 로컬에서 검증하려면:

npm install              # 최초 1회
npm run build            # tokens.json → build/, src/ → dist/
npm run build:tokens     # 토큰만
npm run build:components # 컴포넌트만

운영 규칙

  • main: Tokens Studio가 직접 push. 자동 빌드 트리거.
  • feat/*: 도구 추가, 폴더 구조 변경 등 인프라 작업.
  • 자동화 범위: Tokens Studio Push 이후부터 build/ 갱신까지. Figma → Tokens Studio sync만 수동.

Owner

| 역할 | 이름 | GitHub | |---|---|---| | Primary | 최건의 | choiguneui | | Secondary | 박도은 (Dean) | ilm52626 |


라이선스

내부 사용 (Private). © 2024-2026 비앤브이솔루션