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

@imc0nt0/mirror

v0.1.6

Published

[![npm version](https://badge.fury.io/js/%40imc0nt0%2Fmirror.svg)](https://badge.fury.io/js/%40imc0nt0%2Fmirror) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![npm downloads](https://img.sh

Readme

@imc0nt0/mirror

npm version License: MIT npm downloads

A minimal React UI system focused on clarity, motion, and UX principles. Built with performance and developer experience in mind.

🚀 Features

  • Minimal & Clean: Focused on essential components with clean design
  • Motion-First: Built-in animation system with Framer Motion
  • TypeScript Support: Full TypeScript definitions included
  • Customizable: Easy to customize with CSS variables
  • Lightweight: Tree-shakable and optimized bundle size
  • Accessible: ARIA compliant components

📦 Installation

npm install @imc0nt0/mirror framer-motion bootstrap-icons
# or with yarn
yarn add @imc0nt0/mirror framer-motion bootstrap-icons

📖 Table of Contents

🎨 Color System

The Mirror design system uses a carefully crafted color palette optimized for clarity and accessibility.

{
  "primary": "#b8e8fd",    // Light Blue - Primary actions
  "secondary": "#f4f4fe",  // Light Purple - Secondary actions  
  "error": "#cc0000",      // Red - Error states
  "success": "#4bd964",    // Green - Success states
  "warning": "#ff4d00"     // Orange - Warning states
}

All colors meet WCAG 2.1 AA accessibility standards for contrast ratios.

🧩 Components

Button

Flexible button component with multiple variants and sizes.

import { Button } from '@imc0nt0/mirror';

// Basic usage
<Button variant="primary">Click Me</Button>
<Button variant="secondary" size="large">Large Button</Button>
<Button fullWidth>Full Width Button</Button>

// With icon
<Button variant="outline" icon="bi-download">Download</Button>

Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | variant | 'primary' \| 'secondary' \| 'outline' \| 'ghost' | 'primary' | Button style variant | | size | 'small' \| 'medium' \| 'large' | 'medium' | Button size | | disabled | boolean | false | Disable button interaction | | fullWidth | boolean | false | Make button full width | | icon | string | - | Bootstrap icon class name | | onClick | function | - | Click event handler |

Card

Flexible card container for content grouping.

import { Card } from '@imc0nt0/mirror';

// Basic card
<Card>
  <h2>Card Title</h2>
  <p>Card content goes here...</p>
</Card>

// Interactive card
<Card hoverable onClick={handleClick}>
  <h2>Clickable Card</h2>
</Card>

// No padding card
<Card noPadding>
  <img src="image.jpg" alt="Full width image" />
</Card>

Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | hoverable | boolean | false | Enable hover effect | | noPadding | boolean | false | Remove internal padding | | onClick | function | - | Click event handler |

TextField

Enhanced text input with advanced styling and validation.

import { TextField } from '@imc0nt0/mirror';

// Basic usage
<TextField 
  label="Full Name"
  placeholder="Enter your full name"
  value={name}
  onChange={setName}
/>

// With validation
<TextField 
  label="Email"
  type="email"
  value={email}
  onChange={setEmail}
  error={emailError}
  fullWidth
/>

// Disabled state
<TextField 
  label="Read Only"
  value="Cannot edit this"
  disabled
/>

Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | label | string | - | Input label text | | placeholder | string | - | Placeholder text | | value | string | - | Input value | | onChange | function | - | Change event handler | | error | string | - | Error message to display | | disabled | boolean | false | Disable input interaction | | fullWidth | boolean | false | Make input full width | | type | string | 'text' | HTML input type |

Features:

  • Smooth hover background transition (#fafbfc)
  • Border color changes on hover (#d4f1fd)
  • Focus highlight border (#b8e8fd)
  • Optimized for performance (no motion effects)

IconButton

Icon-only button component using Bootstrap Icons.

import { IconButton } from '@imc0nt0/mirror';

// Basic usage
<IconButton icon="bi-heart-fill" variant="primary" />
<IconButton icon="bi-trash-fill" variant="danger" />
<IconButton icon="bi-search" variant="ghost" size="small" />

// Custom styling
<IconButton 
  icon="bi-settings" 
  variant="secondary"
  size="large"
  rounded={false}
  onClick={handleSettings}
/>

Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | icon | string | - | Bootstrap Icons class name (e.g., 'bi-heart-fill') | | variant | 'primary' \| 'secondary' \| 'ghost' \| 'danger' | 'ghost' | Button style variant | | size | 'small' \| 'medium' \| 'large' | 'medium' | Button size | | disabled | boolean | false | Disable button interaction | | rounded | boolean | true | Use fully rounded shape | | onClick | function | - | Click event handler |

Variants:

  • primary: Light blue background (#b8e8fd)
  • secondary: Light purple background (#f4f4fe)
  • ghost: White background with gray hover effect
  • danger: Transparent background with red icon

ListRow

Flexible list item component for creating structured lists and menus.

import { ListRow, ColorBlock, ListSection } from '@imc0nt0/mirror';

// Basic row with color indicator
<ListRow
  left={<ColorBlock color="#ff6b6b" />}
  title="List Item"
  description="Item description"
  showArrow
  onClick={() => console.log('Clicked')}
/>

// Row with icon and switch
<ListRow
  left={<i className="bi bi-bell-fill"></i>}
  title="Notification Settings"
  right={<Switch />}
/>

// Grouped in section
<ListSection title="Card Management">
  <ListRow title="Credit Card 1" showArrow />
  <ListRow title="Credit Card 2" showArrow />
  <ListRow title="Debit Card 1" showArrow />
</ListSection>

ListRow Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | left | ReactNode | - | Left content (icons, color blocks, etc.) | | title | string | - | Required. Main title text | | description | string | - | Optional description text | | right | ReactNode | - | Right content (icons, switches, text, etc.) | | showArrow | boolean | false | Show right navigation arrow | | divider | boolean | true | Show bottom divider line | | onClick | function | - | Click event handler | | disabled | boolean | false | Disable interaction |

ColorBlock Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | color | string | '#b8e8fd' | Background color | | size | number | 44 | Size in pixels |

ListSection Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | title | string | - | Section title | | children | ReactNode | - | ListRow components |

Toast

Non-blocking notification system with automatic dismissal and animations.

ToastProvider (Recommended)

Declare once at the top level of your app:

import { ToastProvider, useToast } from '@imc0nt0/mirror';

function App() {
  return (
    <ToastProvider>
      <YourApp />
    </ToastProvider>
  );
}

function YourApp() {
  const toast = useToast();

  const handleClick = () => {
    toast.success('Operation completed successfully!');
    toast.error('Something went wrong!');
    toast.warning('Please check your input!');
    toast.info('New update available!');
  };

  return <button onClick={handleClick}>Show Toast</button>;
}

useToast Hook:

  • success(message, options) - Success notification
  • error(message, options) - Error notification
  • warning(message, options) - Warning notification
  • info(message, options) - Info notification
  • showToast(options) - Custom notification
    toast.showToast({
      message: 'Custom message',
      type: 'success',
      position: 'top',
      duration: 5000
    });

Options: | Option | Type | Default | Description | |--------|------|---------|-------------| | position | 'top' \| 'center' \| 'bottom' | 'bottom' | Toast position | | duration | number | 3000 | Display duration in milliseconds |

Features:

  • Single Toast Display - New toast replaces the previous one instantly
  • Type-based Icons & Colors - Automatic icon and color assignment
  • Smooth Animations - Animation plays for each new toast

Icons:

  • Success: bi-check-circle-fill (Check circle)
  • Error: bi-x-circle-fill (X circle)
  • Warning: bi-exclamation-triangle-fill (Warning triangle)
  • Info: bi-info-circle-fill (Info circle)

Animation System:

  • Spring-based bounce effects
  • Icon rotation + scale animation
  • Text fade-in + slide animation
  • Unique animations for each display (using unique keys)

Toast Component (Direct Usage)

For individual usage without the provider:

import { Toast } from '@imc0nt0/mirror';

<Toast
  message="Operation completed!"
  type="success"
  position="top"
  duration={3000}
  isOpen={isToastOpen}
  onClose={() => setIsToastOpen(false)}
/>

Toast Component Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | message | string | - | Required. Toast message | | type | 'success' \| 'error' \| 'warning' \| 'info' | - | Toast type | | position | 'top' \| 'center' \| 'bottom' | 'bottom' | Display position | | duration | number | 3000 | Duration in milliseconds | | isOpen | boolean | - | Required. Toast visibility | | onClose | function | - | Required. Close callback |

Modal

Modal dialog component with normal and confirmation variants.

import { Modal, useModal } from '@imc0nt0/mirror';

function App() {
  const { isOpen, openModal, closeModal } = useModal();

  return (
    <div>
      <button onClick={openModal}>Open Modal</button>
      
      {/* Normal Modal */}
      <Modal
        isOpen={isOpen}
        onClose={closeModal}
        title="Notification"
        type="normal"
      >
        <p>This is the modal content.</p>
      </Modal>

      {/* Confirmation Modal */}
      <Modal
        isOpen={isOpen}
        onClose={closeModal}
        title="Delete Confirmation"
        type="confirm"
        confirmText="Delete"
        cancelText="Cancel"
        onConfirm={() => console.log('Deleted')}
      >
        <p>Are you sure you want to delete this item?</p>
      </Modal>
    </div>
  );
}

Modal Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | isOpen | boolean | - | Required. Modal visibility | | onClose | function | - | Required. Close callback | | title | string | - | Modal title | | children | ReactNode | - | Modal content | | type | 'normal' \| 'confirm' | 'normal' | Modal type | | confirmText | string | 'Confirm' | Confirm button text | | cancelText | string | 'Cancel' | Cancel button text | | onConfirm | function | - | Confirm button callback (confirm type only) | | showCloseButton | boolean | true | Show X close button |

Features:

  • ESC key to close - Press escape to dismiss
  • Click outside to close - Click overlay to dismiss
  • Scroll prevention - Body scroll disabled when modal is open
  • Spring animations - Smooth enter/exit transitions

useModal Hook: | Method | Type | Description | |--------|------|-------------| | isOpen | boolean | Modal open state | | openModal() | function | Open the modal | | closeModal() | function | Close the modal |

🎬 Animation System

Mirror provides a comprehensive animation system built on Framer Motion with predefined motion presets.

Motion Presets

Pre-defined animations for common use cases.

import { Animate, AnimateOnView, AnimateStagger, motions } from '@imc0nt0/mirror';

// Basic animations
<Animate motion="fadeIn">
  <div>Fade in animation</div>
</Animate>

<Animate motion="slideUp" delay={0.2}>
  <div>Slide up with delay</div>
</Animate>

Available Motion Presets:

  • fadeIn, fadeOut - Fade effects
  • slideUp, slideDown, slideLeft, slideRight - Slide effects
  • scaleIn, scaleOut, scaleBounce - Scale effects
  • rotateIn - Rotation effects
  • blurIn - Blur effects
  • entrance - Combined slide + fade + blur effect
  • pop - Pop effect with bounce

AnimateOnView

Trigger animations when elements enter the viewport.

<AnimateOnView motion="slideUp" once={true}>
  <div>Appears when scrolled into view</div>
</AnimateOnView>

<AnimateOnView motion="fadeIn" delay={0.3} amount={0.5}>
  <div>Animated after 50% is visible</div>
</AnimateOnView>

Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | motion | string | - | Motion preset name | | delay | number | 0 | Animation delay in seconds | | once | boolean | true | Animate only once | | amount | number | 0.3 | Visibility threshold (0-1) |

AnimateStagger

Animate child elements sequentially with staggered delays.

<AnimateStagger motion="fadeIn" staggerDelay={0.1}>
  {items.map(item => (
    <div key={item.id}>{item.name}</div>
  ))}
</AnimateStagger>

<AnimateStagger motion="slideUp" staggerDelay={0.05}>
  <Card>First card</Card>
  <Card>Second card</Card>
  <Card>Third card</Card>
</AnimateStagger>

Props: | Prop | Type | Default | Description | |------|------|---------|-------------| | motion | string | - | Motion preset name | | staggerDelay | number | 0.1 | Delay between child animations (seconds) |

useAnimation Hook

Programmatically control animations with advanced sequencing.

import { useAnimation, motions } from '@imc0nt0/mirror';

function MyComponent() {
  const { scope, play, serial, parallel, stagger, timeline } = useAnimation();
  
  const handleClick = async () => {
    // Single execution
    await play('.target', motions.fadeIn);
    
    // Sequential execution
    await serial([
      { target: '.item1', motion: motions.fadeIn },
      { target: '.item2', motion: motions.slideUp },
    ]);
    
    // Parallel execution
    await parallel([
      { target: '.item1', motion: motions.fadeIn },
      { target: '.item2', motion: motions.fadeIn },
    ]);
    
    // Staggered execution
    await stagger([
      { target: '.item1', motion: motions.fadeIn },
      { target: '.item2', motion: motions.fadeIn },
    ], 0.1);
    
    // Timeline composition
    await timeline([
      { type: 'parallel', animations: [
        { target: '.header', motion: motions.slideDown },
        { target: '.sidebar', motion: motions.slideLeft }
      ]},
      { type: 'wait', duration: 0.5 },
      { type: 'serial', animations: [
        { target: '.content', motion: motions.fadeIn },
        { target: '.footer', motion: motions.slideUp }
      ]},
    ]);
  };
  
  return (
    <div ref={scope}>
      <div className="target">Animation target</div>
      <button onClick={handleClick}>Start Animation</button>
    </div>
  );
}

Methods: | Method | Description | |--------|-------------| | play(target, motion, options) | Execute single motion | | serial(animations) | Execute animations sequentially | | parallel(animations) | Execute animations simultaneously | | stagger(animations, delayBetween) | Execute with staggered delays | | timeline(sequence) | Execute complex timeline |

Custom Motions

Create your own motion definitions for specific use cases.

import { createMotion, easings } from '@imc0nt0/mirror';

// Define custom motion
const customMotion = createMotion({
  from: { opacity: 0, y: 20, scale: 0.9 },
  to: { opacity: 1, y: 0, scale: 1 },
  duration: 0.6,
  ease: easings.toss,
});

// Use custom motion
<Animate motion={customMotion}>
  <div>Custom animation</div>
</Animate>

// Complex custom motion
const complexMotion = createMotion({
  from: { 
    opacity: 0, 
    rotate: -180, 
    scale: 0.5,
    filter: "blur(10px)" 
  },
  to: { 
    opacity: 1, 
    rotate: 0, 
    scale: 1,
    filter: "blur(0px)" 
  },
  duration: 0.8,
  ease: easings.springBouncy,
});

Available Easing Functions:

  • Linear: linear
  • Standard: ease, easeIn, easeOut, easeInOut
  • Spring: spring, springBouncy, springSoft
  • Special: toss, smooth, bounce, anticipate

Motion Composition

Combine multiple motion presets for complex animations.

import { combineMotions, motions } from '@imc0nt0/mirror';

// Combine fade and slide effects
const fadeSlideMotion = combineMotions(
  motions.fadeIn,
  motions.slideUp
);

// Combine multiple effects
const complexMotion = combineMotions(
  motions.scaleIn,
  motions.rotateIn,
  motions.fadeIn
);

// Use combined motion
<Animate motion={fadeSlideMotion}>
  <div>Combined animation effect</div>
</Animate>

📚 Advanced Usage

Performance Optimization

Mirror is optimized for performance with several built-in features:

  • Tree Shaking: Import only the components you need
  • Lazy Loading: Components are loaded on demand
  • Motion Optimization: Animations use GPU acceleration when possible
  • Bundle Size: Minimal overhead with efficient bundling
// Import only what you need
import { Button, TextField } from '@imc0nt0/mirror';

// Instead of importing everything
// import * as Mirror from '@imc0nt0/mirror'; // ❌ Don't do this

Theming & Customization

Override default styles using CSS variables:

:root {
  --mirror-primary: #your-primary-color;
  --mirror-secondary: #your-secondary-color;
  --mirror-border-radius: 8px;
  --mirror-font-family: 'Your Font', sans-serif;
}

Accessibility

All Mirror components follow WCAG 2.1 guidelines:

  • Keyboard Navigation: Full keyboard support
  • Screen Readers: Proper ARIA labels and descriptions
  • Focus Management: Visible focus indicators
  • Color Contrast: AA compliant color ratios

🛠️ Development

Prerequisites

  • Node.js 16+
  • React 18+
  • TypeScript 4.5+ (optional but recommended)

Peer Dependencies

{
  "react": ">=18.0.0",
  "react-dom": ">=18.0.0", 
  "framer-motion": ">=10.0.0",
  "bootstrap-icons": ">=1.10.0"
}

📝 Changelog

See CHANGELOG.md for version history.

🐛 Issues & Support

📄 License

MIT License - see the LICENSE file for details.


Made with ❤️ by the HOSHLAB IN KOREA