Skip to main content

Panel

Panels are used to draw information to the attention of the user.

Variants

Information

<div class="panel panel--info panel--no-title">
  <span class="u-vh">Important information: </span>
  <div class="panel__body">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    <ul>
      <li>VAT</li>
      <li>Internet sales</li>
    </ul>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{{
    onsPanel({
        "body": '<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><ul><li>VAT</li><li>Internet sales</li></ul>'
    })
}}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Warning

<div class="panel panel--warn panel--no-title">
  <span class="panel__icon" aria-hidden="true">!</span>
  <span class="u-vh">Warning: </span>
  <div class="panel__body">
    All of the information about this person will be deleted
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{% call onsPanel({
        "type": 'warn'
    })
%}
    All of the information about this person will be deleted
{% endcall %}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Warning branded

This example is a warning variant designed only for the census respond phase. It is to warn users that they must complete the census by law.

<div class="census-warning">
  <div class="container">
    <div class="panel panel--warn-branded panel--no-title">
      <span class="panel__icon" aria-hidden="true">!</span>
      <span class="u-vh">Warning: </span>
      <div class="panel__body">
        <p class="u-mb-no">You must complete the census by law or you could be fined up to £1,000</p>
        <p class="u-fs-r">Some questions are labelled as voluntary. It is not an offence if you do not answer these.</p>
      </div>
    </div>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{% call onsPanel({
        "type": 'warn-branded'
    })
%}
<p class="u-mb-no">You must complete the census by law or you could be fined up to £1,000</p>
<p class="u-fs-r">Some questions are labelled as voluntary. It is not an offence if you do not answer these.</p>
{% endcall %}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Announcement

This example is an important announcement.

<div class="announcement">
  <div class="container">
    <div class="panel panel--announcement panel--no-title">
      <span class="panel__icon" aria-hidden="true">
        <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" focusable="false" aria-hidden="true">
          <path d="M4.2,12c0-0.6,0.4-1,1-1h11.2l-4.9-4.9c-0.4-0.4-0.4-1,0-1.4c0.4-0.4,1-0.4,1.4,0l6.6,6.6c0.4,0.4,0.4,1,0,1.4l-6.6,6.6c-0.4,0.4-1,0.4-1.4,0c-0.4-0.4-0.4-1,0-1.4l4.9-4.9H5.2C4.7,13,4.2,12.6,4.2,12z" fill="currentColor"></path>
        </svg>
      </span>
      <span class="u-vh">Announcement: </span>
      <div class="panel__body">
        <p class="u-mb-no">National lockdown: stay at home</p>
        <div class="u-fs-r">
          <p>Coronavirus (COVID-19) remains a serious threat across the country. <a href="#0">Find out more</a></p>
        </div>
      </div>
    </div>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{% call onsPanel({
        "type": 'announcement'
    })
%}
<p class="u-mb-no">National lockdown: stay at home</p>
<div class="u-fs-r">
    <p>Coronavirus (COVID-19) remains a serious threat across the country. <a href="#0">Find out more</a></p>
</div>
{% endcall %}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Success

This example also has the icon param set to show the tick in the content of the panel.

<div class="panel panel--success panel--no-title" id="success-id">
  <span class="u-vh">Completed: </span>
  <span class="panel__icon u-fs-">
    <svg class="svg-icon" viewBox="0 0 13 10" xmlns="http://www.w3.org/2000/svg" focusable="false">
      <path d="M14.35,3.9l-.71-.71a.5.5,0,0,0-.71,0h0L5.79,10.34,3.07,7.61a.51.51,0,0,0-.71,0l-.71.71a.51.51,0,0,0,0,.71l3.78,3.78a.5.5,0,0,0,.71,0h0L14.35,4.6A.5.5,0,0,0,14.35,3.9Z" transform="translate(-1.51 -3.04)" />
    </svg>
  </span>
  <div class="panel__body">Information has been successfully submitted.
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{{
    onsPanel({
        "type": 'success',
        "id": 'success-id',
        "icon": 'check',
        "body": 'Information has been successfully submitted.'
    })
}}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Error

There are two panel types for errors; error with header and error. See the correct errors pattern for further context and implementation.

Error with header

Used to provide feedback to the user that something is in an error state. This can range from input validation errors to server downtime. Content should be descriptive of the error and always direct the user towards a resolution.

<div aria-labelledby="error-summary-title" role="alert" tabindex="-1" autofocus="autofocus" class="panel panel--error">
  <div class="panel__header">
    <h2 id="error-summary-title" data-qa="error-header" class="panel__title u-fs-r--b">There are 2 problems with your answer</h2>
  </div>
  <div class="panel__body">
    <ol class="list">
      <li class="list__item ">
        <a href="#container-test-number" class="list__link js-inpagelink">Enter a number</a>
      </li>
      <li class="list__item ">
        <a href="#container-test-percent" class="list__link js-inpagelink">Enter a number less than or equal to 100</a>
      </li>
    </ol>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{% from "components/lists/_macro.njk" import onsList %}
{% call onsPanel({
        "title": 'There are 2 problems with your answer',
        "type": 'error',
        "dsExample": isPatternLib
}) %}
    {{
        onsList({
            "element": 'ol',
            "itemsList": [
                {
                    "text": 'Enter a number',
                    "url": '#container-test-number',
                    "classes": 'js-inpagelink'
                },
                {
                    "text": 'Enter a number less than or equal to 100',
                    "url": '#container-test-percent',
                    "classes": 'js-inpagelink'
                }
            ]
        })
    }}
{% endcall %}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Error

<div class="panel panel--error panel--no-title u-mb-s">
  <span class="u-vh">Error: </span>
  <div class="panel__body">
    <p class="panel__error">
      <strong>Enter a number</strong>
    </p>
    <div class="field">
      <label class="label  " for="number">Number of employees paid monthly
      </label>
      <input type="text" id="number" class="input input--text input-type__input input--error input--w-5" pattern="[0-9]*" inputmode="numeric" min required="required" />
    </div>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/input/_macro.njk" import onsInput %}
{{
    onsInput({
        "id": 'number',
        "type": 'number',
        "classes": 'input--w-5',
        "required": true,
        "attributes": {
            "min": 0
        },
        "label": {
            "text": 'Number of employees paid monthly'
        },
        "error": {
            "text": 'Enter a number',
            "dsExample": isPatternLib
        }
    })
}}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Spacious

The spacious variant can be used on all inline variants.

<div class="panel panel--info panel--no-title panel--spacious">
  <span class="u-vh">Important information: </span>
  <div class="panel__body">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    <ul>
      <li>VAT</li>
      <li>Internet sales</li>
    </ul>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{{
    onsPanel({
        "spacious": true,
        "body": '<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><ul><li>VAT</li><li>Internet sales</li></ul>'
    })
}}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Branded - census

<div class="panel panel--branded panel--no-title">
  <span class="u-vh">Important information: </span>
  <div class="panel__body">
    This guidance is for the paper questionnaire.<br>View the <a href="#0">question guidance for completing the census online</a>.
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{% call onsPanel({
        "type": 'branded'
    })
%}
    This guidance is for the paper questionnaire.<br>View the <a href="#0">question guidance for completing the census online</a>.
{% endcall %}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Bare

The bare variant is used to show plain text next to an icon. This is used in the access code pattern.

<div class="panel panel--bare">
  <span class="panel__icon u-fs-">
    <svg class="svg-icon" viewBox="0 0 10 13" xmlns="http://www.w3.org/2000/svg" focusable="false">
      <path d="M12.25,6h-.72V4.49a3.5,3.5,0,0,0-7,0V6H3.75A.77.77,0,0,0,3,6.75v6.5a.77.77,0,0,0,.75.75h8.5a.77.77,0,0,0,.75-.75V6.75A.77.77,0,0,0,12.25,6ZM5.54,4.49a2.5,2.5,0,1,1,5,0V6h-5ZM9,11.66a.3.3,0,0,1-.26.34H7.29A.29.29,0,0,1,7,11.69v0l.39-1.82a1,1,0,1,1,1.4-.18.77.77,0,0,1-.18.18Z" transform="translate(-3 -0.99)" />
    </svg>
  </span>
  <div class="panel__body">
    Here is some text with an icon.
  </div>
</div>
Nunjucks macro options
Name Type Required Description
body string true The contents of the panel. This can be a string of HTML
title string false The title for the panel. If this is not provided the inline/no title version will be rendered
titleTag string false The html tag to wrap the title text in. Will default to a div (for error summaries this is set to h1)
type string false The type of panel to render. Available options are success, warn, error, branded, warn-branded and announcement
spacious boolean false Will render a more spacious version of the panel if set to true
classes string false Custom classes to add to the panel
id string false Custom id to add to the panel
attributes object false HTML attributes to apply to the panel (e.g. data attributes)
icon string false Set this to the name of the icon you want to be included before the contents of the panel
assistiveTextPrefix string false Overrides the visually hidden accessible default prefix text. Available for the following panels with no title:
  • information and branded (‘Important information: ‘)
  • success (‘Completed: ‘)
  • warn and warn-branded (‘Warning: ‘),
  • error (‘Error: ‘)
