Repository: govuk-react/govuk-react
Pull request #1079 (2022-04-30 19:49:17)

Support as= with strict TypeScript
**Checklist**:

* [x] Documentation (N/A)
* [x] Tests
* [x] Ready to be merged

**Motivation**:

When consuming this library with TypeScript, where there are custom overriden `as` props they are often typed with `React.ComponentType`, which means really means `React.ComponentType<{}>`, i.e. a React component without any props.

When using TypeScript in non-strict mode, it allows you to pass in a `React.ComponentType<Something>` for `React.ComponentType<{}>`, even though really it shouldn't - that's why it's been working previously.

This PR corrects the type by expanding it to `React.ComponentType<any>`. While generally the use of `any` is discouraged, here it is actually the right choice given we're saying that our `as` can be a component that takes any props. This strategy is used by many well-known libraries, including react itself and react-router:
- https://github.com/DefinitelyTyped/DefinitelyTyped/blob/310abbeba12679e25003079ebe9f011c2c95092c/types/react/index.d.ts#L828
- https://github.com/DefinitelyTyped/DefinitelyTyped/blob/310abbeba12679e25003079ebe9f011c2c95092c/types/react-router/index.d.ts#L92

In addition to this, where we have a storybook with react-router-dom it didn't do any type-checking because we hadn't installed the types for react-router-dom as dev dependency. I've installed them so it does a bit more checking. Unfortunately enabling strict in tsconfig didn't work on this repo - think there may be other things to fix. So for now it's not as safe as it could be... future work I guess :)

For searchability, the TypeScript error you get with this library looks something like (when used with a Button and react-router-dom v6):

```
No overload matches this call.
  Overload 1 of 3, '(props: ButtonPropsWithoutAs, ref?: ButtonRefType | undefined): ReactElement<ButtonPropsWithoutAs, string | JSXElementConstructor<any>>', gave the following error.
    Type 'ForwardRefExoticComponent<LinkProps & RefAttributes<HTMLAnchorElement>>' is not assignable to type 'undefined'.
  Overload 2 of 3, '(props: ButtonPropsWithAs<string | ComponentType<{}>, string | ComponentType<{}>>, ref?: Ref<string | ComponentType<{}>> | undefined): ReactElement<...>', gave the following error.
    Type 'ForwardRefExoticComponent<LinkProps & RefAttributes<HTMLAnchorElement>>' is not assignable to type 'string | ComponentType<{}> | undefined'.
      Type 'ForwardRefExoticComponent<LinkProps & RefAttributes<HTMLAnchorElement>>' is not assignable to type 'FunctionComponent<{}>'.
        Types of parameters 'props' and 'props' are incompatible.
          Type '{}' is not assignable to type 'LinkProps & RefAttributes<HTMLAnchorElement>'.
            Property 'to' is missing in type '{}' but required in type 'LinkProps'.
  Overload 3 of 3, '(props: ButtonOwnProps): ReactElement<any, string | JSXElementConstructor<any>> | null', gave the following error.
    Type '{ children: string; as: ForwardRefExoticComponent<LinkProps & RefAttributes<HTMLAnchorElement>>; to: string; icon: Element; start: true; onClick: () => void; }' is not assignable to type 'IntrinsicAttributes & ButtonOwnProps'.
      Property 'as' does not exist on type 'IntrinsicAttributes & ButtonOwnProps'.ts(2769)
index.d.ts(55, 5): The expected type comes from property 'as' which is declared here on type 'IntrinsicAttributes & { form?: string | undefined; slot?: string | undefined; style?: CSSProperties | undefined; title?: string | undefined; ... 271 more ...; buttonTextColour?: string | undefined; } & { ...; } & { ...; }'
index.d.ts(53, 5): 'to' is declared here.
index.d.ts(59, 5): The expected type comes from property 'as' which is declared here on type 'IntrinsicAttributes & ButtonPropsWithAs<string | ComponentType<{}>, string | ComponentType<{}>>'
```

penx: @domdomegg thanks for this! Really appreciated.

Please could you resolve conflicts and fix linting issues?
domdomegg: Hi @penx, thank you for the excellent library, I'm happy to contribute :)

