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

@geeksquadstudio/gs-ui

v0.1.0

Published

GS UI — design system built on Ant Design

Downloads

274

Readme

GS UI

A themeable React design system built on top of Ant Design v5, with Storybook as the live playground and a Figma-driven token pipeline.

React 18+ Ant Design 5 Storybook 8 TypeScript


Table of contents


Why GS UI?

Ant Design is a great baseline, but shipping a design system on top of it means adding your own theme, your own component variants (e.g. Masonry, solid-variant Tag, sortable Table), and a cohesive story for every component. GS UI gives you:

  • One import surface — every AntD component re-exported under a single package (gs-ui).
  • Theme-first — tokens exported from Figma drive the whole library. Run npm run build:tokens to re-generate.
  • Light + dark out of the boxlightTheme / darkTheme with full token coverage.
  • Custom extensions — components AntD doesn't ship: Masonry, Table.EditableCell, Table.Sortable, InputNumber.Spinner, ImageCrop, solid Tag variant.
  • Storybook as docs — every component has a Docs page with description, interactive Playground, and demo stories.
  • Tree-shakable — Vite + vite-plugin-dts build to pure ESM.

Quick start

git clone https://github.com/i4BSolutions/gs-ui.git
cd gs-ui
npm install
npm run storybook

Storybook opens at http://localhost:6006 — browse the full component catalog, read per-component docs, and tweak props live in the Controls panel.

Build the library

npm run build          # emits ./dist (ES + .d.ts)

Build a static Storybook

npm run build-storybook   # emits ./storybook-static for hosting

Installation in another project

This repo currently builds to ./dist as a private library. There are three common ways to consume it from another app.

1. Local link (monorepo or side-by-side folders)

# in gs-ui
npm run build
npm link

# in your app
npm link gs-ui

2. Published to a private registry

Publish from ./dist to GitHub Packages, Verdaccio, or any private npm registry, then:

npm install @geeksquadstudio/gs-ui

3. Git submodule / tarball

Point your app's package.json at a git ref or a packed tarball:

{
  "dependencies": {
    "gs-ui": "github:i4BSolutions/gs-ui#main"
  }
}

Peer dependencies

Your app must provide:

| Package | Version | |---|---| | react | >=18 | | react-dom | >=18 |

GS UI ships antd, @ant-design/icons, dayjs, antd-img-crop, and @dnd-kit/* as dependencies, so you don't need to install them separately.


Usage

Wrap your app root with ConfigProvider (for theme) and App (for hook-based message / notification / modal). Then import any component from gs-ui.

// src/main.tsx
import { ConfigProvider, App, theme } from '@geeksquadstudio/gs-ui';
import Dashboard from './Dashboard';

export default function Root() {
  return (
    <ConfigProvider theme={theme}>
      <App>
        <Dashboard />
      </App>
    </ConfigProvider>
  );
}
// src/Dashboard.tsx
import { Button, Form, Input, Card, App } from '@geeksquadstudio/gs-ui';

export default function Dashboard() {
  const { message } = App.useApp();

  return (
    <Card title="New account">
      <Form layout="vertical" onFinish={() => message.success('Saved')}>
        <Form.Item name="email" label="Email" rules={[{ required: true, type: 'email' }]}>
          <Input />
        </Form.Item>
        <Button type="primary" htmlType="submit">Submit</Button>
      </Form>
    </Card>
  );
}

Tip: Use App.useApp() (not the static message.success(...)) so toasts inherit your ConfigProvider theme, prefix, and locale.

Dark mode

import { ConfigProvider, App, darkTheme } from '@geeksquadstudio/gs-ui';

<ConfigProvider theme={darkTheme}>
  <App>{/* … */}</App>
</ConfigProvider>

Theming & tokens

Tokens are generated from Figma variables — they're the source of truth for color, typography, spacing, motion, and per-component overrides.

The pipeline

Figma variables (exported as JSON)
        │
        ▼
scripts/build-tokens.mjs
        │
        ▼
src/theme/tokens.ts  ← auto-generated (seed / map / alias / static / palette / components)
        │
        ▼
src/theme/index.ts   ← builds ThemeConfig (lightTheme / darkTheme)
        │
        ▼
ConfigProvider       ← applies tokens to every antd + gs-ui component

