kor-ui

SKILL.md

KorUI Library

KorUI (@korsolutions/ui) is a minimal-dependency, cross-platform UI library for React Native and Expo. Flexible components with beautiful default styling, compound component patterns, and comprehensive theming support.

Core Principles

  • Beautiful Defaults: Components ship with production-ready styling and a flexible variant system
  • Compound Components: All components follow Root + sub-component pattern
  • Variant System: Each component offers multiple style variants
  • Minimal Dependencies: Only React Native and Expo core dependencies
  • Full TypeScript Support: Complete type definitions for all components
  • Cross-Platform: iOS, Android, and Web support

Quick Start

Installation

npm install @korsolutions/ui
# or
yarn add @korsolutions/ui
# or
bun add @korsolutions/ui

Provider Setup

Wrap your application with UIProvider in your root layout:

import { UIProvider } from "@korsolutions/ui";
import { useSafeAreaInsets } from "react-native-safe-area-context";

export default function RootLayout() {
  const safeAreaInsets = useSafeAreaInsets();

  return (
    <UIProvider safeAreaInsets={safeAreaInsets}>
      <YourApp />
    </UIProvider>
  );
}

Basic Import Pattern

import { Button, Input, Card } from "@korsolutions/ui";

function MyComponent() {
  return (
    <Card.Root>
      <Card.Body>
        <Button onPress={() => console.log("Pressed")}>
          Click Me
        </Button>
      </Card.Body>
    </Card.Root>
  );
}

Your First Component

import { useState } from "react";
import { Button } from "@korsolutions/ui";

function SubmitButton() {
  const [loading, setLoading] = useState(false);

  const handleSubmit = async () => {
    setLoading(true);
    await submitForm();
    setLoading(false);
  };

  return (
    <Button variant="default" isLoading={loading} onPress={handleSubmit}>
      Submit
    </Button>
  );
}

Component Overview

Layout & Structure

Component Description Variants Reference
Card Content container with header, body, and footer default Layout Components
Separator Visual divider between content horizontal, vertical Layout Components
Portal Render components outside hierarchy - Layout Components
List Performance-optimized list rendering - Layout Components
Table Data table with header, body, rows, and cells default Layout Components
Sidebar Collapsible navigation sidebar with menu items default Layout Components

Form Inputs

Component Description Variants Reference
Input Text input field default Input Components
NumericInput Formatted numeric input (currency, percentage, etc.) default Input Components
PhoneInput Phone number input with country selector (E.164) default Input Components
Textarea Multi-line text input default Input Components
Checkbox Toggle selection with label default, outlined Input Components
RadioGroup Single selection from a group of options default, outlined Input Components
Select Dropdown selection from a list of options default Input Components
Combobox Generic autocomplete input with built-in filtering and item selection default Input Components
Field Form field wrapper with label and validation - Input Components

Display Components

Component Description Variants Reference
Typography Text with semantic variants heading, body (+ size: sm, md, lg) Display Components
Avatar User avatar with image and fallback default Display Components
Badge Status indicators and labels default, secondary, success, warning, danger, info Display Components
Icon Icon rendering with render prop pattern - Display Components
Empty Empty state placeholders default Display Components
Progress Linear progress indicators default Display Components

Interactive Components

Component Description Variants Reference
Button Action buttons with loading states default, secondary, ghost Interactive Components
IconButton Icon-only pressable button default, secondary, ghost Interactive Components
Tabs Tabbed navigation default, line Interactive Components
Menu Dropdown menus default Interactive Components
Popover Positioned overlay content default Interactive Components
Calendar Month date picker (compound) default Interactive Components
WeekCalendar Swipeable week strip with date selection default Interactive Components
CalendarTimeline Day timeline with generic event rendering default Interactive Components

Feedback Components

Component Description Variants Reference
Alert Inline notifications with icons default, destructive Feedback Components
AlertDialog Modal confirmation dialogs default Feedback Components
Toast Transient notifications default, success, danger Feedback Components

Compound Component Pattern

All KorUI components follow a compound component pattern where a parent component (usually Root) provides context to child sub-components.

Structure

<Component.Root {...rootProps}>
  <Component.SubComponent1 {...props} />
  <Component.SubComponent2 {...props} />
</Component.Root>

Common Sub-Components

Most components share similar sub-component naming:

  • Root - Parent container that provides context
  • Label - Text label for the component
  • Icon - Icon display with render prop pattern
  • Description - Secondary descriptive text
  • Title - Primary heading text
  • Body - Main content area
  • Header - Top section
  • Footer - Bottom section

Example: Button

<Button variant="default" onPress={handlePress} isLoading={loading}>
  Submit Form