iconSize string false Set this to the size of the icon you want can be set to “m”, “l” “xl” to match heading size. Defaults to the size of regualar text
iconsPath string false Set this to the path to the icon you want to be included before the contents of the panel
dsExample boolean false Defaulted to true in Design System examples but wont be set when used outside of the Design System. This will stop the page focusing on the panel on load - only for use in DS examples
{% from "components/panel/_macro.njk" import onsPanel %}
{% call onsPanel({
        type: 'bare',
        icon: 'lock'
    })
%}
    Here is some text with an icon.
{% endcall %}

{% macro onsPanel(params) %}
    {% if params is defined and params and params.classes is defined and params.classes %}
        {% set classes = ' ' + params.classes %}
    {% endif %}
    {% if params is not defined or params.title is not defined and params.type != "bare" %}
        {% set noTitleClass = ' panel--no-title' %}
    {% endif %}
    {% if params is defined and params and params.type is defined and params.type %}
        {% set typeClass = ' panel--' + params.type %}
    {% else %}
        {% set typeClass = ' panel--info' %}
    {% endif %}
    {% if params is defined and params.type == "warn-branded" %}
        {% set containerClass = 'census-warning' %}
    {% endif %}
    {% if params is defined and params.type == "announcement" %}
        {% set containerClass = 'announcement' %}
    {% endif %}
    {% if params is defined and params and params.spacious is defined and params.spacious %}
        {% set spaciousClass = ' panel--spacious' %}
    {% endif %}
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
    <div class="{{containerClass}}">
        <div class="container">
    {% endif %}
        <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
            {% if params is defined and params and params.type == "warn" or params.type == "warn-branded" %}
                <span class="panel__icon" aria-hidden="true">!</span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Warning: ") }}</span>
            {% endif %}
            {% if params is defined and params and params.type == "announcement" %}
                {% from "components/icons/_macro.njk" import onsIcon %}
                <span class="panel__icon" aria-hidden="true">
                    {{
                        onsIcon({
                            "icon": 'arrow-forward'
                        })
                    }}
                </span>
                <span class="u-vh">{{ params.assistiveTextPrefix | default("Announcement: ") }}</span>
            {% endif %}
            {% if params is defined and params %}
                {% if params.title is defined and params.title %}
                    {% if params is defined and params and params.type == 'error' %}
                        {% set defaultTitleTag = "h2" %}
                    {% else %}
                        {% set defaultTitleTag = "div" %}
                    {% endif %}
                    {% set titleTag = params.titleTag | default(defaultTitleTag) %}
                    <div class="panel__header">
                        <{{ titleTag }} id="error-summary-title" {% if params is defined and params and params.type is defined and params.type %}data-qa="{{ params.type }}-header"{% endif %} class="panel__title u-fs-r--b">{{ params.title | safe }}</{{ titleTag }}>
                    </div>
                {% else %}
                    {% if params.type is not defined or params.type == "branded" %}
                        <span class="u-vh">{{ params.assistiveTextPrefix | default("Important information: ") }}</span>
                    {% else %}
                        {% if params.type is defined and params.type == "success" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Completed: ") }}</span>
                        {% elif params.type is defined and params.type == "error" %}
                            <span class="u-vh">{{ params.assistiveTextPrefix | default("Error: ") }}</span>
                        {% endif %}
                    {% endif %}
                {% endif %}
                {% if params.icon is defined and params.icon %}
                    {% from "components/icons/_macro.njk" import onsIcon %}
                    <span class= "panel__icon u-fs-{{ params.iconSize }}">
                        {{
                            onsIcon({
                                "icon": params.icon,
                                "iconSize": params.iconSize
                            })
                        }}
                    </span>
                {% endif %}
            {% endif %}
            <div class="panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
                {{ caller() if caller }}
            </div>
        </div>
    {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement"  %}
        </div>
    </div>
    {% endif %}
{% endmacro %}

@mixin panel-type($name, $color, $color-bg) {
  .panel {
    &--#{$name} {
      background: $color-bg;
      border-color: $color;
    }
    &--#{$name} & {
      &__header {
        background: $color;
      }
    }
  }
}
.census-warning {
  background: $color-branded-tertiary;
}
.announcement {
  background-color: $color-black;
}
.panel {
  border-radius: 0;
  position: relative;
  // Removes inherited bottom margin to make whitespace inside panel equal
  > *:last-child {
    margin-bottom: 0;
  }
  .field {
    margin-bottom: 0;
  }
  &:focus {
    box-shadow: none;
    outline: 4px solid $color-focus !important;
    outline-offset: 0;
  }
  &__header {
    border-radius: 0;
    color: $color-white;
    margin: 0;
    padding: 0.75rem 1rem;
  }
  &__title {
    margin: 0;
  }
  &__body {
    padding: 1rem;
    // Removes inherited bottom margin to make whitespace inside panel equal
    > *:last-child,
    strong > *:last-child {
      margin-bottom: 0;
    }
    &.svg-icon-margin--xxl {
      padding-left: 3.3rem !important;
    }
    &.svg-icon-margin--xl {
      padding-left: 2.8rem !important;
    }
    &.svg-icon-margin--l {
      padding-left: 2.5rem !important;
    }
    &.svg-icon-margin--m {
      padding-left: 2.2rem !important;
    }
    &.svg-icon-margin--s {
      padding-left: 1.4rem !important;
    }
  }
  &__error {
    color: $color-errors;
  }
  &--warn {
    border: 0 !important;
    margin-bottom: 1rem;
    padding: 0;
    &--footer {
      background-color: $color-grey-15 !important;
      margin-bottom: 0;
      padding: 1rem 0 !important;
    }
  }
  &--warn-branded,
  &--announcement {
    border: 0 !important;
    color: $color-white;
    margin-bottom: 0;
    padding: 1rem 0 !important;
    a {
      color: inherit;
      text-decoration: underline solid $color-white 1px;
    }
    a:hover {
      text-decoration-thickness: 2px;
    }
  }
  &--announcement {
    a:focus {
      box-shadow: 0 -2px #fd0, 0 4px #fd0 !important; // Override focus style because the black border is not visible on a black background
    }
  }
  &--no-title {
    border-left: 8px solid transparent;
    padding: 1rem;
    .panel__body {
      background: none;
      padding: 0;
    }
    &.panel--warn {
      padding: 0;
    }
  }
  &--spacious {
    padding: 1rem;
    @include mq(m) {
      padding: 2rem;
    }
  }
  &--warn &,
  &--warn-branded &,
  &--announcement & {
    &__body {
      font-weight: $font-weight-bold;
      min-height: 2rem; // Height of icon
      padding: 0.222rem 0 0.222rem 2.8rem; // Alignment tweak
    }
    &__icon {
      background: $color-black;
      border-radius: 50%;
      color: $color-white;
      font-size: 1.5rem;
      font-weight: 900;
      line-height: 2rem;
      min-height: 2rem;
      min-width: 2rem;
      text-align: center;
    }
  }
  &--announcement & {
    &__body div > *:last-child {
      margin-bottom: 0;
    }
    &__icon {
      background-color: $color-white;
      color: $color-black;
      display: flex;
      svg {
        margin: auto;
      }
    }
  }
  &--warn-branded & {
    &__icon {
      background-color: $color-white;
      color: $color-branded-tertiary;
    }
  }
  &--success & {
    &__icon {
      fill: $color-success;
      left: 0;
      padding-left: 1rem;
      .svg-icon {
        margin-top: -15% !important;
      }
    }
    &__body {
      padding-left: 1.8rem;
    }
  }
  &--bare & {
    &__icon {
      height: 1.3rem;
      width: 1.3rem;
    }
    &__body {
      padding: 0.1rem 0 0 1.5rem;
    }
  }
  &--bare,
  &--success,
  &--warn,
  &--warn-branded,
  &--announcement {
    .panel__icon {
      position: absolute;
    }
  }
}
@include panel-type(error, $color-errors, $color-errors-tint);
@include panel-type(success, $color-success, $color-success-tint);
@include panel-type(info, $color-info, $color-info-tint);
@include panel-type(branded, $color-branded, $color-branded-tint);
@include panel-type(warn, $color-white, $color-white);
@include panel-type(warn-branded, $color-branded-tertiary, $color-branded-tertiary);
@include panel-type(announcement, $color-black, $color-black);

Help improve this component

Let us know how we could improve this component or share your user research findings.

Discuss the ‘Panel’ component on GitHub