Composable, immutable PHP primitives for building UI components: alerts, breadcrumbs, dropdowns, navbars, toggles, and menu items.
Accessible by default, fluent API, framework-friendly data hooks, and rendering powered by html-core.
composer require ui-awesome/html-core-component:^0.4This package ships both abstract base classes (for subclassing) and ready-to-use concrete classes (Alert, Breadcrumb, Dropdown, NavBar, Toggle, Item, Menu). The concrete classes can be used directly via ::tag() without any subclassing.
The exposed abstractions are:
BaseAlert/Alertdismissible alerts with prefix/suffix containers and an optional toggle.BaseBreadcrumb/Breadcrumbaccessible breadcrumb navigation with active-path detection.BaseDropdown/Dropdowndropdown menus with toggles, dividers, and active-link wiring.BaseNavBar/NavBarnavigation bars with brand, menu, and collapsible toggle.BaseToggle/Togglebutton or link toggles with full data-attribute coverage (Bootstrap, Flowbite, Tailwind UI).
use UIAwesome\Html\Core\Component\{BaseBreadcrumb, Item};
final class Breadcrumb extends BaseBreadcrumb {}
echo Breadcrumb::tag()
->items(
Item::tag()->label('Home')->link('/'),
Item::tag()->label('Library')->link('/library'),
Item::tag()->label('Data')->active(true),
)
->currentPath('/library')
->render();use UIAwesome\Html\Core\Component\{BaseDropdown, Item};
final class Dropdown extends BaseDropdown {}
echo Dropdown::tag()
->items(
Item::tag()->label('Profile')->link('/profile'),
Item::tag()->label('Settings')->link('/settings'),
Item::tag()->divider('<hr>'),
Item::tag()->label('Sign out')->link('/logout'),
)
->render();use UIAwesome\Html\Core\Component\{BaseNavBar, BaseToggle, Item};
final class NavBar extends BaseNavBar {}
final class Toggle extends BaseToggle {}
echo NavBar::tag()
->brandText('My App')
->brandLink('/')
->menu(
Item::tag()->label('Home')->link('/'),
Item::tag()->label('About')->link('/about'),
)
->render();Each item label can be wrapped in its own element (for styling or truncation) via labelTag/labelClass. Without labelTag, the label renders as plain text.
use UIAwesome\Html\Core\Component\{Item, Menu};
use UIAwesome\Html\Interop\Inline;
echo Menu::tag()
->type('nav')
->linkClass('nav-link')
->linkActiveClass('is-active')
->items(
Item::tag()
->label('Request')
->link('/request')
->active()
->labelTag(Inline::SPAN)
->labelClass('nav-link-label'),
Item::tag()
->label('Logs')
->link('/logs')
->labelTag(Inline::SPAN)
->labelClass('nav-link-label'),
)
->render();Framework styling is supplied by a ThemeInterface implementation resolved through Config and applied with BaseTag::config(). The theme reads the ComponentContext to pick the recipe, so variants (danger, info, warning, ...) travel with the context instead of being hard-coded on the component.
use UIAwesome\Html\Core\Component\Alert;
use UIAwesome\Html\Core\Config\{Call, ComponentContext, Config, Cookbook, Recipe};
use UIAwesome\Html\Core\Theme\ThemeInterface;
final class AppTheme implements ThemeInterface
{
public function getName(): string
{
return 'app';
}
public function getRecipes(ComponentContext $context): iterable
{
if ($context->component !== 'alert' || $context->variant === null) {
return;
}
yield new Recipe(
'app.alert',
new Cookbook(new Call('class', "alert alert-{$context->variant}")),
);
}
}
$config = new Config(new AppTheme());
echo Alert::tag()
->config($config, new ComponentContext('alert', variant: 'danger'))
->content('Watch out!')
->render();config() applies recipes immediately. Call it before fluent setters that must remain local overrides.
For per-instance defaults that do not belong to a theme, pass them to the factory:
use UIAwesome\Html\Core\Component\Alert;
echo Alert::tag(['class' => 'alert alert-danger'])->content('Watch out!')->render();Note
The Bootstrap5 and Flowbite cookbooks were removed in 0.3.0. Flowbite is discontinued, and the Bootstrap 5
presets are being republished as standalone theme packages. See the Upgrade Guide for the migration.
For detailed testing, migration, and quality workflows.