</Button>

Example: Alert with Icon

import { AlertCircle } from "lucide-react-native";

<Alert.Root variant="destructive">
  <Alert.Icon render={AlertCircle} />
  <Alert.Body>
    <Alert.Title>Error</Alert.Title>
    <Alert.Description>Something went wrong</Alert.Description>
  </Alert.Body>
</Alert.Root>;

Example: Field with Input

<Field.Root>
  <Field.Label for="email">Email Address</Field.Label>
  <Input id="email" value={email} onChange={setEmail} placeholder="you@example.com" />
  <Field.Description>We'll never share your email.</Field.Description>
  {error && <Field.Error>{error}</Field.Error>}
</Field.Root>

Style Composition

Component styles are always composed with variant styles first, allowing user styles to override:

// Variant styles are applied first
<Button style={{ marginTop: 16 }}>
  Custom Button
</Button>

This ensures your custom styles always take precedence over variant defaults.

Theme System Basics

KorUI includes a comprehensive theming system with light/dark mode support.

Theme Tokens

The theme provides these customizable tokens:

  • colors - Color palette with light/dark schemes
  • radius - Border radius (default: 10)
  • fontSize - Base font size (default: 16)
  • fontFamily - Font family (default: "System")
  • letterSpacing - Letter spacing (default: 0)

Color Tokens

Each color scheme (light/dark) includes:

  • background - Main background color
  • foreground - Main text color
  • primary - Primary brand color
  • primaryForeground - Text on primary color
  • secondary - Secondary brand color
  • secondaryForeground - Text on secondary color
  • muted - Muted background color
  • mutedForeground - Muted text color
  • border - Border color
  • surface - Surface/card background
  • success, warning, danger, info - Semantic colors

Using the Theme

Access the theme in your components:

import { useTheme } from "@korsolutions/ui";

function MyComponent() {
  const theme = useTheme();

  return (
    <View
      style={{
        backgroundColor: theme.colors.background,
        borderRadius: theme.radius,
        padding: 16,
      }}
    >
      <Text
        style={{
          color: theme.colors.foreground,
          fontSize: theme.fontSize,
          fontFamily: theme.fontFamily,
        }}
      >
        Themed Content
      </Text>
    </View>
  );
}

Color Scheme

Toggle between light and dark mode:

const theme = useTheme();

// Get current scheme
console.log(theme.colorScheme); // "light" | "dark"

// Set color scheme
theme.setColorScheme("dark");

Quick Customization

Customize the theme via UIProvider:

<UIProvider
  theme={{
    radius: 12,
    fontSize: 18,
    colors: {
      light: {
        primary: "hsla(220, 90%, 56%, 1)",
        primaryForeground: "hsla(0, 0%, 100%, 1)",
      },
      dark: {
        primary: "hsla(220, 90%, 70%, 1)",
        primaryForeground: "hsla(0, 0%, 100%, 1)",
      },
    },
  }}
  safeAreaInsets={safeAreaInsets}
>
  <App />
</UIProvider>

For detailed theming documentation, see Theme Customization.

Common Patterns

Form Field with Validation

import { Field, Input } from "@korsolutions/ui";

<Field.Root>
  <Field.Label for="email">Email</Field.Label>
  <Input id="email" value={email} onChange={setEmail} placeholder="you@example.com" />
  <Field.Description>Enter your email address</Field.Description>
  {error && <Field.Error>{error}</Field.Error>}
</Field.Root>;

Icons with Render Prop

KorUI uses a render prop pattern for icons, supporting any icon library:

import { AlertCircle, CheckCircle } from "lucide-react-native";
import { Alert } from "@korsolutions/ui";

// With lucide-react-native
<Alert.Icon render={AlertCircle} />

// With custom function
<Alert.Icon render={(props) => <CheckCircle {...props} size={20} />} />

// With lucide-react-native
import { AlertCircle } from "lucide-react-native";
<Alert.Icon render={AlertCircle} />

Icon Button

A pressable button that renders a single icon. Uses the same render prop pattern as Icon:

import { IconButton } from "@korsolutions/ui";
import { Heart, Settings, Trash } from "lucide-react-native";

// Basic usage
<IconButton render={Heart} onPress={() => console.log("Liked")} />

// Variants (matches Button variants)
<IconButton render={Settings} variant="secondary" />
<IconButton render={Settings} variant="ghost" />

// Custom size and color
<IconButton render={Trash} size={32} color="red" />

// Disabled
<IconButton render={Heart} isDisabled />

Separator

A visual divider between content sections:

import { Separator } from "@korsolutions/ui";

