New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@tekton-ui/ui

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tekton-ui/ui

Tekton UI Reference Component Library

latest
Source
npmnpm
Version
0.6.0
Version published
Weekly downloads
5
-58.33%
Maintainers
1
Weekly downloads
 
Created
Source

@tekton/ui

Tekton UI Reference Component Library - High-quality, accessible React components with CSS Variables theming.

Overview

@tekton/ui provides 20 production-ready components + 13 screen templates built with:

  • Screen Templates (NEW): 13 full-page layouts for rapid development
  • React 19 - Latest React features with Server Components support
  • TypeScript 5.7+ - Full type safety with strict mode
  • Radix UI v1.0+ - Accessible headless primitives
  • CSS Variables - 3-layer architecture (Atomic → Semantic → Component)
  • WCAG 2.1 AA - Fully accessible

Installation

pnpm add @tekton/ui
# or
yarn add @tekton/ui

Quick Start

Import Components

import { Button, Input, Card } from '@tekton/ui';
import '@tekton/ui/styles';

export default function App() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Welcome to Tekton UI</CardTitle>
        <CardDescription>Build accessible UIs faster</CardDescription>
      </CardHeader>
      <CardContent>
        <Input placeholder="Enter your email..." />
      </CardContent>
      <CardFooter>
        <Button variant="primary">Get Started</Button>
      </CardFooter>
    </Card>
  );
}

CSS Variables Theming

Import the CSS Variables template and customize:

@import '@tekton/ui/styles';

:root {
  /* Button Tokens */
  --button-primary-background: #3b82f6;
  --button-primary-foreground: white;

  /* Input Tokens */
  --input-border: #d1d5db;
  --input-background: white;

  /* Card Tokens */
  --card-background: white;
  --card-border: #e5e7eb;

  /* ... customize 100+ other tokens */
}

Components

Primitive Components (14)

Core UI building blocks with single responsibility:

  • Button - Interactive button with loading states and variants (default, primary, secondary, destructive, outline, ghost, link)
  • Input - Text input with error states and type support (text, email, password, number)
  • Checkbox - Checkbox with indeterminate support and form integration
  • RadioGroup - Radio button groups with keyboard navigation
  • Switch - Toggle switch with checked/unchecked states
  • Slider - Range slider with min/max/step configuration
  • Text - Polymorphic text component with size variants
  • Heading - Hierarchical headings (h1-h6) with level prop
  • Badge - Status badges (default, primary, secondary, destructive, outline)
  • Avatar - User avatars with image/fallback support
  • Progress - Progress bar with value 0-100
  • Link - Navigation links (default, muted, underline variants)
  • Image - Image component with alt text and optional object-fit
  • List - Polymorphic list component (ul/ol)

Composed Components (6)

Complex components built from primitives:

  • Card - Card container with header/content/footer structure
  • Form - Form with validation context and error handling
  • Modal - Dialog/modal overlay with Portal rendering
  • Dropdown - Dropdown menu with keyboard navigation
  • Tabs - Tabbed navigation with automatic ARIA labels
  • Table - Data table with semantic HTML structure

Component Examples

Button

import { Button } from '@tekton/ui';

// Variants
<Button variant="default">Default</Button>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

// Sizes
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>

// States
<Button loading>Loading...</Button>
<Button disabled>Disabled</Button>

Props:

  • variant: "default" | "primary" | "secondary" | "destructive" | "outline" | "ghost" | "link"
  • size: "sm" | "md" | "lg"
  • loading: boolean
  • All native <button> props

Input

import { Input } from '@tekton/ui';

// Basic usage
<Input type="text" placeholder="Enter text..." />
<Input type="email" placeholder="Email address" />
<Input type="password" placeholder="Password" />

// With error state
<Input type="text" aria-invalid="true" />

// Disabled
<Input disabled placeholder="Disabled input" />

Props:

  • type: "text" | "email" | "password" | "number" | "search" | "tel" | "url"
  • All native <input> props

Card

import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@tekton/ui';

