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

tinky-theme

v1.0.1

Published

The flexible, type-safe, and slot-based theming engine for Tinky

Readme

tinky-theme

The flexible, type-safe theming engine for Tinky

tinky-theme provides a robust architecture for building themeable React components. It decouples component logic from visual styling using a powerful slot-based system, enabling deeply customizable UIs without the maintenance headache.

Designed for scalability, it supports global overrides, dynamic prop-based styling, and automatic deep merging—all fully typed with TypeScript.

Features

  • 🧩 Slot-Based Architecture: Define independent styles for every part of a component (e.g., root, label, icon).
  • 🎨 Dynamic Styling: Use functions to drive styles based on component props (e.g., disabled, variant).
  • Global Overrides: Instantly rebrand components application-wide via a simple context provider.
  • 🔄 Smart Deep Merging: User overrides intelligently merge with default themes—change a color without resetting the padding.
  • 📐 TypeScript First: First-class type definitions ensuring autocompletion and type safety for your custom themes.

Installation

Install the package via your preferred package manager:

npm install tinky-theme
# or
yarn add tinky-theme
# or
pnpm add tinky-theme

Note: This package requires react (>=16.8.0) and tinky as peer dependencies.

Key Concepts

1. The Component Theme

A Component Theme acts as the blueprint for a component's appearance. It is divided into two main sections:

  • styles: Not just a single style object, but a collection of styles targeting specific slots (internal parts) of the component. Each slot can be a static object or a dynamic function.
  • config: Non-visual settings (e.g., animation speeds, default icon sets) that consumers might want to override globally.

2. The Slot System

Instead of prop drilling dozens of style props (labelStyle, containerStyle), tinky-theme maps styles to semantic names.

Example component structure:

  • root: The outer container.
  • icon: The visual indicator.
  • label: The text content.

Users can target these specific slots in their theme overrides.

Usage Guide

Step 1: Defining a Component's Default Theme

When you build a component, you define its "contract" by exporting a default theme. This sets the baseline look and feel.

import type { ComponentTheme } from "tinky-theme";

// 1. Define your component props
interface BadgeProps {
  variant?: "solid" | "subtle";
  status?: "success" | "warning" | "error";
  children: React.ReactNode;
}

// 2. Create the default theme definition
const defaultBadgeTheme: ComponentTheme<BadgeProps> = {
  styles: {
    // Dynamic style function for the root container
    root: (props) => ({
      display: "inline-flex",
      padding: "4px 8px",
      borderRadius: "4px",
      // Change color based on status prop
      backgroundColor: props.status === "success" ? "green" : "red",
      opacity: props.variant === "subtle" ? 0.8 : 1,
    }),
    // Static style for the text label
    label: {
      fontSize: "0.875rem",
      fontWeight: 600,
      color: "white",
    },
  },
};

Step 2: Consuming the Theme

Inside your component, use the useComponentTheme hook to resolve the final styles. This hook automatically merges the default theme with any global context overrides.

import { useComponentTheme } from "tinky-theme";
import { Box, Text } from "tinky";

export function Badge(props: BadgeProps) {
  // 3. Resolve the theme
  const theme = useComponentTheme("Badge", defaultBadgeTheme, props);

  return (
    // 4. Apply styles to slots
    <Box {...theme.styles?.root}>
      <Text {...theme.styles?.label}>{props.children}</Text>
    </Box>
  );
}

Step 3: Overriding Globally

Consumers of your library can override specific parts of the component without rewriting the CSS.

import { ThemeProvider, type Theme } from "tinky-theme";

// Define an application-level theme
const appTheme: Theme = {
  components: {
    Badge: {
      styles: {
        root: {
          // Override just the border radius, keep everything else
          borderRadius: "999px",
          textTransform: "uppercase",
        },
      },
    },
  },
};

function App() {
  return (
    <ThemeProvider theme={appTheme}>
      <Badge status="success">Approved</Badge>
    </ThemeProvider>
  );
}

API Documentation

useComponentTheme

function useComponentTheme<P>(
  componentName: string,
  defaultTheme: ComponentTheme<P>,
  props: P,
): ComponentTheme<P>;

Returns: A resolved theme object where all functions are executed and merged.

  • componentName: The unique key used in the global theme registry.
  • defaultTheme: The fallback styles defined by the component author.
  • props: The current props, passed to style functions to generate dynamic values.

ThemeProvider

A wrapper component that injects the theme context.

<ThemeProvider theme={myTheme}>
  <App />
</ThemeProvider>

| Prop | Type | Description | | ---------- | ---------------- | ---------------------------------------------------- | | theme | Partial<Theme> | The global theme object. Can be updated dynamically. | | children | ReactNode | The app or component tree. |

extendTheme

A utility to deep-merge standard themes with user customizations.

const finalTheme = extendTheme(baseTheme, userOverrides);

Advanced Usage

TypeScript Integration

tinky-theme exports all necessary types (Theme, ComponentTheme, StyleObject) to ensure your theme definitions are type-checked.

Conflict Resolution

When merging styles:

  1. Global Overrides take precedence over Default Themes.
  2. Dynamic Prop Styles are re-evaluated on every render if props change.
  3. Deep Merging is used, so valid nested properties (like config) are merged rather than replaced, unless a conflict occurs at a primitive level.

License

MIT © ByteLand Technology Limited