// Horizontal (default)
<Separator />

// Vertical
<Separator variant="vertical" />

Controlled State Management

Most input components use controlled state:

import { useState } from "react";
import { Input, Checkbox } from "@korsolutions/ui";

function Form() {
  const [text, setText] = useState("");
  const [checked, setChecked] = useState(false);

  return (
    <>
      <Input value={text} onChange={setText} />
      <Checkbox.Root checked={checked} onChange={setChecked}>
        <Checkbox.Indicator />
        <Checkbox.Content>
          <Checkbox.Title>Accept terms</Checkbox.Title>
        </Checkbox.Content>
      </Checkbox.Root>
    </>
  );
}

Loading States

Buttons support loading states with built-in spinner:

<Button isLoading={isSubmitting} onPress={handleSubmit}>
  Submit
</Button>

When isLoading is true, the button displays ActivityIndicator and disables interaction.

Disabled States

Most components support disabled states:

<Button isDisabled={!formValid} onPress={handleSubmit}>
  Submit
</Button>

<Input isDisabled value={email} onChange={setEmail} />

<Checkbox.Root disabled checked={value} onChange={setValue}>
  <Checkbox.Indicator />
  <Checkbox.Content>
    <Checkbox.Title>Disabled option</Checkbox.Title>
  </Checkbox.Content>
</Checkbox.Root>

Selecting Variants

Most components offer multiple variants:

// Button variants
<Button variant="default">
  Default Button
</Button>

<Button variant="secondary">
  Secondary Button
</Button>

<Button variant="ghost">
  Ghost Button
</Button>

// Alert variants
<Alert.Root variant="default">
  <Alert.Body>
    <Alert.Title>Info</Alert.Title>
  </Alert.Body>
</Alert.Root>

<Alert.Root variant="destructive">
  <Alert.Body>
    <Alert.Title>Error</Alert.Title>
  </Alert.Body>
</Alert.Root>

// Badge variants
<Badge variant="success">Active</Badge>
<Badge variant="danger">Inactive</Badge>
<Badge variant="warning">Pending</Badge>

Style Overrides

Override component styles using the style prop:

<Button
  style={{
    marginTop: 20,
    backgroundColor: "blue",
  }}
>
  Custom Styled
</Button>

Import Reference

Component Imports

// Import individual components
import { Button, Input, Card, Alert } from "@korsolutions/ui";

// Import all components
import * as UI from "@korsolutions/ui";

Hook Imports

// Theme hook
import { useTheme } from "@korsolutions/ui";

// Responsive design hook
import { useScreenSize } from "@korsolutions/ui";

// React Navigation theme integration
import { useReactNavigationTheme } from "@korsolutions/ui";

Provider Import

import { UIProvider } from "@korsolutions/ui";

Type Imports

// Component prop types
import type { ButtonProps } from "@korsolutions/ui";
import type { InputProps } from "@korsolutions/ui";

// Theme types
import type { ThemeAssets, Colors } from "@korsolutions/ui";

Quick Troubleshooting

Provider Not Wrapping App

Issue: Components don't render or theme doesn't apply

Solution: Ensure UIProvider wraps your app in the root layout:

// app/_layout.tsx
import { UIProvider } from "@korsolutions/ui";

export default function RootLayout() {
  return (
    <UIProvider>
      <Stack />
    </UIProvider>
  );
}

Import Errors

Issue: Cannot resolve @korsolutions/ui

Solution: Install the package and restart your bundler:

npm install @korsolutions/ui
# Restart Metro bundler

Theme Not Updating

Issue: Theme changes don't reflect in components

Solution: Ensure theme customization is passed to UIProvider before app renders:

const customTheme = {
  colors: { light: { primary: "hsla(220, 90%, 56%, 1)" } },
};

<UIProvider theme={customTheme}>
  <App />
</UIProvider>;

Styles Not Applying

Issue: Custom styles don't override component styles

Solution: Remember style composition order - user styles always override variant styles:

// This works - style prop overrides variant
<Button style={{ backgroundColor: "red" }}>
  Red Button
</Button>

For comprehensive troubleshooting, see Troubleshooting Guide.

Reference Documentation

Consult these detailed references as needed:

Component References

System References

  • Theme Customization - Complete theming guide with color schemes, typography, and responsive design
  • Patterns & Recipes - Common implementation patterns for forms, modals, navigation, and feedback
  • Troubleshooting - Solutions for setup, component, type, and platform-specific issues
Weekly Installs
40
GitHub Stars
1
First Seen
Jan 28, 2026
Installed on
codex40
opencode38
github-copilot38
kimi-cli38
gemini-cli38
amp38