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

@uptodateconnect/ui

v0.4.0

Published

UP TO DATE shared React + Tailwind components

Readme

@uptodateconnect/ui

Shared React + Tailwind components that give every UP TO DATE product the same look for AI features: one icon, one color, one set of animations.

  • React 18+, TypeScript, Tailwind CSS 3.4+ or 4
  • Light and dark mode
  • Import everything from the root, or one component at a time
  • Respects prefers-reduced-motion

Install

npm install @uptodateconnect/ui

Peer dependencies: react, react-dom, tailwindcss.

Tailwind setup (required)

Tailwind has to scan the package, otherwise the layout classes are not generated.

Tailwind v4, in your main CSS file:

@source "../node_modules/@uptodateconnect/ui/dist";

Tailwind v3, in tailwind.config.js:

content: ["./src/**/*.{ts,tsx}", "./node_modules/@uptodateconnect/ui/dist/**/*.js"]

Usage

import { AiButton, AiInput, AiBadge } from "@uptodateconnect/ui";

// or one component at a time
import { AiButton } from "@uptodateconnect/ui/ai-button";

export function Example() {
  return (
    <>
      <AiBadge>AI-generated</AiBadge>
      <AiInput placeholder="Ask AI anything..." />
      <AiButton shine>Generate with AI</AiButton>
    </>
  );
}

Components

Animations are opt-in (off by default) unless noted. Every component accepts the normal props of its HTML element (className, onClick, ...).

AI

| Component | Import path | What it is | |---|---|---| | AiIcon | /ai-icon | The official AI sparkle icon. Use it instead of wands or other sparkles. | | AiSpinner | /ai-spinner | The official loading spinner (twinkling sparkles). Use it for every loading state. | | AiButton | /ai-button | Gradient button with the AI icon. | | AiBadge | /ai-badge | Small pill that marks content as AI-generated. | | AiInput | /ai-input | Text input with a gradient border and the AI icon. | | AiContainer | /ai-container | Wrapper for AI content, with a rotating border. | | AiImageLoader | /ai-image-loader | Preloader while an AI image is generated. |

Chat

| Component | Import path | What it is | |---|---|---| | AiMessage | /ai-message | One chat bubble, for the assistant or the user. | | AiChatInput | /ai-chat-input | Message composer. Enter sends, Shift+Enter adds a new line. | | AiSuggestions | /ai-suggestions | Clickable prompt suggestion chips. | | AiThinking | /ai-thinking | "AI is thinking" indicator. |

Import paths are shown relative to @uptodateconnect/ui, for example @uptodateconnect/ui/ai-button.

Props

AiButton

| Prop | Type | Default | Notes | |---|---|---|---| | variant | "primary" \| "secondary" \| "outline" \| "ghost" | "primary" | Primary is solid brand blue. Secondary is a light blue tint. Outline is white with a gray border. Ghost has no border. ("soft" is the old name for secondary and still works.) | | size | "sm" \| "md" \| "lg" | "md" | | | iconOnly | boolean | false | Square button with only the icon. Add an aria-label. | | icon | ReactNode | AI sparkle | Replaces the sparkle. null removes it. | | loading | boolean | false | Shows the AiSpinner instead of the icon and disables the button. | | shine | boolean | false | Shine across the caption, once on mount and on hover. | | animatedBorder | boolean | false | Rotating gradient border. Adds 2px per side. |

AiSpinner

| Prop | Type | Default | Notes | |---|---|---|---| | size | number | 20 | Width and height in px. | | label | string | "Loading" | Accessible label. Use "" when the parent already says it is loading. |

It takes the current text color, and stays still when the user has reduced motion on.

AiBadge

| Prop | Type | Default | Notes | |---|---|---|---| | children | ReactNode | "AI" | Badge text. | | tone | "brand" \| "success" \| "purple" \| "neutral" \| "warning" \| "info" | "brand" | Color of the badge. | | icon | ReactNode | AI sparkle | Replaces the sparkle. null removes it. | | shine | boolean | false | Shine across the text. |

AiInput

