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.
tw-content- sets the max-width to a decent reading widthtw-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:
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 |
Code:
<table class="datatable">...</table>
Datatables can also have a row hover state.
Example:
| Col | Col | Col |
|---|---|---|
| Col | Col | Col |
| Col | Col | Col |
Code:
<table class="datatable hover">...</table>
Datatables can also be styled as "selectable".
Example:
| Col | Col | |
|---|---|---|
| Col | Col | |
| Col | Col |
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:
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>