<Card>
  <CardHeader>
    <CardTitle>Card Title</CardTitle>
    <CardDescription>Card description or subtitle</CardDescription>
  </CardHeader>
  <CardContent>
    <p>Main content goes here</p>
  </CardContent>
  <CardFooter>
    <Button>Action</Button>
  </CardFooter>
</Card>;

Form

import { Form, FormField, FormLabel, FormControl, FormDescription, FormMessage } from '@tekton/ui';
import { Input } from '@tekton/ui';

<Form
  onSubmit={e => {
    e.preventDefault(); /* handle submit */
  }}
>
  <FormField name="email">
    <FormLabel htmlFor="email">Email</FormLabel>
    <FormControl>
      <Input id="email" type="email" />
    </FormControl>
    <FormDescription>We'll never share your email.</FormDescription>
    <FormMessage name="email">Invalid email address</FormMessage>
  </FormField>
</Form>;

Modal (Dialog)

import {
  Modal,
  ModalTrigger,
  ModalContent,
  ModalHeader,
  ModalTitle,
  ModalDescription,
  ModalFooter,
  ModalClose,
} from '@tekton/ui';
import { Button } from '@tekton/ui';

<Modal>
  <ModalTrigger asChild>
    <Button>Open Modal</Button>
  </ModalTrigger>
  <ModalContent>
    <ModalHeader>
      <ModalTitle>Modal Title</ModalTitle>
      <ModalDescription>Modal description text</ModalDescription>
    </ModalHeader>
    <div>Modal body content</div>
    <ModalFooter>
      <ModalClose asChild>
        <Button variant="outline">Cancel</Button>
      </ModalClose>
      <Button variant="primary">Confirm</Button>
    </ModalFooter>
  </ModalContent>
</Modal>;

Dropdown Menu

import {
  Dropdown,
  DropdownTrigger,
  DropdownContent,
  DropdownItem,
  DropdownSeparator,
} from '@tekton/ui';
import { Button } from '@tekton/ui';

<Dropdown>
  <DropdownTrigger asChild>
    <Button>Open Menu</Button>
  </DropdownTrigger>
  <DropdownContent>
    <DropdownItem onClick={() => console.log('Edit')}>Edit</DropdownItem>
    <DropdownItem onClick={() => console.log('Duplicate')}>Duplicate</DropdownItem>
    <DropdownSeparator />
    <DropdownItem disabled>Disabled Item</DropdownItem>
    <DropdownItem onClick={() => console.log('Delete')}>Delete</DropdownItem>
  </DropdownContent>
</Dropdown>;

Tabs

import { Tabs, TabsList, TabsTrigger, TabsContent } from '@tekton/ui';

<Tabs defaultValue="tab1">
  <TabsList>
    <TabsTrigger value="tab1">Tab 1</TabsTrigger>
    <TabsTrigger value="tab2">Tab 2</TabsTrigger>
    <TabsTrigger value="tab3">Tab 3</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">
    <p>Content for Tab 1</p>
  </TabsContent>
  <TabsContent value="tab2">
    <p>Content for Tab 2</p>
  </TabsContent>
  <TabsContent value="tab3">
    <p>Content for Tab 3</p>
  </TabsContent>
</Tabs>;

Checkbox

import { Checkbox } from '@tekton/ui';

// Basic checkbox
<label>
  <Checkbox id="terms" />
  Accept terms and conditions
</label>

// Indeterminate state
<Checkbox checked="indeterminate" />

// Disabled
<Checkbox disabled />

Props:

  • checked: boolean | "indeterminate"
  • onCheckedChange: (checked: boolean | "indeterminate") => void
  • All Radix UI Checkbox props

RadioGroup

import { RadioGroup, RadioGroupItem } from '@tekton/ui';

<RadioGroup defaultValue="option1">
  <div>
    <RadioGroupItem value="option1" id="opt1" />
    <label htmlFor="opt1">Option 1</label>
  </div>
  <div>
    <RadioGroupItem value="option2" id="opt2" />
    <label htmlFor="opt2">Option 2</label>
  </div>
  <div>
    <RadioGroupItem value="option3" id="opt3" />
    <label htmlFor="opt3">Option 3</label>
  </div>
