a React component library inspired by Valorant's UI design aesthetic.
  • TypeScript 93.6%
  • CSS 6.1%
  • HTML 0.3%
Find a file
Cyril Leblanc 3cf60d4370 Fix ProgressBar hydration mismatch by initializing with real value
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 22:07:43 +02:00
dev Add Vite dev playground for live component preview 2026-04-19 14:24:41 +02:00
dist Fix ProgressBar hydration mismatch by initializing with real value 2026-04-19 22:07:43 +02:00
src Fix ProgressBar hydration mismatch by initializing with real value 2026-04-19 22:07:43 +02:00
.gitignore Fix remaining border shorthand conflicts in Modal and Stat 2026-04-19 22:03:19 +02:00
LICENSE first commit 2026-04-19 13:26:58 +02:00
package-lock.json Add Vite dev playground for live component preview 2026-04-19 14:24:41 +02:00
package.json Add Vite dev playground for live component preview 2026-04-19 14:24:41 +02:00
README.md first commit 2026-04-19 13:26:58 +02:00
tsconfig.json first commit 2026-04-19 13:26:58 +02:00
tsup.config.ts first commit 2026-04-19 13:26:58 +02:00
vite.config.ts Add Vite dev playground for live component preview 2026-04-19 14:24:41 +02:00

React 18+ shadcn/ui TypeScript MIT License

🔫 VALORANT-UI

Valorant-inspired component library for React + shadcn/ui
Angular clip-paths · Scan-line effects · Glitch animations · Red / Cyan / Gold palette

Components Zero Dependencies Tree-Shakeable


Features

  • 🎨 20+ components — Buttons, Cards, Tables, Modals, Alerts, Badges, Inputs, Toggles, Tabs, Tooltips, Toasts, and more
  • 🔷 Angular clip-paths — Skewed buttons, cut-corner cards, Valorant-style UI shapes
  • 📺 Scan effects — CRT scan-lines overlay + periodic scan beam
  • Glitch text — Randomized glitch distortion with cyan/red offsets
  • 🌈 Full color system — Red, Cyan, Gold, Green, Purple — all as CSS variables
  • 🔤 Typography — Rajdhani (display), Barlow Condensed (labels), Barlow (body)
  • 📱 Responsive — Mobile-first with drawer nav, breakpoint hook, adaptive grids
  • 🧩 shadcn/ui compatible — CSS variables map directly to shadcn tokens
  • 🌳 Tree-shakeable — Import only what you need
  • 📦 Zero runtime dependencies — Only react and react-dom as peer deps
  • 🔑 Fully typed — TypeScript with exported types for every component

📦 Installation

# npm
npm install valorant-ui

# yarn
yarn add valorant-ui

# pnpm
pnpm add valorant-ui

# bun
bun add valorant-ui

Peer dependencies: react >= 18.0.0 and react-dom >= 18.0.0


🚀 Quick Start

1. Import the global styles

Add the Valorant CSS variables and keyframes to your app. If you're using shadcn/ui, place this before your main CSS:

/* app/globals.css (or tailwind.css) */

/* Option A: Import the full theme file */
@import "valorant-ui/styles";

/* Option B: Copy-paste the :root block from src/styles/globals.css */

2. Use components

import {
  Btn,
  Badge,
  Card,
  Alert,
  Modal,
  Input,
  Toggle,
  ProgressBar,
  Table,
  AgentCard,
  Section,
  GlitchText,
  ScanLines,
  ScanBeam,
  ToastContainer,
  useToast,
} from "valorant-ui";

function App() {
  const { toasts, add, dismiss } = useToast();

  return (
    <>
      {/* Ambient effects */}
      <ScanLines />
      <ScanBeam />

      {/* Toast notifications */}
      <ToastContainer toasts={toasts} dismiss={dismiss} />

      <div style={{ padding: 32 }}>
        <GlitchText size={48} color="#FF4655">
          DEFUSE THE SITE
        </GlitchText>

        <div style={{ display: "flex", gap: 10, marginTop: 16 }}>
          <Btn variant="primary" onClick={() =>
            add({ title: "MATCH FOUND", message: "10/10 accepted", variant: "success" })
          }>
            FIND MATCH
          </Btn>
          <Btn variant="outline">VIEW DETAILS</Btn>
          <Btn variant="ghost">CANCEL</Btn>
        </div>

        <Badge variant="green" dot pulse style={{ marginTop: 16 }}>ONLINE</Badge>
      </div>
    </>
  );
}

