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

ctt-ds

v1.0.19

Published

CTT Design System - Framework agnostic component library

Readme

CTT Design System

A framework-agnostic design system built with Web Components and design tokens.

Installation

npm install ctt-ds

Usage

Framework Agnostic (Web Components)

<!-- Include CSS -->
<link rel="stylesheet" href="node_modules/ctt-ds/dist/styles.css">

<!-- Use components directly in HTML -->
<ctt-button variant="primary" size="large" label="Click me"></ctt-button>
<ctt-radio-button name="option" value="1" label="Option 1"></ctt-radio-button>
<ctt-input-field label="Email" type="email" placeholder="Enter your email"></ctt-input-field>
<ctt-textarea-field label="Message" placeholder="Enter your message" rows="4"></ctt-textarea-field>

<script type="module">
  import 'ctt-ds';
  
  document.querySelector('ctt-button').addEventListener('ctt-click', (e) => {
    console.log('Button clicked!');
  });
  
  document.querySelector('ctt-input-field').addEventListener('ctt-input', (e) => {
    console.log('Input changed:', e.detail.value);
  });
</script>

React

import 'ctt-ds';
import 'ctt-ds/css';

function App() {
  return (
    <div>
      <ctt-button 
        variant="primary" 
        size="large" 
        label="Click me"
        onCtt-click={() => console.log('Clicked!')}
      />
      <ctt-input-field
        label="Email"
        type="email"
        placeholder="Enter your email"
        onCtt-input={(e) => console.log('Input:', e.detail.value)}
      />
      <ctt-radio-button
        name="option"
        value="1"
        label="Option 1"
        onCtt-change={(e) => console.log('Radio changed:', e.detail)}
      />
    </div>
  );
}

Vue

<template>
  <div>
    <ctt-button 
      variant="primary" 
      size="large" 
      label="Click me"
      @ctt-click="handleClick"
    />
    <ctt-input-field
      label="Email"
      type="email"
      placeholder="Enter your email"
      @ctt-input="handleInput"
    />
    <ctt-textarea-field
      label="Message"
      placeholder="Enter your message"
      :rows="4"
      @ctt-input="handleTextareaInput"
    />
  </div>
</template>

<script>
import '@ctt/design-system';
import '@ctt/design-system/css';

export default {
  methods: {
    handleClick() {
      console.log('Clicked!');
    },
    handleInput(event) {
      console.log('Input:', event.detail.value);
    },
    handleTextareaInput(event) {
      console.log('Textarea:', event.detail.value);
    }
  }
}
</script>

Angular

// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@ctt/design-system';

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}
<!-- component.html -->
<ctt-button 
  variant="primary" 
  size="large" 
  label="Click me"
  (ctt-click)="handleClick()">
</ctt-button>

<ctt-input-field
  label="Email"
  type="email"
  placeholder="Enter your email"
  (ctt-input)="handleInput($event)">
</ctt-input-field>

<ctt-radio-button
  name="option"
  value="1"
  label="Option 1"
  (ctt-change)="handleRadioChange($event)">
</ctt-radio-button>

Using Fonts Only

/* Import fonts CSS */
@import 'ctt-ds/fonts.css';

.my-element {
  font-family: 'ActoCTT', Arial, sans-serif;
  font-weight: 400; /* Book/Regular */
}

/* Available font weights: */
.thin { font-weight: 250; }
.light { font-weight: 300; }
.regular { font-weight: 400; } /* Book */
.medium { font-weight: 500; }
.bold { font-weight: 700; }
.black { font-weight: 900; }
<!-- Include fonts in HTML -->
<link rel="stylesheet" href="node_modules/@ctt/design-system/dist/assets/fonts.css">

<!-- Optional: Preload critical fonts for better performance -->
<link rel="preload" href="node_modules/@ctt/design-system/dist/assets/fonts/ActoCTT-Book.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="node_modules/@ctt/design-system/dist/assets/fonts/ActoCTT-Bold.woff2" as="font" type="font/woff2" crossorigin>

Component Usage Examples

<!-- Button with icon -->
<ctt-button 
  variant="primary" 
  size="large" 
  label="Save Document"
  icon-left="true"
  icon-left-element="<svg>...</svg>">
</ctt-button>

<!-- Input field with validation -->
<ctt-input-field
  label="Email Address"
  type="email"
  placeholder="Enter your email"
  required="true"
  error="Please enter a valid email address">
</ctt-input-field>

