Skip to main content

Customization

The Qbit Design includes default skins for all components, which you can use directly. If you require customized designs for your components, you can create custom skins or do modifications to an existing skin. Follow Below steps to integrate a custom skin into a component.

Skins and Customization

In Qbit Design customizing UI designs can be simply done using a custom skin. Qbit Design renderer is intelligent enough to identify which skin to be loaded during the runtime.

Customize skin

Let's create a skin from the scratch. To create a skin just you need to know the props which are available. Check the official documentation to know about the required element prop.

Skin folder structure

You can store your skin as your needs. Here is a way to store the skins in a proper way. Please refer below structure.

Project file
├── src
│ └── skins
│ ├── default skins
│ │ └──element skins folder
│ │ └──element skins
│ └── optional skin
│ └──element skins folder
│ └──other skins for the element
│ └──other skins for the element

The standard location to save your custom skin is under src/skins/<custom_skin_name>.

UI Design

For the styling you can use the tailwind or bootstrap or display it with an svg

Install tailwind via npm
npm install -D tailwindcss postcss autoprefixer
Install tailwind via pnpm
pnpm add -D tailwindcss postcss autoprefixer
Install bootstrap via npm
npm install bootstrap
Install bootstrap via pnpm
pnpm add bootstrap
Display with an SVG

An SVG (Scalable Vector Graphics) is a widely used format for displaying vector images, icons, and UI components in web applications. Using SVG for UI design ensures scalability, flexibility, and high-quality rendering across different screen sizes.


Let's Start to Create the Skin

To create a skin, define a React functional component that takes the appropriate props. Refer to the documentation for the property definitions (type definition interface name) to pass the correct props.

Example: Tab Item Element Skin

Example Output

Tab Example


Tab Item Skin Code

const TabItemSkin: com.qbit.Skin<TabItemProps> = (props) => {
const { name, onClick, disabled, active, className } = props;

return (
<button
className={`${className} ${active ? 'border-b-2 border-blue-500 text-blue-500' : 'text-gray-500 hover:text-blue-500'}
${disabled ? 'cursor-not-allowed opacity-50' : ''}`}
onClick={(e) => {
if (!disabled) {
onClick?.(e);
}
}}
>
{name}
</button>
);
};

export default TabItemSkin;

Step-by-Step Code Breakdown

Define the Functional Component

const TabItemSkin: com.qbit.Skin<TabItemProps> = (props) => {
  • TabItemSkin is a functional component.
  • It accepts props defined by TabItemProps.

Destructure Props

const { name, onClick, disabled, active, className } = props;
  • name: Text inside the tab button.
  • onClick: Function to handle tab click.
  • disabled: Boolean that disables interaction.
  • active: Boolean indicating if the tab is selected.
  • className: Custom styles from the parent component.

Rendering the Button

The skin renders a <button> element, styled dynamically using Tailwind CSS classes.

Dynamic Styling
  • The className combines custom classes and conditional classes based on the active and disabled props.

  • Styling Behavior:

    • If active is true:
      • Adds styles: border-b-2 border-blue-500 text-blue-500 (active tab appearance with a blue underline and blue text).
    • If active is false:
      • Adds styles: text-gray-500 hover:text-blue-500 (gray text by default, turning blue on hover).
    • If disabled is true:
      • Adds styles: cursor-not-allowed opacity-50 (disables pointer events and makes the button semi-transparent).
Click Handler
  • The button’s click event is handled via the onClick function passed as a prop.
  • If disabled is true, the onClick function is not executed.
  • Optional chaining (onClick?.(e)) ensures the function is only called if it exists.
Button Content
  • The {name} prop displays the name inside the button.

Skin Usage

To apply the TabItemSkin, we need to pass it into the renderers prop of the parent Tab component. The renderers prop accepts two properties:

  1. renderer → Defines the parent element's skin.
  2. childRenderer → Defines the child elements' skin (required).

Example: Using the Tab Skin in a Page
<Tab
keyExtractor={(value: string, i: number) => `${value}-${i}`}
renderers={{ renderer: TabSkin, childRenderer: TabItemSkin }}
>
<TabItem active={true} name="Tasks" content={<SampleContent />} />
<TabItem active={false} name="Removed task" content={<Element />} />
<TabItem active={false} name="Sign in/up" content={<Login />} />
</Tab>

Breaking Down the renderers Prop

renderer (Parent Skin)

renderer: TabSkin
  • Purpose: Defines how the Tab container looks and behaves.
  • Example: If TabSkin styles the tab container, it could define background colors, padding, borders, etc.
  • Effect: This affects the whole tab group, not individual items.
childRenderer (Child Skin)
childRenderer: TabItemSkin
  • Purpose: Controls the appearance of individual tab items.
  • Example: TabItemSkin styles each tab button, including text color, borders, and hover effects.
  • Effect: It applies to all TabItem elements inside the Tab component.
  • Requirement: childRenderer is mandatory, ensuring every tab item has a consistent style.

How It Works

  1. The Tab component takes a list of tab items.
  2. TabSkin defines the overall layout and appearance of the tab container.
  3. TabItemSkin ensures each tab item is styled correctly.
  4. The active prop changes the visual state of a selected tab.

This approach allows customization while maintaining modularity in your design.

Styling

note

In TypeScript, you need to specify the type for the skin. This can be done as follows:
com.qbit.Skin<{ComponentProps}>

Here, ComponentProps varies for each component based on its specific properties.

Simple Button Design

Below is an example of a simple button design using a custom skin.

Here's how you can structure the documentation with the requested example and sandbox embed:

Example 01: Simple Button Design

const CustomizedButton: com.qbit.Skin<ButtonProps> = (props: com.qbit.SkinProps<ButtonProps>) => {
const { value, onClick, disabled } = props;

return (
<button
disabled={disabled}
onClick={onClick}
className="flex w-full justify-center rounded-md bg-[#212121] px-3 py-2 text-sm/6 font-semibold text-white shadow-sm hover:bg-neutral-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#212121]"
>
{value}
</button>
);
};

export default CustomizedButton;

Example 02: Hover Animation Button Design

const CustomizedButton: com.qbit.Skin<ButtonProps> = (props: com.qbit.SkinProps<ButtonProps>) => {
const { value, onClick, disabled } = props;

return (
<button
type="button"
disabled={disabled}
onClick={onClick}
className="relative inline-flex items-center justify-start px-6 py-3 overflow-hidden font-medium transition-all bg-white rounded border-2 border-[#FBDD07] group"
>
<span class="w-48 h-48 rounded rotate-[-40deg] bg-[#FBDD07] absolute bottom-0 left-0 -translate-x-full ease-out duration-500 transition-all translate-y-full mb-9 ml-9 group-hover:ml-0 group-hover:mb-32 group-hover:translate-x-0"></span>
<span class="relative w-full text-left text-[#212121] transition-colors duration-300 ease-in-out">Button Text</span>
{value}
</button>
);
};

export default CustomizedButton;