Customizing components

When theming doesn't suffice, PhlexUI allows you to tailor the components to your specific needs.

Introduction

While theming provides a powerful tool for modifying aspects such as fonts, brand colors, and border attributes, there may be instances where you need to directly customize the components. PhlexUI is designed to facilitate this process with ease.

Updating attributes & classes

All components accept any HTML attribute, and will pass it through to the underlying HTML element. This is great for quick changes, or when you need to add a custom class for a one off situation.

How it works
When you pass an attribute to a PhlexUI component, it will be processed by thePhlexUI::AttributeMerger class. You can read more about the PhlexUI::Base and the PhlexUI::AttributeMerger classes on Github.
Adding attributes

By default, attribute values are added to the existing values of the component. For instance, if you want to make a button span the full width of its container, you can do it like this: Button(class: 'w-full'). This will add the w-full class to the button, causing it to span the full width of its container.

Overriding Classes

There might be instances where you need to override a specific style attribute. For instance, if you wish to alter the color of a button while keeping the rest of the styles intact, you can achieve this as follows: Button(class: '!bg-red-500'). This will replace the default background color with red by utilizing the !important modifier.

Replacing Attributes

In some rare cases, you might need to replace the default value of an attribute entirely. For instance, if you want to change all the styles of a button, you can do it as follows: Button(class!: 'bg-red-500 text-white py-2 px-4 font-medium hover:bg-red-600'). This will override all the default classes and apply only the ones you specify. In this case, it will apply bg-red-500 text-white py-2 px-4 font-medium hover:bg-red-600.

Redefining components

Redefining components is a powerful concept that allows you to redefine the underlying components through inheritance, or completely. This is useful when you need to make more complex changes to the components, that can't be achieved with attributes and classes alone. In other words, you can change the whole damn thing if you like.

How it works

To redefine a component, find the component you want to redefine in the source code, and copy it into your application. Then, make the changes you need. For example, if you want to change the button component, you can copy the button component from the source code, and paste it into your application. Then, you can make the changes you need.

Let's redefine the Alert component

Let's say you want to change the alert component to use a particular icon every time it is rendered. You can do this by redefining the component as follows:

1


Find the source code

First, find the source code for the component you want to redefine. In this case, we want to redefine the Alert component, so we'll find the source code for the alert component here on Github.

2


Copy the source code

Next, copy the source code for the component into your application. You can do this by creating a new file at app/views/components/phlex_u_i/alert.rb, and pasting the source code into it. When using the phlex-rails gem, all components are loaded from this directory. So if you want to redefine a component, it will always sit somewhere inside the app/views/components/phlex_u_i directory.

Your new file should look something like this:

# frozen_string_literal: true

module PhlexUI
	class Alert < Base
		def initialize(variant: nil, **attrs)
			@variant = variant
			super(**attrs) # must be called after variant is set
		end

		def view_template(&block)
			div(**attrs, &block)
		end

		private

		def colors
			case @variant
			when nil then 'ring-border bg-muted/20 text-foreground [&>svg]:opacity-80'
			when :warning then 'ring-warning/20 bg-warning/5 text-warning [&>svg]:text-warning/80'
			when :success then 'ring-success/20 bg-success/5 text-success [&>svg]:text-success/80'
			when :destructive then 'ring-destructive/20 bg-destructive/5 text-destructive [&>svg]:text-destructive/80'
			end
		end

		def default_attrs
			base_classes = 'backdrop-blur relative w-full ring-1 ring-inset rounded-lg px-4 py-4 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg~*]:pl-8'
			{
				class: tokens(base_classes, colors),
			}
		end
	end
end

3

Edit to perfection!