Regenerating tokens

  1. Export the seven Figma variable collections to ~/Downloads/: seed.json, map.json, alias.json, static.json, colors.json, components.json, responsive.json.

  2. Run:

    npm run build:tokens
  3. The script overwrites src/theme/tokens.ts — commit and open a PR.

Available exports

import {
  theme,         // same as lightTheme — default export for convenience
  lightTheme,    // full ThemeConfig with default algorithm
  darkTheme,     // full ThemeConfig with dark algorithm
  lightToken,    // merged seed+map+alias+static+palette (light)
  darkToken,     // same (dark)
  // Raw token sets (for direct consumption)
  seedLight, seedDark,
  mapLight,  mapDark,
  aliasLight, aliasDark,
  staticLight, staticDark,
  paletteLight, paletteDark,
  componentsLight, componentsDark,
  responsive,
} from '@geeksquadstudio/gs-ui';

Overriding per-app

Nest a ConfigProvider to override tokens in a subtree:

<ConfigProvider theme={{ token: { colorPrimary: '#722ed1' } }}>
  <MyBrandedArea />
</ConfigProvider>

See the Foundations / Tokens story in Storybook for a browsable table of every token.


Component catalog

| Category | Components | |---|---| | General | Button, FloatButton, Icon, Typography | | Layout | Divider, Flex, Grid (Row, Col), Layout, Masonry, Space, Splitter | | Navigation | Anchor, Breadcrumb, Dropdown, Menu, Pagination, Steps, Tabs | | Data Entry | AutoComplete, Cascader, Checkbox, ColorPicker, DatePicker, Form, ImageCrop, Input, InputNumber (+ .Spinner), Mentions, Radio, Rate, Select, Slider, Switch, TimePicker, Transfer, TreeSelect, Upload | | Data Display | Avatar, Badge, Calendar, Card, Carousel, Collapse, Descriptions, Empty, Image, List, Popover, QRCode, Segmented, Statistic, Table (+ .EditableCell, .Sortable), Tag (+ variant="solid"), Timeline, Tooltip, Tour, Tree | | Feedback | Alert, Drawer, Message, Modal, Notification, Popconfirm, Progress, Result, Skeleton, Spin, Watermark | | Other | Affix, App, ConfigProvider |

Every component has a Docs page in Storybook with:

  • 1–2 paragraph purpose statement
  • Props reference
  • An interactive Playground story
  • Focused demo stories (variants, sizes, states, common patterns)
  • A matrix / kitchen-sink view where applicable

GS extensions (not in vanilla antd)

These ship with GS UI but are not in upstream Ant Design:

| Component | Purpose | |---|---| | Masonry | Pinterest-style variable-height column layout, responsive via antd's breakpoints. | | Tag with variant="solid" | Saturated-background variant on top of antd's outlined / filled. | | InputNumber.Spinner | Horizontal stepper layout with / + buttons on either side. | | Table.EditableCell | Click-to-edit cell. Enter / blur commits, Escape reverts. | | Table.Sortable | Drag-handle column + drop-reorder rows (powered by @dnd-kit). | | ImageCrop | Opens an "Edit image" modal (zoom / rotate / aspect) before Upload transport. Wraps antd-img-crop. |

Usage examples:

import { Masonry, InputNumber, Table, Tag, ImageCrop, Upload } from '@geeksquadstudio/gs-ui';

// Pinterest-style grid
<Masonry columns={{ xs: 1, sm: 2, md: 3, lg: 4 }} gap={16}>
  {items.map(i => <Card key={i.id}>{/* … */}</Card>)}
</Masonry>

// Solid tag
<Tag variant="solid" color="red">Urgent</Tag>

// Horizontal stepper
<InputNumber.Spinner min={0} max={10} defaultValue={3} />

// Editable + sortable table
<Table.Sortable<Row>
  dataSource={rows}
  onSort={setRows}
  rowKey="id"
  columns={[
    {
      title: 'Name',
      dataIndex: 'name',
      render: (v, r) => (
        <Table.EditableCell value={v} onChange={(next) => update(r.id, next)} />
      ),
    },
  ]}
/>

// Crop before upload
<ImageCrop aspect={1} cropShape="round">
  <Upload listType="picture-circle" maxCount={1}>
    <div>+ Avatar</div>
  </Upload>
</ImageCrop>

Project layout