🧩 Components

Atoms

Component Description
VLabel Small uppercase label (Barlow Condensed)
VTitle Bold uppercase heading (Rajdhani)
Divider Horizontal separator line
Glow Radial glow effect for backgrounds

Effects

Component Description
GlitchText Text with periodic glitch distortion
ScanLines CRT-style scan-line overlay
ScanBeam Periodic vertical cyan scan beam

UI

Component Description
Btn Button with 7 variants + 4 sizes + shimmer hover
Badge Status pill with 7 color variants + dot + pulse
Input Text input with focus glow, icon, error state
Select Custom dropdown with animated open state
Tooltip Hover tooltip (top/bottom/right)
Toggle Animated switch with glow
Checkbox Checkbox with glow on checked
ProgressBar Animated bar with glow tip
Tabs Tab switcher (line / pill variants)

Feedback

Component Description
Modal Dialog with cut-corner shape + Escape dismiss
Alert Alert banner (error/warning/success/info)
ToastContainer + useToast() Toast notification system (auto-dismiss 4s)

Layout

Component Description
Card Content card with colored accent + hover glow
Stat Stat card with value, delta %, label
Table Sortable data table with hover highlight
AgentCard Compact agent card with avatar + selection
Section Section wrapper with accent bar + divider

Navigation

Component Description
DrawerNav Mobile slide-in drawer navigation

Hooks

Hook Description
useBreakpoint() Returns { w, isMobile, isTablet, isDesktop }
useToast() Returns { toasts, add, dismiss } for toast notifications

🎨 Design Tokens

All tokens are available as CSS variables (for shadcn/ui) and as JS constants:

import { colors, clip, clipCard, shadows, ease } from "valorant-ui";

// Colors
colors.red      // "#FF4655"
colors.cyan     // "#00D4FF"
colors.gold     // "#C89B3C"
colors.surface  // "#152230"
colors.border   // "#243B52"

// Clip-paths
clip(8)         // "polygon(8px 0%, 100% 0%, calc(100% - 8px) 100%, 0% 100%)"
clipCard(14)    // "polygon(0 0, calc(100% - 14px) 0, 100% 14px, ...)"

// Shadows
shadows.red     // "0 0 20px hsl(354 100% 63% / 0.3)"

// Easing
ease.val        // "cubic-bezier(0.16, 1, 0.3, 1)"

CSS Variables (for shadcn/ui)

:root {
  --primary:          354 100% 63%;   /* Valorant Red  #FF4655 */
  --secondary:        193 100% 50%;   /* Valorant Cyan  #00D4FF */
  --accent:           40 56% 51%;     /* Gold           #C89B3C */
  --success:          159 100% 45%;   /* Green          #00E5A0 */
  --destructive:      354 100% 63%;
  --background:       210 35% 8%;
  --foreground:       200 20% 93%;
  --card:             210 40% 14%;
  --border:           210 38% 24%;
  --radius:           0px;            /* Angular! No rounded corners */
  --font-display:     'Rajdhani', sans-serif;
  --font-label:       'Barlow Condensed', sans-serif;
  --font-body:        'Barlow', sans-serif;
  --clip-md:          polygon(8px 0%, 100% 0%, calc(100% - 8px) 100%, 0% 100%);
  --clip-card:        polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 14px 100%, 0 calc(100% - 14px));
  --ease-val:         cubic-bezier(0.16, 1, 0.3, 1);
}

📖 API Reference

<Btn>

<Btn
  variant="primary"    // "primary" | "outline" | "ghost" | "cyan" | "gold" | "danger" | "success"
  size="md"            // "sm" | "md" | "lg" | "xl"
  disabled={false}
  fullWidth={false}
  icon={<span></span>}
  onClick={() => {}}
>
  FIND MATCH
</Btn>

<Badge>

<Badge variant="red" dot pulse>LIVE</Badge>
// variant: "red" | "cyan" | "gold" | "green" | "purple" | "muted" | "white"

