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

@curetcore/ui

v3.6.6

Published

Design system compartido para productos Curetcore

Readme

@curetcore/ui

Shared design system for the Curetcore product ecosystem. One package, one visual identity, every product.

Vision

@curetcore/ui is the visual infrastructure that connects all Curetcore products. A user moving between Linkship, Karrito, Clicky, or Logoeassy should feel they are in the same ecosystem — same motion, same glassmorphism, same attention to detail. Each product changes one CSS variable and everything adapts.

This package was born from Linkship, the most polished product in the family. It grows organically: components are extracted when they prove themselves in production across 2+ products, not designed in abstract. That makes it more robust than trying to predict what you will need.

The rule is simple: if a component is used in 2+ products, it gets extracted here. If it lives in only one product, it stays local.

Ecosystem

| Product | Accent | Domain | Description | |---------|--------|--------|-------------| | Linkship | Violet | linkship.cc | Link-in-bio platform | | Karrito | Emerald | — | E-commerce tools | | Clicky | Cobalt | — | QR code generator | | Logoeassy | Amber | — | AI logo generator |

Every product imports the same preset, overrides --color-accent-*, and gets a fully themed UI out of the box.

Architecture

@curetcore/ui
├── css/                  # CSS foundation (imported in globals.css)
│   ├── preset.css        # Theme tokens, accent scale, typography, dark mode
│   ├── animations.css    # 18 keyframes + 20 utility classes + reduced motion
│   └── utilities.css     # Glassmorphism, shadows, hover effects, scrollbars
├── components/           # 13 React components (all "use client")
├── hooks/                # 3 hooks (useTheme, useDebounce, useCopyToClipboard)
├── provider/             # CuretcoreProvider (LazyMotion strict + MotionConfig)
├── theme/                # Color tokens, accent presets, easings, shadows
├── motion/               # Spring presets, animation variants (Framer Motion)
└── utils/                # cn() utility (clsx wrapper)

Design principles

  1. Glassmorphism as identity — Cards, overlays, and containers use backdrop blur with subtle borders. This is the visual signature that ties everything together.

  2. Accent-driven theming — A single CSS variable scale (--color-accent-50 through --color-accent-950) plus a deep variant controls all color. Components reference accent tokens, never hardcoded colors.

  3. Motion with springs — All animations use physics-based springs via Framer Motion, not CSS timing functions. The CuretcoreProvider enables LazyMotion strict for tree-shaking and MotionConfig reducedMotion="user" for accessibility.

  4. Server-safe exportstheme, utils, and motion subpaths have no "use client" directive and can be imported in server components. components, hooks, and provider are client-only.

Subpath exports

| Import path | Content | Client-only | |-------------|---------|:-----------:| | @curetcore/ui | Everything re-exported | Yes | | @curetcore/ui/components | All 13 components + types | Yes | | @curetcore/ui/hooks | useTheme, useDebounce, useCopyToClipboard | Yes | | @curetcore/ui/provider | CuretcoreProvider | Yes | | @curetcore/ui/theme | BRAND_COLORS, ACCENT_PRESETS, EASINGS, SHADOWS | No | | @curetcore/ui/motion | springs, variants, staggerContainer | No | | @curetcore/ui/utils | cn() | No | | @curetcore/ui/css/preset.css | Theme tokens + base styles | — | | @curetcore/ui/css/animations.css | Keyframes + utility classes | — | | @curetcore/ui/css/utilities.css | Glass, shadows, scrollbars | — |


Installation

npm install @curetcore/ui

Published to GitHub Packages (npm.pkg.github.com). Requires .npmrc with @curetcore:registry=https://npm.pkg.github.com.

Peer dependencies

| Package | Version | |---------|---------| | react | ^18.2.0 or ^19.0.0 | | react-dom | ^18.2.0 or ^19.0.0 | | framer-motion | ^12.0.0 | | lucide-react | ^0.400.0 | | next | >=14.0.0 |


Setup

1. CSS (globals.css)

@import "@curetcore/ui/css/preset.css";
@import "@curetcore/ui/css/animations.css";
@import "@curetcore/ui/css/utilities.css";

/* Tailwind v4: scan component classes from the package */
@source "../node_modules/@curetcore/ui/dist/**/*.js";

2. Provider (root layout)

import { CuretcoreProvider } from "@curetcore/ui/provider";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <CuretcoreProvider>{children}</CuretcoreProvider>
      </body>
    </html>
  );
}

The provider wraps your app with:

  • LazyMotion features={domMax} strict — enables all Framer Motion features with strict tree-shaking (use m instead of motion)
  • MotionConfig reducedMotion="user" — respects prefers-reduced-motion

3. Accent customization

Override the accent scale in your globals.css after importing the preset:

