This guide will help you build your first UI with Kivora React components. We’ll create a simple contact form using Button, Input, and Badge components.
Prerequisites
Before you begin, make sure you’ve:
Installed Kivora React
Imported the global stylesheet
Set up your React project (Next.js, Vite, CRA, etc.)
Your First Component
Let’s start with a simple button:
import { Button } from '@kivora/react' ;
export default function App () {
return (
< Button
label = "Save changes"
variant = "primary"
size = "md"
onClick = { () => alert ( 'Saved!' ) }
/>
);
}
This renders a primary button with medium size. The onClick handler is called when the button is clicked.
Hover over the Button component in your editor to see all available props and their documentation.
Kivora provides several semantic variants:
import { Button } from '@kivora/react' ;
export default function ButtonVariants () {
return (
< div style = { { display: 'flex' , gap: '1rem' , flexWrap: 'wrap' } } >
< Button label = "Primary" variant = "primary" />
< Button label = "Secondary" variant = "secondary" />
< Button label = "Ghost" variant = "ghost" />
< Button label = "Destructive" variant = "destructive" />
< Button label = "Outline" variant = "outline" />
</ div >
);
}
The Input component supports labels, error states, and different sizes:
import { Input } from '@kivora/react' ;
import { useState } from 'react' ;
export default function InputExample () {
const [ email , setEmail ] = useState ( '' );
return (
< Input
label = "Email"
type = "email"
placeholder = "[email protected] "
value = { email }
onChange = { setEmail }
size = "md"
/>
);
}
The onChange prop receives the string value directly, not the DOM event. This makes it easier to work with controlled inputs.
Adding Validation
Show error states with the error prop:
import { Input } from '@kivora/react' ;
import { useState } from 'react' ;
export default function ValidatedInput () {
const [ email , setEmail ] = useState ( '' );
const [ error , setError ] = useState < string >();
const validateEmail = ( value : string ) => {
if ( ! value . includes ( '@' )) {
setError ( 'Please enter a valid email' );
} else {
setError ( undefined );
}
};
return (
< Input
label = "Email"
type = "email"
placeholder = "[email protected] "
value = { email }
onChange = { ( value ) => {
setEmail ( value );
validateEmail ( value );
} }
error = { error }
/>
);
}
Using Badges
Badges are perfect for status indicators:
import { Badge } from '@kivora/react' ;
export default function StatusBadges () {
return (
< div style = { { display: 'flex' , gap: '0.5rem' , flexWrap: 'wrap' } } >
< Badge variant = "success" > Active </ Badge >
< Badge variant = "warning" > Pending </ Badge >
< Badge variant = "error" > Failed </ Badge >
< Badge variant = "info" > Info </ Badge >
< Badge variant = "default" > Default </ Badge >
</ div >
);
}
Now let’s combine everything into a complete contact form:
import { Button , Input , Badge } from '@kivora/react' ;
import { useState } from 'react' ;
export default function ContactForm () {
const [ name , setName ] = useState ( '' );
const [ email , setEmail ] = useState ( '' );
const [ loading , setLoading ] = useState ( false );
const [ status , setStatus ] = useState < 'idle' | 'success' | 'error' >( 'idle' );
const handleSubmit = async () => {
setLoading ( true );
setStatus ( 'idle' );
try {
// Simulate API call
await new Promise (( resolve ) => setTimeout ( resolve , 1000 ));
setStatus ( 'success' );
setName ( '' );
setEmail ( '' );
} catch ( error ) {
setStatus ( 'error' );
} finally {
setLoading ( false );
}
};
return (
< div style = { { maxWidth: '400px' , padding: '2rem' } } >
< h2 > Contact Us </ h2 >
< div style = { { marginBottom: '1rem' } } >
< Input
label = "Name"
placeholder = "Your name"
value = { name }
onChange = { setName }
/>
</ div >
< div style = { { marginBottom: '1rem' } } >
< Input
label = "Email"
type = "email"
placeholder = "[email protected] "
value = { email }
onChange = { setEmail }
/>
</ div >
< Button
label = "Submit"
variant = "primary"
loading = { loading }
onClick = { handleSubmit }
/>
{ status === 'success' && (
< div style = { { marginTop: '1rem' } } >
< Badge variant = "success" > Message sent successfully! </ Badge >
</ div >
) }
{ status === 'error' && (
< div style = { { marginTop: '1rem' } } >
< Badge variant = "error" > Failed to send message </ Badge >
</ div >
) }
</ div >
);
}
Using Hooks
Kivora React includes powerful hooks. Let’s enhance our form with useDisclosure to show a success modal:
import { Button , Input , Modal , useDisclosure } from '@kivora/react' ;
import { useState } from 'react' ;
export default function FormWithModal () {
const [ email , setEmail ] = useState ( '' );
const { isOpen , open , close } = useDisclosure ();
const handleSubmit = async () => {
// Submit form...
open (); // Show success modal
};
return (
<>
< div style = { { padding: '2rem' } } >
< Input
label = "Email"
type = "email"
value = { email }
onChange = { setEmail }
/>
< Button label = "Subscribe" onClick = { handleSubmit } />
</ div >
< Modal open = { isOpen } onClose = { close } title = "Success!" >
< p > Thank you for subscribing! </ p >
</ Modal >
</>
);
}
Use useDebounce to delay expensive operations like API calls:
import { Input , useDebounce } from '@kivora/react' ;
import { useState , useEffect } from 'react' ;
export default function SearchInput () {
const [ query , setQuery ] = useState ( '' );
const debouncedQuery = useDebounce ( query , 300 );
useEffect (() => {
if ( debouncedQuery ) {
// Only runs 300ms after user stops typing
console . log ( 'Searching for:' , debouncedQuery );
// fetchResults(debouncedQuery);
}
}, [ debouncedQuery ]);
return (
< Input
label = "Search"
placeholder = "Type to search..."
value = { query }
onChange = { setQuery }
/>
);
}
Copying to Clipboard
The useClipboard hook makes it easy to add copy functionality:
import { Button , useClipboard } from '@kivora/react' ;
export default function CopyButton () {
const { copy , copied } = useClipboard ();
return (
< Button
label = { copied ? 'Copied!' : 'Copy to clipboard' }
variant = { copied ? 'success' : 'secondary' }
onClick = { () => copy ( 'Hello, world!' ) }
/>
);
}
Next Steps
You now know the basics of Kivora React! Here’s what to explore next:
Theming Customize colors and design tokens
Dark Mode Implement theme switching
TypeScript Learn about TypeScript support
All Components Explore the full component library