Button Component
To create a button component, you can use any HTML element such as button
or a
tag. However, it is recommended to use the button
element for actions and the a
tag for navigation. Both elements can be easily styled with CSS
or Tailwind CSS
.
In this example, we will create a reusable button component. The button component can be customized with different styles and attributes. Here is an example of how to define the button component:
To get started, create a new file at src/app/Lib/PHPX/Components/Button.php
and add the following code snippet:
The button component will accept the following attributes, along with any other attributes you wish to pass:
variant
: Specifies the button's style variant (default, secondary, destructive, outline, ghost, link).size
: Specifies the button's size (default, sm, lg, icon).type
: Specifies the button's type attribute (button, submit, reset).class
: Custom CSS classes for additional styling.
Note: If the variant
or size
attributes are not specified, they will default to "default". Similarly, the type
attribute defaults to "button" if not provided.
<?php
namespace Lib\PHPX\Components;
use Lib\PHPX\IPHPX;
use Lib\PHPX\Utils;
class Button implements IPHPX
{
/**
* @var array<string, mixed> The properties or attributes passed to the component.
*/
private array $props;
/**
* @var mixed The children elements or content to be rendered within the component.
*/
private mixed $children;
/**
* @var string The CSS class for custom styling.
*/
private string $class;
/**
* @var string Stores the precomputed CSS classes for the component.
*/
private string $computedClass;
/**
* Constructor to initialize the component with the given properties.
*
* @param array<string, mixed> $props Optional properties to customize the component.
*/
public function __construct(array $props = [])
{
// echo "__construct: " . print_r($props, true);
$this->props = $props;
$this->children = $props['children'] ?? '';
$this->class = $props['class'] ?? '';
// Precompute the static classes once during construction
$this->computedClass = $this->getComputedClasses();
}
/**
* Registers or initializes any necessary components or settings. (Placeholder method).
*/
public static function init(): void
{
// Register the component or any necessary initialization
}
/**
* Combines and returns the CSS classes for the component.
*
* @return string The merged CSS class string.
*/
private function getComputedClasses(): string
{
$variant = $this->props['variant'] ?? 'default';
$size = $this->props['size'] ?? 'default';
// Base Tailwind CSS classes
$baseClass = 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';
// Variant classes mapped to Tailwind CSS
$variantClasses = [
'default' => 'bg-blue-500 text-white hover:bg-blue-600',
'destructive' => 'bg-red-500 text-white hover:bg-red-600',
'outline' => 'border border-gray-300 bg-white hover:bg-gray-100 hover:text-gray-900',
'secondary' => 'bg-gray-200 text-gray-800 hover:bg-gray-300',
'ghost' => 'hover:bg-gray-100 hover:text-gray-900',
'link' => 'text-blue-500 underline-offset-4 hover:underline',
];
// Size classes
$sizeClasses = [
'default' => 'h-10 px-4 py-2',
'sm' => 'h-9 px-3',
'lg' => 'h-11 px-8',
'icon' => 'h-10 w-10',
];
// Merge the classes
$classes = Utils::mergeClasses(
$baseClass,
$variantClasses[$variant] ?? $variantClasses['default'],
$sizeClasses[$size] ?? $sizeClasses['default'],
$this->class
);
return $classes;
}
/**
* Generates and returns a string of HTML attributes from the provided props.
* Excludes 'class' and 'children' props from being added as attributes.
*
* @return string The generated HTML attributes.
*/
private function getAttributes(): string
{
// Filter out 'class' and 'children' props
$filteredProps = array_filter($this->props, function ($key) {
return !in_array($key, ['class', 'children']);
}, ARRAY_FILTER_USE_KEY);
// Build attributes string by escaping keys and values
$attributes = [];
foreach ($filteredProps as $key => $value) {
$escapedKey = htmlspecialchars($key, ENT_QUOTES, 'UTF-8');
$escapedValue = htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
$attributes[] = "$escapedKey='$escapedValue'";
}
return implode(' ', $attributes);
}
/**
* Renders the component as an HTML string with the appropriate classes and attributes.
* Also, allows for dynamic children rendering if a callable is passed.
*
* @return string The final rendered HTML of the component.
*/
public function render(): string
{
$attributes = $this->getAttributes();
$class = $this->computedClass;
$type = $this->props['type'] ?? 'button';
return "<button type='$type' class='$class' $attributes>" . $this->children . "</button>";
}
/**
* Converts the object to its string representation by rendering it.
*
* @return string The rendered HTML output of the component.
*/
public function __toString(): string
{
return $this->render();
}
}
Now, you can integrate the Button
component into your Prisma PHP application by following the example below:
<?php
use Lib\PHPX\Components\Button;
Button::init();
?>
<div class="w-screen h-screen grid place-items-center">
<div class="grid grid-cols-2 gap-4">
<div class="flex flex-col gap-2">
<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
<div class="flex flex-col gap-2">
<Button>Default Size</Button>
<Button variant="secondary" size="sm">Secondary Size sm</Button>
<Button variant="destructive" size="lg">Destructive Size lg</Button>
<Button variant="outline" size="icon">
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"& gt;
<path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z" />
</svg>
</Button>
</div>
</div>
</div>
By following the steps above, you have successfully created a reusable Button
component using Prisma PHPX. You can now use this component in your application to display buttons with various styles and sizes.
In the render
method, we use the button
tag to render the button. You can customize the button by passing different props such as variant
and size
to achieve the desired look and feel.