Skip to main content

Getting Started

VhyxUI works with any React 18 project. No configuration required. Import tokens, wrap with provider, use components.

Requirements

Node.js≥ 18
React≥ 18
react-dom≥ 18

Installation

Install both packages. Tokens are required — they define every visual decision the components make.

npm install @vhyxui/react @vhyxui/tokens
@vhyxui/react

All 22 components, VhyxUIProvider, and the toast() API.

@vhyxui/tokens

Pure CSS. Zero JavaScript. Every visual decision as a CSS custom property. Import once — override anything.

Peer dependenciesThis example uses react-hook-form and zod. Install them separately: npm install react-hook-form @hookform/resolvers zod

Provider Setup

Wrap your app with VhyxUIProvider and import the token CSS. Do this once at the root of your application.

App Router

app/layout.tsx
import '@vhyxui/tokens/index.css';
import { VhyxUIProvider } from '@vhyxui/react';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <VhyxUIProvider>
          {children}
        </VhyxUIProvider>
      </body>
    </html>
  );
}

Pages Router

pages/_app.tsx
import '@vhyxui/tokens/index.css';
import type { AppProps } from 'next/app';
import { VhyxUIProvider } from '@vhyxui/react';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <VhyxUIProvider>
      <Component {...pageProps} />
    </VhyxUIProvider>
  );
}

First Component

Import any component from @vhyxui/react. Every component is tree-shakeable — only what you import ships.

import { Button } from '@vhyxui/react';

function MyComponent() {
  return (
    <div>
      <Button variant="primary">Primary</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="destructive">Destructive</Button>
    </div>
  );
}

Complete Example

A login form using react-hook-form and zod for validation. Field handles label association, error display, and accessibility automatically.

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Button, Input, Form, Field } from '@vhyxui/react';

const schema = z.object({
  email: z.string().email('Enter a valid email address'),
  password: z.string().min(8, 'Password must be at least 8 characters'),
});

type LoginFormData = z.infer<typeof schema>;

export function LoginForm() {
  const form = useForm<LoginFormData>({
    resolver: zodResolver(schema),
  });

  async function onSubmit(data: LoginFormData) {
    // Replace with your auth logic — e.g. signIn from next-auth
    await signIn(data);
  }

  return (
    <Form form={form} onSubmit={form.handleSubmit(onSubmit)}>
      <Field name="email" label="Email address" required>
        <Input
          {...form.register('email')}
          type="email"
          placeholder="you@example.com"
          error={!!form.formState.errors.email}
        />
      </Field>
      <Field name="password" label="Password" required>
        <Input
          {...form.register('password')}
          type="password"
          placeholder="••••••••"
          error={!!form.formState.errors.password}
        />
      </Field>
      <Button
        type="submit"
        variant="primary"
        size="md"
        loading={form.formState.isSubmitting}
      >
        Sign in
      </Button>
    </Form>
  );
}