UI Styleguide

General

CSS Classes

All CSS classes used in AdminUI are generated using the Tailwind CSS utility-first CSS framework.

Note: Classes are prefixed with tw- whilst we are still sharing some classes with the legacy Bootstrap CSS framework.

Classes can be found using the Tailwind CSS documentation, or by reviewing the Tailwind config file, located at: /UI/AdminUI/src/tailwind/tailwind.config.js.

Example:

Lorem ipsum dolar sit amet

Code:

<p id="test-id" class="tw-text-green-500 tw-text-xl">...</p>

Where possible, attributes should be added in order of: id, class, and for/name, followed by remaining attributes.

Responsive

Tailwind CSS also generates responsive classes for CSS.

Example:

Lorem ipsum dolar sit amet

Code:

<p class="tw-text-orange-500 tw-text-xl md:tw-text-green-500">...</p>

Layout

Containers

There are two CSS container classes in use.

  1. tw-content - sets the max-width to a decent reading width
  2. tw-container - sets the max-width to max site width

However, it is easy to use Tailwind CSS to restrict your own content. To set a max-width of 24rem (based on the Tailwind CSS config settings), you can use the following class: tw-max-w-sm

Grid

There is a basic grid that shortcuts some flexbox setup. You can use responsive classes to disable wrapping and to set the widths of columns.

Example:

First col
Second col
First col
Second col
First col
Second col
Third col

Code:

<div class="tw-flex-grid md:tw-flex-nowrap">
    <div class="tw-flex-grid-col md:tw-w-1/3">...</div>
    <div class="tw-flex-grid-col md:tw-w-2/3">...</div>
</div>
<div class="tw-flex-grid md:tw-flex-nowrap">
    <div class="tw-flex-grid-col md:tw-w-1/2">...</div>
    <div class="tw-flex-grid-col md:tw-w-1/2">...</div>
</div>
<div class="tw-flex-grid md:tw-flex-nowrap">
    <div class="tw-flex-grid-col md:tw-w-1/3">...</div>
    <div class="tw-flex-grid-col md:tw-w-1/3">...</div>
    <div class="tw-flex-grid-col md:tw-w-1/3">...</div>
</div>

Components

Alerts

There are several different options for alerts.

Note: Alerts use flexbox. If you are using child HTML elements in an alert, you will also need to wrap the inner content in another HTML element (i.e. span)

Example:

Code:

<p class="tw-alert tw-mb-4" role="alert"><span>...</span></p>
<p class="tw-alert-success tw-mb-4" role="alert"><span>...</span></p>
<p class="tw-alert-warning tw-mb-4" role="alert"><span>...</span></p>
<p class="tw-alert-danger tw-mb-4" role="alert"><span>...</span></p>

Buttons

There are several different options for buttons.

Example:

Code:

<button class="tw-btn">...</button>
<button class="tw-btn-success">...</button>
<button class="tw-btn-warning">...</button>
<button class="tw-btn-danger">...</button>
<button class="tw-btn-blue">...</button>
<button class="tw-btn-white">...</button>
<button class="tw-btn-link">...</button>

All button styles can be made smaller or larger.

Example:

Code:

<button class="tw-btn tw-btn-small">...</button>
<button class="tw-btn-success tw-btn-small">...</button>
<button class="tw-btn-warning tw-btn-small">...</button>

Example:

Code:

<button class="tw-btn tw-btn-large">...</button>
<button class="tw-btn-success tw-btn-large">...</button>
<button class="tw-btn-warning tw-btn-large">...</button>

All button styles can also be disabled.

Example:

Code:

<button class="tw-btn" disabled>...</button>
<button class="tw-btn-success" disabled>...</button>
<button class="tw-btn-warning" disabled>...</button>

Datatable

Datatables are contructed using regular HTML table markup.

Example:

Col Col Col
Col Col Col
Col Col Col
2 result(s) found

Code:

<table class="datatable">...</table>

Datatables can also have a row hover state.

Example:

Col Col Col
Col Col Col
Col Col Col
2 result(s) found

Code:

<table class="datatable hover">...</table>

Datatables can also be styled as "selectable".

Example:

Col Col
Col Col
Col Col
2 result(s) found

Code:

<table class="datatable hover selectable">...</table>

Forms

Form controls include: input, select and textarea. All form controls must have an ID and associated label.

Note: Do not use the placeholder attribute with form controls. It causes duplicate labelling with screen readers.

Stacked Controls

Example:

Code:

<form>
    <div class="tw-form-group">
        <label class="tw-form-label" for="input-email">Email Address</label>
        <input id="input-email" class="tw-form-control" name="email" type="email" />
    </div>
    <div class="tw-form-group">
        <label class="tw-form-label" for="input-options">Options</label>
        <div class="tw-form-select">
            <select id="input-options" class="tw-form-control" name="options">...</select>
        </div>
    </div>
    <div class="tw-form-group">
        <label class="tw-form-label" for="input-message">Message</label>
        <textarea id="input-message" class="tw-form-control" name="message"></textarea>
    </div>
</form>

Horizontal Controls

Form controls can also display horizontally. Horizontal controls have borders between each form control.

Note: The last form control in a group must not have a border (see below).

Example:

Code:

<form>
    <div class="tw-form-row-border">
        <label class="tw-form-label-inline" for="input-email">Email Address</label>
        <input id="input-email" class="tw-form-control" name="email" type="email" />
    </div>
    <div class="tw-form-row-border">
        <label class="tw-form-label-inline" for="input-options">Options</label>
        <div class="tw-form-select">
            <select id="input-options" class="tw-form-control" name="options">...</select>
        </div>
    </div>
    <-- note: last from controls must not have a border -->
    <div class="tw-form-row">
        <label class="tw-form-label-inline" for="input-message">Message</label>
        <textarea id="input-message" class="tw-form-control" name="message"></textarea>
    </div>
</form>

Inputs with Buttons

Example:

Code:

<form>
    <div class="tw-form-row">
        <label class="tw-form-label-inline" for="uid">Unique ID</label>
        <div class="tw-flex tw-w-full lg:tw-max-w-2xl">
            <input id="uid" class="tw-form-control tw-rounded-r-none tw-border-r-0" name="id" type="text" />
            <button class="tw-btn tw-rounded-l-none">
                <span class="far fa-random" aria-hidden="true"></span>
                <span class="sr-only">Random</span>
            </button>
        </div>
    </div>
</form>

Example:

Code:

<form>
    <div class="tw-form-row">
        <label class="tw-form-label-inline" for="uid">Lifetime</label>
        <div class="tw-flex-grid tw-w-full sm:tw-flex-nowrap lg:tw-max-w-2xl">
            <div class="tw-flex-grid-col">
                <input id="lifetime" class="tw-form-control" name="lifetime" type="text" />
            </div>
            <div class="tw-flex-grid-col sm:tw-w-auto">
                <ul class="tw-flex tw-items-center"">
                    <li>
                        <button class="tw-btn">
                            <span class="tw-mr-1">5</span>
                            <span>mins</span>
                        </button>
                    </li>
                    <li>
                        <button class="tw-btn-link">
                            <span class="tw-mr-1">10</span>
                            <span>mins</span>
                        </button>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</form>

Checkboxes and Radios

Chexkboxes and radios share the same markup, except for the name and type attributes.

Example:

Checkboxes

Radios

Code:

<form>
    <div class="tw-form-row-border" role="group" aria-labelled-by="checkbox-group-label">
        <p id="checkbox-group-label" class="tw-form-label-inline">Checkboxes</p>
        <ul class="tw-form-checks">
            <li class="tw-form-checks__item">
                <label class="tw-form-checks__label" for="checkbox-group-1">
                    <input id="checkbox-group-1" class="tw-form-checks__input" name="checkboxes" />
                </label>
            </li>
            <li class="tw-form-checks__item">...</li>
        </ul>
    </div>
    <div class="tw-form-row" role="group" aria-labelled-by="radio-group-label">
        <p id="radio-group-label" class="tw-form-label-inline">Radios</p>
        <ul class="tw-form-checks">
            <li class="tw-form-checks__item">
                <label class="tw-form-checks__label" for="radio-group-1">
                    <input id="radio-group-1" class="tw-form-checks__input" name="radios" />
                </label>
            </li>
            <li class="tw-form-checks__item">...</li>
        </ul>
    </div>
</form>

Switches

Example:

Code:

<form>
    <div class="tw-form-row-border">
        <label class="tw-form-label-inline" for="default-switch">Default Switch</p>
        <div class="tw-block">
            <label class="tw-form-switch" for="default-switch">
                <input id="default-switch" class="tw-form-switch__input" name="default-switch" />
                    <span class="tw-form-switch__slider">
                    <span class="tw-form-switch__state"></span>
                </span>
            </label>
        </div>
    </div>
    <div class="tw-form-row-border">
        <label class="tw-form-label-inline" for="default-switch">Traffic Switch</p>
        <div class="tw-block">
            <label class="tw-form-switch" for="default-switch">
                <input id="default-switch" class="tw-form-switch__input" name="default-switch" />
                    <span class="tw-form-switch__slider tw-form-switch__slider--traffic">
                    <span class="tw-form-switch__state tw-form-switch__state--traffic"></span>
                </span>
            </label>
        </div>
    </div>
    <div class="tw-form-row-border">
        <label class="tw-form-label-inline" for="default-switch">Inverted Switch</p>
        <div class="tw-block">
            <label class="tw-form-switch" for="default-switch">
                <input id="default-switch" class="tw-form-switch__input" name="default-switch" />
                    <span class="tw-form-switch__slider tw-form-switch__slider--alt">
                    <span class="tw-form-switch__state tw-form-switch__state--alt"></span>
                </span>
            </label>
        </div>
    </div>
    <div class="tw-form-row">
        <label class="tw-form-label-inline" for="default-switch">Inverted Traffic Switch</p>
        <div class="tw-block">
            <label class="tw-form-switch" for="default-switch">
                <input id="default-switch" class="tw-form-switch__input" name="default-switch" />
                    <span class="tw-form-switch__slider tw-form-switch__slider--alt tw-form-switch__slider--traffic">
                    <span class="tw-form-switch__state tw-form-switch__state--alt tw-form-switch__state--traffic"></span>
                </span>
            </label>
        </div>
    </div>
