0.6.0 • Published 7 months ago

rael-ui v0.6.0

Weekly downloads
-
License
-
Repository
-
Last release
7 months ago

rael-ui is a modern UI library for React that enables developers to build beautifully styled websites without having to create styles from scratch. With built-in support for both light and dark themes, rael-ui ensures your components follow best practices in UI/UX while maintaining full customization options. It leverages compound components for seamless styling and includes a built-in form management system to simplify complex form handling.

Key Features

  • Modern, UX-Friendly Styles: Predefined styles that follow UI/UX best practices, saving time and enhancing user experience.
  • Built-In Theming: Supports both dark and light themes with easy configuration.
  • Automatic Styling Sync: Child components automatically inherit styles from parent elements (e.g., cards and their inputs).
  • Full Customizability: Customizable like shadcn’s components, supporting outline and fill styles, plus compound component patterns.
  • Integrated Form Management: Provides built-in form management to streamline form creation.

Installation

To get started, install rael-ui via npm:

npm install rael-ui

After installation, make sure to include the predefined colors and animations in your project’s Tailwind configuration. Add the following to your tailwind.config.js and index.css files:

Tailwind Configuration

const colors = {
  'primary': '#421BDD',
  'secondary' : '#423A5E',
  'danger': '#e74c3c',
  'black': '#09090b',
  // 'black': '#09090b',
  'white': '#fafafa',
  'dark': '#12161C',
}

/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
  darkMode: ['class', '[data-mode="dark"]', 'selector'],
  theme: {
    extend: {
      colors: {
        'danger': colors.danger,
        'dark': colors.dark,
        primary: {
          DEFAULT: colors.primary,
          100: 'hsl(var(--color-primary-100))',
          80: 'hsl(var(--color-primary-80))',
          60: 'hsl(var(--color-primary-60))',
        },
        secondary: {
          DEFAULT: colors.secondary,
          100: 'hsl(var(--color-secondary-100))',
          80: 'hsl(var(--color-secondary-80))',
        },
        white: {
          DEFAULT: colors.white,
          100: 'hsl(var(--color-white-100))',
          80: 'hsl(var(--color-white-80))',
        },
        black: {
          DEFAULT: colors.black,
          100: 'hsl(var(--color-black-100))',
          80: 'hsl(var(--color-black-80))',
          60: 'hsl(var(--color-black-60))',
        },
        'neutral-dark': {
          100: 'hsl(var(--color-neutral-dark-100))',
          80: 'hsl(var(--color-neutral-dark-80))',
          60: 'hsl(var(--color-neutral-dark-60))',
          40: 'hsl(var(--color-neutral-dark-40))',
        }
        ,
        'neutral-light': {
          100: 'hsl(var(--color-neutral-light-100))',
          80: 'hsl(var(--color-neutral-light-80))',
          60: 'hsl(var(--color-neutral-light-60))',
        }
        ,
      },
      fontSize: {
        "title":
                "56px",
        "button":
                "17px"
      }
      ,
      fontFamily: {
        sans: ['Roboto', 'sans-serif'],
      }
      ,
      animation: {
        'slide-in':
                'slide-in 0.3s ease-out forwards',
        'slide-out':
                'slide-out 0.3s ease-out forwards',
      }
      ,

    },
  },
  plugins: [],
}
;

CSS Import

@tailwind base;
@tailwind components;
@tailwind utilities;


@layer base {
  .rael-password-input::-ms-reveal,
  .rael-password-input::-ms-clear {
    display: none;
  }

  .rael-number-input::-webkit-inner-spin-button {
    display: none;
  }

  .hide-scrollbar::-webkit-scrollbar {
    background: transparent;
    width: 8px;
  }

  .hide-scrollbar::-webkit-scrollbar-thumb {
    border-radius: 10px;
    border: none;
    background: #9ca3af;
  }

  :root {
    --color-primary-100: 252 78% 49%;
    --color-primary-80: 252 78% 60%;
    --color-primary-60: 252 78% 80%;

    --color-secondary-100: 253 24% 30%;
    --color-secondary-80: 254 78% 40%;

    --color-white-100: 255 80% 98%;
    --color-white-80: 255 80% 90%;

    --color-black-100: 255 80% 10%;
    --color-black-80: 240 19% 39%;
    --color-black-60: 240 19% 45%;

    --color-neutral-dark-100: 215 22% 9%;
    --color-neutral-dark-80: 215 22% 16%;
    --color-neutral-dark-60: 215 22% 20%;
    --color-neutral-dark-40: 215 22% 30%;

    --color-neutral-light-100: 0 0% 100%;
    --color-neutral-light-80: 0 0% 93%;
    --color-neutral-light-60: 0 0% 84%;
  }
}


@keyframes slide-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slide-out {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(10px);
  }
}

Documentation

You can check the documentation at : https://rael-ui-doc.vercel.app/

Form Management Example

