Display

Package Info

A contract-driven package change card with version, dependency, loading, empty and error states.

Preview in your theme

Loading preview…

import * as React from "react"
import {
  AlertCircle,
  ArrowRight,
  Box,
  CircleMinus,
  CirclePlus,
  PackageOpen,
  RefreshCw,
} from "lucide-react"
import { cn } from "@/lib/utils"
import type { PackageInfoData } from "./package-info.contract"

export type PackageInfoProps = PackageInfoData &

Installation

npx shadcn@latest add https://ui.zyeon.ai/r/package-info.json

Prompt

Build a React + TypeScript + Tailwind "PackageInfo" component using zod,
lucide-react and the local cn() utility.

Contract
- Export packageChangeTypeSchema, packageDependencySchema, packageRecordSchema
  and packageInfoSchema from package-info.contract.ts, plus their inferred
  TypeScript types. The root schema is a discriminated union on status:
  loading, empty, error { errorMessage }, or ready { package }.
- A ready package contains id, name, optional description, optional
  currentVersion/newVersion, changeType = major | minor | patch | added |
  removed, and dependencies [{ id, name, version }].
- Export a forwardRef<HTMLElement> PackageInfo. Its props combine the inferred
  PackageInfoData union with native article attributes (except children);
  className is merged with cn() and remaining native props reach the root.

Behavior
- Treat all four statuses as first-class synchronous branches. Loading renders
  an aria-busy skeleton, empty renders a neutral selection hint, error uses
  role="alert" and its contract message, and ready renders the package record.
- In ready state, label the article from the package name, map changeType to a
  readable chip, show a version transition when either version exists, and
  omit the dependency section when the array is empty.
- Keep the visual transition arrow decorative, but pair current and target
  values with sr-only labels and announce the transition direction as
  "updates to". A lone version must still be identified as current or target.
- Preserve source order for dependencies. Truncate only long package/dependency
  names; allow version strings such as git URLs and commit hashes to break
  across narrow cards instead of overflowing.

Rendering & styling
- Use semantic tokens only: bg-card, bg-muted, bg-primary/10,
  bg-destructive/10, text-card-foreground, text-muted-foreground,
  text-primary, text-destructive and border. Merge className with cn().
- Lucide glyphs are decorative and aria-hidden. Loading copy remains available
  to screen readers through sr-only text; the skeleton pulse uses
  motion-reduce:animate-none.
- Version semantics do not depend on the aria-hidden arrow: sr-only copy names
  current and target values and supplies the transition phrase.
- Give the ready article an accessible label derived from the package name;
  keep the contract id as business data rather than interpolating it into a DOM
  id, where arbitrary API values may be unsafe or duplicate.
- Keep the component server-renderable: it needs no hooks, browser APIs or
  client-only directive.

Customization levers
- Change card density at the three section wrappers without altering the
  contract or state branches.
- Add a changeType by extending the zod enum and the label, icon and token maps
  together; do not infer severity from a hardcoded color.
- Hide the version or dependency blocks by transforming the ready payload
  before render, or replace those blocks with slots while keeping the
  discriminated status union intact.
- Swap Package/Refresh icons, change the dependency row density, or map chip
  treatments to a product's semantic status tokens.

Concepts

  • Discriminated render state — every branch has a valid, minimal payload, so impossible combinations such as an error without a message never reach the renderer.
  • Semantic change severitychangeType drives label, icon and token treatment together; color is reinforcement rather than the only meaning.
  • Version transition — current and target versions form a directional change, while either value can stand alone for added or removed packages.
  • Dependency summary — the card preserves producer order and shows only direct dependencies, keeping the surface scannable instead of pretending to be a full dependency graph.

On This Page