</RadioGroup>;

Switch

import { Switch } from '@tekton/ui';

<label>
  <Switch id="notifications" />
  Enable notifications
</label>

<Switch checked onCheckedChange={(checked) => console.log(checked)} />

Props:

  • checked: boolean
  • onCheckedChange: (checked: boolean) => void
  • All Radix UI Switch props

Slider

import { Slider } from '@tekton/ui';

// Basic slider
<label htmlFor="volume" id="volume-label">Volume</label>
<Slider
  id="volume"
  defaultValue={[50]}
  min={0}
  max={100}
  step={1}
  aria-labelledby="volume-label"
/>

// Range slider
<Slider defaultValue={[25, 75]} min={0} max={100} />

Props:

  • defaultValue: number[]
  • min: number
  • max: number
  • step: number
  • All Radix UI Slider props

Progress

import { Progress } from '@tekton/ui';

<Progress value={50} aria-label="Upload progress" />
<Progress value={75} aria-label="Loading" />
<Progress value={100} aria-label="Complete" />

Props:

  • value: number (0-100)
  • All Radix UI Progress props

Avatar

import { Avatar, AvatarImage, AvatarFallback } from '@tekton/ui';

<Avatar>
  <AvatarImage src="https://example.com/avatar.jpg" alt="John Doe" />
  <AvatarFallback>JD</AvatarFallback>
</Avatar>;

Badge

import { Badge } from '@tekton/ui';

<Badge variant="default">Default</Badge>
<Badge variant="primary">Primary</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Error</Badge>
<Badge variant="outline">Outline</Badge>

Props:

  • variant: "default" | "primary" | "secondary" | "destructive" | "outline"

Text

import { Text } from '@tekton/ui';

// Sizes
<Text size="xs">Extra small text</Text>
<Text size="sm">Small text</Text>
<Text size="md">Medium text</Text>
<Text size="lg">Large text</Text>

// Polymorphic rendering
<Text as="p">Paragraph</Text>
<Text as="span">Inline text</Text>
<Text as="div">Block text</Text>

Props:

  • as: "p" | "span" | "div" | "label"
  • size: "xs" | "sm" | "md" | "lg"
  • variant: "default" | "muted"

Heading

import { Heading } from '@tekton/ui';

<Heading level={1}>Heading 1</Heading>
<Heading level={2}>Heading 2</Heading>
<Heading level={3}>Heading 3</Heading>
<Heading level={4}>Heading 4</Heading>
<Heading level={5}>Heading 5</Heading>
<Heading level={6}>Heading 6</Heading>

// Sizes
<Heading level={1} size="sm">Small H1</Heading>
<Heading level={2} size="lg">Large H2</Heading>

Props:

  • level: 1 | 2 | 3 | 4 | 5 | 6
  • size: "sm" | "md" | "lg"
import { Link } from '@tekton/ui';

<Link href="/home" variant="default">Default Link</Link>
<Link href="/about" variant="muted">Muted Link</Link>
<Link href="/contact" variant="underline">Underlined Link</Link>

Props:

  • href: string
  • variant: "default" | "muted" | "underline"
  • All native <a> props

List

import { List, ListItem } from '@tekton/ui';

// Unordered list
<List as="ul">
  <ListItem>Item 1</ListItem>
  <ListItem>Item 2</ListItem>
  <ListItem>Item 3</ListItem>
</List>

// Ordered list
<List as="ol">
  <ListItem>First item</ListItem>
  <ListItem>Second item</ListItem>
  <ListItem>Third item</ListItem>
</List>

Props:

  • as: "ul" | "ol"

Image

import { Image } from '@tekton/ui';

<Image
  src="https://example.com/image.jpg"
  alt="Description of image"
/>

<Image
  src="https://example.com/image.jpg"
  alt="Cover image"
  className="object-cover w-full h-64"
/>

Props:

  • src: string
  • alt: string (required for accessibility)
  • All native <img> props

Table

import {
  Table,
  TableHeader,
  TableBody,
  TableFooter,
  TableRow,
  TableHead,
  TableCell,
  TableCaption,
} from '@tekton/ui';