<Modal>

const [open, setOpen] = useState(false);

<Modal
  open={open}
  onClose={() => setOpen(false)}
  title="FIND MATCH"
  footer={
    <>
      <Btn variant="ghost" onClick={() => setOpen(false)}>CANCEL</Btn>
      <Btn onClick={() => setOpen(false)}>CONFIRM</Btn>
    </>
  }
>
  <p>Modal content here</p>
</Modal>

<Alert>

<Alert
  variant="error"        // "error" | "warning" | "success" | "info"
  title="Connection Lost"
  message="Reconnecting to server..."
  dismissible
  onDismiss={() => {}}
/>

<Table>

<Table
  columns={[
    { key: "map",    label: "Map",  sortable: true },
    { key: "result", label: "Result", render: (row) => <Badge variant="green">{row.result}</Badge> },
    { key: "score",  label: "Score", align: "center" },
  ]}
  rows={[
    { map: "ASCENT", result: "WIN", score: "13-7" },
    { map: "HAVEN",  result: "LOSS", score: "9-13" },
  ]}
/>

<AgentCard>

<AgentCard
  name="JETT"
  role="Duelist"
  rank="S-TIER"
  color="#00D4FF"
  initials="JT"
  selected={true}
  onClick={() => {}}
/>

useToast()

const { toasts, add, dismiss } = useToast();

add({ title: "MATCH FOUND", message: "10 players accepted", variant: "success" });
add({ title: "ERROR", variant: "error" });

useBreakpoint()

const { w, isMobile, isTablet, isDesktop } = useBreakpoint();

// isMobile  → w < 640
// isTablet  → w >= 640 && w < 1024
// isDesktop → w >= 1024

🎬 Animations

All keyframes are included in the CSS and ready to use:

Animation Usage
val-scan Scan beam vertical sweep
val-glitch Glitch text distortion (layer 1)
val-glitch2 Glitch text distortion (layer 2)
val-ping Pulsing dot (badge dot)
val-slide-in Slide from right (toasts, alerts)
val-fade-up Fade + translate up (dropdowns, modals)
val-shimmer Shimmer sweep (button hover)
val-drawer-in Slide from left (drawer nav)
.your-element {
  animation: val-fade-up 0.2s ease forwards;
}

🏗️ Project Structure

valorant-ui/
├── src/
│   ├── components/
│   │   ├── atoms/          # VLabel, VTitle, Divider, Glow
│   │   ├── effects/        # GlitchText, ScanLines, ScanBeam
│   │   ├── ui/             # Btn, Badge, Input, Select, Tooltip, Toggle, Checkbox, ProgressBar, Tabs
│   │   ├── feedback/       # Modal, Alert, ToastContainer, useToast
│   │   ├── layout/         # Card, Stat, Table, AgentCard, Section
│   │   └── navigation/     # DrawerNav
│   ├── hooks/              # useBreakpoint
│   ├── styles/
│   │   └── globals.css     # CSS variables + keyframes + reset
│   ├── tokens/
│   │   └── index.ts        # JS color tokens + clip-path helpers
│   ├── types/
│   │   └── index.ts        # TypeScript interfaces for all props
│   └── index.ts            # Barrel export
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── LICENSE
└── README.md

🛠️ Development

# Install dependencies
npm install

# Watch mode (rebuild on change)
npm run dev

# Production build
npm run build

# Lint
npm run lint

🔧 Integration with shadcn/ui

This library is designed to work alongside shadcn/ui. The CSS variables follow the same naming convention:

  1. Import valorant-ui/styles in your globals.css
  2. The :root variables will override shadcn/ui defaults
  3. shadcn/ui components automatically inherit the Valorant theme
/* your app/globals.css */
@import "valorant-ui/styles";
@tailwind base;
@tailwind components;
@tailwind utilities;

Note: Valorant UI uses --radius: 0px for angular shapes. If you want rounded corners on specific shadcn components, override locally.


📄 License

MIT — Free for personal and commercial use.


⚠️ Disclaimer

This project is not affiliated with, endorsed by, or connected to Riot Games. Valorant and all related assets are trademarks of Riot Games, Inc. This is a fan-made design system for educational and creative purposes.