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

@janbox/storefront-ui

v4.0.15

Published

Storefront UI component library for Janbox

Readme

@janbox/storefront-ui

Thư viện component React nội bộ của Janbox — được thiết kế để AI agents và developers có thể làm việc hiệu quả.

Tổng quan

@janbox/storefront-ui là design system component library được xây dựng trên React 19, Emotion CSS, và Vite. Thư viện cung cấp 60+ components có thể customize, type-safe hoàn toàn, và tuân thủ các convention nhất quán để AI agents có thể hiểu và sử dụng dễ dàng.

Phiên bản hiện tại: v2.0.29

Đặc điểm nổi bật

  • Pure ESM — Module format hiện đại, tree-shakeable
  • Type-safe 100% — TypeScript strict mode, generic types đầy đủ
  • Convention-driven — Mọi component tuân thủ cùng một pattern, dễ dự đoán
  • Polymorphic componentsPrimitive component với as prop linh hoạt
  • Responsive-first — Built-in responsive props cho mọi component
  • Emotion CSS — CSS-in-JS với type safety và performance tốt
  • 60+ Components — Từ primitive đến complex UI patterns
  • AI-friendly — Documentation rõ ràng, naming nhất quán, patterns dễ học

Installation

Yêu cầu

  • Node.js ≥ 18
  • pnpm ≥ 8 (khuyến nghị)
  • React ≥ 19

Cài đặt qua pnpm

pnpm add @janbox/storefront-ui

Peer dependencies

Đảm bảo đã cài đặt các peer dependencies:

pnpm add react react-dom @emotion/react

Nếu sử dụng Button với routing:

pnpm add react-router

Quick Start

1. Wrap app với ThemeProvider

import { ThemeProvider } from '@janbox/storefront-ui/theme';

function App() {
  return <ThemeProvider>{/* Your app */}</ThemeProvider>;
}

2. Import và sử dụng components

import { Button, Input, Box, Text } from '@janbox/storefront-ui';

function LoginForm() {
  return (
    <Box sx={{ md: { maxWidth: 400 } }}>
      <Text size="2xl" sx={{ marginBottom: 16 }}>
        Đăng nhập
      </Text>

      <Input type="email" placeholder="Email" size="md" sx={{ marginBottom: 12 }} />

      <Input type="password" placeholder="Mật khẩu" size="md" sx={{ marginBottom: 16 }} />

      <Button variant="contained" color="primary" size="lg" fullWidth>
        Đăng nhập
      </Button>
    </Box>
  );
}

3. Import stylesheet (nếu dùng component có CSS)

Một số component (như DatePicker) import CSS từ third-party libraries. Styles này được tách ra thành file dist/style.css riêng biệt trong quá trình build. Consumer app cần import file này khi sử dụng các component đó:

// Import CSS stylesheet cho các component có external CSS (DatePicker, v.v.)
import '@janbox/storefront-ui/style.css';

Nếu app không dùng DatePicker hay component nào import CSS, bạn có thể bỏ qua bước này.

4. Sử dụng responsive props

import { Flexbox, Box, Button } from '@janbox/storefront-ui';

function ResponsiveLayout() {
  return (
    <Flexbox direction="column" md={{ direction: 'row' }} gap={16}>
      <Box sx={{ sm: { flex: 1 } }}>Nội dung chính</Box>

      <Box sx={{ sm: { width: 300 } }}>Sidebar</Box>
    </Flexbox>
  );
}

Features

1. Convention-Driven Architecture

Mọi component tuân thủ cùng một pattern:

src/lib/<component>/
├── index.ts          → Barrel export
├── types.ts          → TypeScript interfaces
├── helpers.ts        → CSS helpers + merge props logic
├── <component>.tsx   → Component implementation
└── <component>.stories.tsx → Storybook stories

Pattern nhất quán:

// Mọi component đều nhận props theo format này
export const Button = ({ ref, ..._props }: ButtonProps) => {
  // 1. Merge với default props qua helper
  const { size, variant, color, children, ...rest } = getButtonProps(_props);

  // 2. Build CSS từ helpers
  const css = [
    getButtonCssBySize(size),
    getButtonCssByVariant(variant),
    getButtonCssByColor(color),
    createSxInterpolation(sx),
  ];

  // 3. Render với Primitive hoặc native element
  return (
    <button css={css} ref={ref} {...rest}>
      {children}
    </button>
  );
};

2. Type-Safe Responsive Props

import { Box } from '@janbox/storefront-ui';

// Base props (mobile-first)
<Box display="none" />

// Responsive overrides theo breakpoint
<Box
  display="none"
  md={{ display: 'flex' }}
  lg={{ display: 'grid' }}
/>

Breakpoints:

| Screen | Min-width | | ------ | --------------------------------- | | xs | 0px (default, không cần khai báo) | | sm | 768px (tablet) | | md | 1280px (desktop) | | lg | 1680px (large desktop) |

3. Polymorphic Components

import { Primitive } from '@janbox/storefront-ui';

// Render as div (mặc định)
<Primitive>Content</Primitive>

// Render as button
<Primitive as="button" onClick={handleClick}>
  Click me
</Primitive>

// Render as Link từ react-router
<Primitive as={Link} to="/home">
  Go home
</Primitive>

4. Design Token System

import { getColorVar, getTypographyVar, mediaQuery } from '@janbox/storefront-ui/theme';

// Color tokens
const style = {
  backgroundColor: getColorVar('primary.600'),
  color: getColorVar('neutral.50'),
};

// Typography tokens
const { fontSize, lineHeight } = getTypographyVar('lg');

// Media queries
const responsiveStyle = {
  [mediaQuery('md')]: { fontSize: 16 },
  [mediaQuery('lg')]: { fontSize: 18 },
};

5. Utility Functions

import {
  cn, // Class names combiner
  mergeComponentProps, // Deep merge props
  getColorShadesByVariant, // Color utilities
  getSizeVariantState, // Size utilities
  formatNumber, // Number formatter
  formatPrice, // Price formatter
  formatDateTime, // DateTime formatter
} from '@janbox/storefront-ui/utils';

// Example: merge props
const props = mergeComponentProps(defaultProps, userProps);

// Example: get color shades
const { main, dark, light, contrast } = getColorShadesByVariant('primary');

// Example: format price
const formatted = formatPrice(1000000, 'VND', 'vi-VN'); // "1.000.000 ₫"

Usage

Component Categories

Thư viện cung cấp 60+ components được tổ chức theo các nhóm. Xem danh sách README theo từng component tại Component Documentation.

Export Paths

// Main components
import { Button, Input, Box } from '@janbox/storefront-ui';

// Theme utilities
import { ThemeProvider, getColorVar } from '@janbox/storefront-ui/theme';

// Hooks
import { useWindowScreen, useControllableState } from '@janbox/storefront-ui/hooks';

// Types
import type { SizeVariant, ColorScale, StyledCSS } from '@janbox/storefront-ui/types';

// Utils
import { cn, formatPrice } from '@janbox/storefront-ui/utils';

// Constants
import { HTMLDatasetAttributes } from '@janbox/storefront-ui/constants';

Size Variants

Hầu hết components hỗ trợ 4 size variants:

<Button size="xs">Extra Small</Button>
<Button size="sm">Small</Button>
<Button size="md">Medium (default)</Button>
<Button size="lg">Large</Button>

Size mapping:

| size | iconSize | inputSize | inputPaddingX | textVariant | | ---- | -------- | --------- | ------------- | ----------- | | xs | 20px | 24px | 8px | xs | | sm | 20px | 32px | 12px | sm | | md | 24px | 40px | 12px | sm | | lg | 24px | 48px | 16px | base |

Color Variants

<Button color="primary">Primary</Button>
<Button color="secondary">Secondary</Button>
<Button color="green">Success</Button>
<Button color="red">Error</Button>
<Button color="orange">Warning</Button>
<Button color="blue">Info</Button>
<Button color="neutral">Neutral</Button>