| Prop | Type | Default | Notes | |---|---|---|---| | shine | boolean | false | Shine across the placeholder while the input is empty. Needs a placeholder. |

AiContainer

| Prop | Type | Default | Notes | |---|---|---|---| | animatedBorder | boolean | false | Rotating gradient border. | | sparkles | boolean | true | Faint decorative sparkles in the corner. | | shine | boolean | false | Shines the text inside (p, headings, li, blockquote, label, figcaption, or anything with data-ai-shine). Elements with their own background are left alone. |

AiImageLoader

| Prop | Type | Default | Notes | |---|---|---|---| | aspectRatio | string | "1 / 1" | CSS aspect ratio. Match the final image to avoid layout jumps. | | label | string | none | Text in the center. | | showIcon | boolean | false | AI icon in the center. | | progress | number (0-100) | none | Shows a thin progress bar when set. |

Fills the width of its parent. Size it with className (for example max-w-sm). Loops continuously.

AiMessage

| Prop | Type | Default | Notes | |---|---|---|---| | role | "assistant" \| "user" | "assistant" | Assistant is left with an AI avatar. User is right in the brand gradient. |

Plain text only. It does not render markdown.

AiChatInput

| Prop | Type | Default | Notes | |---|---|---|---| | onSend | (text: string) => void | none | Called with the trimmed text. | | placeholder | string | "Ask anything..." | | | onAttach | () => void | none | Shows a paperclip button. Open your own file picker in the handler. | | loading | boolean | false | Blocks sending while waiting for the AI. | | disabled | boolean | false | |

It manages its own text. It grows as the user types, up to a limit.

AiSuggestions

| Prop | Type | Notes | |---|---|---| | suggestions | (string \| { label: string; icon?: ReactNode })[] | Chip labels. Use the object form for your own icon. The default icon is the AI sparkle. | | onSelect | (suggestion: string) => void | Called with the chosen text. |

AiThinking

| Prop | Type | Default | Notes | |---|---|---|---| | variant | "bubble" \| "ghost" | "bubble" | Bubble is a tinted chat bubble. Ghost has no box: just the sparkle and text. | | label | string | "Thinking" | | | dots | boolean | true | Bouncing dots. Loops continuously. | | shine | boolean | true | Looping shine on the label. |

Chat example

<AiMessage role="user">Summarize my last report.</AiMessage>
<AiMessage>Sure, here is the summary...</AiMessage>
{loading && <AiThinking />}
<AiSuggestions suggestions={["Draft a reply"]} onSelect={send} />
<AiChatInput onSend={send} loading={loading} />

Brand colors

All colors live in one place: src/lib/ai-brand.ts. Edit it and publish a new version to rebrand every AI component in every project.

A single project can also override the colors with CSS variables, without touching the package:

:root {
  --utd-ai-from: #0b92fa;   /* primary */
  --utd-ai-to: #0181ef;     /* gradient end */
  --utd-ai-soft: #e7f4fe;   /* light tint (badges, bubbles) */
  --utd-ai-border: #a5d3fb;
  --utd-ai-text: #0567c8;
}

Dark-mode tints use --utd-ai-soft-dark, --utd-ai-border-dark and --utd-ai-text-dark.

Dark mode

Components use Tailwind dark: classes, so they follow your project's own dark-mode setup:

  • Tailwind v4: follows the OS (prefers-color-scheme) by default. For a class toggle, add this to your main CSS:
    @custom-variant dark (&:where(.dark, .dark *));
  • Tailwind v3: set darkMode: "class", or leave the default media.

Development

npm install
npm run storybook        # preview components at http://localhost:6006
npm run typecheck
npm run build            # builds dist/

Storybook has a Theme switcher in the toolbar to check light and dark.

Add a component

  1. Create src/components/<name>.tsx and <name>.stories.tsx.
  2. Export it from src/index.ts.
  3. Add an entry in tsup.config.ts and an exports subpath in package.json.

Publish

npm login
npm version patch        # or minor / major
npm publish              # runs typecheck + build first

The package is public under the uptodateconnect npm organization. npm does not accept the same version twice, so bump the version for every release.