.
├── .storybook/                   # Storybook config
│   ├── main.ts                   # stories glob, framework, addons
│   └── preview.tsx               # global ConfigProvider + light/dark toolbar
│
├── src/
│   ├── components/
│   │   └── <Name>/
│   │       ├── index.tsx         # re-export or wrapped antd component
│   │       └── <Name>.stories.tsx
│   │
│   ├── foundations/
│   │   └── Tokens.stories.tsx    # browsable seed/map/alias/palette/components
│   │
│   ├── theme/
│   │   ├── tokens.ts             # AUTO-GENERATED from Figma
│   │   └── index.ts              # builds ThemeConfig (lightTheme / darkTheme)
│   │
│   ├── Introduction.stories.tsx  # landing page in Storybook
│   └── index.ts                  # public package entry
│
├── scripts/
│   ├── build-tokens.mjs          # Figma → tokens.ts pipeline
│   └── apply-docs.mjs            # injects component-level Docs text
│
├── package.json
├── tsconfig.json
├── tsconfig.stories.json         # includes stories in typecheck
└── vite.config.ts                # library build config

Scripts

| Command | What it does | |---|---| | npm run storybook | Start Storybook dev server at http://localhost:6006. | | npm run build-storybook | Build a static Storybook in ./storybook-static/. | | npm run build | Build the library to ./dist/ (ESM + .d.ts). | | npm run dev | Run a bare Vite dev server (rarely needed; prefer Storybook). | | npm run typecheck | TypeScript check on the library code. | | npm run build:tokens | Regenerate src/theme/tokens.ts from Figma JSONs in ~/Downloads/. |


Customizing a component

Every component folder is a drop-in seam. To give Button a variant="brand" prop, replace the re-export in src/components/Button/index.tsx:

import { Button as AntButton, type ButtonProps as AntButtonProps } from 'antd';
import React from 'react';

export type ButtonProps = AntButtonProps & { variant?: 'brand' | 'muted' };

export const Button: React.FC<ButtonProps> = ({ variant, style, ...rest }) => {
  const brand = variant === 'brand' ? { boxShadow: '0 0 0 3px rgba(22,119,255,0.15)' } : {};
  return <AntButton {...rest} style={{ ...brand, ...style }} />;
};
  • The import path (gs-ui) stays the same.
  • Existing consumers keep working — you're extending, not replacing.
  • Static members (Button.Group, Form.Item, Typography.Text, etc.) are preserved.

For bigger additions — a new component not in antd — put it in a new folder under src/components/<Name>/, export it from src/index.ts, and write a <Name>.stories.tsx next to it.


Contributing

Tooling

  • Node ≥ 18
  • npm ≥ 9

Typical workflow

# 1. Start Storybook
npm run storybook

# 2. Edit a component
$EDITOR src/components/Button/index.tsx

# 3. Confirm types pass
npm run typecheck

# 4. Confirm the library + Storybook build
npm run build
npm run build-storybook

Adding or changing a component story

  1. Update src/components/<Name>/<Name>.stories.tsx.
  2. Add a parameters.docs.description.story to each story.
  3. Keep an interactive Playground at the top of the file.
  4. Run npm run typecheck.

Refreshing tokens

  1. Export the 7 Figma variable collections to ~/Downloads/.
  2. npm run build:tokens.
  3. Commit the regenerated src/theme/tokens.ts.

FAQ

Why not just use Ant Design directly?

You can — GS UI is a thin opinionated layer. What it adds:

  • A token pipeline so Figma stays the source of truth.
  • A handful of missing components (Masonry, drag-sort Table, inline-edit cells, ImageCrop, solid Tag, spinner InputNumber).
  • A Storybook you can host internally and share with designers / PMs.
  • One import surface for the team to agree on.

How do I get the full AntD v5 API for <Button>?

Every GS UI component passes props through unchanged. <Button type="primary" danger loading /> works identically.

Why does message.success(...) not respect my theme?

Use the hook version — the static one reads from a global fallback that doesn't see your ConfigProvider:

import { App } from '@geeksquadstudio/gs-ui';

const { message } = App.useApp();
message.success('Saved');

Where are hover / active states documented?

Those render via native CSS pseudo-classes — hover or click the component in its Matrix / States story in Storybook to see them live.

Can I use this without Storybook?

Yes — Storybook is only a dev-time dep. Your app only needs the built ./dist/.


License

MIT © i4BSolutions


Built on top of Ant Design. Token pipeline powered by Figma Variables. Drag-and-drop by @dnd-kit. Image cropping by antd-img-crop.