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

@my-bid/ui

v0.14.0

Published

MyBid storefront design system — Tailwind v4 tokens, shadcn/Radix primitives, and generalized Header/Footer shells.

Readme

@my-bid/ui

MyBid storefront design system: Tailwind v4 design tokens, shadcn/Radix primitives, and generalized (prop-driven) Header/Footer shells. Extracted from mybid-landing (the most mature MFE) — this package does not redesign anything, it packages the existing system so every other MFE can consume it instead of re-implementing it.

Source of the design system remains docs/frontend/frontend-architecture-standard.md §8. This package is the distribution of that system, not a second spec.

Install

@my-bid/ui is published to GitHub Packages under the @mybid scope. Add a project-level .npmrc (do not put the token in it — it is read from the environment):

@my-bid:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}

NODE_AUTH_TOKEN must be a GitHub token with read:packages (CI already exports one via secrets.GITHUB_TOKEN; locally, use a personal access token with that scope).

pnpm add @my-bid/ui

Peer dependencies

react, react-dom, lucide-react, radix-ui, class-variance-authority, clsx, tailwind-merge are required peers. next and swiper are optional peers (peerDependenciesMeta.optional):

  • next is optional because no primitive or shell in this package imports next/image or next/link — the shells accept LinkComponent/ ImageComponent overrides instead (see below), so the package itself has no hard runtime dependency on Next. It remains a listed peer because every real consumer today is a Next MFE and version alignment still matters.
  • swiper is optional because only the Swiper/SwiperSlide primitives need it — a consumer that never renders a carousel shouldn't be forced to install it.

Tailwind v4 wiring (tokens)

This package ships only the token layer — not tailwindcss itself, not tw-animate-css, not shadcn/tailwind.css. Your MFE's own app/styles/globals.css still owns those app-level imports; @my-bid/ui just supplies the @theme inline mapping + :root/.dark variable values

  • base layer rules on top:
/* app/styles/globals.css */
@import "tailwindcss";
@import "tw-animate-css";        /* if you use it, same as before */

@import "@my-bid/ui/tokens.css";  /* @theme inline + :root + .dark + base */

/* your own MFE-specific tokens/overrides, if any, go after this line */

Tailwind v4 scans classes at build time by walking @source globs; add this so Tailwind also scans the compiled classes shipped inside @my-bid/ui's dist/:

@source "../node_modules/@my-bid/ui/dist";

(adjust the relative path to wherever your globals.css lives relative to node_modules).

If you use the Swiper/SwiperSlide primitives, additionally import:

@import "@my-bid/ui/swiper.css";

Usage

import { Button, Container, cn } from "@my-bid/ui";

export function Example() {
  return (
    <Container>
      <Button variant="outline" className={cn("mt-4")}>
        Click me
      </Button>
    </Container>
  );
}

Header/Footer shells

HeaderShell and FooterShell are presentational, prop-driven — they know nothing about next-intl, routing, or @my-bid/config URL maps. Every MFE resolves its own translations/URLs and passes plain strings/hrefs in.

import { HeaderShell } from "@my-bid/ui";
import { Link } from "@/shared/i18n"; // your MFE's own locale-aware Link
import { getTranslations, getLocale } from "next-intl/server";

export async function Header() {
  const t = await getTranslations("Header");
  const locale = await getLocale();

  return (
    <HeaderShell
      LinkComponent={Link}
      logo={{ src: "/assets/images/mybid-logo.webp", alt: t("logoAlt"), href: "/", ariaLabel: t("logoAria") }}
      infoLinks={[{ label: t("info.about"), href: "/about" }]}
      channelLinks={[{ label: t("nav.marketplace"), href: urls.channel("marketplace", locale) }]}
      infoNavAriaLabel={t("info.ariaLabel")}
      channelNavAriaLabel={t("nav.ariaLabel")}
      localeSlot={<LocaleSwitcher />}
      searchSlot={<SearchBar />}
      actionsSlot={<AuthEntryButton locale={locale} />}
    />
  );
}

FooterShell follows the same pattern — see src/shells/footer-shell.tsx for the full prop contract (FooterShellProps).

ImageComponent

