Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
AI-powered UI styling skill with 67 UI styles and 161 reasoning rules for professional interface design.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/shadcn_add.py
1#!/usr/bin/env python32"""3shadcn/ui Component Installer45Add shadcn/ui components to project with automatic dependency handling.6Wraps shadcn CLI for programmatic component installation.7"""89import argparse10import json11import subprocess12import sys13from pathlib import Path14from typing import List, Optional151617class ShadcnInstaller:18"""Handle shadcn/ui component installation."""1920def __init__(self, project_root: Optional[Path] = None, dry_run: bool = False):21"""22Initialize installer.2324Args:25project_root: Project root directory (default: current directory)26dry_run: If True, show actions without executing27"""28self.project_root = project_root or Path.cwd()29self.dry_run = dry_run30self.components_json = self.project_root / "components.json"3132def check_shadcn_config(self) -> bool:33"""34Check if shadcn is initialized in project.3536Returns:37True if components.json exists38"""39return self.components_json.exists()4041def get_installed_components(self) -> List[str]:42"""43Get list of already installed components.4445Returns:46List of installed component names47"""48if not self.check_shadcn_config():49return []5051try:52with open(self.components_json) as f:53config = json.load(f)5455components_dir = self.project_root / config.get("aliases", {}).get(56"components", "components"57).replace("@/", "")58ui_dir = components_dir / "ui"5960if not ui_dir.exists():61return []6263return [f.stem for f in ui_dir.glob("*.tsx") if f.is_file()]64except (json.JSONDecodeError, KeyError, OSError):65return []6667def add_components(68self, components: List[str], overwrite: bool = False69) -> tuple[bool, str]:70"""71Add shadcn/ui components.7273Args:74components: List of component names to add75overwrite: If True, overwrite existing components7677Returns:78Tuple of (success, message)79"""80if not components:81return False, "No components specified"8283if not self.check_shadcn_config():84return (85False,86"shadcn not initialized. Run 'npx shadcn@latest init' first",87)8889# Check which components already exist90installed = self.get_installed_components()91already_installed = [c for c in components if c in installed]9293if already_installed and not overwrite:94return (95False,96f"Components already installed: {', '.join(already_installed)}. "97"Use --overwrite to reinstall",98)99100# Build command101cmd = ["npx", "shadcn@latest", "add"] + components102103if overwrite:104cmd.append("--overwrite")105106if self.dry_run:107return True, f"Would run: {' '.join(cmd)}"108109# Execute command110try:111result = subprocess.run(112cmd,113cwd=self.project_root,114capture_output=True,115text=True,116check=True,117)118119success_msg = f"Successfully added components: {', '.join(components)}"120if result.stdout:121success_msg += f"\n\nOutput:\n{result.stdout}"122123return True, success_msg124125except subprocess.CalledProcessError as e:126error_msg = f"Failed to add components: {e.stderr or e.stdout or str(e)}"127return False, error_msg128except FileNotFoundError:129return False, "npx not found. Ensure Node.js is installed"130131def add_all_components(self, overwrite: bool = False) -> tuple[bool, str]:132"""133Add all available shadcn/ui components.134135Args:136overwrite: If True, overwrite existing components137138Returns:139Tuple of (success, message)140"""141if not self.check_shadcn_config():142return (143False,144"shadcn not initialized. Run 'npx shadcn@latest init' first",145)146147cmd = ["npx", "shadcn@latest", "add", "--all"]148149if overwrite:150cmd.append("--overwrite")151152if self.dry_run:153return True, f"Would run: {' '.join(cmd)}"154155try:156result = subprocess.run(157cmd,158cwd=self.project_root,159capture_output=True,160text=True,161check=True,162)163164success_msg = "Successfully added all components"165if result.stdout:166success_msg += f"\n\nOutput:\n{result.stdout}"167168return True, success_msg169170except subprocess.CalledProcessError as e:171error_msg = f"Failed to add all components: {e.stderr or e.stdout or str(e)}"172return False, error_msg173except FileNotFoundError:174return False, "npx not found. Ensure Node.js is installed"175176def list_installed(self) -> tuple[bool, str]:177"""178List installed components.179180Returns:181Tuple of (success, message with component list)182"""183if not self.check_shadcn_config():184return False, "shadcn not initialized"185186installed = self.get_installed_components()187188if not installed:189return True, "No components installed"190191return True, f"Installed components:\n" + "\n".join(f" - {c}" for c in sorted(installed))192193194def main():195"""CLI entry point."""196parser = argparse.ArgumentParser(197description="Add shadcn/ui components to your project",198formatter_class=argparse.RawDescriptionHelpFormatter,199epilog="""200Examples:201# Add single component202python shadcn_add.py button203204# Add multiple components205python shadcn_add.py button card dialog206207# Add all components208python shadcn_add.py --all209210# Overwrite existing components211python shadcn_add.py button --overwrite212213# Dry run (show what would be done)214python shadcn_add.py button card --dry-run215216# List installed components217python shadcn_add.py --list218""",219)220221parser.add_argument(222"components",223nargs="*",224help="Component names to add (e.g., button, card, dialog)",225)226227parser.add_argument(228"--all",229action="store_true",230help="Add all available components",231)232233parser.add_argument(234"--overwrite",235action="store_true",236help="Overwrite existing components",237)238239parser.add_argument(240"--dry-run",241action="store_true",242help="Show what would be done without executing",243)244245parser.add_argument(246"--list",247action="store_true",248help="List installed components",249)250251parser.add_argument(252"--project-root",253type=Path,254help="Project root directory (default: current directory)",255)256257args = parser.parse_args()258259# Initialize installer260installer = ShadcnInstaller(261project_root=args.project_root,262dry_run=args.dry_run,263)264265# Handle list command266if args.list:267success, message = installer.list_installed()268print(message)269sys.exit(0 if success else 1)270271# Handle add all command272if args.all:273success, message = installer.add_all_components(overwrite=args.overwrite)274print(message)275sys.exit(0 if success else 1)276277# Handle add specific components278if not args.components:279parser.print_help()280sys.exit(1)281282success, message = installer.add_components(283args.components,284overwrite=args.overwrite,285)286287print(message)288sys.exit(0 if success else 1)289290291if __name__ == "__main__":292main()293