sx Prop — Inline Styling

Mọi component đều hỗ trợ sx prop để override styles:

<Button
  sx={{
    borderRadius: 8,
    fontWeight: 600,
    md: { fontSize: 16 },
    lg: { fontSize: 18 },
  }}
>
  Custom Button
</Button>

Theming

ThemeProvider

Wrap root app với ThemeProvider để inject design tokens:

import { ThemeProvider } from '@janbox/storefront-ui/theme';

function App() {
  return (
    <ThemeProvider>
      <YourApp />
    </ThemeProvider>
  );
}

Design Tokens

Design tokens được expose qua CSS variables:

/* Colors */
--color-primary-50
--color-primary-100
...
--color-primary-900

/* Typography */
--typography-xs-font-size
--typography-xs-line-height
...
--typography-6xl-font-size
--typography-6xl-line-height

Accessing Tokens in JS

import { getColorVar, getTypographyVar, breakpoint } from '@janbox/storefront-ui/theme';

// Get color CSS variable
const primaryColor = getColorVar('primary.600'); // 'var(--color-primary-600)'

// Get typography values
const { fontSize, lineHeight } = getTypographyVar('lg');

// Get breakpoint values
console.log(breakpoint.md); // 1280

Development

Prerequisites

  • Node.js ≥ 18
  • pnpm ≥ 8

Setup

# Clone repo
git clone <repo-url>
cd storefront-ui

# Install dependencies
pnpm install

# Start Storybook dev server
pnpm storybook

Storybook sẽ chạy tại http://localhost:6006

Development Commands

| Command | Description | | ---------------------- | ------------------------ | | pnpm storybook | Dev server (port 6006) | | pnpm build | Build thư viện → dist/ | | pnpm dev | Build với watch mode | | pnpm type-check | TypeScript type checking | | pnpm lint | ESLint | | pnpm build-storybook | Build Storybook static |

Creating New Components

Tham khảo CLAUDE.md để hiểu đầy đủ về component architecture và conventions.

Quick steps:

  1. Tạo folder src/lib/<component>/
  2. Tạo files: types.ts, helpers.ts, <component>.tsx, <component>.stories.tsx, index.ts
  3. Implement theo pattern chuẩn (xem CLAUDE.md section 4)
  4. Export trong src/lib/index.ts
  5. Viết Storybook stories

Pattern template:

// types.ts
export type XxxProps = PropsWithSx<
  ShallowMerge<
    React.HTMLAttributes<HTMLDivElement>,
    ToResponsiveProps<XxxResponsiveProps> & {
      children?: React.ReactNode;
    }
  >
>;

// helpers.ts
const defaultProps = { size: 'md' as const } satisfies Partial<XxxProps>;
export const getXxxProps = (p: XxxProps) => mergeComponentProps(defaultProps, p);

// xxx.tsx
export const Xxx = ({ ref, ..._props }: XxxProps) => {
  const { size, children, ...rest } = getXxxProps(_props);
  return (
    <Primitive ref={ref} {...rest}>
      {children}
    </Primitive>
  );
};

Component Documentation

Mọi component đều có README riêng với API reference, examples, và usage notes.


API Reference

Documentation

  • Storybook: Chạy pnpm storybook để xem interactive docs
  • CLAUDE.md: Convention guide đầy đủ cho AI agents và developers
  • TypeScript: Mọi component đều có JSDoc comments và type definitions

Key Types

// Size variants
type SizeVariant = 'xs' | 'sm' | 'md' | 'lg';

// Color variants
type ColorScale = 'primary' | 'secondary' | 'green' | 'red' | 'orange' | 'blue' | 'neutral' | 'yellow' | 'violet';

// Button variants
type ButtonVariant = 'contained' | 'outlined' | 'text';

// Responsive props wrapper
type ToResponsiveProps<T> = T & Partial<Record<'sm' | 'md' | 'lg', T>>;

// sx prop type
type PropsWithSx<T> = T & { sx?: ToResponsiveProps<StyledCSS> };

// Polymorphic component props
type PrimitiveProps<Props, ElementType> = Props & { as?: ElementType };

Hooks

// Window screen detection
useWindowScreen(): Screen;

// Controllable state pattern
useControllableState<T>(value, defaultValue, onChange): [T, Dispatch<T>];

// Countdown timer
useCountdownTimer(target, options): CountdownState;

// Query params sync
useQueryParams<T>(key, defaultValue): [T, (value: T) => void];

// First mount detection
useFirstMountState(): boolean;

// Update effect (skip first mount)
useUpdateEffect(effect, deps);

// Deep compare effect
useDeepCompareEffect(effect, deps);

// Formatters
useFormatter(): FormatterUtils;

AI Agent Guidelines

Thư viện này được thiết kế để AI agents có thể làm việc hiệu quả. Dưới đây là các nguyên tắc quan trọng:

1. Convention nhất quán

  • Mọi component tuân thủ cùng một pattern: types.tshelpers.ts<component>.tsxindex.ts
  • Props destructuring: ({ ref, ..._props })getXxxProps(_props) → destructure
  • Default props luôn ở helpers.ts, không trong component
  • CSS helpers luôn có prefix getXxxCssBy...

2. Type-first approach

  • Mọi component có TypeScript types đầy đủ
  • Sử dụng generic types: PropsWithSx, ToResponsiveProps, ShallowMerge
  • Props type luôn export cùng với component

3. File naming

  • Kebab-case cho tất cả files: input-number.tsx, ripple-effect.tsx
  • PascalCase cho component exports: export const InputNumber = ...

4. Import patterns

// ✅ Preferred — từ main entry
import { Button, Input } from '@janbox/storefront-ui';

// ✅ Subpath exports
import { getColorVar } from '@janbox/storefront-ui/theme';
import { cn } from '@janbox/storefront-ui/utils';

// ❌ Avoid — deep imports
import { Button } from '@janbox/storefront-ui/lib/button';

5. lodash-es requirement

// ✅ Tree-shakeable
import { isNil, debounce } from 'lodash-es';

// ❌ Non-tree-shakeable
import { isNil } from 'lodash';

6. Emotion CSS pragma

Mọi file .tsx sử dụng css={} prop phải có:

/** @jsxImportSource @emotion/react */

Lưu ý: Nếu component chỉ dùng <Primitive> + sx prop, không cần pragma này.

7. Responsive props pattern

// Base (xs) — mobile-first
<Box display="flex" />

// Tablet breakpoint (sm: 768px)
<Box display="flex" sm={{ display: 'grid' }} />

// Desktop breakpoint (md: 1280px)
<Box display="flex" md={{ flexDirection: 'row' }} />

// Large desktop breakpoint (lg: 1680px)
<Box display="flex" lg={{ gap: 32 }} />

8. Testing trong Storybook

  • Mọi component mới bắt buộc.stories.tsx
  • Storybook là môi trường dev/test chính
  • Chưa có unit test runner (Jest/Vitest)

License & Contributing

License

Private package — chỉ dùng nội bộ Janbox.

Contributing

  1. Đọc kỹ CLAUDE.md trước khi contribute
  2. Mọi component mới phải tuân thủ conventions trong CLAUDE.md
  3. Bắt buộc có Storybook stories
  4. Type-check và lint phải pass: pnpm type-check && pnpm lint
  5. Tạo PR, không commit trực tiếp lên main

Workflow

# 1. Create feature branch
git checkout -b feat/my-component

# 2. Develop với Storybook
pnpm storybook

# 3. Type-check
pnpm type-check

# 4. Lint
pnpm lint

# 5. Build
pnpm build

# 6. Commit & push
git add .
git commit -m "feat: add MyComponent"
git push origin feat/my-component

# 7. Create PR

Support

Để được hỗ trợ hoặc báo lỗi, liên hệ team Janbox qua internal channels.


Phiên bản: v2.0.29
Last updated: 2026-06-02