/* Example: Linkship uses violet */
@theme inline {
  --color-accent-50: #f5f3ff;
  --color-accent-100: #ede9fe;
  --color-accent-200: #ddd6fe;
  --color-accent-300: #c4b5fd;
  --color-accent-400: #a78bfa;
  --color-accent-500: #8B5CF6;
  --color-accent-600: #7C3AED;
  --color-accent-700: #6D28D9;
  --color-accent-800: #5B21B6;
  --color-accent-900: #4C1D95;
  --color-accent-950: #2E1065;
}

Pre-built presets are available in code:

import { ACCENT_PRESETS } from "@curetcore/ui/theme";
// ACCENT_PRESETS.violet, .cobalt, .lime, .emerald, .amber

Components

import { Button, Card, Input, Toggle, Modal, Badge } from "@curetcore/ui/components";

| Component | Description | |-----------|-------------| | Button | 8 variants (primary, secondary, ghost, danger, destructive, pro, success, outline). Sizes xs-lg. Loading state with spinner. | | Card | Glassmorphism card with 4 variants (default, nested, accent, danger). Accent border with 6 color options. | | Input | Form input with label, error, prefix/suffix, icon, character count. Forwards ref to <input>. | | Textarea | Same API as Input for multiline text. Forwards ref to <textarea>. | | Toggle | Animated spring switch in 3 sizes (xs, sm, md). role="switch" + aria-checked. Requires aria-label. Forwards ref. | | Modal | Confirmation dialog on native <dialog>. Typed-confirmation support, aria-modal, aria-describedby. i18n-ready labels. | | ToastContainer | Auto-dismiss toast system with undo support. Pair with useToast() from the same import. | | Badge | 7 variants: pro (animated shimmer), beta, status (dot indicator), count, founders, live (pulse), default. | | Skeleton | 5 layout skeletons: SkeletonCard, SkeletonKPI, SkeletonChart, SkeletonList, SkeletonTable. | | EmptyState | Icon + title + description + optional CTA button. | | ErrorAlert | Inline error message with role="alert" and dismiss button. | | LoadingButton | Button wrapper that shows loading text while submitting. | | SafeImage | Next.js Image with automatic DiceBear Croodles fallback on error. |

Exported types

All component prop types are exported: ButtonProps, CardProps, CardAccentColor, InputProps, TextareaProps, ToggleProps, ModalProps, ToastContainerProps, BadgeProps, SkeletonProps, EmptyStateProps, ErrorAlertProps, LoadingButtonProps, SafeImageProps.


Hooks

import { useTheme, useDebounce, useCopyToClipboard } from "@curetcore/ui/hooks";

useTheme

const { theme, setTheme, resolvedTheme, mounted } = useTheme();
// theme: "light" | "dark" | "system"
// resolvedTheme: "light" | "dark" (resolved from system preference)
// mounted: boolean (true after hydration — use to avoid flash)

Persists to localStorage("theme"). Toggles .dark class on <html>. Listens to prefers-color-scheme changes when set to "system".

useDebounce

const debouncedSearch = useDebounce(searchQuery, 300);

useCopyToClipboard

const { copy, copied } = useCopyToClipboard(2000); // reset after 2s
await copy("https://linkship.cc/ronaldo");
// copied === true for 2 seconds

Also exports the pure function copyToClipboard(text: string) for use outside React.


Utils

import { cn } from "@curetcore/ui/utils";

<div className={cn("px-4 rounded-xl", isActive && "bg-accent-500/10", className)} />

cn() wraps clsx for conditional class merging. Every component in the package uses it internally.


Motion presets

import { springs, fadeSlideUp, staggerContainer, sectionReveal } from "@curetcore/ui/motion";

Springs

Physics-based spring configs for Framer Motion transitions.

| Spring | Feel | Use case | |--------|------|----------| | springs.gentle | Ultra-soft, languid | Page transitions, large elements | | springs.smooth | Default — natural | General-purpose, most components | | springs.snappy | Quick, minimal overshoot | Toggles, buttons, small interactions | | springs.bounce | Playful | Notifications, badges, celebrations | | springs.floating | Very damped, glassy | Parallax, glassmorphism layers | | springs.easeOutExpo | Fast out with decel | Dropdowns, menus, slide-overs |

Variants

| Variant | Description | |---------|-------------| | fadeSlideUp | Fade + slide from 30px below with blur | | fadeSlideLeft | Fade + slide from 60px right with blur | | fadeSlideRight | Fade + slide from 60px left with blur | | scaleFade | Scale up from 0.85 + fade with blur | | sectionReveal | Container for viewport-triggered stagger | | REDUCED_MOTION_VARIANTS | Opacity-only fallback for accessibility |

staggerContainer(amount, delay)

