Engram

Item popup

component

The item inspect flyout — a dark glass panel modeled on the in-game tooltip: a rarity header band, a damage-type + power/ammo readout, flavor, an optional kill tracker, the stat block, the intrinsic frame row, a perk band (`children`, e.g. a `SocketGrid`), and an action `footer` (e.g. Apply).

Install

npx shadcn@latest add @engram/item-popup

Registry item: /r/item-popup.json — the machine-readable definition agents install from.

Example

Festival Flight

Grenade Launcher

Legendary
510special

Light up the sky anew.

Blast Radius
100Velocity
95Stability
28Handling
90Reload Speed
75Rounds Per Minute72Magazine1
Area Denial Frame

Bungie API

source the props

Fetch the data with @engram/api (a typed bungie-api-ts client) and map it to this component's props with @engram/core. This is the exact code the docs' live examples run.

/** Resolve a Bungie name → membership, then fetch that profile. Returns a
 *  bungie-api-ts DestinyProfileResponse. */
export async function fetchProfile(
  client: BungieClient,
  bungieName: string,
  components: DestinyComponentType[] = PROFILE_COMPONENTS,
): Promise<DestinyProfileResponse> {
  const memberships = await client.searchByBungieName(bungieName);
  const membership = memberships.find((m) => m.membershipId) ?? memberships[0];
  if (!membership) throw new Error(`No Destiny profile for "${bungieName}"`);
  return client.getProfile(
    membership.membershipType,
    membership.membershipId,
    components,
  );
}

export function resolveEquipped(
  profile: DestinyProfileResponse,
  characterId: string,
  getDef: GetDefinition,
): ResolvedItem[] {
  const equip = profile.characterEquipment?.data?.[characterId]?.items ?? [];
  const instances = profile.itemComponents?.instances?.data ?? {};
  const stats = profile.itemComponents?.stats?.data ?? {};
  const sockets = profile.itemComponents?.sockets?.data ?? {};
  const reusable = profile.itemComponents?.reusablePlugs?.data ?? {};
  return equip
    .map((it) => {
      const id = it.itemInstanceId;
      return resolveItem(
        it,
        {
          instance: id ? instances[id] : undefined,
          stats: id ? stats[id]?.stats : undefined,
          sockets: id ? sockets[id]?.sockets : undefined,
          reusablePlugs: id ? reusable[id]?.plugs : undefined,
        },
        getDef,
      );
    })
    .filter((r): r is ResolvedItem => r !== null);
}

Props

PropTypeDefaultDescription
header*HeaderData
seasonIconImageRefSeason watermark shown in the header's tier strip (matches the tile).
archetype{ name: string; icon?: ImageRef }New-armor archetype (Brawler/Paragon/…) shown beside the power readout.
statsStatProps[]
frameWeaponFrameRefIntrinsic frame row (weapons).
trackerItemTrackerKill / usage tracker row.
annotationsItemAnnotationsTyped curated-roll annotations — verdict + tags.
childrenReactNodePerk / socket content (e.g. a `SocketGrid`).
footerReactNodeAction buttons (e.g. Apply / Compare).
classNamestring

Composition

pulled in on install

Dependencies

npm
@engram/core

Own the code: shadcn add copies this component's source into your repo to read and edit directly. Extend without forking — edit the source, use asChild to swap the element, or pass the typed annotations prop for curated data.