</form>

Pager

Example:

Page 1 of 2 14 result(s) found

Code:

<div class="tw-flex tw-flex-wrap tw-items-center tw-justify-between tw-mt-2">...</p>
    <-- note: hide pages and bullet if not showing pages -->
    <div class="tw-flex tw-items-center tw-justify-center tw-w-full tw-text-xs tw-text-grey-700 tw-px-3 tw-py-2 sm:tw-w-auto">
        <span class="tw-hidden md:tw-inline">Page 1 of 2</span>
        <span class="tw-hidden tw-text-base tw-mx-2 tw-opacity-50 md:tw-inline" aria-hidden="true">•</span>
        <span id="pager-total-results">14 result(s) found</span>
    </div>
    <-- note: hide pages if not needed -->
    <nav class="tw-mt-2 tw-mx-auto sm:mt-0 sm:tw-mr-0" aria-label="Page">
        <ul class="tw-flex tw-items-center tw-justify-center tw-bg-white tw-rounded">
            <li>
                <button class="tw-btn-link" disabled>
                    <span>
                        <span class="fas fa-angle-double-left" aria-hidden="true"></span>
                    </span>
                    <span class="sr-only">First</span>
                </button>
            </li>
            <li class="tw-border-l-2 tw-border-grey-100">
                <button class="tw-btn-link" disabled>
                    <span>
                        <span class="fas fa-angle-left" aria-hidden="true"></span>
                    </span>
                    <span class="sr-only">Previous</span>
                </button>
            </li>
            <li class="tw-border-l-2 tw-border-grey-100">
                <button class="tw-btn-link">
                    <span>
                        <span class="fas fa-angle-right" aria-hidden="true"></span>
                    </span>
                    <span class="sr-only">Next</span>
                </button>
            </li>
            <li class="tw-border-l-2 tw-border-grey-100">
                <button class="tw-btn-link">
                    <span>
                        <span class="fas fa-angle-double-right" aria-hidden="true"></span>
                    </span>
                    <span class="sr-only">Last</span>
                </button>
            </li>
        </ul>
    </nav>
</div>

Pills

There are several different options for pills.

Example:

Default

Info

Success

Warning

Danger

Code:

<p class="tw-pill">...</p>
<p class="tw-pill-info">...</p>
<p class="tw-pill-success">...</p>
<p class="tw-pill-warning">...</p>
<p class="tw-pill-danger">...</p>

Example:

Info

Warning

Danger

Code:

<p class="tw-pill-info">
    <span class="fas fa-info-circle tw-mr-1" aria-hidden="true"></span>
    <span>...</span>
</p>
<p class="tw-pill-warning">
    <span class="fas fa-exclamation-triangle tw-mr-1" aria-hidden="true"></span>
    <span>...</span>
</p>
<p class="tw-pill-danger">
    <span class="fas fa-times tw-mr-1" aria-hidden="true"></span>
    <span>...</span>
</p>

Tabs

Example:

Code:

<div class="tw-border-b tw-border-grey-300 tw-mb-4">
    <ul class="tabs" role="tablist" aria-label="Sections">
        <li class="tabs__item">
            <button class="tabs__link active" role="tab" aria-selected="true" aria-controls="tab-1">...</button>
        </li>
        <li class="tabs__item">
            <button class="tabs__link" role="tab" aria-selected="false" aria-controls="tab-2">...</button>
        </li>
        <li class="tabs__item">
            <button class="tabs__link" role="tab" aria-selected="false" aria-controls="tab-3">...</button>
        </li>
    </ul>
</div>
<section id="tab-1" role="tabpanel" aria-label="First tab name" tabindex="0">...</section>
<section id="tab-2" role="tabpanel" aria-label="Second tab name" tabindex="0">...</section>
<section id="tab-3" role="tabpanel" aria-label="Third tab name" tabindex="0">...</section>

Pill Tabs

Example:

Code:

<ul class="pill-tabs" role="tablist" aria-label="Sections">
    <li class="pill-tabs__item">
        <button class="pill-tabs__link active" role="tab" aria-selected="true" aria-controls="tab-1">...</button>
    </li>
    <li class="pill-tabs__item">
        <button class="pill-tabs__link" role="tab" aria-selected="false" aria-controls="tab-2">...</button>
    </li>
    <li class="pill-tabs__item">
        <button class="pill-tabs__link" role="tab" aria-selected="false" aria-controls="tab-3">...</button>
    </li>
</ul>
<section id="tab-1" role="tabpanel" aria-label="First tab name" tabindex="0">...</section>
<section id="tab-2" role="tabpanel" aria-label="Second tab name" tabindex="0">...</section>
<section id="tab-3" role="tabpanel" aria-label="Third tab name" tabindex="0">...</section>