<!-- Radio button group -->
<ctt-radio-button name="plan" value="basic" label="Basic Plan"></ctt-radio-button>
<ctt-radio-button name="plan" value="pro" label="Pro Plan" checked></ctt-radio-button>
<ctt-radio-button name="plan" value="enterprise" label="Enterprise Plan"></ctt-radio-button>

<!-- Textarea with custom dimensions -->
<ctt-textarea-field
  label="Comments"
  placeholder="Enter your feedback"
  rows="6"
  resize="vertical">
</ctt-textarea-field>

Using Design Tokens Only

// Import tokens as JavaScript objects
import { tokens } from '@ctt/design-system/tokens';

// Use in your CSS-in-JS
const buttonStyles = {
  fontFamily: tokens.typography.fontFamilies.primary,
  fontSize: tokens.typography.fontSize.medium,
  color: tokens.colors.primary[500]
};
/* Import as CSS custom properties */
@import '@ctt/design-system/tokens.css';

.my-button {
  font-family: var(--ctt-typography-font-families-primary);
  font-size: var(--ctt-typography-font-size-medium);
  color: var(--ctt-colors-primary-500);
}
// Import as JSON
import tokens from '@ctt/design-system/tokens.json';

Available Components

  • <ctt-button> - Button component with various variants, sizes and styles
  • <ctt-radio-button> - Radio button component with error states and accessibility
  • <ctt-input-field> - Input field component with label, validation and error states
  • <ctt-textarea-field> - Textarea field component with resizing and validation
  • <ctt-header> - Header component for application navigation
  • <ctt-page> - Page layout component

Available Imports

// Full library
import '@ctt/design-system';

// Individual components (for tree-shaking)
import { 
  Button, CttButton,
  RadioButton, CttRadioButton,
  InputField, CttInputField,
  TextareaField, CttTextareaFieldElement,
  Header, CttHeader,
  Page, CttPage
} from '@ctt/design-system';

// Tokens only
import { tokens } from '@ctt/design-system/tokens';

// CSS bundle (includes fonts and tokens)
import '@ctt/design-system/css';

// Fonts only
import '@ctt/design-system/fonts.css';
/* CSS imports */
@import '@ctt/design-system/css'; /* Full styles */
@import '@ctt/design-system/fonts.css'; /* Fonts only */
@import '@ctt/design-system/tokens.css'; /* Tokens only */

Component Props

Button

| Prop | Type | Default | Description | |------|------|---------|-------------| | variant | 'primary' | 'secondary' | 'tertiary' | 'primary' | Button variant style | | size | 'small' | 'medium' | 'large' | 'medium' | Button size | | label | string | 'Button' | Button text | | iconLeft | boolean | false | Show icon on the left | | iconLeftElement | string | '' | SVG or HTML for left icon | | iconRight | boolean | false | Show icon on the right | | iconRightElement | string | '' | SVG or HTML for right icon | | borderRadius | 'pill' | 'small' | 'extraSmall' | 'pill' | Border radius style | | backgroundColor | string | null | Custom background color | | disabled | boolean | false | Disable the button | | ariaLabel | string | null | Accessible name for screen readers |

RadioButton

| Prop | Type | Default | Description | |------|------|---------|-------------| | label | string | '' | Label text for the radio button | | name | string | '' | Name attribute for form grouping | | value | string | '' | Value of the radio button | | checked | boolean | false | Whether the radio button is checked | | disabled | boolean | false | Whether the radio button is disabled | | errorText | string | '' | Error message to display |

InputField

| Prop | Type | Default | Description | |------|------|---------|-------------| | label | string | '' | Label text for the input | | value | string | '' | Current value of the input | | name | string | '' | Name attribute for forms | | type | string | 'text' | Input type (text, email, password, etc.) | | placeholder | string | '' | Placeholder text | | error | string | null | Error message to display | | disabled | boolean | false | Whether the input is disabled | | required | boolean | false | Whether the input is required | | size | 'small' | 'medium' | 'large' | 'medium' | Input size |

TextareaField

| Prop | Type | Default | Description | |------|------|---------|-------------| | label | string | '' | Label text for the textarea | | value | string | '' | Current value of the textarea | | name | string | '' | Name attribute for forms | | placeholder | string | '' | Placeholder text | | errorText | string | null | Error message to display | | disabled | boolean | false | Whether the textarea is disabled | | required | boolean | false | Whether the textarea is required | | rows | number | 4 | Number of visible rows | | cols | number | null | Number of visible columns | | resize | 'none' | 'vertical' | 'horizontal' | 'both' | 'vertical' | Resize behavior |

Header

| Prop | Type | Default | Description | |------|------|---------|-------------| | user | any | null | User object for authentication state | | onLogin | function | null | Login event handler | | onLogout | function | null | Logout event handler | | onCreateAccount | function | null | Create account event handler |