import {Button, Card,
  CardDescription,
  CardSection,
  CardTitle, Checkbox,
  Form,
  FormControl,
  FormDescription,
  FormItem,
  FormLabel,
  FormMessage,
  PasswordInput,
  Select, SelectGroup,
  SelectGroupContainer, SelectGroupTitle, SelectItem,
  SelectLabel,
  SelectTrigger,
  TextInput,
  useForm,
  ValidationRules, useToast,
  CheckboxLabel,
} from "rael-ui"
const FormTest = () => {
    const validations: ValidationRules<FormField>[] = [
        {
            name : 'email',
            pattern : /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
            required: true,
            message : 'Please enter a valid email address'
        },
        {
            name : 'password',
            valid : ({password}) => password!.length >= 5,
            required: true,
            message : 'Password must be at least 5 characters',
        },
        {
            name : 'confirm',
            valid : ({confirm, password}) => confirm === password,
            required : true,
            message : "The password doesn't match"
        },
        {
            name : 'country',
            required : true,
        },
        {
            name : 'condition',
            required : true,
            valid : ({condition}) => condition!,
            message : 'We cannot create your account unless you accept the terms and conditions'
        }
    ]

    const form = useForm<FormField>({
        defaultValue : {
            password : '',
            country : '',
            confirm: '',
            email : '',
            condition : false,
        },
        validations
    });
    
    const {renderToastContainer, toast} = useToast();

    const {formData} = form;

    const onSubmit = async () => {
        await new Promise<void>((resolve) => {
            setTimeout(() => resolve(), 2000)
        })
        console.log(formData);
        toast({
            title : 'Login success',
            message : 'Login successfully done',
        })
    }
    return (
        <Form form={form} onSubmit={onSubmit} className={"flex flex-col w-full justify-center items-center h-screen gap-4"}>
            {renderToastContainer()}
            <Card  className={'w-[420px]'}>
                <CardSection rFor={'meta'}>
                    <CardTitle>Create your account</CardTitle>
                    <CardDescription>Delve into the world of ...</CardDescription>
                </CardSection>
                <CardSection>
                    <FormItem>
                        <FormLabel>Email</FormLabel>
                        <FormControl name={'email'} type={'input'} render={({...fields}) => (
                            <TextInput block {...fields} placeholder={'eg : rael@gmail.com'}/>
                        )}/>
                        <FormDescription>We recommend to use a professional email</FormDescription>
                        <FormMessage name={'email'}/>
                    </FormItem>
                    <FormItem>
                        <FormLabel>Password</FormLabel>
                        <FormControl name={'password'} type={'input'} render={({...fields}) => (
                            <PasswordInput block {...fields} placeholder={''}/>
                        )}/>
                        <FormMessage name={'password'}/>
                    </FormItem>
                    <FormItem>
                        <FormLabel>Confirm</FormLabel>
                        <FormControl name={'confirm'} type={'input'} render={({...fields}) => (
                            <PasswordInput block {...fields} placeholder={''}/>
                        )}/>
                        <FormDescription>Confirm your password</FormDescription>
                        <FormMessage name={'confirm'}/>
                    </FormItem>
                    <FormItem>
                        <FormLabel>Country</FormLabel>
                        <FormControl type={'select'} name={'country'} render={({...fields}) => (
                            <Select block {...fields}>
                                <SelectTrigger>
                                    <SelectLabel placeholder={'Select your country'}/>
                                    <ChevronDown/>
                                </SelectTrigger>
                                <SelectGroupContainer>
                                    <SelectGroup>
                                        <SelectGroupTitle>Countries</SelectGroupTitle>
                                        {
                                            countries.map(country => (
                                                <SelectItem key={country} value={country}>{country}</SelectItem>))
                                        }
                                    </SelectGroup>
                                </SelectGroupContainer>
                            </Select>
                        )}/>
                        <FormDescription>This wont be publicly displayed</FormDescription>
                        <FormMessage name={'country'}/>
                    </FormItem>
                    <FormItem>
                        <FormControl name={'condition'} type={'checkbox'} render={({...fields}) => (
                            <Checkbox {...fields}>
                                <CheckboxLabel>I accept terms and conditions</CheckboxLabel>
                            </Checkbox>
                        )}/>
                        <FormMessage name={'condition'}/>
                    </FormItem>
                </CardSection>
                <CardSection>
                    <Button type={'submit'} onClick={() => {
                        toast({
                            title : 'Toast'
                        })
                    }} loading={form.isSubmitting} block>Login</Button>
                </CardSection>
            </Card>
        </Form>
    )
}

Author

0.6.0

7 months ago

0.5.0

8 months ago

0.4.0

8 months ago

0.3.0

8 months ago

0.2.0

9 months ago

0.1.7

9 months ago

0.1.6

9 months ago

0.1.5

9 months ago

0.1.4

9 months ago

0.1.3

9 months ago

0.1.2

9 months ago

0.1.1

9 months ago

0.1.0

9 months ago