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

formica-ui-lib

v1.0.174

Published

This repository contains Formica's Storybook-based UI component library.

Readme

Formica UI

This repository contains Formica's Storybook-based UI component library.

The goal of this repo is to keep UI pieces:

  • reusable
  • easy to compose
  • easy to wire into a BFF or app layer
  • free from business logic

If you are new to the codebase, read this file first. If you need the stricter engineering rules, read CONTRIBUTING.md.

What Lives Here

This project is mainly for:

  • atoms, molecules, organisms, templates, and scenes
  • Storybook stories for those components
  • shared prop contracts and callback payload types

This project is not where UI components should:

  • fetch data
  • handle routing
  • talk directly to APIs
  • make business decisions

Folder Basics

  • src/stories/... UI components and Storybook-facing implementations
  • src/componentProps/... prop contracts and shared exported types
  • mocks/... mock data used by stories and scene simulations

Working Rule Of Thumb

Think of most UI components as display components.

Their job is to:

  • render data
  • accept callback props
  • emit typed payloads upward
  • keep only small visual state when needed

Their job is not to:

  • decide where the app navigates
  • call APIs
  • manage app-wide state
  • invent behavior on their own

Coding Standards In Plain English

1. Put props and types in their own files

If a component needs props, create a dedicated prop file for it under src/componentProps/....

Do not define the full prop contract inline inside the component unless it is truly private and temporary.

Good:

export type ImageGridProps = {
  images: GridImage[];
  onImageClick?: (payload: ImageGridClickPayload) => void;
};

2. Keep UI components dumb

A UI component should mostly just render what it is given.

Good:

  • render text, images, layout, and controls
  • call onClick, onChange, onSelect, etc.

Bad:

  • calling fetch
  • importing routing logic
  • mutating app-wide data
  • logging app behavior from deep inside a presentational component unless it is only a temporary local debug step

3. Pass behavior down, emit events up

The app layer, BFF simulation layer, or scene story should own behavior.

The deeper UI component should only emit a typed callback.

Example flow:

  1. story or scene owns the state
  2. scene passes callback props down
  3. item component calls the callback
  4. typed payload comes back up

4. Use explicit callback names

Prefer clear names over generic handlers.

Good:

  • onCartClick
  • onLoginClick
  • onPromoClick
  • onImageClick
  • onCountrySelect

Less preferred:

  • onAction
  • onEvent
  • handleThing

5. Do not use any

If a callback sends data upward, define a real payload type and export it.

Good:

export type ImageGridClickPayload = {
  image: GridImage;
  index: number;
};

Storybook Standards

Stories should use .stories.js

Use .stories.js files for Storybook stories in this repo.

Stories should use args

Prefer args-based stories and simple templates.

Avoid complex JSX-heavy story files unless there is a real need.

Stories must match the final prop contract

If the component props change, update the story right away.

Do not leave stale story args, controls, or fake props around.

Scene Stories

Scene stories are special.

They should act like a lightweight simulation of how the UI will behave when wired into a BFF or application layer.

That means scene stories should often own:

  • selected values
  • visible/hidden state
  • click handlers
  • change handlers
  • log output for interaction testing

In other words: if a child component needs a callback to feel real, the scene story should usually provide it.

Generic Layout Containers

We now have a few reusable layout primitives:

  • ContentContainer
  • ContentGrid
  • FlowRow

Use them when several components share the same layout pattern.

Examples:

  • centered max-width wrappers
  • responsive content grids
  • rows of controls or logos with shared spacing

Do not force everything into one generic container.

A generic container is worth using when the shared part is structural:

  • width
  • spacing
  • columns
  • wrapping
  • alignment

It is not the right tool when the component needs domain-specific rules.

Good use of a generic container

  • ImageGrid using ContentGrid
  • DecorGrid using ContentGrid

Bad use of a generic container

  • a grid deciding what happens when a card is clicked
  • a layout wrapper deciding navigation or selection logic

Responsive Layout Rule

Use one breakpoint for normal responsive work:

  • unprefixed Tailwind classes are mobile below md
  • md: classes are PC at md and above

Avoid sm:, lg:, xl:, and 2xl: layout variants unless the design explicitly requires an exception. Most responsive changes should live in templates and organisms, with fewer changes in molecules and very few in atoms.

When To Use ClickableCard

Use ClickableCard when a whole card or large visual surface acts as one click target.

Examples:

  • an image tile that opens detail
  • a swatch card where clicking the image opens the decor

Do not use ClickableCard when only a normal CTA inside the card is interactive.

Examples:

  • a card with a single "Learn More" button
  • a card with a standard text link

Important rule

The component that owns the clickable surface should own ClickableCard.

Good:

  • SwatchCard uses ClickableCard
  • ImageGrid uses ClickableCard per image tile

Bad:

  • DecorGrid wrapping every child in ClickableCard
  • ContentGrid trying to handle clicks

Atomic Design Guidance

Try to keep responsibility at the right layer:

  • atoms simple UI pieces and layout primitives
  • molecules small composed patterns like ClickableCard
  • organisms richer composed sections like grids, navs, banners, panels
  • scenes higher-level composition and interaction simulation

If a primitive starts learning too much about a domain concept, it is probably in the wrong layer.

Branching / Git Workflow

Direct commits to main are not allowed.

Create feature branches from dev.

Create a feature branch from dev

  1. Checkout dev
  2. Pull the latest changes
  3. Create a feature branch named feature/YourFeature
git fetch
git checkout dev
git pull
git checkout -b feature/YourFeature

Final Advice For Junior Devs

If you are unsure where code should live, ask these questions:

  1. Is this layout or behavior?
  2. Does this component need to know app logic, or just render?
  3. Is this click target owned by the item, or by the container?
  4. Is this type reusable enough to belong in componentProps?
  5. Would this be easier to understand if the story owned the state instead?

If you stay strict about those five questions, your changes will usually fit the codebase well.

For the stricter rule set, examples, and review checklist, see CONTRIBUTING.md.