Factory function that creates a Framer Motion Variants object for orchestrating child animations.

<m.div variants={staggerContainer(0.1)} initial="hidden" animate="visible">
  <m.div variants={fadeSlideUp}>First</m.div>
  <m.div variants={fadeSlideUp}>Second</m.div>
  <m.div variants={fadeSlideUp}>Third</m.div>
</m.div>

Theme tokens

import { BRAND_COLORS, ACCENT_PRESETS, EASINGS, SHADOWS } from "@curetcore/ui/theme";

Brand colors

Fixed across all products — the Curetcore family palette:

| Token | Hex | Usage | |-------|-----|-------| | navy | #1E2330 | Dark backgrounds | | navyDeep | #13141b | Deepest dark | | cobalt | #3B42F0 | Primary brand blue | | lime | #D2E823 | Highlight, CTA accent | | sand | #EDE9DF | Warm neutral | | cream | #F5F0E8 | Light warm background |

CSS utilities (from CSS files)

Glassmorphism: .glass, .glass-white

Shadows: .shadow-card, .shadow-card-hover, .shadow-float, .shadow-glow-lime

Hover: .hover-lift (translateY + scale on hover)

Scrollbars: .scrollbar-violet, .scrollbar-hide (accent-colored, dark mode aware)

Animations: .animate-float-up, .animate-shimmer, .animate-pulse-glow, .animate-breathe, .animate-smoke, .animate-aurora, .animate-in, .animate-card-shake, .animate-hero-zoom, .animate-profile-reveal, .animate-brand-fade, .animate-glow-breathe, .animate-marquee

Stagger patterns: .public-stagger > * (auto-stagger up to 10 children), .public-social-stagger > *

Reduced motion: All animations are disabled when prefers-reduced-motion: reduce is active.


CSS layers

The three CSS files form a layered system:

  1. preset.css — Foundation. Theme tokens (@theme inline), accent scale, typography (Outfit), dark mode via .dark class, base body styles, selection color.

  2. animations.css — Motion. 18 keyframes, 20+ utility classes, stagger patterns, reduced motion override. All animations use the easing variables from the preset.

  3. utilities.css — Effects. Glassmorphism, shadow presets, hover interactions, accent-colored scrollbars (WebKit + Firefox), scrollbar variants.


Versioning

This package follows strict Semantic Versioning:

| Type | When | Example | |------|------|---------| | MAJOR (X.0.0) | Breaking changes: required props added, APIs removed, behavior changes that break existing consumers | Toggle now requires aria-label | | MINOR (0.X.0) | Backwards-compatible additions: new components, hooks, exports, optional props | Add useDebounce hook, add motion presets | | PATCH (0.0.X) | Bug fixes, internal improvements, documentation, no API change | Fix build race condition, add displayName |

What counts as breaking

  • Making an optional prop required
  • Removing an exported component, hook, type, or function
  • Changing the behavior of an existing prop in a way that breaks consumers
  • Removing a CSS class or variable that consumers reference
  • Changing the default value of a prop in a way that changes rendered output

What does NOT count as breaking

  • Adding new optional props with sensible defaults
  • Adding new components, hooks, or exports
  • Adding new CSS keyframes or utility classes
  • Internal refactoring that preserves the public API
  • Improving accessibility without changing the API

Pre-release

For testing breaking changes before committing:

2.0.0-beta.1 → 2.0.0-beta.2 → 2.0.0-rc.1 → 2.0.0

Contributing

Extraction rule

A component qualifies for @curetcore/ui when:

  1. It is used in 2 or more Curetcore products
  2. It is generic enough to work with just the accent system (no product-specific logic)
  3. It has been tested in production in at least one product

Process

  1. Identify the component in product A
  2. Confirm it is needed in product B
  3. Extract to src/components/ with generic props and accent-based styling
  4. Add displayName, forwardRef (for form elements), JSDoc, and i18n-ready string props
  5. Export from src/components/index.ts
  6. Build, verify types, publish minor version
  7. Update both products to import from @curetcore/ui/components

Component standards

  • All components use clsx() for class composition (never template literals)
  • All components have displayName
  • Form components (Input, Textarea, Toggle) forward refs
  • Interactive components have proper ARIA attributes
  • Hardcoded strings are exposed as props with English defaults
  • Springs are imported from ../motion, never hardcoded inline

Build

npm run build      # rm -rf dist && tsup (two parallel configs)
npm run typecheck   # tsc --noEmit
npm run dev         # tsup --watch

The build uses two tsup configurations that run in parallel:

  • Client config: components, hooks, provider, index — with "use client" banner
  • Server config: theme, utils, motion — no banner

The dist/ directory is pre-cleaned in the build script to avoid race conditions between parallel configs.


Made by Ronaldo Paulino