Skip to content

DanTsk/scape-css

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎨 scape

Build-time CSS-in-JS library with powerful variants and compound variants support

MIT License TypeScript Zero Runtime

Zero-runtime styling solution that extracts your CSS at build time while maintaining full type safety and dynamic capabilities where you need them.

✨ Features

πŸš€ Zero Runtime Overhead - CSS is extracted at build time
🎯 Type-Safe Variants - Full TypeScript support for variants and compound variants
⚑ Dynamic Properties - Support for runtime dynamic styles when needed
πŸ”₯ Powerful Variants System - Simple variants and complex compound variants
πŸ› οΈ Build-Time Optimized - Minimal JavaScript bundle size
🎨 CSS-in-JS DX - Familiar API with modern developer experience
πŸ“¦ Framework Agnostic - Works with React (more frameworks coming soon)

πŸš€ Quick Start

Installation

npm install @scape-css/react @scape-css/compiler
# or
pnpm add @scape-css/react @scape-css/compiler

Basic Usage

import { styled } from '@scape-css/react';

const Button = styled('button', {
  backgroundColor: 'blue',
  color: 'white',
  padding: '8px 16px',
  borderRadius: '4px',
  border: 'none',
  cursor: 'pointer',
  
  '&:hover': {
    backgroundColor: 'darkblue',
  },
});

function App() {
  return <Button>Click me!</Button>;
}

🎯 Variants System

Simple Variants

Create multiple style variations for your components:

const Button = styled('button', {
  // Base styles
  padding: '8px 16px',
  borderRadius: '4px',
  border: 'none',
  cursor: 'pointer',
  
  variants: {
    intent: {
      primary: {
        backgroundColor: 'blue',
        color: 'white',
      },
      secondary: {
        backgroundColor: 'gray',
        color: 'black',
      },
      danger: {
        backgroundColor: 'red',
        color: 'white',
      },
    },
    size: {
      small: {
        padding: '4px 8px',
        fontSize: '12px',
      },
      medium: {
        padding: '8px 16px',
        fontSize: '14px',
      },
      large: {
        padding: '12px 24px',
        fontSize: '16px',
      },
    },
  },
});

// Usage with full type safety
<Button intent="primary" size="large">
  Primary Large Button
</Button>

Compound Variants

Handle complex styling combinations with compound variants:

const Button = styled('button', {
  // Base styles
  padding: '8px 16px',
  borderRadius: '4px',
  border: 'none',
  cursor: 'pointer',
  
  variants: {
    intent: {
      primary: { backgroundColor: 'blue', color: 'white' },
      secondary: { backgroundColor: 'gray', color: 'black' },
    },
    size: {
      small: { padding: '4px 8px', fontSize: '12px' },
      large: { padding: '12px 24px', fontSize: '16px' },
    },
    disabled: {
      true: { opacity: 0.5, cursor: 'not-allowed' },
      false: {},
    },
  },
  
  // Compound variants for specific combinations
  compoundVariants: [
    {
      intent: 'primary',
      size: 'large',
      css: {
        boxShadow: '0 4px 8px rgba(0, 0, 255, 0.3)',
        fontWeight: 'bold',
      },
    },
    {
      intent: 'secondary',
      disabled: true,
      css: {
        backgroundColor: '#f5f5f5',
        color: '#999',
      },
    },
  ],
});

// The compound variant styles are automatically applied
<Button intent="primary" size="large">
  // Gets primary + large + compound variant styles
</Button>

πŸ”₯ Dynamic Properties

While scape optimizes for build-time extraction, it supports dynamic properties when you need runtime flexibility:

const Card = styled('div', {
  padding: '16px',
  borderRadius: '8px',
  backgroundColor: 'white',
  boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
});

// Dynamic styles are handled at runtime
function DynamicCard({ color }: { color: string }) {
  return (
    <Card style={{ borderLeft: `4px solid ${color}` }}>
      Dynamic colored border
    </Card>
  );
}

πŸ› οΈ How It Works

Scape uses a sophisticated build-time compiler that:

  1. Parses your styled components during build
  2. Extracts CSS styles into static stylesheets
  3. Generates optimized class names and runtime helpers
  4. Transforms your code to use the generated classes
  5. Preserves type safety throughout the process
// What you write:
const Button = styled('button', {
  backgroundColor: 'blue',
  variants: {
    size: {
      small: { padding: '4px' },
      large: { padding: '8px' }
    }
  }
});

// What gets generated:
// CSS: .btn-abc123 { background-color: blue; }
//      .btn-small-def456 { padding: 4px; }
//      .btn-large-ghi789 { padding: 8px; }
// 
// JS: Optimized runtime with minimal overhead

πŸ“¦ Packages

Package Description
@scape-css/react React bindings and runtime
@scape-css/compiler Build-time compiler and transformer
@scape-css/webpack-loader Webpack integration
@scape-css/swc-parser SWC-based parser for optimal performance

βš™οΈ Setup

Webpack Configuration

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/,
        use: [
          {
            loader: '@scape-css/webpack-loader',
            options: {
              // Configuration options
            },
          },
          // Your other loaders (ts-loader, etc.)
        ],
      },
    ],
  },
};

Vite Configuration

// vite.config.ts
import { defineConfig } from 'vite';
import { scapePlugin } from '@scape-css/vite-plugin';

export default defineConfig({
  plugins: [
    scapePlugin({
      // Configuration options
    }),
  ],
});

🎨 Advanced Examples

Responsive Design

const Container = styled('div', {
  padding: '16px',
  
  '@media (min-width: 768px)': {
    padding: '32px',
  },
  
  '@media (min-width: 1024px)': {
    padding: '48px',
  },
});

Complex Nested Selectors

const Navigation = styled('nav', {
  '& ul': {
    listStyle: 'none',
    margin: 0,
    padding: 0,
  },
  
  '& li': {
    display: 'inline-block',
    
    '& a': {
      color: 'blue',
      textDecoration: 'none',
      
      '&:hover': {
        textDecoration: 'underline',
      },
    },
  },
});

Theme Integration

const theme = {
  colors: {
    primary: '#007bff',
    secondary: '#6c757d',
  },
  spacing: {
    sm: '8px',
    md: '16px',
    lg: '24px',
  },
};

const ThemedButton = styled('button', {
  backgroundColor: theme.colors.primary,
  padding: `${theme.spacing.sm} ${theme.spacing.md}`,
  color: 'white',
  border: 'none',
  borderRadius: '4px',
});

πŸš€ Performance

Bundle Size Impact

  • Base runtime: ~2KB gzipped
  • Per component: ~50-100 bytes additional
  • CSS extraction: Styles are moved to CSS files, reducing JS bundle size

Build Performance

  • SWC-powered: Leverages SWC for ultra-fast parsing
  • Incremental: Only reprocesses changed files
  • Parallel: Supports parallel processing for large codebases

πŸ” Comparison

Feature scape styled-components emotion stitches
Runtime Size ~2KB ~15KB ~7KB ~5KB
Build-time CSS βœ… ❌ ❌ βœ…
Variants βœ… Manual Manual βœ…
Compound Variants βœ… Manual Manual βœ…
TypeScript βœ… βœ… βœ… βœ…
SSR βœ… βœ… βœ… βœ…

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/DanTsk/scape.git
cd scape

# Install dependencies
pnpm install

# Run tests
pnpm test

# Build packages
pnpm build

πŸ“„ License

MIT Β© Dan T.


Documentation β€’ Examples β€’ Discord β€’ Twitter

Made with ❀️ for the React community

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors