PHPackages                             locomotivemtl/charcoal-ui - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. locomotivemtl/charcoal-ui

ActiveLibrary[Admin Panels](/categories/admin)

locomotivemtl/charcoal-ui
=========================

UI tools (Dashboard, Layout, Form and Menu)

0.3.13.1(4y ago)316.0k21MITPHPPHP &gt;7.1CI failing

Since May 11Pushed 4y ago8 watchersCompare

[ Source](https://github.com/locomotivemtl/charcoal-ui)[ Packagist](https://packagist.org/packages/locomotivemtl/charcoal-ui)[ Docs](https://charcoal.locomotive.ca)[ RSS](/packages/locomotivemtl-charcoal-ui/feed)WikiDiscussions master Synced 2mo ago

READMEChangelog (10)Dependencies (12)Versions (41)Used By (1)

Charcoal UI
===========

[](#charcoal-ui)

The `Charcoal\Ui` module provides tools to create UI elements (dashboards, layouts, forms and menus) from simple metadata / config.

Table of contents
=================

[](#table-of-contents)

- [How to install](#how-to-install)
    - [Dependencies](#dependencies)
- [Base UI Item](#base-ui-item)
- [Dashboard](#dashboard)
- [Layout](#layout)
- [Form](#form)
- [Form Group](#form-group)
- [Form Input](#form-input)
- [Menu](#menu)
- [Menu Item](#menu-item)
- [Service Providers](#service-provider)
- [Development](#development)
    - [Development dependencies](#development-dependencies)
    - [Coding Style](#coding-style)
    - [Authors](#authors)
    - [Changelog](#changelog)

How to install
==============

[](#how-to-install)

The preferred (and only supported) way of installing charcoal-ui is with **composer**:

```
$ composer require locomotivemtl/charcoal-ui
```

Dependencies
------------

[](#dependencies)

- PHP 7.1+
- [`psr/log`](http://www.php-fig.org/psr/psr-3/)
    - A PSR-3 compliant logger should be provided to the various services / classes.
- [`locomotivemtl/charcoal-config`](https://github.com/locomotivemtl/charcoal-config) 0.6+
    - The UI objects are *configurable* with various configs.
- [`locomotivemtl/charcoal-translation`](https://github.com/locomotivemtl/charcoal-translation)
    - To provide l10n to the UI objects.
- [`locomotivemtl/charcoal-view`](https://github.com/locomotivemtl/charcoal-view) 0.1+
    - The base `UiItem` are `Viewable`, meaning they can be rendered with a `View`.

Example Usage
=============

[](#example-usage)

Form
----

[](#form)

```
use Charcoal\Config\GenericMetadata;
use Charcoal\Ui\Form\FormBuilder;
use Charcoal\Ui\Form\FormFactory;

$metadata = new GenericMetadata([
    'properties' => [
        'first_name' => [
            'type' => 'string',
        ],
        'last_name' => [
            'type' => 'string',
        ],
        'email' => [
            'type' => 'email',
        ],
    ],
]);

$formData = [
    'first_name' => 'Mathieu',
    'last_name'  => 'Ducharme',
    'email'      => 'mat@locomotive.ca',
];

$formConfig = [
    'type'           => 'charcoal/ui/form/generic'
    'template_ident' => 'foo/bar/form',
    'template_data'  => [],
    'label'          => 'Example Form',
    'groups'         => [
        'info' => [
            'layout' => [
                'structure' => [
                    'columns' => [
                        [ 1, 1 ],
                        [ 1 ],
                    ],
                ],
            ],
            'properties' => [
                'first_name',
                'last_name',
                'email',
            ],
        ],
    ],
];

$formBuilder = new FormBuilder([
    'form_factory' => new FormFactory(),
    'view'         => $container['view'],
]);

$form = $formBuilder->build($formConfig);
$form->setMetadata($metadata);
$form->setFormData($formData);

echo $form->render();
```

Base UI Item
============

[](#base-ui-item)

All UI classes implements the same basic class: `\Charcoal\Ui\UiItemInterface`. This interface defines a basic set of properties that are shared across (almost) all ui item types.

Base UI Item config
-------------------

[](#base-ui-item-config)

KeyTypeDefaultDescription**type**`string`**title**`string[1]`**subtitle**`string[1]`**description**`string[1]`**notes**`string[1]`**template\_ident**`string``''`The default view template.\[1\] indicates a l10n string (`TranslationString`)

View Integration
----------------

[](#view-integration)

The `UiItemInterface` is a *Viewable* item; that means it also implements the `\Charcoal\View\ViewableInterface`. The `AbstractUiItem` fully implements this interface by using `\Charcoal\View\ViewableTrait`.

*Viewable* objects can set a *View* object with `setView($view)` have a `template_ident` (which can be set with `setTemplateIdent($id)`). See the [charcoal-view](https://github.com/locomotivemtl/charcoal-view) module for details.

The easiest way to use a View is by setting a `ViewInterface` object as `view` service on a DI container / Service Provider.

Dashboard
=========

[](#dashboard)

Dashboards define a *layout* of *widgets*.

- `layout` is a `LayoutInterface` object that can be created with a `LayoutBuilder`.
- `widgets` is a collection of any `UiItemInterface` objects. - Any PHP class can actually be a "widget", but base widgets are provided as convenience.

Dashboard config
----------------

[](#dashboard-config)

KeyTypeDefaultDescription**type**`string`**layout**`LayoutConfig`**widgets**`array`Dashboard dependencies
----------------------

[](#dashboard-dependencies)

- `logger`
- `view`
- `widget_factory`

Dashboard API
-------------

[](#dashboard-api)

- `setLayout()`
- `layout()`
- `setWidgets(array $widgets)`
- `widgets()`
- `addWidget()`
- `numWidgets()`
- `hasWidget()`

Layout
======

[](#layout)

Layouts define a grid (column-based) structure.

Layout config
-------------

[](#layout-config)

KeyTypeDefaultDescription**structure**`array`**structure.columns**`array`**Example layout JSON config**

```
"layout": {
    "structure": [
        { "columns": [ 2, 1 ] },
        { "columns": [ 1 ] },
        { "columns": [ 1 ] }
    ]
}
```

Layout API
----------

[](#layout-api)

- `setStructure(array $layouts)`
- `structure()`
- `numRows()`
- `rowIndex($position = null)`
- `rowData($position = null)`
- `rowNumColumns($position = null)`
- `rowNumCells($position = null)`
- `rowFirstCellIndex($position = null)`
- `cellRowIndex($position = null)`
- `numCellsTotal()`
- `cellSpan($position = null)`
- `cellSpanBy12($position = null)`
- `cellStartsRow($position = null)`
- `cellEndsRow($position = null)`
- `start()`
- `end()`

Layout Aware objects
--------------------

[](#layout-aware-objects)

In the `charcoal-ui` module, 3 base objects use a layout: *dashboards*, *forms* and *form groups*.

Those classes implement the Layout requirement by implementing the `\Charcoal\Ui\Layout\LayoutAwareInterface` with the use of its corresponding `LayoutAwareTrait`.

Form
====

[](#form-1)

Forms define a layout of form groups, form options, data and metadata.

- Forms have [*groups*](#form-group), which have [*inputs*](#form-input).
- Groups can be layouted with a `layout` object.
- Form can be pre-populated with *form data*.
- *Metadata* ca

Form config
-----------

[](#form-config)

KeyTypeDefaultDescription**type**`string`**action**`string``''`URL where the form will be submitted.**method**`string``'post'`HTTP method to submit ("post" or "get").**layout**`LayoutConfig`**groups**`FormGroupConfig[]`**form\_data**`array`**metadata**`array`Form dependencies
-----------------

[](#form-dependencies)

- `view`
- `group_factory`

Form API
--------

[](#form-api)

- `setAction($action)`
- `action()`
- `setMethod($method)`
- `method()`
- `setGroups(array $groups)`
- `groups()`
- `addGroup($groupIdent, $groupData)`
- `numGroups()`
- `hasGroups()`
- `setFormData(array $formData)`
- `formData()`
- `addFormData()`

Form Group
==========

[](#form-group)

Form group config
-----------------

[](#form-group-config)

KeyTypeDefaultDescription**form****template\_ident**`string`**template\_controller**`string`**priority**`int`**layout**`LayoutConfig`**properties**`array`Form group API
--------------

[](#form-group-api)

- `setForm($form)`
- `setInputs(array $groups)`
- `inputs()`
- `addInput($inputIdent, $inputData)`
- `numInputs()`
- `hasInputs()`

Form Input
==========

[](#form-input)

- `form`
- `label`
- `property_ident`
- `template_ident`
- `template_data`
- `read_only`
- `required`
- `disabled`
- `multiple`
- `input_id`
- `input_name`

Menu
====

[](#menu)

Menu Item
=========

[](#menu-item)

Menu items define a menu level (ident, label and url) and its children (array of Menu Item).

Menu item config
----------------

[](#menu-item-config)

- `ident`
- `icon_ident`
- `label`
- `url`
- `children`

Menu item API
-------------

[](#menu-item-api)

- `setIdent($ident)`
- `ident()`
- `setLabel($label)`
- `label()`
- `setUrl($url)`
- `url()`
- `setChildren($children)`
- `children()`
- `numChildren()`
- `hasChildren()`

Creational Helpers
==================

[](#creational-helpers)

Most UI elements are very dynamic. The types of object to create is often read from a string in a configuration object. Therefore, factories are the preferred way of instanciating new UI items.

Ui items have also many inter-connected dependencies. Builders should therefore be used for object creation / instanciation. They use a factory internally, and have a `build($opts)` methods that allow to retrieve class name from a dynamic source, do initialization, dpendencies management and more. Builders require `Pimple` for a DI container.

Factories
---------

[](#factories)

- `\Charcoal\Ui\Dashboard\DashboardFactory`
- `\Charcoal\Ui\Layout\LayoutFactory`
- `\Charcoal\Ui\Form\FormFactory`
- `\Charcoal\Ui\FormGroup\FormGroupFactory`
- `\Charcoal\Ui\FormInput\FormInputFactory`
- `\Charcoal\Ui\Menu\MenuFactory`
- `\Charcoal\Ui\MenuItem\MenuItemFactory`

Builders
--------

[](#builders)

- `\Charcoal\Ui\Dashboard\DashboardBuilder`
- `\Charcoal\Ui\Layout\LayoutBuilder`
- `\Charcoal\Ui\Form\FormBuilder`
- `\Charcoal\Ui\FormGroup\FormGroupBuilder`
- `\Charcoal\Ui\FormInput\FormInputBuilder`
- `\Charcoal\Ui\Menu\MenuBuilder`
- `\Charcoal\Ui\MenuItem\MenuItemBuilder`

Service Providers
=================

[](#service-providers)

Service providers are provided in the `Charcoal\Ui\ServiceProvider` namespace for for convenience. They are the recommended way of using `charcoal-ui`, as they register all the creational utilities to a container, taking care of dependencies.

- `\Charcoal\Ui\ServiceProvider\DashboardServiceProvider`
    - `dashboard/factory`
    - `dashboard/builder`
- `\Charcoal\Ui\ServiceProvider\FormServiceProvider`
    - `form/factory`
    - `form/builder`
    - `form/group/factory`
    - `form/input/factory`
    - `form/input/builder`
- `\Charcoal\Ui\ServiceProvider\LayoutServiceProvider`
    - `layout/factory`
    - `layout/builder`
- `\Charcoal\Ui\ServiceProvider\MenuServiceProvider`
    - `menu/factory`
    - `menu/builder`
    - `menu/item/factory`
    - `menu/item/builder`
- `\Charcoal\Ui\ServiceProvider\UiServiceProvider`
    - Register all the other service providers (dashboard, form, layout and menu).

Required services
-----------------

[](#required-services)

There are a few dependencies on external services, that should be set on the same DI container as the one passed to the service providers:

- `logger`, a PSR-3 logger instance.
    - Typically a `monolog` instance from `charcoal-app`.
- `view`, a `\Charcoal\View\ViewInterface` instance.
    - Typically provided with `\Charcoal\App\Provider\ViewServiceProvider`.

Development
===========

[](#development)

To install the development environment:

```
$ composer install --prefer-source
```

API documentation
-----------------

[](#api-documentation)

- The auto-generated `phpDocumentor` API documentation is available at
- The auto-generated `apigen` API documentation is available at [https://codedoc.pub/locomotivemtl/charcoal-ui/master/](https://codedoc.pub/locomotivemtl/charcoal-ui/master/index.html)

Development dependencies
------------------------

[](#development-dependencies)

- `phpunit/phpunit`
- `squizlabs/php_codesniffer`
- `satooshi/php-coveralls`

Continuous Integration
----------------------

[](#continuous-integration)

ServiceBadgeDescription[Travis](https://travis-ci.org/locomotivemtl/charcoal-ui)[![Build Status](https://camo.githubusercontent.com/f26295c36db133017cd008af6f2b1e34b9c6c6c38aa5521a9d9f7eea3a0bb450/68747470733a2f2f7472617669732d63692e6f72672f6c6f636f6d6f746976656d746c2f63686172636f616c2d75692e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/locomotivemtl/charcoal-ui)Runs code sniff check and unit tests. Auto-generates API documentation.[Scrutinizer](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-ui/)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/79e3eb16b5a3d55a3320b6cc6f0d16287c9eee06a4c5d8f3d8c39a140770d4c3/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c6f636f6d6f746976656d746c2f63686172636f616c2d75692f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-ui/?branch=master)Code quality checker. Also validates API documentation quality.[Coveralls](https://coveralls.io/github/locomotivemtl/charcoal-ui)[![Coverage Status](https://camo.githubusercontent.com/8f77d226cf0de6901c4a8b5038e900dfb4c0360ce424350959f2fdadef605e8f/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6c6f636f6d6f746976656d746c2f63686172636f616c2d75692f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/locomotivemtl/charcoal-ui?branch=master)Unit Tests code coverage.[Sensiolabs](https://insight.sensiolabs.com/projects/533b5796-7e69-42a7-a046-71342146308a)[![SensioLabsInsight](https://camo.githubusercontent.com/dbc93126feedf6cf35ed018588318fc13e03ac2c65620f55d186232ea71f0883/68747470733a2f2f696e73696768742e73656e73696f6c6162732e636f6d2f70726f6a656374732f61643564313639392d303763632d343562352d396261342d3962336234356636373765302f6d696e692e706e67)](https://insight.sensiolabs.com/projects/ad5d1699-07cc-45b5-9ba4-9b3b45f677e0)Another code quality checker, focused on PHP.Coding Style
------------

[](#coding-style)

The Charcoal-Ui module follows the Charcoal coding-style:

- [*PSR-1*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
- [*PSR-2*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
- [*PSR-4*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md), autoloading is therefore provided by *Composer*.
- [*phpDocumentor*](http://phpdoc.org/) comments.
- Read the [phpcs.xml](phpcs.xml) file for all the details on code style.

> Coding style validation / enforcement can be performed with `composer phpcs`. An auto-fixer is also available with `composer phpcbf`.

Authors
=======

[](#authors)

- Mathieu Ducharme

License
=======

[](#license)

Charcoal is licensed under the MIT license. See [LICENSE](LICENSE) for details.

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity26

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~60 days

Recently: every ~249 days

Total

35

Last Release

1602d ago

PHP version history (4 changes)0.1PHP &gt;=5.5.0

0.2PHP &gt;=5.6.0

0.3.8PHP &gt;=5.6.0 || &gt;=7.0

0.3.12PHP &gt;7.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfb071c0ff7ce9500c528a003a2c53124248debc3e5bf367c17f89f5e6136125?d=identicon)[mducharme](/maintainers/mducharme)

---

Top Contributors

[![mducharme](https://avatars.githubusercontent.com/u/12157?v=4)](https://github.com/mducharme "mducharme (55 commits)")[![mcaskill](https://avatars.githubusercontent.com/u/29353?v=4)](https://github.com/mcaskill "mcaskill (48 commits)")[![JoelAlphonso](https://avatars.githubusercontent.com/u/10762266?v=4)](https://github.com/JoelAlphonso "JoelAlphonso (13 commits)")[![dominiclord](https://avatars.githubusercontent.com/u/1775204?v=4)](https://github.com/dominiclord "dominiclord (5 commits)")[![BeneRoch](https://avatars.githubusercontent.com/u/3017380?v=4)](https://github.com/BeneRoch "BeneRoch (1 commits)")

---

Tags

charcoaldashboardformlayoutmenuphpuiuimenulayoutdashboardformcharcoalcontrol

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/locomotivemtl-charcoal-ui/health.svg)

```
[![Health](https://phpackages.com/badges/locomotivemtl-charcoal-ui/health.svg)](https://phpackages.com/packages/locomotivemtl-charcoal-ui)
```

###  Alternatives

[redchamps/module-clean-admin-menu

It will merge all third party extensions menu items to single menu item named 'Extensions'.

164416.3k](/packages/redchamps-module-clean-admin-menu)[awes-io/indigo-layout

Basic styles and components set for building user interfaces.

4424.6k4](/packages/awes-io-indigo-layout)[andreia/filament-ui-switcher

Add a modal with options to switch between different UI layouts and styles (colors, fonts, font sizes).

233.8k](/packages/andreia-filament-ui-switcher)[kamona/kui-laravel-jetstream

Different UI for laravel/jetstream

669.3k](/packages/kamona-kui-laravel-jetstream)[locomotivemtl/charcoal-admin

The Charcoal Administration Dashboard

1110.8k8](/packages/locomotivemtl-charcoal-admin)[locomotivemtl/charcoal-app

Charcoal application, based on Slim 3

1320.3k12](/packages/locomotivemtl-charcoal-app)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