Page

| Prop | Type | Default | Description | |------|------|---------|-------------| | user | any | null | User object for authentication state | | onLogin | function | null | Login event handler | | onLogout | function | null | Logout event handler | | onCreateAccount | function | null | Create account event handler |

Events

| Component | Event | Description | |-----------|-------|-------------| | Button | ctt-click | Fired when button is clicked | | RadioButton | ctt-change | Fired when radio button state changes | | InputField | ctt-input | Fired when input value changes | | InputField | ctt-change | Fired when input loses focus | | InputField | ctt-focus | Fired when input gains focus | | InputField | ctt-blur | Fired when input loses focus | | TextareaField | ctt-input | Fired when textarea value changes | | TextareaField | ctt-change | Fired when textarea loses focus | | TextareaField | ctt-focus | Fired when textarea gains focus | | TextareaField | ctt-blur | Fired when textarea loses focus |

Development

Getting Started

# Install dependencies
npm install

# Start development with Storybook
npm run storybook

# Build the package
npm run build

# Run tests
npm test

📚 Documentation

Generating New Components

Use the built-in component generator to quickly scaffold new components with full TypeScript support:

npm run generate:component MyComponent

This command will create:

  • src/components/MyComponent/index.js - Main component file
  • src/components/MyComponent/MyComponentElement.js - Web Component wrapper
  • src/styles/components/my-component.css - Component styles with design tokens
  • src/stories/MyComponent.stories.js - Comprehensive Storybook documentation
  • Updates src/index.js with exports
  • Updates src/styles/index.css with style imports
  • Updates src/index.d.ts with TypeScript definitions

Example Usage

# Generate a Card component
npm run generate:component Card

# Generate a Navigation component  
npm run generate:component Navigation

# Generate an InputField component
npm run generate:component InputField

📖 For detailed component assembly instructions, see COMPONENT-ASSEMBLY.md

Development Workflow

  1. Generate Component: Start with the component generator

    npm run generate:component MyComponent
  2. Implement Logic: Edit the generated component file

    // src/components/MyComponent.js
    export const MyComponent = ({ variant = 'default', ...props }) => {
      // Your component implementation
    };
  3. Style the Component: Add styles using design tokens

    /* src/tokens/my-component-tokens.css */
    .ctt-my-component {
      font-family: var(--ctt-typography-font-families-primary);
      color: var(--ctt-colors-primary-500);
    }
  4. Create Stories: Update the Storybook story for documentation

    // src/stories/MyComponent.stories.js
    export const Default = {
      args: {
        variant: 'default',
      },
    };
  5. Test: View your component in Storybook

    npm run storybook

Available Scripts

| Command | Description | |---------|-------------| | npm run storybook | Start Storybook development server | | npm run build-storybook | Build Storybook for production | | npm run generate:component <Name> | Generate a new component scaffold | | npm run build | Build the entire package for distribution | | npm run build:tokens | Build design tokens | | npm run build:components | Build component library | | npm run build:css | Build CSS bundle | | npm run dev | Watch mode for components | | npm run watch | Run dev mode and Storybook concurrently | | npm run test | Run unit tests | | npm run release | Build and publish package |

Project Structure

src/
├── components/           # Component implementations
│   ├── Button.js        # Functional component
│   └── ButtonElement.js # Web Component wrapper
├── tokens/              # Design tokens and CSS
│   ├── index.js         # Token exports
│   ├── colors.js        # Color tokens
│   ├── typography.js    # Typography tokens
│   └── button-tokens.css # Component-specific styles
├── stories/             # Storybook stories
│   └── Button.stories.js
└── index.js            # Main entry point

Component Architecture

Components follow a dual-pattern approach:

  1. Functional Components (*.js): Framework-agnostic functions that return Lit HTML templates
  2. Web Components (*Element.js): LitElement wrappers for native web component support

Design Tokens

Design tokens are the foundation of the design system:

  • JavaScript: Import as objects (import { tokens } from '@ctt/design-system/tokens')
  • CSS: Use as custom properties (var(--ctt-colors-primary-500))
  • JSON: Available as static data (tokens.json)

Testing

# Run all tests
npm test

# Run tests in watch mode
npm run test -- --watch

# Run tests with coverage
npm run test -- --coverage

Publishing

# Patch version (1.0.0 → 1.0.1)
npm run version:patch

# Minor version (1.0.0 → 1.1.0)
npm run version:minor

# Major version (1.0.0 → 2.0.0)
npm run version:major

License

CTT