Installation

No MCP yet? Connect your agent.

Usage

import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';
<Button>
  <Text>Button</Text>
</Button>

Link

You can use the buttonVariants and buttonTextVariants helpers to create a link that looks like a button.

import { buttonVariants, buttonTextVariants } from "@/components/ui/button"
<Link className={buttonVariants({ variant: 'outline' })}>
  <Text className={buttonTextVariants({ variant: 'outline' })}>Click here</Text>
</Link>

Alternatively, you can set the asChild parameter and nest the link component.

<Link href="/login" asChild>
  <Button>
    <Text>Login</Text>
  </Button>
</Link>

Examples

Primary

import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';

export function ButtonPreview() {
  return (
    <Button>
      <Text>Button</Text>
    </Button>
  );
}

Secondary

import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';

export function ButtonSecondaryPreview() {
  return (
    <Button variant="secondary">
      <Text>Secondary</Text>
    </Button>
  );
}

Destructive

import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';

export function ButtonDestructivePreview() {
  return (
    <Button variant="destructive">
      <Text>Destructive</Text>
    </Button>
  );
}

Outline

import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';

export function ButtonOutlinePreview() {
  return (
    <Button variant="outline">
      <Text>Outline</Text>
    </Button>
  );
}

Ghost

import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';

export function ButtonGhostPreview() {
  return (
    <Button variant="ghost">
      <Text>Ghost</Text>
    </Button>
  );
}

Link

import { Button } from '@/components/ui/button';
import { Text } from '@/components/ui/text';

export function ButtonLinkPreview() {
  return (
    <Button variant="link">
      <Text>Link</Text>
    </Button>
  );
}

Icon

import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { ChevronRight } from 'lucide-react-native';

export function ButtonIconPreview() {
  return (
    <Button variant="outline" size="icon">
      <Icon as={ChevronRight} />
    </Button>
  );
}

With Icon

import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { Text } from '@/components/ui/text';
import { Mail } from 'lucide-react-native';

export function ButtonWithIconPreview() {
  return (
    <Button>
      <Icon as={Mail} className="text-primary-foreground" />
      <Text>Login with Email</Text>
    </Button>
  );
}

Loading

import { Button } from '@/components/ui/button';
import { Icon } from '@/components/ui/icon';
import { Text } from '@/components/ui/text';
import { Loader2 } from 'lucide-react-native';
import { View } from 'react-native';

export function ButtonLoadingPreview() {
  return (
    <Button disabled>
      <View className="pointer-events-none animate-spin">
        <Icon as={Loader2} className="text-primary-foreground" />
      </View>
      <Text>Please wait</Text>
    </Button>
  );
}

Agent guide

Add the cn helper and the theme color variables the files useWhen: The project has no components.json file.From the collection

The files import cn from @/lib/utils:

import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Class names such as bg-background, text-muted-foreground, border-border, bg-primary, and rounded-lg resolve through these theme variables. Define them in the global CSS and map each color in the Tailwind theme as hsl(var(--name)), with --radius mapped to borderRadius.lg (md is calc(var(--radius) - 2px), sm is calc(var(--radius) - 4px)).

Light:

VariableValue
--backgroundhsl(0 0% 100%)
--foregroundhsl(0 0% 3.9%)
--cardhsl(0 0% 100%)
--card-foregroundhsl(0 0% 3.9%)
--popoverhsl(0 0% 100%)
--popover-foregroundhsl(0 0% 3.9%)
--primaryhsl(0 0% 9%)
--primary-foregroundhsl(0 0% 98%)
--secondaryhsl(0 0% 96.1%)
--secondary-foregroundhsl(0 0% 9%)
--mutedhsl(0 0% 96.1%)
--muted-foregroundhsl(0 0% 45.1%)
--accenthsl(0 0% 96.1%)
--accent-foregroundhsl(0 0% 9%)
--destructivehsl(0 84.2% 60.2%)
--borderhsl(0 0% 89.8%)
--inputhsl(0 0% 89.8%)
--ringhsl(0 0% 63%)
--radius0.625rem

Dark:

VariableValue
--backgroundhsl(0 0% 3.9%)
--foregroundhsl(0 0% 98%)
--cardhsl(0 0% 3.9%)
--card-foregroundhsl(0 0% 98%)
--popoverhsl(0 0% 3.9%)
--popover-foregroundhsl(0 0% 98%)
--primaryhsl(0 0% 98%)
--primary-foregroundhsl(0 0% 9%)
--secondaryhsl(0 0% 14.9%)
--secondary-foregroundhsl(0 0% 98%)
--mutedhsl(0 0% 14.9%)
--muted-foregroundhsl(0 0% 63.9%)
--accenthsl(0 0% 14.9%)
--accent-foregroundhsl(0 0% 98%)
--destructivehsl(0 70.9% 59.4%)
--borderhsl(0 0% 14.9%)
--inputhsl(0 0% 14.9%)
--ringhsl(300 0% 45%)
--radius0.625rem

Nativewind projects: the files assume 1rem is 16px, so pass inlineRem: 16 to Nativewind in metro.config.js:

module.exports = withNativeWind(config, { input: './global.css', inlineRem: 16 });

Related items

Requires