I've resolved the conflicts and lint issues.
codecov-commenter: # [Codecov](https://codecov.io/gh/govuk-react/govuk-react/pull/1079?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react) Report
> Merging [#1079](https://codecov.io/gh/govuk-react/govuk-react/pull/1079?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react) (b526a29) into [main](https://codecov.io/gh/govuk-react/govuk-react/commit/553e19df15243b98cb153662fceb27d8d6346fa9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react) (553e19d) will **not change** coverage.
> The diff coverage is `n/a`.

> :exclamation: Current head b526a29 differs from pull request most recent head 1df9a88. Consider uploading reports for the commit 1df9a88 to get more accurate results

```diff
@@           Coverage Diff           @@
##             main    #1079   +/-   ##
=======================================
  Coverage   99.18%   99.18%           
=======================================
  Files         112      112           
  Lines         858      858           
  Branches      232      232           
=======================================
  Hits          851      851           
  Misses          7        7           
```


| [Impacted Files](https://codecov.io/gh/govuk-react/govuk-react/pull/1079?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react) | Coverage Δ | |
|---|---|---|
| [components/button/src/index.tsx](https://codecov.io/gh/govuk-react/govuk-react/pull/1079/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react#diff-Y29tcG9uZW50cy9idXR0b24vc3JjL2luZGV4LnRzeA==) | `100.00% <ø> (ø)` | |
| [components/heading/src/heading.tsx](https://codecov.io/gh/govuk-react/govuk-react/pull/1079/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react#diff-Y29tcG9uZW50cy9oZWFkaW5nL3NyYy9oZWFkaW5nLnRzeA==) | `100.00% <ø> (ø)` | |
| [components/pagination/src/anchor.tsx](https://codecov.io/gh/govuk-react/govuk-react/pull/1079/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react#diff-Y29tcG9uZW50cy9wYWdpbmF0aW9uL3NyYy9hbmNob3IudHN4) | `100.00% <ø> (ø)` | |
| [components/tabs/src/atoms/tab/index.tsx](https://codecov.io/gh/govuk-react/govuk-react/pull/1079/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react#diff-Y29tcG9uZW50cy90YWJzL3NyYy9hdG9tcy90YWIvaW5kZXgudHN4) | `100.00% <ø> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/govuk-react/govuk-react/pull/1079?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/govuk-react/govuk-react/pull/1079?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react). Last update [553e19d...1df9a88](https://codecov.io/gh/govuk-react/govuk-react/pull/1079?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=govuk-react).


Patch:
diff --git a/API.md b/API.md
index 565c1f85..cc0fe8e8 100644
--- a/API.md
+++ b/API.md
@@ -2159,6 +2159,7 @@ Prop | Required | Default | Type | Description
  `children` |  | ```undefined``` | ReactNode | Footer navigation links
  `container` |  | ```Footer.WidthContainer``` | ElementType<any> | Override the default footer container component.<br/>`children`, `copyright` and `meta` will be placed inside this component.
  `copyright` |  | ```undefined``` | CopyrightProps | Copyright information
+ `licence` |  | ```<Licence />``` | ReactNode | Licence content
  `meta` |  | ```undefined``` | ReactNode | Meta text and links
 
 
diff --git a/components/button/src/index.tsx b/components/button/src/index.tsx
index 2979f817..d5e240bf 100644
--- a/components/button/src/index.tsx
+++ b/components/button/src/index.tsx
@@ -231,7 +231,8 @@ type ButtonRefType = React.Ref<HTMLButtonElement>;
 
 export interface ButtonType extends React.ForwardRefExoticComponent<ButtonOwnProps> {
   (props: ButtonPropsWithoutAs, ref?: ButtonRefType): React.ReactElement<ButtonPropsWithoutAs>;
-  <AsC extends string | React.ComponentType = 'button', FAsC extends string | React.ComponentType = AsC>(
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  <AsC extends string | React.ComponentType<any> = 'button', FAsC extends string | React.ComponentType<any> = AsC>(
     props: ButtonPropsWithAs<AsC, FAsC>,
     ref?: React.Ref<AsC>
   ): React.ReactElement<ButtonPropsWithAs<AsC, FAsC>>;
@@ -243,8 +244,10 @@ type ButtonPropsWithoutAs = StyledComponentProps<'button', never, ButtonOwnProps
 };
 
 type ButtonPropsWithAs<
-  AsC extends string | React.ComponentType,
-  FAsC extends string | React.ComponentType = AsC
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  AsC extends string | React.ComponentType<any>,
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  FAsC extends string | React.ComponentType<any> = AsC
 > = StyledComponentProps<AsC, never, ButtonOwnProps, never, FAsC> & {
   as?: AsC | undefined;
   forwardedAs?: FAsC | undefined;
diff --git a/components/footer/README.md b/components/footer/README.md
index 9be624dd..1c969feb 100644
--- a/components/footer/README.md
+++ b/components/footer/README.md
@@ -18,6 +18,7 @@ Prop | Required | Default | Type | Description
  `children` |  | ```undefined``` | ReactNode | Footer navigation links
  `container` |  | ```Footer.WidthContainer``` | ElementType<any> | Override the default footer container component.<br/>`children`, `copyright` and `meta` will be placed inside this component.
  `copyright` |  | ```undefined``` | CopyrightProps | Copyright information
+ `licence` |  | ```<Licence />``` | ReactNode | Licence content
  `meta` |  | ```undefined``` | ReactNode | Meta text and links
 
 
diff --git a/components/footer/src/index.tsx b/components/footer/src/index.tsx
index e9677bbf..2b9901ca 100644
--- a/components/footer/src/index.tsx
+++ b/components/footer/src/index.tsx
@@ -16,6 +16,7 @@ import Navigation from './atoms/navigation';
 import Link from './atoms/link';
 import SectionBreak from './atoms/section-break';
 import MetaCustom from './atoms/meta-custom';
+import Licence from './atoms/licence';
 
 import MetaContainer from './molecules/meta-container';
 import MetaLinks from './molecules/meta-links';
@@ -48,6 +49,7 @@ export const Footer: FooterType = ({
   container: Container = Footer.WidthContainer,
   copyright = undefined,
   meta = undefined,
+  licence = <Licence />,
   ...props
 }: FooterProps) => (
   <FooterContainer role="contentinfo" {...props}>
@@ -58,7 +60,9 @@ export const Footer: FooterType = ({
           <SectionBreak />
         </>
       )}
-      <MetaContainer copyright={copyright}>{meta}</MetaContainer>
+      <MetaContainer copyright={copyright} licence={licence}>
+        {meta}
+      </MetaContainer>
     </Container>
   </FooterContainer>
 );
@@ -72,6 +76,7 @@ export interface FooterType extends React.FC<FooterProps> {
   MetaLinks: typeof MetaLinks;
   NavigationLinks: typeof NavigationLinks;
   WidthContainer: typeof WidthContainer;
+  Licence: typeof Licence;
 }
 
 interface FooterProps {
@@ -92,6 +97,10 @@ interface FooterProps {
    * Meta text and links
    */
   meta?: React.ReactNode;
+  /**
+   * Licence content
+   */
+  licence?: false | string | React.ReactNode;
 }
 Footer.Link = Link;
 Footer.Navigation = Navigation;
@@ -99,12 +108,14 @@ Footer.MetaCustom = MetaCustom;
 Footer.MetaLinks = MetaLinks;
 Footer.NavigationLinks = NavigationLinks;
 Footer.WidthContainer = WidthContainer;
+Footer.Licence = Licence;
 
 Footer.defaultProps = {
   children: undefined,
   container: Footer.WidthContainer,
   copyright: undefined,
   meta: undefined,
+  licence: <Licence />,
 };
 
 export default Footer;
diff --git a/components/footer/src/molecules/meta-container/index.tsx b/components/footer/src/molecules/meta-container/index.tsx
index fde7008c..4e6958ee 100644
--- a/components/footer/src/molecules/meta-container/index.tsx
+++ b/components/footer/src/molecules/meta-container/index.tsx
@@ -5,12 +5,12 @@ import MetaItem from '../../atoms/meta-item';
 import Licence from '../../atoms/licence';
 import Copyright from '../../atoms/copyright';
 
-const MetaContainer: React.FC<MetaContainerProps> = ({ children, copyright }: MetaContainerProps) => {
+const MetaContainer: React.FC<MetaContainerProps> = ({ children, copyright, licence }: MetaContainerProps) => {
   return (
     <Meta>
       <MetaItem grow>
         {children}
-        <Licence />
+        {licence}
       </MetaItem>
       {copyright && (
         <MetaItem>
@@ -39,11 +39,16 @@ interface MetaContainerProps {
     };
     link?: string;
   };
+  /**
+   * Licence content
+   */
+  licence?: false | string | React.ReactNode;
 }
 
 MetaContainer.defaultProps = {
   children: undefined,
   copyright: undefined,
+  licence: <Licence />,
 };
 
 export default MetaContainer;
diff --git a/components/footer/src/stories.tsx b/components/footer/src/stories.tsx
index dcc74782..8ec15dc6 100644
--- a/components/footer/src/stories.tsx
+++ b/components/footer/src/stories.tsx
@@ -46,6 +46,26 @@ WithCopyright.args = {
   },
 };
 
+export const WithCustomLicense = Template.bind({});
+
+WithCustomLicense.args = {
+  licence: (
+    <span>
+      All content is available under the{' '}
+      <Footer.Link href="https://creativecommons.org/licenses/by/4.0/" rel="license">
+        Creative Commons Attribution 4.0 International Licence
+      </Footer.Link>
+      , except where otherwise stated
+    </span>
+  ),
+};
+
+export const WithNoLicense = Template.bind({});
+
+WithNoLicense.args = {
+  licence: false,
+};
+
 export const WithMetaLinks = Template.bind({});
 WithMetaLinks.args = {
   meta: (
diff --git a/components/heading/src/heading.tsx b/components/heading/src/heading.tsx
index 901b2f6d..8cbf78de 100644
--- a/components/heading/src/heading.tsx
+++ b/components/heading/src/heading.tsx
@@ -75,7 +75,8 @@ Heading.displayName = 'Heading';
 
 export interface HeadingType extends React.FC<HeadingOwnProps & WithWhiteSpaceProps> {
   (props: HeadingPropsWithoutAs): React.ReactElement<HeadingPropsWithoutAs>;
-  <AsC extends string | React.ComponentType = 'h1', FAsC extends string | React.ComponentType = AsC>(
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  <AsC extends string | React.ComponentType<any> = 'h1', FAsC extends string | React.ComponentType<any> = AsC>(
     props: HeadingPropsWithAs<AsC, FAsC>
   ): React.ReactElement<HeadingPropsWithAs<AsC, FAsC>>;
 }
@@ -86,8 +87,10 @@ type HeadingPropsWithoutAs = StyledComponentProps<'h1', never, HeadingOwnProps,
 };
 
 type HeadingPropsWithAs<
-  AsC extends string | React.ComponentType,
-  FAsC extends string | React.ComponentType = AsC
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  AsC extends string | React.ComponentType<any>,
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  FAsC extends string | React.ComponentType<any> = AsC
 > = StyledComponentProps<AsC, never, HeadingOwnProps, never, FAsC> & {
   as?: AsC | undefined;
   forwardedAs?: FAsC | undefined;
diff --git a/components/pagination/src/anchor.tsx b/components/pagination/src/anchor.tsx
index c191399f..df80fa2c 100644
--- a/components/pagination/src/anchor.tsx
+++ b/components/pagination/src/anchor.tsx
@@ -114,7 +114,8 @@ const PaginationAnchor: PaginationAnchorType = ({
 
 interface PaginationAnchorType extends React.FC<PaginationAnchorProps> {
   (props: PaginationAnchorPropsWithoutAs): React.ReactElement<PaginationAnchorPropsWithoutAs>;
-  <AsC extends string | React.ComponentType = 'a', FAsC extends string | React.ComponentType = AsC>(
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  <AsC extends string | React.ComponentType<any> = 'a', FAsC extends string | React.ComponentType<any> = AsC>(
     props: PaginationAnchorPropsWithAs<AsC, FAsC>
   ): React.ReactElement<PaginationAnchorPropsWithAs<AsC, FAsC>>;
 }
@@ -125,8 +126,10 @@ type PaginationAnchorPropsWithoutAs = StyledComponentProps<'a', never, Paginatio
 };
 
 type PaginationAnchorPropsWithAs<
-  AsC extends string | React.ComponentType,
-  FAsC extends string | React.ComponentType = AsC
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  AsC extends string | React.ComponentType<any>,
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  FAsC extends string | React.ComponentType<any> = AsC
 > = StyledComponentProps<AsC, never, PaginationAnchorProps, never, FAsC> & {
   as?: AsC | undefined;
   forwardedAs?: FAsC | undefined;
diff --git a/components/tabs/src/atoms/tab/index.tsx b/components/tabs/src/atoms/tab/index.tsx
index 2df36895..ad0179b9 100644
--- a/components/tabs/src/atoms/tab/index.tsx
+++ b/components/tabs/src/atoms/tab/index.tsx
@@ -78,7 +78,8 @@ Tab.defaultProps = {
 
 interface TabType extends React.FC<TabOwnProps> {
   (props: TabPropsWithoutAs): React.ReactElement<TabPropsWithoutAs>;
-  <AsC extends string | React.ComponentType = 'a', FAsC extends string | React.ComponentType = AsC>(
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  <AsC extends string | React.ComponentType<any> = 'a', FAsC extends string | React.ComponentType<any> = AsC>(
     props: TabPropsWithAs<AsC, FAsC>
   ): React.ReactElement<TabPropsWithAs<AsC, FAsC>>;
 }
@@ -89,8 +90,10 @@ type TabPropsWithoutAs = StyledComponentProps<'a', never, TabOwnProps, never> &
 };
 
 type TabPropsWithAs<
-  AsC extends string | React.ComponentType,
-  FAsC extends string | React.ComponentType = AsC
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  AsC extends string | React.ComponentType<any>,
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  FAsC extends string | React.ComponentType<any> = AsC
 > = StyledComponentProps<AsC, never, TabOwnProps, never, FAsC> & {
   as?: AsC | undefined;
   forwardedAs?: FAsC | undefined;
diff --git a/package.json b/package.json
index 1a1fe763..6dd88c3c 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
     "@testing-library/react": "^11.2.7",
     "@testing-library/user-event": "^13.1.9",
     "@types/react": "^16.14.16",
+    "@types/react-router-dom": "5",
     "@types/styled-components": "^5.1.14",
     "@typescript-eslint/eslint-plugin": "^4.0.0",
     "@typescript-eslint/parser": "^4.25.0",
diff --git a/yarn.lock b/yarn.lock
index 2d046b2a..d133bd83 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2544,6 +2544,7 @@ __metadata:
     "@testing-library/react": ^11.2.7
     "@testing-library/user-event": ^13.1.9
     "@types/react": ^16.14.16
+    "@types/react-router-dom": 5
     "@types/styled-components": ^5.1.14
     "@typescript-eslint/eslint-plugin": ^4.0.0
     "@typescript-eslint/parser": ^4.25.0
@@ -5694,6 +5695,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/history@npm:^4.7.11":
+  version: 4.7.11
+  resolution: "@types/history@npm:4.7.11"
+  checksum: c92e2ba407dcab0581a9afdf98f533aa41b61a71133420a6d92b1ca9839f741ab1f9395b17454ba5b88cb86020b70b22d74a1950ccfbdfd9beeaa5459fdc3464
+  languageName: node
+  linkType: hard
+
 "@types/hoist-non-react-statics@npm:*":
   version: 3.3.1
   resolution: "@types/hoist-non-react-statics@npm:3.3.1"
@@ -5941,6 +5949,27 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/react-router-dom@npm:5":
+  version: 5.3.3
+  resolution: "@types/react-router-dom@npm:5.3.3"
+  dependencies:
+    "@types/history": ^4.7.11
+    "@types/react": "*"
+    "@types/react-router": "*"
+  checksum: 28c4ea48909803c414bf5a08502acbb8ba414669b4b43bb51297c05fe5addc4df0b8fd00e0a9d1e3535ec4073ef38aaafac2c4a2b95b787167d113bc059beff3
+  languageName: node
+  linkType: hard
+
+"@types/react-router@npm:*":
+  version: 5.1.18
+  resolution: "@types/react-router@npm:5.1.18"
+  dependencies:
+    "@types/history": ^4.7.11
+    "@types/react": "*"
+  checksum: f08b37ee822f9f9ff904ffd0778fe2bb7c717ed3ee311610382ee024d02a35169bd3301ecde863cac21aae8fdee919501e8ea22bad0260c02c10cfbdba5c71be
+  languageName: node
+  linkType: hard
+
 "@types/react-syntax-highlighter@npm:11.0.5":
   version: 11.0.5
   resolution: "@types/react-syntax-highlighter@npm:11.0.5"


Test patch:
diff --git a/components/footer/src/__snapshots__/test.tsx.snap b/components/footer/src/__snapshots__/test.tsx.snap
index 18b4994a..4304452d 100644
--- a/components/footer/src/__snapshots__/test.tsx.snap
+++ b/components/footer/src/__snapshots__/test.tsx.snap
@@ -47,6 +47,17 @@ exports[`Footer matches default snapshot: Footer 1`] = `
   color: #171819;
 }
 
+.c4 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c5 {
+  display: inline-block;
+}
+
 .c2 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -82,17 +93,6 @@ exports[`Footer matches default snapshot: Footer 1`] = `
   flex-basis: 320px;
 }
 
-.c4 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c5 {
-  display: inline-block;
-}
-
 .c0 {
   border-top: 1px solid #a1acb2;
   background: #f3f2f1;
@@ -135,6 +135,12 @@ exports[`Footer matches default snapshot: Footer 1`] = `
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c4 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c2 {
     font-family: sans-serif;
@@ -149,12 +155,6 @@ exports[`Footer matches default snapshot: Footer 1`] = `
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c4 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c0 {
     font-size: 14px;
@@ -214,6 +214,7 @@ exports[`Footer matches default snapshot: Footer 1`] = `
       "withComponent": [Function],
     }
   }
+  licence={<Licence />}
 >
   <src__FooterContainer
     role="contentinfo"
@@ -226,7 +227,9 @@ exports[`Footer matches default snapshot: Footer 1`] = `
         <div
           className="c1"
         >
-          <MetaContainer>
+          <MetaContainer
+            licence={<Licence />}
+          >
             <meta__Meta>
               <div
                 className="c2"
@@ -347,6 +350,17 @@ exports[`Footer matches with copyright snapshot: FooterWithCopyright 1`] = `
   color: #171819;
 }
 
+.c4 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c5 {
+  display: inline-block;
+}
+
 .c2 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -388,17 +402,6 @@ exports[`Footer matches with copyright snapshot: FooterWithCopyright 1`] = `
   margin-left: 15px;
 }
 
-.c4 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c5 {
-  display: inline-block;
-}
-
 .c9 {
   display: inline-block;
   text-align: center;
@@ -464,6 +467,12 @@ exports[`Footer matches with copyright snapshot: FooterWithCopyright 1`] = `
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c4 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c2 {
     font-family: sans-serif;
@@ -478,12 +487,6 @@ exports[`Footer matches with copyright snapshot: FooterWithCopyright 1`] = `
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c4 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c0 {
     font-size: 14px;
@@ -555,6 +558,7 @@ exports[`Footer matches with copyright snapshot: FooterWithCopyright 1`] = `
         "text": "Crown copyright",
       }
     }
+    licence={<Licence />}
   >
     <src__FooterContainer
       role="contentinfo"
@@ -579,6 +583,7 @@ exports[`Footer matches with copyright snapshot: FooterWithCopyright 1`] = `
                   "text": "Crown copyright",
                 }
               }
+              licence={<Licence />}
             >
               <meta__Meta>
                 <div
@@ -702,6 +707,293 @@ exports[`Footer matches with copyright snapshot: FooterWithCopyright 1`] = `
 </FooterWithCopyright>
 `;
 
+exports[`Footer matches with custom licence: FooterWithCustomLicence 1`] = `
+.c1 {
+  max-width: 960px;
+  margin: 0 15px;
+}
+
+.c4 {
+  font-family: "nta",Arial,sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.c4:focus {
+  outline: 3px solid #ffdd00;
+  outline-offset: 0;
+  background-color: #ffdd00;
+}
+
+.c4:link {
+  color: #1d70b8;
+}
+
+.c4:visited {
+  color: #4c2c92;
+}
+
+.c4:hover {
+  color: #2b8cc4;
+}
+
+.c4:active {
+  color: #2b8cc4;
+}
+
+.c4:focus {
+  color: #0b0c0c;
+}
+
+.c5:link,
+.c5:visited {
+  color: #454a4c;
+}
+
+.c5:hover {
+  color: #171819;
+}
+
+.c2 {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  margin-right: -15px;
+  margin-left: -15px;
+  -webkit-flex-wrap: wrap;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  -webkit-align-items: flex-end;
+  -webkit-box-align: flex-end;
+  -ms-flex-align: flex-end;
+  align-items: flex-end;
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+  -ms-flex-pack: center;
+  justify-content: center;
+  font-family: "nta",Arial,sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.c3 {
+  margin-right: 15px;
+  margin-bottom: 25px;
+  margin-left: 15px;
+  -webkit-flex: 1;
+  -ms-flex: 1;
+  flex: 1;
+  -webkit-flex-basis: 320px;
+  -ms-flex-preferred-size: 320px;
+  flex-basis: 320px;
+}
+
+.c0 {
+  border-top: 1px solid #a1acb2;
+  background: #f3f2f1;
+  color: #454a4c;
+  font-family: "nta",Arial,sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  font-weight: 400;
+  font-size: 14px;
+  line-height: 1.1428571428571428;
+  padding-top: 25px;
+  padding-bottom: 15px;
+}
+
+@media only screen and (min-width:641px) {
+  .c1 {
+    margin: 0 30px;
+  }
+}
+
+@media only screen and (min-width:1020px) {
+  .c1 {
+    margin: 0 auto;
+  }
+}
+
+@media print {
+  .c4 {
+    font-family: sans-serif;
+  }
+}
+
+@media print {
+  .c4[href^="/"]::after,
+  .c4[href^="http://"]::after,
+  .c4[href^="https://"]::after {
+    content: " (" attr(href) ")";
+    font-size: 90%;
+    word-wrap: break-word;
+  }
+}
+
+@media print {
+  .c2 {
+    font-family: sans-serif;
+  }
+}
+
+@media only screen and (min-width:769px) {
+  .c3 {
+    -webkit-flex-basis: 0;
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+  }
+}
+
+@media print {
+  .c0 {
+    font-size: 14px;
+    line-height: 1.2;
+  }
+}
+
+@media only screen and (min-width:641px) {
+  .c0 {
+    font-size: 16px;
+    line-height: 1.25;
+  }
+}
+
+@media only screen and (min-width:641px) {
+  .c0 {
+    padding-top: 40px;
+  }
+}
+
+@media only screen and (min-width:641px) {
+  .c0 {
+    padding-bottom: 25px;
+  }
+}
+
+<FooterWithCustomLicence>
+  <Footer
+    container={
+      Object {
+        "$$typeof": Symbol(react.forward_ref),
+        "attrs": Array [],
+        "componentStyle": e {
+          "baseHash": -2081739897,
+          "baseStyle": undefined,
+          "componentId": "width-container__WidthContainer-sc-213f5v-0",
+          "isStatic": false,
+          "rules": Array [
+            "max-width: 960px;",
+            "margin: 0 15px;",
+            "@media only screen and (min-width: 641px) {",
+            "margin: 0 30px;",
+            "}",
+            "@media only screen and (min-width: 1020px) {",
+            "margin: 0 auto;",
+            "}",
+            [Function],
+          ],
+          "staticRulesId": "",
+        },
+        "foldedComponentIds": Array [],
+        "render": [Function],
+        "shouldForwardProp": undefined,
+        "styledComponentId": "width-container__WidthContainer-sc-213f5v-0",
+        "target": "div",
+        "toString": [Function],
+        "warnTooManyClasses": [Function],
+        "withComponent": [Function],
+      }
+    }
+    licence={
+      <span>
+        All content is available under the
+         
+        <link__FooterLink
+          href="https://creativecommons.org/licenses/by/4.0/"
+          muted={false}
+          noVisitedState={false}
+          rel="license"
+          textColour={false}
+        >
+          Creative Commons Attribution 4.0 International Licence
+        </link__FooterLink>
+        , except where otherwise stated
+      </span>
+    }
+  >
+    <src__FooterContainer
+      role="contentinfo"
+    >
+      <footer
+        className="c0"
+        role="contentinfo"
+      >
+        <width-container__WidthContainer>
+          <div
+            className="c1"
+          >
+            <MetaContainer
+              licence={
+                <span>
+                  All content is available under the
+                   
+                  <link__FooterLink
+                    href="https://creativecommons.org/licenses/by/4.0/"
+                    muted={false}
+                    noVisitedState={false}
+                    rel="license"
+                    textColour={false}
+                  >
+                    Creative Commons Attribution 4.0 International Licence
+                  </link__FooterLink>
+                  , except where otherwise stated
+                </span>
+              }
+            >
+              <meta__Meta>
+                <div
+                  className="c2"
+                >
+                  <meta-item__MetaItem
+                    grow={true}
+                  >
+                    <div
+                      className="c3"
+                    >
+                      <span>
+                        All content is available under the
+                         
+                        <link__FooterLink
+                          href="https://creativecommons.org/licenses/by/4.0/"
+                          muted={false}
+                          noVisitedState={false}
+                          rel="license"
+                          textColour={false}
+                        >
+                          <a
+                            className="c4 c5"
+                            href="https://creativecommons.org/licenses/by/4.0/"
+                            rel="license"
+                          >
+                            Creative Commons Attribution 4.0 International Licence
+                          </a>
+                        </link__FooterLink>
+                        , except where otherwise stated
+                      </span>
+                    </div>
+                  </meta-item__MetaItem>
+                </div>
+              </meta__Meta>
+            </MetaContainer>
+          </div>
+        </width-container__WidthContainer>
+      </footer>
+    </src__FooterContainer>
+  </Footer>
+</FooterWithCustomLicence>
+`;
+
 exports[`Footer matches with custom width snapshot: FooterWithCustomWidth 1`] = `
 .c1 {
   max-width: 960px;
@@ -749,6 +1041,17 @@ exports[`Footer matches with custom width snapshot: FooterWithCustomWidth 1`] =
   color: #171819;
 }
 
+.c5 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c6 {
+  display: inline-block;
+}
+
 .c3 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -784,17 +1087,6 @@ exports[`Footer matches with custom width snapshot: FooterWithCustomWidth 1`] =
   flex-basis: 320px;
 }
 
-.c5 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c6 {
-  display: inline-block;
-}
-
 .c0 {
   border-top: 1px solid #a1acb2;
   background: #f3f2f1;
@@ -841,6 +1133,12 @@ exports[`Footer matches with custom width snapshot: FooterWithCustomWidth 1`] =
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c5 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c3 {
     font-family: sans-serif;
@@ -855,12 +1153,6 @@ exports[`Footer matches with custom width snapshot: FooterWithCustomWidth 1`] =
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c5 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c0 {
     font-size: 14px;
@@ -941,6 +1233,7 @@ exports[`Footer matches with custom width snapshot: FooterWithCustomWidth 1`] =
         "withComponent": [Function],
       }
     }
+    licence={<Licence />}
   >
     <src__FooterContainer
       role="contentinfo"
@@ -953,7 +1246,9 @@ exports[`Footer matches with custom width snapshot: FooterWithCustomWidth 1`] =
           <div
             className="c1 c2"
           >
-            <MetaContainer>
+            <MetaContainer
+              licence={<Licence />}
+            >
               <meta__Meta>
                 <div
                   className="c3"
@@ -1079,6 +1374,17 @@ exports[`Footer matches with meta custom snapshot: FooterWithMetaCustom 1`] = `
   margin-bottom: 20px;
 }
 
+.c7 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c8 {
+  display: inline-block;
+}
+
 .c2 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -1114,17 +1420,6 @@ exports[`Footer matches with meta custom snapshot: FooterWithMetaCustom 1`] = `
   flex-basis: 320px;
 }
 
-.c7 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c8 {
-  display: inline-block;
-}
-
 .c0 {
   border-top: 1px solid #a1acb2;
   background: #f3f2f1;
@@ -1167,6 +1462,12 @@ exports[`Footer matches with meta custom snapshot: FooterWithMetaCustom 1`] = `
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c7 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c2 {
     font-family: sans-serif;
@@ -1181,12 +1482,6 @@ exports[`Footer matches with meta custom snapshot: FooterWithMetaCustom 1`] = `
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c7 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c0 {
     font-size: 14px;
@@ -1247,6 +1542,7 @@ exports[`Footer matches with meta custom snapshot: FooterWithMetaCustom 1`] = `
         "withComponent": [Function],
       }
     }
+    licence={<Licence />}
     meta={
       <meta-custom__MetaCustom>
         Built by the 
@@ -1272,7 +1568,9 @@ exports[`Footer matches with meta custom snapshot: FooterWithMetaCustom 1`] = `
           <div
             className="c1"
           >
-            <MetaContainer>
+            <MetaContainer
+              licence={<Licence />}
+            >
               <meta__Meta>
                 <div
                   className="c2"
@@ -1418,6 +1716,17 @@ exports[`Footer matches with meta links and custom snapshot: FooterWithMetaLinks
   margin-bottom: 20px;
 }
 
+.c11 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c12 {
+  display: inline-block;
+}
+
 .c2 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -1453,17 +1762,6 @@ exports[`Footer matches with meta links and custom snapshot: FooterWithMetaLinks
   flex-basis: 320px;
 }
 
-.c11 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c12 {
-  display: inline-block;
-}
-
 .c5 {
   color: #0b0c0c;
   font-family: "nta",Arial,sans-serif;
@@ -1550,6 +1848,12 @@ exports[`Footer matches with meta links and custom snapshot: FooterWithMetaLinks
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c11 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c2 {
     font-family: sans-serif;
@@ -1564,12 +1868,6 @@ exports[`Footer matches with meta links and custom snapshot: FooterWithMetaLinks
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c11 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c5 {
     color: #000;
@@ -1679,6 +1977,7 @@ exports[`Footer matches with meta links and custom snapshot: FooterWithMetaLinks
             "withComponent": [Function],
           }
         }
+        licence={<Licence />}
         meta={
           <React.Fragment>
             <MetaLinks
@@ -1747,7 +2046,9 @@ exports[`Footer matches with meta links and custom snapshot: FooterWithMetaLinks
               <div
                 className="c1"
               >
-                <MetaContainer>
+                <MetaContainer
+                  licence={<Licence />}
+                >
                   <meta__Meta>
                     <div
                       className="c2"
@@ -2029,6 +2330,17 @@ exports[`Footer matches with meta links snapshot: FooterWithMetaLinks 1`] = `
   color: #171819;
 }
 
+.c10 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c11 {
+  display: inline-block;
+}
+
 .c2 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -2064,17 +2376,6 @@ exports[`Footer matches with meta links snapshot: FooterWithMetaLinks 1`] = `
   flex-basis: 320px;
 }
 
-.c10 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c11 {
-  display: inline-block;
-}
-
 .c5 {
   color: #0b0c0c;
   font-family: "nta",Arial,sans-serif;
@@ -2161,6 +2462,12 @@ exports[`Footer matches with meta links snapshot: FooterWithMetaLinks 1`] = `
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c10 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c2 {
     font-family: sans-serif;
@@ -2175,12 +2482,6 @@ exports[`Footer matches with meta links snapshot: FooterWithMetaLinks 1`] = `
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c10 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c5 {
     color: #000;
@@ -2290,6 +2591,7 @@ exports[`Footer matches with meta links snapshot: FooterWithMetaLinks 1`] = `
             "withComponent": [Function],
           }
         }
+        licence={<Licence />}
         meta={
           <MetaLinks
             heading="Support links"
@@ -2345,7 +2647,9 @@ exports[`Footer matches with meta links snapshot: FooterWithMetaLinks 1`] = `
               <div
                 className="c1"
               >
-                <MetaContainer>
+                <MetaContainer
+                  licence={<Licence />}
+                >
                   <meta__Meta>
                     <div
                       className="c2"
@@ -2630,6 +2934,17 @@ exports[`Footer matches with navigation and meta snapshot: FooterWithNavigationA
   margin-bottom: 20px;
 }
 
+.c19 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c20 {
+  display: inline-block;
+}
+
 .c12 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -2665,17 +2980,6 @@ exports[`Footer matches with navigation and meta snapshot: FooterWithNavigationA
   flex-basis: 320px;
 }
 
-.c19 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c20 {
-  display: inline-block;
-}
-
 .c5 {
   color: #0b0c0c;
   font-family: "nta",Arial,sans-serif;
@@ -2830,6 +3134,12 @@ exports[`Footer matches with navigation and meta snapshot: FooterWithNavigationA
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c19 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c12 {
     font-family: sans-serif;
@@ -2844,12 +3154,6 @@ exports[`Footer matches with navigation and meta snapshot: FooterWithNavigationA
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c19 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c5 {
     color: #000;
@@ -3025,6 +3329,7 @@ exports[`Footer matches with navigation and meta snapshot: FooterWithNavigationA
             "withComponent": [Function],
           }
         }
+        licence={<Licence />}
         meta={
           <React.Fragment>
             <MetaLinks
@@ -3421,7 +3726,9 @@ exports[`Footer matches with navigation and meta snapshot: FooterWithNavigationA
                     className="c11"
                   />
                 </section-break__SectionBreak>
-                <MetaContainer>
+                <MetaContainer
+                  licence={<Licence />}
+                >
                   <meta__Meta>
                     <div
                       className="c12"
@@ -3722,6 +4029,17 @@ exports[`Footer matches with navigation snapshot: FooterWithNavigation 1`] = `
   margin-bottom: 30px;
 }
 
+.c14 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c15 {
+  display: inline-block;
+}
+
 .c12 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -3757,17 +4075,6 @@ exports[`Footer matches with navigation snapshot: FooterWithNavigation 1`] = `
   flex-basis: 320px;
 }
 
-.c14 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c15 {
-  display: inline-block;
-}
-
 .c5 {
   color: #0b0c0c;
   font-family: "nta",Arial,sans-serif;
@@ -3878,6 +4185,12 @@ exports[`Footer matches with navigation snapshot: FooterWithNavigation 1`] = `
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c14 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c12 {
     font-family: sans-serif;
@@ -3892,12 +4205,6 @@ exports[`Footer matches with navigation snapshot: FooterWithNavigation 1`] = `
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c14 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c5 {
     color: #000;
@@ -4047,6 +4354,7 @@ exports[`Footer matches with navigation snapshot: FooterWithNavigation 1`] = `
             "withComponent": [Function],
           }
         }
+        licence={<Licence />}
       >
         <src__FooterContainer
           role="contentinfo"
@@ -4387,7 +4695,9 @@ exports[`Footer matches with navigation snapshot: FooterWithNavigation 1`] = `
                     className="c11"
                   />
                 </section-break__SectionBreak>
-                <MetaContainer>
+                <MetaContainer
+                  licence={<Licence />}
+                >
                   <meta__Meta>
                     <div
                       className="c12"
@@ -4472,6 +4782,185 @@ exports[`Footer matches with navigation snapshot: FooterWithNavigation 1`] = `
 </FooterWithNavigation>
 `;
 
+exports[`Footer matches with no licence: FooterWithNoLicense 1`] = `
+.c1 {
+  max-width: 960px;
+  margin: 0 15px;
+}
+
+.c2 {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  margin-right: -15px;
+  margin-left: -15px;
+  -webkit-flex-wrap: wrap;
+  -ms-flex-wrap: wrap;
+  flex-wrap: wrap;
+  -webkit-align-items: flex-end;
+  -webkit-box-align: flex-end;
+  -ms-flex-align: flex-end;
+  align-items: flex-end;
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+  -ms-flex-pack: center;
+  justify-content: center;
+  font-family: "nta",Arial,sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.c3 {
+  margin-right: 15px;
+  margin-bottom: 25px;
+  margin-left: 15px;
+  -webkit-flex: 1;
+  -ms-flex: 1;
+  flex: 1;
+  -webkit-flex-basis: 320px;
+  -ms-flex-preferred-size: 320px;
+  flex-basis: 320px;
+}
+
+.c0 {
+  border-top: 1px solid #a1acb2;
+  background: #f3f2f1;
+  color: #454a4c;
+  font-family: "nta",Arial,sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  font-weight: 400;
+  font-size: 14px;
+  line-height: 1.1428571428571428;
+  padding-top: 25px;
+  padding-bottom: 15px;
+}
+
+@media only screen and (min-width:641px) {
+  .c1 {
+    margin: 0 30px;
+  }
+}
+
+@media only screen and (min-width:1020px) {
+  .c1 {
+    margin: 0 auto;
+  }
+}
+
+@media print {
+  .c2 {
+    font-family: sans-serif;
+  }
+}
+
+@media only screen and (min-width:769px) {
+  .c3 {
+    -webkit-flex-basis: 0;
+    -ms-flex-preferred-size: 0;
+    flex-basis: 0;
+  }
+}
+
+@media print {
+  .c0 {
+    font-size: 14px;
+    line-height: 1.2;
+  }
+}
+
+@media only screen and (min-width:641px) {
+  .c0 {
+    font-size: 16px;
+    line-height: 1.25;
+  }
+}
+
+@media only screen and (min-width:641px) {
+  .c0 {
+    padding-top: 40px;
+  }
+}
+
+@media only screen and (min-width:641px) {
+  .c0 {
+    padding-bottom: 25px;
+  }
+}
+
+<FooterWithNoLicense>
+  <Footer
+    container={
+      Object {
+        "$$typeof": Symbol(react.forward_ref),
+        "attrs": Array [],
+        "componentStyle": e {
+          "baseHash": -2081739897,
+          "baseStyle": undefined,
+          "componentId": "width-container__WidthContainer-sc-213f5v-0",
+          "isStatic": false,
+          "rules": Array [
+            "max-width: 960px;",
+            "margin: 0 15px;",
+            "@media only screen and (min-width: 641px) {",
+            "margin: 0 30px;",
+            "}",
+            "@media only screen and (min-width: 1020px) {",
+            "margin: 0 auto;",
+            "}",
+            [Function],
+          ],
+          "staticRulesId": "",
+        },
+        "foldedComponentIds": Array [],
+        "render": [Function],
+        "shouldForwardProp": undefined,
+        "styledComponentId": "width-container__WidthContainer-sc-213f5v-0",
+        "target": "div",
+        "toString": [Function],
+        "warnTooManyClasses": [Function],
+        "withComponent": [Function],
+      }
+    }
+    licence={false}
+  >
+    <src__FooterContainer
+      role="contentinfo"
+    >
+      <footer
+        className="c0"
+        role="contentinfo"
+      >
+        <width-container__WidthContainer>
+          <div
+            className="c1"
+          >
+            <MetaContainer
+              licence={false}
+            >
+              <meta__Meta>
+                <div
+                  className="c2"
+                >
+                  <meta-item__MetaItem
+                    grow={true}
+                  >
+                    <div
+                      className="c3"
+                    />
+                  </meta-item__MetaItem>
+                </div>
+              </meta__Meta>
+            </MetaContainer>
+          </div>
+        </width-container__WidthContainer>
+      </footer>
+    </src__FooterContainer>
+  </Footer>
+</FooterWithNoLicense>
+`;
+
 exports[`Footer matches with single meta link snapshot: FooterWithSingleMetaLink 1`] = `
 .c1 {
   max-width: 960px;
@@ -4519,6 +5008,17 @@ exports[`Footer matches with single meta link snapshot: FooterWithSingleMetaLink
   color: #171819;
 }
 
+.c10 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c11 {
+  display: inline-block;
+}
+
 .c2 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -4554,17 +5054,6 @@ exports[`Footer matches with single meta link snapshot: FooterWithSingleMetaLink
   flex-basis: 320px;
 }
 
-.c10 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c11 {
-  display: inline-block;
-}
-
 .c5 {
   color: #0b0c0c;
   font-family: "nta",Arial,sans-serif;
@@ -4651,6 +5140,12 @@ exports[`Footer matches with single meta link snapshot: FooterWithSingleMetaLink
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c10 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c2 {
     font-family: sans-serif;
@@ -4665,12 +5160,6 @@ exports[`Footer matches with single meta link snapshot: FooterWithSingleMetaLink
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c10 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c5 {
     color: #000;
@@ -4780,6 +5269,7 @@ exports[`Footer matches with single meta link snapshot: FooterWithSingleMetaLink
             "withComponent": [Function],
           }
         }
+        licence={<Licence />}
         meta={
           <MetaLinks
             heading="Support links"
@@ -4806,7 +5296,9 @@ exports[`Footer matches with single meta link snapshot: FooterWithSingleMetaLink
               <div
                 className="c1"
               >
-                <MetaContainer>
+                <MetaContainer
+                  licence={<Licence />}
+                >
                   <meta__Meta>
                     <div
                       className="c2"
@@ -5017,6 +5509,17 @@ exports[`Footer matches with single navigation link snapshot: FooterWithSingleNa
   margin-bottom: 30px;
 }
 
+.c13 {
+  display: inline-block;
+  margin-right: 10px;
+  margin-bottom: 15px;
+  vertical-align: top;
+}
+
+.c14 {
+  display: inline-block;
+}
+
 .c11 {
   display: -webkit-box;
   display: -webkit-flex;
@@ -5052,17 +5555,6 @@ exports[`Footer matches with single navigation link snapshot: FooterWithSingleNa
   flex-basis: 320px;
 }
 
-.c13 {
-  display: inline-block;
-  margin-right: 10px;
-  margin-bottom: 15px;
-  vertical-align: top;
-}
-
-.c14 {
-  display: inline-block;
-}
-
 .c5 {
   color: #0b0c0c;
   font-family: "nta",Arial,sans-serif;
@@ -5165,6 +5657,12 @@ exports[`Footer matches with single navigation link snapshot: FooterWithSingleNa
   }
 }
 
+@media only screen and (min-width:769px) {
+  .c13 {
+    margin-bottom: 0;
+  }
+}
+
 @media print {
   .c11 {
     font-family: sans-serif;
@@ -5179,12 +5677,6 @@ exports[`Footer matches with single navigation link snapshot: FooterWithSingleNa
   }
 }
 
-@media only screen and (min-width:769px) {
-  .c13 {
-    margin-bottom: 0;
-  }
-}
-
 @media print {
   .c5 {
     color: #000;
@@ -5304,6 +5796,7 @@ exports[`Footer matches with single navigation link snapshot: FooterWithSingleNa
         "withComponent": [Function],
       }
     }
+    licence={<Licence />}
   >
     <src__FooterContainer
       role="contentinfo"
@@ -5395,7 +5888,9 @@ exports[`Footer matches with single navigation link snapshot: FooterWithSingleNa
                 className="c10"
               />
             </section-break__SectionBreak>
-            <MetaContainer>
+            <MetaContainer
+              licence={<Licence />}
+            >
               <meta__Meta>
                 <div
                   className="c11"
diff --git a/components/footer/src/test.tsx b/components/footer/src/test.tsx
index a4a7651f..43f81de3 100644
--- a/components/footer/src/test.tsx
+++ b/components/footer/src/test.tsx
@@ -114,6 +114,22 @@ const FooterWithNavigation: React.FC = () => withRoutes(<Footer>{navigation}</Fo
 
 const FooterWithNavigationAndMeta: React.FC = () => withRoutes(<Footer meta={metaLinksAndCustom}>{navigation}</Footer>);
 
+const FooterWithCustomLicence: React.FC = () => (
+  <Footer
+    licence={
+      <span>
+        All content is available under the{' '}
+        <Footer.Link href="https://creativecommons.org/licenses/by/4.0/" rel="license">
+          Creative Commons Attribution 4.0 International Licence
+        </Footer.Link>
+        , except where otherwise stated
+      </span>
+    }
+  />
+);
+
+const FooterWithNoLicense: React.FC = () => <Footer licence={false} />;
+
 describe('Footer', () => {
   it('matches default snapshot', () => {
     expect(mount(<Footer />)).toMatchSnapshot('Footer');
@@ -154,4 +170,12 @@ describe('Footer', () => {
   it('matches with navigation and meta snapshot', () => {
     expect(mount(<FooterWithNavigationAndMeta />)).toMatchSnapshot('FooterWithNavigationAndMeta');
   });
+
+  it('matches with custom licence', () => {
+    expect(mount(<FooterWithCustomLicence />)).toMatchSnapshot('FooterWithCustomLicence');
+  });
+
+  it('matches with no licence', () => {
+    expect(mount(<FooterWithNoLicense />)).toMatchSnapshot('FooterWithNoLicense');
+  });
 });