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

@ebay-dt/bonfire-react

v0.1.0

Published

React components for Bonfire.

Readme

@ebay-dt/bonfire-react

Opinionated React components for Bonfire.

Application color tokens

AppHeader, GitHubCliLoginPage, and PrototypeDashboard share one inherited application color-token contract. Their CSS Modules consume those tokens; applications should import the package defaults once from their root layout or stylesheet entry point:

import "@ebay-dt/bonfire-react/styles/defaults.css";

The defaults use light-dark() without imposing a global color scheme. A host that consumes the tokens outside the packaged components should establish the schemes it supports, for example:

:root {
  color-scheme: light dark;
}

Token contract

The namespaces are default, danger, and information. Each namespace has the same 12 semantic roles:

| Group | Role | Default namespace | Danger namespace | | ---------- | ---------- | ------------------------------------------ | ----------------------------------------- | | Background | primary | --app-color-default-background-primary | --app-color-danger-background-primary | | Background | secondary | --app-color-default-background-secondary | --app-color-danger-background-secondary | | Background | tertiary | --app-color-default-background-tertiary | --app-color-danger-background-tertiary | | Foreground | primary | --app-color-default-foreground-primary | --app-color-danger-foreground-primary | | Foreground | secondary | --app-color-default-foreground-secondary | --app-color-danger-foreground-secondary | | Foreground | tertiary | --app-color-default-foreground-tertiary | --app-color-danger-foreground-tertiary | | Border | default | --app-color-default-border | --app-color-danger-border | | Border | muted | --app-color-default-border-muted | --app-color-danger-border-muted | | Border | strong | --app-color-default-border-strong | --app-color-danger-border-strong | | Action | background | --app-color-default-action-background | --app-color-danger-action-background | | Action | foreground | --app-color-default-action-foreground | --app-color-danger-action-foreground | | Action | border | --app-color-default-action-border | --app-color-danger-action-border |

Use the roles according to their semantics rather than according to a particular component selector:

  • Background primary is a canvas, secondary is an elevated surface, and tertiary is an inset or subtle surface.
  • Foreground primary is principal content, secondary is supporting content, and tertiary is disabled or deliberately low-emphasis content. The package defaults for tertiary foregrounds are not intended for normal body text.
  • The unsuffixed border is a standard structural boundary, muted is a subtle separator, and strong is an emphasized boundary.
  • Action colors are for interactive or accent treatment. Action borders do not replace ordinary panel or separator borders.

The information namespace uses the same role suffixes listed above, prefixed with --app-color-information- (for example, --app-color-information-background-primary). Its blue defaults style informational banners, including the duplicate-source context and deployment notes, using primary background, primary foreground, and strong border tokens.

The default, danger, and information segments communicate semantic intent; they are not light/dark theme selectors.

Overriding tokens

The package defaults are in a low-priority bonfire.defaults cascade layer and use a zero-specificity :where(:root) selector. Ordinary unlayered consumer CSS can override them without !important or unusually specific selectors:

