Crystal
Components

Form Components

Crystal-styled form inputs, selects, checkboxes, and layout components — all crystallization-responsive.

All Crystal form components extend their shadcn/ui counterparts with crystallization-responsive styling. Border radius, border width, shadows, and transition timing automatically adapt to the active crystallization preset via CSS variables.

Shared Crystal Behavior

Every form component uses these CSS variables, so changing crystallization changes all forms at once:

CSS VariableControlled ByEffect
var(--radius)CrystallizationBorder radius (sharp in edge, rounded in dream)
var(--border-width)CrystallizationBorder thickness
var(--motion-duration)CrystallizationTransition/animation speed
var(--shadow)CrystallizationBox shadow depth

Many components also accept an explicit crystallization prop to override the inherited preset.


Button

Open in Storybook
import { Button } from '@artasce/crystal-ui';

<Button>Default</Button>
<Button variant="outline" size="lg">Outline Large</Button>
<Button variant="destructive">Delete</Button>
<Button variant="ghost" size="icon"><Settings /></Button>

Button

<Button />

Button Props (Crystal additions)

TokenVariableValue
variant
'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link''default'
size
'default' | 'sm' | 'lg' | 'icon' | 'icon-sm' | 'icon-lg''default'
crystallization
CrystalCrystallization
asChild
booleanfalse

Values update live with theme changes. Click any row to copy the CSS variable.

Crystallization Effects on Button

CrystallizationEffect
cleanDefault — CSS variable styling only
dreamshadow-lg, hover scale 1.02
edgeNo shadow
luxeshadow-lg, hover shadow-2xl
boldfont-semibold, hover scale 1.01

Input

import { Input } from '@artasce/crystal-ui';

<Input placeholder="Email address" type="email" />
<Input crystallization="dream" placeholder="Dreamy input" />

Input

<Input />

Input Props (Crystal additions)

TokenVariableValue
crystallization
CrystalCrystallization

Values update live with theme changes. Click any row to copy the CSS variable.

Extends all native <input> HTML attributes. Crystallization adjusts shadow depth on focus.


Textarea

import { Textarea } from '@artasce/crystal-ui';

<Textarea placeholder="Your message..." rows={4} />

Same crystallization behavior as Input. Extends native <textarea> attributes.


Select

import {
  Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@artasce/crystal-ui';

<Select>
  <SelectTrigger>
    <SelectValue placeholder="Choose a theme" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="diamond">Diamond</SelectItem>
    <SelectItem value="onyx">Onyx</SelectItem>
    <SelectItem value="sapphire">Sapphire</SelectItem>
  </SelectContent>
</Select>

Also exports: SelectGroup, SelectLabel, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton.


Checkbox, Switch, RadioGroup

import { Checkbox, Switch, RadioGroup, RadioGroupItem } from '@artasce/crystal-ui';

<Checkbox id="terms" />

<Switch id="notifications" />

<RadioGroup defaultValue="option-1">
  <RadioGroupItem value="option-1" id="r1" />
  <RadioGroupItem value="option-2" id="r2" />
</RadioGroup>

All three use crystallization-responsive radius and border width.


Slider

import { Slider } from '@artasce/crystal-ui';

<Slider defaultValue={[50]} max={100} step={1} />

InputOTP

One-time password input with grouped slots.

import { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from '@artasce/crystal-ui';

<InputOTP maxLength={6}>
  <InputOTPGroup>
    <InputOTPSlot index={0} />
    <InputOTPSlot index={1} />
    <InputOTPSlot index={2} />
  </InputOTPGroup>
  <InputOTPSeparator />
  <InputOTPGroup>
    <InputOTPSlot index={3} />
    <InputOTPSlot index={4} />
    <InputOTPSlot index={5} />
  </InputOTPGroup>
</InputOTP>

InputGroup

Composite input with addons, buttons, and text decorations.

import { InputGroup, InputGroupInput, InputGroupAddon, InputGroupButton } from '@artasce/crystal-ui';

<InputGroup>
  <InputGroupAddon>https://</InputGroupAddon>
  <InputGroupInput placeholder="example.com" />
  <InputGroupButton>Go</InputGroupButton>
</InputGroup>

Also exports: InputGroupText, InputGroupTextarea.


Label

import { Label } from '@artasce/crystal-ui';

<Label htmlFor="email">Email</Label>

Field

A higher-level form layout system with multiple layout variants. Handles labels, descriptions, errors, and validation state.

import { Field, FieldLabel, FieldDescription, FieldError } from '@artasce/crystal-ui';

<Field>
  <FieldLabel>Email address</FieldLabel>
  <Input type="email" />
  <FieldDescription>We'll never share your email.</FieldDescription>
  <FieldError>Please enter a valid email.</FieldError>
</Field>

Also exports: FieldSet, FieldLegend, FieldGroup, FieldSeparator, FieldContent, FieldTitle.

Field supports layout variants via the layout prop: vertical (default), horizontal, inline.


Form (React Hook Form)

Integration with react-hook-form via Radix Form primitives.

import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@artasce/crystal-ui';

<Form {...form}>
  <FormField
    control={form.control}
    name="email"
    render={({ field }) => (
      <FormItem>
        <FormLabel>Email</FormLabel>
        <FormControl>
          <Input {...field} />
        </FormControl>
        <FormMessage />
      </FormItem>
    )}
  />
</Form>

Also exports: FormDescription, useFormField.


Calendar

Date picker powered by react-day-picker.

import { Calendar } from '@artasce/crystal-ui';

<Calendar mode="single" selected={date} onSelect={setDate} />

Import All

import {
  Button, Input, Textarea, Label,
  Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
  Checkbox, Switch, RadioGroup, RadioGroupItem,
  Slider, Calendar,
  InputOTP, InputOTPGroup, InputOTPSlot,
  InputGroup, InputGroupInput, InputGroupAddon,
  Field, FieldLabel, FieldDescription, FieldError,
  Form, FormField, FormItem, FormLabel, FormControl, FormMessage,
} from '@artasce/crystal-ui';