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

@multiplatform.one/components

v7.11.0

Published

multiplatform.one ui components

Readme

@multiplatform.one/components

Cross-platform catalog UI for multiplatform.one — surfaces, feedback, navigation, media, and layout components built on Tamagui, themed through the knobs system.

Install

pnpm add @multiplatform.one/components

Requires react (and react-native / react-dom for the target platform) as peers.

What it owns

  • SurfacesCard, CardHeader, CardFooter, Panel, DialogContent, PopoverContent, SheetFrame (knob-aware, shadowing the raw Tamagui primitives)
  • FeedbackAlert, Toast / useToast, Skeleton, ProgressSteps, DotIndicator
  • Navigation & disclosureTabs, Accordion, DropdownMenu, Pagination, SkipLink
  • DisplayAvatar, Badge, Chip, Quote, Tooltip, Carousel, Video, Image, code blocks, icons, layouts, ErrorBoundary
  • ChartsBarChart, LineChart, AreaChart, PieChart, Sparkline: one universal codebase (headless d3 math + SVG) on web, iOS, and Android; series colors come from the canonical useChartPalette() in @multiplatform.one/theme, explicit data colors pass through untouched. react-native-svg is an optional peer, needed only on native
  • A full re-export of tamagui (YStack, XStack, Text, …), so this package is the only UI import apps and features need

What it must not do

  • No Frappe or API assumptions — data-aware wrappers live in @multiplatform.one/frappe-ui
  • No form fields — fields, Form, and input parts live in @multiplatform.one/forms
  • No data tables — DataTable lives in @multiplatform.one/table

Per house rules, apps and features import this package instead of raw tamagui.

Usage

import { Avatar, Card, CardHeader, Chip, Text, YStack } from "@multiplatform.one/components";

export function UserCard() {
  return (
    <Card>
      <CardHeader>
        <Avatar name="Ada Lovelace" src="https://example.com/ada.png" />
      </CardHeader>
      <YStack>
        <Text>Ada Lovelace</Text>
        <Chip>Admin</Chip>
      </YStack>
    </Card>
  );
}

TreeView scroll retention

Keep scroll memory outside the mounted tree, alongside expansion. Pass the measured height of the available viewport to height; TreeView owns its virtual scrolling.

import { TreeView, type TreeNode } from "@multiplatform.one/components";
import { Button } from "@multiplatform.one/forms";
import { useState } from "react";

export function Library({ nodes, height }: { nodes: TreeNode[]; height: number }) {
  const [showTree, setShowTree] = useState(true);
  const [offset, setOffset] = useState<number>();
  const [expandedIds, setExpandedIds] = useState<string[]>([]);
  return (
    <>
      <Button onPress={() => setShowTree((shown) => !shown)}>Toggle tree</Button>
      {showTree && (
        <TreeView
          nodes={nodes}
          height={height}
          expandedIds={expandedIds}
          onExpandedIdsChange={setExpandedIds}
          initialScrollOffset={offset}
          onScrollOffsetChange={setOffset}
        />
      )}
    </>
  );
}

initialScrollOffset?: number is a mount-time seed, including when omitted. Changing it after mount never requests another scroll. Values use vertical CSS pixels on web and layout units on native; fractions are preserved. Negative and non-finite seeds become zero. Restoration waits for nonempty data, loaded content and a usable visible viewport, then clamps to the actual list extent. An unchanged pending target with identical bounds isn't replayed on each layout notification.

onScrollOffsetChange?: (offset: number) => void reports observed offsets, clamped to the current scroll range and deduplicated. It covers manual scrolling, keyboard navigation, drag auto-scroll and explicit reveal. A scroll command alone isn't confirmation. Subpixel requests reach the list unchanged; observed device rounding is reported as observed. No provisional mount-time zero overwrites saved memory while restoration is waiting. Callback identity changes alone don't emit.

A new explicit revealRequest or user scroll/navigation cancels pending initial restoration. The seed never returns after reveal cancellation or later dataset changes. Acknowledge completed reveals in the persistent controller and only pass still-pending requests on remount. Restoration doesn't select, focus, expand, or call onRevealComplete.

Restore data and expansion together before the first usable nonempty layout. If saved state itself arrives asynchronously, wait to mount the tree until it's known. Retention stores a pixel offset, not an item anchor across dataset edits. After restoration, replacing data with an empty list doesn't rearm the seed; retain previous rows during refresh or deliberately remount with saved state.

The Retained scroll across unmount and delayed layout story uses 500 variable height rows. Manually scroll, unmount/mount, then test delayed data and hidden layout. Remount with reveal to check that reveal wins. Change viewport height to check clamping. The story shows observed offsets separately from measured reveal completion. Native sheet sizing is a separate host responsibility.

SheetModal body sizing

SheetModal sizes its body to the content by default. A consumer-owned viewport — a virtualized list, a measured workspace — cannot bootstrap from that: on native it is delivered height 0, reports zero, and mounts nothing, while a sibling with a declared height gets the space it asked for.

fill?: boolean (default false) opts that body into the sheet's height instead. On native it turns the existing keyboard-aware cap into a definite frame height and opens every link down to the body, so the remaining height reaches the consumer. On web it opens the same chain inside the percent-height snapped frame. The grabber, the header and the bottom safe-area spacer stay outside the flexible body.

<SheetModal open={open} onOpenChange={setOpen} fill snapPoint={88} header={<Title />}>
  <YStack flex={1} minHeight={0}>
    <Toolbar />
    <MyVirtualList />
  </YStack>
</SheetModal>

fill allocates height; it does not add a scroll owner. With scrollable false the children keep sole ownership of scrolling and virtualization; with scrollable true the sheet's own scroller fills the slot instead, and there is still exactly one. Leaving fill off, or passing false, renders the unchanged intrinsic body.

The contract is proven at the fully expanded rest, where the panel is not translated. Smaller detents translate the whole panel down, so an allocated body can extend below the visible window there; check the settled rest before relying on fill with a shorter snapPoint.

Styling

Components resolve structural styling (radius, spacing, elevation, typography) through the knobs system in @multiplatform.one/theme — wrap screens in a <Preset> and flip knobs instead of hardcoding style props. See agent-os/standards/frontend/knobs-system.md in the multiplatform.one repo.

License

Apache-2.0