<Table>
  <TableCaption>List of users</TableCaption>
  <TableHeader>
    <TableRow>
      <TableHead>Name</TableHead>
      <TableHead>Email</TableHead>
      <TableHead>Role</TableHead>
    </TableRow>
  </TableHeader>
  <TableBody>
    <TableRow>
      <TableCell>John Doe</TableCell>
      <TableCell>john@example.com</TableCell>
      <TableCell>Admin</TableCell>
    </TableRow>
    <TableRow>
      <TableCell>Jane Smith</TableCell>
      <TableCell>jane@example.com</TableCell>
      <TableCell>User</TableCell>
    </TableRow>
  </TableBody>
  <TableFooter>
    <TableRow>
      <TableCell colSpan={3}>Total: 2 users</TableCell>
    </TableRow>
  </TableFooter>
</Table>;

Features

CSS Variables First

All themeable properties use CSS Variables:

<Button variant="primary">
  {/* Uses --button-primary-background and --button-primary-foreground */}
</Button>

Type-Safe Variants

Powered by class-variance-authority:

<Button variant="secondary" size="lg" loading>
  Click me
</Button>

Accessibility Built-In

  • WCAG 2.1 AA compliant - All components pass axe-core validation
  • Proper ARIA attributes - Screen reader friendly
  • Keyboard navigation - Full keyboard support (Tab, Arrow keys, Enter, Escape)
  • Focus management - Visible focus indicators and proper focus trapping

Zero Config Setup

Works out of the box with sensible defaults:

import { Button } from '@tekton/ui';

<Button>Just works</Button>;

Screen Templates (Phase 3)

New in Phase 3: 13 Screen Templates for rapid full-screen composition.

Overview

Screen Templates provide pre-built, theme-aware full-screen layouts that combine multiple components into cohesive user experiences. Each template is registered in a centralized TemplateRegistry for easy discovery and reuse.

Features:

  • 13 Pre-built Layouts: Auth (4), Core (3), Feedback (5), Dashboard (1)
  • Theme-Aware: Automatically adapts to active theme via CSS Variables
  • AI-Friendly: Clear customization boundaries for AI agents
  • Type-Safe: Full TypeScript support with ScreenTemplate interface
  • Responsive: Desktop, Tablet, Mobile layouts

Quick Start

import { templateRegistry } from '@tekton/ui/templates';

// Get all templates
const allTemplates = templateRegistry.getAll(); // 13 templates

// Get by category
const authTemplates = templateRegistry.getByCategory('auth'); // 4 templates

// Get specific template
const loginTemplate = templateRegistry.get('auth.login');

Available Templates (13)

Auth Templates (4)

import {
  LoginTemplate,
  SignupTemplate,
  ForgotPasswordTemplate,
  VerificationTemplate,
} from '@tekton/ui/templates/auth';
  • LoginTemplate (auth.login) - Centered login card with email/password
  • SignupTemplate (auth.signup) - Registration form with terms acceptance
  • ForgotPasswordTemplate (auth.forgot-password) - Password reset flow
  • VerificationTemplate (auth.verification) - Email verification confirmation

Core Templates (3)

import { LandingTemplate, PreferencesTemplate, ProfileTemplate } from '@tekton/ui/templates/core';
  • LandingTemplate (home.landing) - Full-width landing page with CTA
  • PreferencesTemplate (settings.preferences) - Sidebar settings layout
  • ProfileTemplate (account.profile) - User profile with avatar editing

Feedback Templates (5)

import {
  LoadingTemplate,
  ErrorTemplate,
  EmptyTemplate,
  ConfirmationTemplate,
  SuccessTemplate,
} from '@tekton/ui/templates/feedback';
  • LoadingTemplate (feedback.loading) - Loading skeleton state
  • ErrorTemplate (feedback.error) - Error state with retry button
  • EmptyTemplate (feedback.empty) - Empty state with CTA
  • ConfirmationTemplate (feedback.confirmation) - Dialog confirmation
  • SuccessTemplate (feedback.success) - Success message with next steps