:root {
  --app-color-default-background-primary: light-dark(#f7f3ff, #17121f);
  --app-color-default-foreground-primary: light-dark(#24172f, #f8efff);
  --app-color-default-border: light-dark(#ded2e8, #493d54);
  --app-color-default-action-background: light-dark(#6f2da8, #d8a7ff);
  --app-color-default-action-foreground: light-dark(#ffffff, #24172f);
  --app-color-default-action-border: var(--app-color-default-action-background);
}

Custom properties inherit, so a non-portaled component can receive a local variant from an ordinary wrapper:

.loginTheme {
  --app-color-default-background-secondary: light-dark(#fffdf7, #211e17);
  --app-color-danger-background-primary: light-dark(#fff1ef, #381d20);
}
<div className="loginTheme">
  <GitHubCliLoginPage {...model} />
</div>

AppHeader renders its account popover through a portal. When it is inside a PrototypeEnvironment, the popover uses the provider-owned portal container so it inherits the active prototype scheme and variables. Outside that environment, the popover is portaled to body; overrides intended to style both the header and popover must then be placed on a shared ancestor such as html or body.

Importing @ebay-dt/bonfire-react/styles/defaults.css explicitly is the supported way to establish the defaults for packaged components and host-owned UI.

Migrating legacy component tokens

The component-specific properties have been removed and are not compatibility aliases. Existing consumers can migrate them as follows:

| Legacy property | Shared replacement | | ----------------------------- | ------------------------------------------------------------------------------------------------------------------ | | --bf-header-background | --app-color-default-background-primary | | --bf-header-surface | --app-color-default-background-secondary | | --bf-header-foreground | --app-color-default-foreground-primary | | --bf-header-muted | --app-color-default-foreground-secondary | | --bf-header-border | --app-color-default-border | | --bf-header-focus | --app-color-default-action-border | | --bf-auth-background | --app-color-default-background-primary | | --bf-auth-surface | --app-color-default-background-secondary | | --bf-auth-foreground | --app-color-default-foreground-primary | | --bf-auth-muted | --app-color-default-foreground-secondary | | --bf-auth-border | --app-color-default-border | | --bf-auth-accent | --app-color-default-action-background and --app-color-default-action-border | | --bf-auth-accent-foreground | --app-color-default-action-foreground | | --bf-auth-danger | --app-color-danger-foreground-primary, --app-color-danger-border, and --app-color-danger-background-tertiary | | --bf-auth-danger-surface | --app-color-danger-background-primary | | --bf-auth-code-background | --app-color-default-background-tertiary |

The login status surface now uses --app-color-default-background-tertiary. Consumers that previously relied on --bf-auth-background for both the page canvas and its derived status surface can override the two roles independently.

App header

import { AppHeader } from "@ebay-dt/bonfire-react";

<AppHeader applicationName="My App" user={user} />;

AppHeader renders an authenticated dashboard header with an account popover and POST sign-out form. Passing user={null} renders nothing. The home and logout destinations default to / and /auth/logout; use homeUrl and logoutUrl to override them.

The component imports its CSS Module internally. Its block size follows the package layout contract, with a 2.5rem component fallback. Next.js consumers can apply that contract without knowing its internal attribute or CSS property names:

const { htmlProps, headerProps } = await bonfire.auth.getAppLayoutModel();

return (
  <html lang="en" {...htmlProps}>
    <body>
      <AppHeader {...headerProps} />
      {children}
    </body>
  </html>
);

AppHeader owns the user: null rendering decision. Consumers using another server integration can pass an identity directly; the header's normal document flow generally requires no content-spacing adjustment. htmlProps belongs on the root <html> element and headerProps belongs on <AppHeader>; keep both values from the same getAppLayoutModel() result. It uses the shared application color-token contract above.

Prototype themes

PrototypeEnvironment owns the generic theme boundary for a prototype. It sets data-theme and data-color-scheme on the boundary, and exposes the selection through usePrototypeEnvironment or usePrototypeTheme. Next hosts should pass the validated prototype.themeRegistry from the route model rather than importing application configuration into client code:

import {
  PrototypeEnvironment,
  usePrototypeTheme,
} from "@ebay-dt/bonfire-react";

function PrototypeContent() {
  const { theme, colorScheme } = usePrototypeTheme();
  return <p>{`${theme} / ${colorScheme}`}</p>;
}

<PrototypeEnvironment
  prototypeUrl="/alice/example"
  theme={prototype.theme}
  themeRegistry={prototype.themeRegistry}
>
  <PrototypeContent />
</PrototypeEnvironment>;

Instance CSS owns the values and targets the public attributes, for example:

[data-theme="alpha"][data-color-scheme="light"] {
  --prototype-background: #f5f9ff;
}

[data-theme="alpha"][data-color-scheme="dark"] {
  --prototype-background: #10243d;
}

[data-theme="alpha"][data-color-scheme="system"] {
  --prototype-background: #f5f9ff;
}

@media (prefers-color-scheme: dark) {
  [data-theme="alpha"][data-color-scheme="system"] {
    --prototype-background: #10243d;
  }
}

system remains the value of data-color-scheme; the boundary establishes color-scheme: light dark so native controls and light-dark() resolve from the visitor's system preference. The provider exposes both colorScheme (which may be system) and resolvedColorScheme (always light or dark).

PrototypeThemeSwitcher is the generic registry-driven switcher used by AppHeader. It lists registered themes and System/Light/Dark options, disabling values that the active prototype policy or active theme does not support. Hosts can build custom controls with the same hooks. usePrototypePortalContainer allows portaled host UI to remain inside the themed boundary.

Explicit Light/Dark visitor choices are stored in localStorage, scoped by prototype URL and invalidated when the theme policy or registry fingerprint changes. System is an in-memory selection and clears the stored override; after a reload, the configured prototype default is restored. The provider includes a nonce-aware pre-hydration restoration script to apply a stored explicit choice before React hydrates. Hosts using a Content Security Policy should pass the server-provided nonce to PrototypeEnvironment so the inline restoration script is permitted.

GitHub CLI login page

import { GitHubCliLoginPage } from "@ebay-dt/bonfire-react";

<GitHubCliLoginPage {...model} />;

GitHubCliLoginPage includes accessible device-login status polling, activation instructions, and failure guidance. It imports its CSS Module internally, so consumers do not need a global stylesheet. It uses the shared default and danger color roles described above.

Prototype dashboard

import { PrototypeDashboard } from "@ebay-dt/bonfire-react";

<PrototypeDashboard {...dashboardModel} user={user} />;

PrototypeDashboard renders a PrototypeDashboardModel from @ebay-dt/bonfire-core. It provides labeled native GET filters, a responsive catalog of prototype cards, deterministic dates, internal prototype links, and safe external preview links. Filter controls submit their native GET form when changed. When rendered with an authenticated user inside LifecycleProvider, it also renders the lifecycle-owned create and duplicate controls. Edit and delete actions appear in a card's overflow menu only when the authenticated user owns that prototype. Without lifecycle context it remains read-only. Import @ebay-dt/bonfire-react/styles/defaults.css once from the application root before rendering it. It owns its scoped CSS Module with support for narrow layouts, light/dark color preferences, visible focus, and reduced motion.

Agent controls

PrototypeDashboard accepts optional agentActions bindings. When supplied, owner cards render icon buttons with Cursor and Claude Code tooltips; other users' cards and unauthenticated cards remain free of agent controls. AppHeader accepts the same bindings when rendered inside LifecycleProvider and renders text menu rows for an active owned prototype. It uses the lifecycle session's validated reference and closes the account popover when an agent action is clicked.

The bindings are framework-neutral functions, so a Next host can pass Server Action references without making this package depend on Next.js:

import {
  PrototypeAgentControls,
  PrototypeDashboard,
  type PrototypeAgentActionBindings,
} from "@ebay-dt/bonfire-react";

const agentActions: PrototypeAgentActionBindings = {
  openInCursor,
  openInClaudeCode,
};

<PrototypeDashboard
  {...dashboardModel}
  user={user}
  agentActions={agentActions}
/>;
<AppHeader applicationName="My App" user={user} agentActions={agentActions} />;

For a custom surface, render PrototypeAgentControls directly with a validated prototypeRef. PrototypeOnboardingCard provides the same agent launch behavior in the generated new-prototype surface:

import { PrototypeOnboardingCard } from "@ebay-dt/bonfire-react";

<PrototypeOnboardingCard
  title="Checkout prototype"
  description={null}
  prototypeRef={{ login: "alice", slug: "checkout-prototype" }}
/>;

The card reads optional agent bindings from PrototypeEnvironment; they can also be supplied directly through its actions prop. PrototypeEnvironment accepts the same agentActions bindings as AppHeader, which lets a host wire the generated prototype without embedding application-specific imports in the scaffold.

PrototypeAgentControls and the card own pending state, command-install help, Claude Code terminal selection, launch-failure retry/change-terminal flows, and safe typed error messaging. They never access the filesystem or process APIs and do not write preferences from the browser. Hosts provide the action functions; the Next and Node documentation describes their server-only composition.

Lifecycle controller

The framework-neutral lifecycle controller and its React adapter are available from @ebay-dt/bonfire-react/lifecycle. When the lifecycle provider is mounted, AppHeader renders the active prototype indicator and compact save/discard actions in the global popover. When the active prototype has a persisted preview URL, it also renders a View deployment link. When deployment capability is configured, it renders the owner-only Deploy prototype action alongside the same lifecycle controls:

import { AppHeader } from "@ebay-dt/bonfire-react";

<AppHeader applicationName="My App" user={user} />;

Without a mounted lifecycle provider, AppHeader renders the regular account menu without lifecycle controls.

import {
  LifecycleProvider,
  createLifecycleController,
} from "@ebay-dt/bonfire-react/lifecycle";

const controller = createLifecycleController({ actions, navigation });

<LifecycleProvider controller={controller}>{children}</LifecycleProvider>;

The dashboard and header consume lifecycle context directly. For an active owned prototype, render PrototypeEditingControls inside the provider to expose the package-owned saved/unsaved status and save/discard workflow. Save creates a local path-scoped checkpoint; discard restores tracked files and removes untracked files within that prototype path:

import { PrototypeEditingControls } from "@ebay-dt/bonfire-react/lifecycle";

<PrototypeEditingControls />;

Deployment availability is optional; without a mounted lifecycle provider or without a persisted preview URL, the regular header remains unchanged and no view link is rendered. The deployment dialog shows provider ready state and partial-success/failure copy, but does not poll deployment IDs.

The controller accepts typed create, duplicate, edit, and delete command ports and exposes derived view state through useLifecycleViewState() or useLifecycleState(). Use useOptionalLifecycle() for components that can render with or without the provider. Supply a route adapter, the authenticated user, and a dirty-observation adapter to track an owned prototype's clean/dirty state. The browser adapter provides injectable EventSource parsing, bounded retry, and cleanup without importing React or Next.js. Navigation is requested through the supplied adapter; the controller does not perform browser navigation itself. Its optional refresh() capability is host-provided and is invoked once after successful edit/delete mutations. Stop the controller when its host lifecycle ends.

PrototypeFormDialog supports create, duplicate, and edit modes. Edit is prefilled from the supplied summary and preserves the existing URL/slug. The form validates title and description locally, presents typed failures without closing, prevents duplicate submissions while an operation is running, and closes only after matching success. PrototypeDeleteDialog requires an explicit destructive confirmation and warns that uncommitted files are also removed. The provider also installs the package-owned navigation guard: dirty internal links, browser history, and reload/close attempts are protected, while leave choices are resolved through the controller. The controller and forms are safe to restart after development effect cleanup; the React package owns the XState implementation while the public command and view-state contracts remain framework-neutral.