Skip to content

# 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:

Info

Success

Warning

Danger

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:

Email Address
Options
Message

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:

Email Address
Options
Message

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:

Unique ID

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:

Lifetime

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

- Option 1
- Option 2
- Option 3 (disabled)

Radios

- Option 1
- Option 2
- Option 3 (disabled)

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:

Default Switch
Traffic Switch
Inverted Switch
Inverted Traffic Switch

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>

## General

- CSS Classes
- Responsive

## Layout

- Containers
- Grid

## Components

- Alerts
- Buttons
- Datatable
- Forms
- Pager
- Pills
- Tabs
- Pill Tabs