Both shells default ImageComponent to a plain <img>. To get next/image (recommended for the logo, for LCP), pass a thin wrapper from your MFE so this package never has to agree with your images.remotePatterns/loader config:

import Image from "next/image";

const NextLogo = (props: { src: string; alt: string; width?: number; height?: number; className?: string }) => (
  <Image {...props} priority />
);

<HeaderShell ImageComponent={NextLogo} /* ... */ />

Composed (@my-bid/ui/composed)

HeaderShell/FooterShell above are generic, nav-content-agnostic primitives. @my-bid/ui/composed ships MyBid's actual site navigation pre-wired on top of them — SiteHeader/SiteFooter — so every storefront MFE renders the identical header/footer instead of re-declaring the same info/channel-nav/footer-column config per app. Ported 1:1 from mybid-landing's widgets/header/widgets/footer.

Requires @my-bid/config (optional peer — only needed if you import this subpath) for urls.channel(...) / siteConfig. No next-intl dependency: you inject t already bound to the "Header"/"Footer" namespace.

import { SiteHeader } from "@my-bid/ui/composed";
import { Link } from "@/shared/i18n";
import { getTranslations, getLocale } from "next-intl/server";

export async function Header() {
  const t = await getTranslations("Header");
  const locale = await getLocale();

  return (
    <SiteHeader
      t={t}
      locale={locale}
      LinkComponent={Link}
      localeSlot={<LocaleSwitcher />}
      searchSlot={<SearchBar />}
      actionsSlot={<AuthEntryButton locale={locale} />}
    />
  );
}

SiteFooter follows the same pattern (t, locale, LinkComponent, optional ImageComponent/logoSrc/year) — see src/composed/site-footer.tsx for the full prop contract (SiteFooterProps).

SiteCategoryNav

The header-bottom category bar — a "Kateqoriyalar" mega-menu (CategoryMenu) plus the top-category strip, all linking out to the marketplace MFE. Ported 1:1 from mybid-landing's widgets/category-nav. Client component with a progressive top→full-tree fetch (via @tanstack/react-query, a new optional peer), a skeleton while loading, and renders nothing (null) if the catalog is unavailable.

Since a server→client boundary can't carry a function reference through next-intl, SiteCategoryNav takes resolved labels (plain strings, not a TranslateFn) and a fetchCategories transport you inject — typically your own same-origin /api/categories route handler called through your app's shared/api client (this component never calls fetch/axios itself):

"use client";

import { SiteCategoryNav } from "@my-bid/ui/composed";
import type { CategoryMenuNodeInterface } from "@my-bid/ui/composed";
import { useLocale, useTranslations } from "next-intl";
import { requestInstanceSelf } from "@/shared/api/client";

async function fetchCategories(locale: string, depth?: 1): Promise<CategoryMenuNodeInterface[]> {
  return requestInstanceSelf.get<CategoryMenuNodeInterface[]>(
    `/api/categories?lang=${encodeURIComponent(locale)}${depth ? `&depth=${depth}` : ""}`
  );
}

export function CategoryNav() {
  const locale = useLocale();
  const t = useTranslations("Categories");

  return (
    <SiteCategoryNav
      locale={locale}
      fetchCategories={fetchCategories}
      labels={{
        all: t("all"),
        menuAriaLabel: t("menuAriaLabel"),
        topAriaLabel: t("topAriaLabel"),
        close: t("close"),
      }}
    />
  );
}

Requires a QueryClientProvider ancestor (the same TanStack Query client the rest of your app already uses).

Versioning

Strict semver via changesets. Breaking changes bump major and add an entry to MIGRATION.md. Run pnpm changeset alongside any PR that touches src/ or styles/. Pushing to main runs the publish workflow: build → typecheck → consumer smoke test → token-compliance lint → changeset publish (or opens a release PR if there are pending changesets).

Scope — what this package does NOT include

  • No Field/Label/form-validation primitives — those live with mybid-web-forms (react-hook-form + zod wiring is MFE-local).
  • No i18n catalogs, no locale-aware routing — mybid-web-i18n / @my-bid/config own that; shells only accept resolved strings/hrefs.
  • No data fetching — @my-bid/api/@my-bid/auth (separate mybid-frontend-core package) own that.