Dashboard Template (1)

import { DashboardTemplate } from '@tekton/ui/templates/dashboard';
  • DashboardTemplate (dashboard.overview) - Dashboard layout with sidebar

Template Features

  • Type-Safe: Full TypeScript support with ScreenTemplate interface
  • AI-Friendly: Clear customization boundaries (slots, texts, options)
  • Theme-Aware: CSS Variables for automatic theme adaptation
  • Responsive: Breakpoint-based layouts (Desktop 1024px+, Tablet 768-1024px, Mobile <768px)
  • Accessible: WCAG 2.1 AA compliance (validation in progress)

TemplateRegistry API

The TemplateRegistry provides centralized template management:

import { templateRegistry } from '@tekton/ui/templates/registry';

// Get all templates
const allTemplates = templateRegistry.getAll(); // 13 templates

// Get templates by category
const authTemplates = templateRegistry.getByCategory('auth'); // 4 templates

// Get specific template
const loginTemplate = templateRegistry.get('auth.login');

// Find by required components
const formsTemplates = templateRegistry.findByRequiredComponents(['Button', 'Input', 'Form']);

Design Reference: All templates follow Claude.ai Design Philosophy - clarity, accessibility, universality.

Phase 3 Status

Completed (2026-02-01):

  • ✅ Template type system (ScreenTemplate, TemplateRegistry)
  • ✅ 13 templates implemented (Auth 4, Core 3, Feedback 5, Dashboard 1)
  • ✅ Template registry with category filtering
  • ✅ Storybook stories for all templates
  • ✅ SPEC TAG annotations (TAG-UI002-001 ~ 035)
  • ⚠️ Test coverage: 17.26% (improvement planned)

Next Steps:

  • Test coverage to 85%+
  • Accessibility validation (axe-core, WCAG 2.1 AA)
  • Additional template variants
  • Template preview gallery in Storybook

CSS Variables Reference

@tekton/ui uses a 3-layer CSS Variables architecture:

Layer 1: Atomic Tokens

--color-primary: #3b82f6;
--color-destructive: #ef4444;
--spacing-sm: 0.5rem;
--radius-md: 0.375rem;

Layer 2: Semantic Tokens

--text-primary: var(--color-primary);
--bg-destructive: var(--color-destructive);

Layer 3: Component Tokens

Button Tokens:

--button-default-background
--button-default-foreground
--button-primary-background
--button-primary-foreground
--button-secondary-background
--button-secondary-foreground
--button-destructive-background
--button-destructive-foreground
--button-outline-border
--button-outline-foreground
--button-ghost-hover-background
--button-link-foreground
--button-disabled-opacity
--button-focus-ring

Input Tokens:

--input-background
--input-foreground
--input-border
--input-placeholder
--input-focus-ring
--input-disabled-background
--input-disabled-foreground

Card Tokens:

--card-background
--card-foreground
--card-border

Modal Tokens:

--modal-background
--modal-border
--modal-overlay-background
--modal-title-foreground
--modal-description-foreground

Form Tokens:

--form-label-foreground
--form-message-destructive
--form-description-foreground

Other Component Tokens:

  • Badge: --badge-*-background, --badge-*-foreground, --badge-*-border
  • Dropdown: --dropdown-*-background, --dropdown-item-*
  • Tabs: --tabs-*-background, --tabs-trigger-*
  • Table: --table-*-background, --table-border
  • Progress: --progress-background, --progress-indicator-background
  • Slider: --slider-track-background, --slider-thumb-*
  • Avatar: --avatar-background, --avatar-foreground

Custom Theme Example

/* dark-theme.css */
@import '@tekton/ui/styles';

:root {
  /* Atomic Layer */
  --color-primary: #60a5fa;
  --color-background: #1f2937;
  --color-foreground: #f9fafb;

  /* Button Layer */
  --button-primary-background: var(--color-primary);
  --button-primary-foreground: #000000;
  --button-default-background: #374151;
  --button-default-foreground: var(--color-foreground);

  /* Input Layer */
  --input-background: #374151;
  --input-foreground: var(--color-foreground);
  --input-border: #4b5563;

  /* Card Layer */
  --card-background: #374151;
  --card-foreground: var(--color-foreground);
  --card-border: #4b5563;
}

Development

Setup

# Clone repository
git clone https://github.com/your-org/tekton.git
cd tekton/packages/ui

# Install dependencies (requires pnpm)
pnpm install

Scripts

# Run tests
pnpm test

# Run tests with coverage (target: ≥90%)
pnpm test:coverage

# Run tests in watch mode
pnpm test:watch

# Type check (TypeScript 5.7+ strict mode)
pnpm type-check

# Lint (ESLint 9)
pnpm lint

# Build (outputs to dist/)
pnpm build

# Clean build artifacts
pnpm clean

Project Structure

packages/ui/
├── src/
│   ├── primitives/          # 14 primitive components
│   │   ├── button.tsx
│   │   ├── input.tsx
│   │   ├── checkbox.tsx
│   │   └── ...
│   ├── components/          # 6 composed components
│   │   ├── card.tsx
│   │   ├── form.tsx
│   │   ├── modal.tsx
│   │   └── ...
│   ├── lib/
│   │   └── utils.ts         # cn() utility
│   └── index.ts             # Main export
├── __tests__/
│   ├── primitives/          # Primitive tests
│   ├── components/          # Component tests
│   ├── lib/                 # Utility tests
│   └── accessibility.test.tsx  # WCAG compliance
├── vitest.config.ts
├── tsconfig.json
└── package.json

Testing

All 20 components include comprehensive test coverage:

Test Coverage (98.93%)

  • Statement Coverage: 98.93%
  • Branch Coverage: 95.52%
  • Function Coverage: 100%
  • Line Coverage: 98.93%

Test Categories

Unit Tests (Vitest + Testing Library)

  • Component rendering
  • Props validation
  • Variant behavior
  • State management
  • Event handling

Accessibility Tests (vitest-axe)

  • WCAG 2.1 AA compliance
  • ARIA attributes
  • Semantic HTML
  • Color contrast (disabled in jsdom)

Keyboard Navigation Tests

  • Tab navigation
  • Arrow key navigation (RadioGroup, Tabs, Slider)
  • Enter/Space activation
  • Escape key handling (Modal, Dropdown)

User Interaction Tests (userEvent)

  • Click events
  • Form submissions
  • Input changes
  • Focus management

Running Tests

# All tests
pnpm test

# Specific file
pnpm vitest run __tests__/primitives/button.test.tsx

# Watch mode
pnpm test:watch

# Coverage report
pnpm test:coverage

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Note: Internet Explorer is not supported.

TypeScript Support

All components are fully typed with TypeScript 5.7+:

import { Button, ButtonProps } from '@tekton/ui';

// Type-safe props
const MyButton: React.FC<ButtonProps> = props => {
  return <Button {...props} />;
};

// Type inference
<Button
  variant="primary" // ✓ Valid
  variant="invalid" // ✗ TypeScript error
  size="lg" // ✓ Valid
  onClick={e => {
    // e is typed as MouseEvent<HTMLButtonElement>
    console.log(e.currentTarget);
  }}
/>;

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting a PR.

Development Workflow

  • Fork the repository
  • Create a feature branch (git checkout -b feature/amazing-feature)
  • Make your changes
  • Run tests (pnpm test)
  • Run type check (pnpm type-check)
  • Run linter (pnpm lint)
  • Commit changes (git commit -m 'Add amazing feature')
  • Push to branch (git push origin feature/amazing-feature)
  • Open a Pull Request

Code Quality Standards

  • Test Coverage: ≥90% (currently 98.93%)
  • TypeScript: Strict mode, no any types
  • Accessibility: WCAG 2.1 AA compliant
  • ESLint: Zero warnings/errors
  • Documentation: All public APIs documented

License

MIT License - see LICENSE for details

Acknowledgments

Built with:

Version: 1.0.0 Last Updated: 2026-01-26 Maintained by: Tekton Team

Keywords

design-system

FAQs

Package last updated on 22 Feb 2026

Related posts