main d5a42c7725f3 cached
96 files
192.0 KB
54.8k tokens
24 symbols
1 requests
Download .txt
Showing preview only (215K chars total). Download the full file or copy to clipboard to get everything.
Repository: AccessibleForAll/AccessibleWebDev
Branch: main
Commit: d5a42c7725f3
Files: 96
Total size: 192.0 KB

Directory structure:
gitextract_u4kywwvh/

├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── appreciation.yml
│       └── axe.yaml
├── .gitignore
├── .gitpod.yml
├── .husky/
│   └── pre-commit
├── .prettierignore
├── .prettierrc.json
├── CODE_OF_CONDUCT.md
├── CODING_STANDARDS.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── components/
│   ├── CodeBlock/
│   │   ├── CodeBlock.module.css
│   │   └── CodeBlock.tsx
│   ├── ContentTemplates/
│   │   ├── AlertsTemplate.tsx
│   │   ├── AnimationsTemplate.tsx
│   │   ├── AudioTemplate.tsx
│   │   ├── BreadcrumbsTemplate.module.css
│   │   ├── BreadcrumbsTemplate.tsx
│   │   ├── ButtonsTemplate.module.css
│   │   ├── ButtonsTemplate.tsx
│   │   ├── CaptchasTemplate.tsx
│   │   ├── ChartsTemplate.tsx
│   │   ├── FormsTemplate.tsx
│   │   ├── HeadingsTemplate.tsx
│   │   ├── IconsTemplate.tsx
│   │   ├── ImagesTemplate.tsx
│   │   ├── LinksTemplate.module.css
│   │   ├── LinksTemplate.tsx
│   │   ├── ListsTemplate.tsx
│   │   ├── MenusTemplate.tsx
│   │   ├── ModalsTemplate.tsx
│   │   ├── NavigationTemplate.tsx
│   │   ├── PaginationTemplate.tsx
│   │   ├── TablesTemplate.tsx
│   │   └── VideoTemplate.tsx
│   ├── CopyCodeBlock/
│   │   ├── CopyCodeBlock.module.css
│   │   └── CopyCodeBlock.tsx
│   ├── Footer/
│   │   ├── Footer.module.css
│   │   └── Footer.tsx
│   ├── Header/
│   │   ├── Header.module.css
│   │   └── Header.tsx
│   ├── Layout/
│   │   ├── Layout.module.css
│   │   └── Layout.tsx
│   ├── MaintainerCard/
│   │   ├── MaintainerCard.module.css
│   │   └── MaintainerCard.tsx
│   ├── Nav/
│   │   ├── NavItem.tsx
│   │   ├── NavPrimary.module.css
│   │   ├── NavPrimary.tsx
│   │   └── NavPrimaryMobile.tsx
│   ├── NavPage/
│   │   ├── NavPage.module.css
│   │   └── NavPage.tsx
│   ├── PageUpdated/
│   │   ├── PageUpdated.module.css
│   │   └── PageUpdated.tsx
│   ├── SkipLink/
│   │   ├── SkipLink.module.css
│   │   └── SkipLink.tsx
│   ├── TemplateSection/
│   │   ├── TemplateSection.module.css
│   │   └── TemplateSection.tsx
│   ├── ThemeSwitcher/
│   │   ├── ThemeSwitcher.module.css
│   │   ├── ThemeSwitcher.tsx
│   │   └── themes.ts
│   ├── TipOfTheDay/
│   │   ├── TipOfTheDay.module.css
│   │   └── TipOfTheDay.tsx
│   └── WorkInProgress/
│       ├── WorkInProgress.module.css
│       └── WorkInProgress.tsx
├── customHooks/
│   └── useOnClickOutside.ts
├── data/
│   ├── maintainers.ts
│   ├── pageNavigationLists.ts
│   ├── pages.ts
│   └── tipsOfTheDay.ts
├── docs-style-guide.md
├── next-env.d.ts
├── next-i18next.config.js
├── next.config.js
├── package.json
├── pages/
│   ├── 404.tsx
│   ├── [content].tsx
│   ├── _app.tsx
│   ├── about.tsx
│   ├── api/
│   │   └── hello.ts
│   ├── docs/
│   │   └── Style Guide.md
│   └── index.tsx
├── public/
│   ├── locales/
│   │   ├── en/
│   │   │   ├── common.json
│   │   │   └── homepage.json
│   │   └── sv/
│   │       ├── common.json
│   │       └── homepage.json
│   └── site.webmanifest
├── styles/
│   ├── about.module.css
│   └── globals.css
├── tsconfig.json
└── utils.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintignore
================================================


================================================
FILE: .eslintrc.json
================================================
{
	"extends": [
		"next/core-web-vitals",
		"prettier",
		"plugin:@typescript-eslint/recommended",
		"plugin:jsx-a11y/strict"
	],
	"rules": {
		"comma-spacing": ["error", { "before": false, "after": true }],
		"react/no-unescaped-entities": 0,
		"react/prop-types": "off",
		// suppress errors for missing 'import React' in files
		"react/react-in-jsx-scope": "off",
		// allow jsx syntax in js files (for next.js project)
		"react/jsx-filename-extension": [
			1,
			{ "extensions": [".js", ".jsx", ".ts", ".tsx"] }
		] //should add ".ts" if typescript project
	},
	"overrides": [
		{
			"files": ["*.ts", "*.tsx"],
			"rules": {
				"react/prop-types": "off",
				"@typescript-eslint/naming-convention": [
					"warn",
					{
						"selector": "default",
						"format": ["camelCase"],
						"leadingUnderscore": "forbid",
						"trailingUnderscore": "forbid"
					},
					{
						"selector": "objectLiteralProperty",
						"modifiers": ["requiresQuotes"],
						"format": null
					},
					{
						"selector": "objectLiteralProperty",
						"format": ["strictCamelCase", "StrictPascalCase"]
					},
					{
						"selector": "typeLike",
						"format": ["StrictPascalCase", "PascalCase"]
					},
					{
						"selector": "interface",
						"format": ["PascalCase"]
					},
					{
						"selector": "function",
						// Exception for FunctionComponents
						"format": ["strictCamelCase", "StrictPascalCase"]
					},
					{
						"selector": "parameter",
						"format": ["strictCamelCase", "StrictPascalCase"]
					},
					{
						"selector": "variable",
						"format": ["camelCase", "UPPER_CASE"]
					},
					{
						"selector": "variable",
						"modifiers": ["exported"],
						// Exception for components wrapped in HOC's and for React's Context
						"format": ["strictCamelCase", "StrictPascalCase", "UPPER_CASE"]
					},
					{
						"selector": "enumMember",
						"format": ["StrictPascalCase"]
					}
				]
			}
		}
	]
}


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**Smartphone (please complete the following information):**
 - Device: [e.g. iPhone6]
 - OS: [e.g. iOS8.1]
 - Browser [e.g. stock browser, safari]
 - Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## Describe your changes

## Screenshots - If Any (Optional)

## Link to issue
<!-- Example: Closes #31 -->
Closes #

## Checklist before requesting a review

- [ ] I have performed a self-review of my code.
- [ ] Followed the repository's [Contributing Guidelines](/CONTRIBUTING.md).
- [ ] I ran the app and tested it locally to verify that it works as expected.
- [ ] I have checked my code with an automatic accessibility tool such as Axe Dev Tools or Wave 
      and it shows no errors.
## Additional Information (Optional)
Any additional information that you want to give us.


================================================
FILE: .github/workflows/appreciation.yml
================================================
name: 'Thank Contributors'

on:
  issues:
    types: [opened]
  pull_request_target:
    types: [opened]

jobs:
  welcome-new-contributor:
    runs-on: ubuntu-latest
    steps:
      - name: 'Greet the contributor'
        uses: garg3133/welcome-new-contributors@v1.2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-message: 'Hello @contributor_name, thanks for raising an issue in this project. The maintainers of this project are volunteers so please be understanding if it takes time before you get a response. We still appreciate your help with raising issues!'
          pr-message: 'Hello @contributor_name, thanks for raising a pull request in this project. The maintainers of this project are volunteers so please be understanding if it takes time before you get a response. We still appreciate your help with creating pull requests!'


================================================
FILE: .github/workflows/axe.yaml
================================================
name: axe
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
jobs:
  axe:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js 16.x
        uses: actions/setup-node@v1
        with:
          node-version: 16.x
      - run: npm ci
      - run: npm run dev & npx wait-on http://localhost:3000
      - name: Install browser drivers
        run: npx browser-driver-manager install chrome
      - name: Run axe
        run: |
          npm install -g @axe-core/cli
          axe http://localhost:3000 --exit


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo

# VS code
.vscode

# IDEA
.idea


================================================
FILE: .gitpod.yml
================================================
# List the start up tasks. Learn more https://www.gitpod.io/docs/config-start-tasks/
tasks:
  - name: npm
    init: npm install
    command: npm run dev
# List the ports to expose. Learn more https://www.gitpod.io/docs/config-ports/
ports:
  - port: 3000
    onOpen: open-browser
github:
  prebuilds:
    master: true
    branches: true
    pullRequests: true
    pullRequestsFromForks: true
    addCheck: true
    addComment: false
    addBadge: true


================================================
FILE: .husky/pre-commit
================================================
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged


================================================
FILE: .prettierignore
================================================
# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.md

================================================
FILE: .prettierrc.json
================================================
{
	"trailingComma": "es5",
	"useTabs": true,
	"tabWidth": 2,
	"semi": false,
	"singleQuote": false,
	"bracketSpacing": true,
	"bracketSameLine": true,
	"endOfLine": "lf",
	"singleAttributePerLine": false
}


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
emma.l.dawson@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: CODING_STANDARDS.md
================================================
# Coding Standards

## Naming

Choosing good names is critical to creating code that is easy to use and easy to understand. You
should always take the time to think about whether you have chosen the right name for something.

### English

All code, names, comments, etc. must be in English.

### Use one name for one thing

Do not reuse names. Do not use names that can mean multiple things. Always use the same name for the
same thing. 

### Descriptive

Names must be descriptive for the working or usage of the class, method or variable.

### Context

A name should make sense within its context and should not have unnecessary information for that
context. For example a variable that holds the name of a user can be named `name` within a `User`
context. However if you need to hold the name of a user in another place, `userName` might be a
better name. Adding `user` within a `User` context (`user.userName`) is redundant and should be
avoided.

### Interfaces

Interfaces should use the `I` as prefix. Like `IMyInterface`

### Functions

Prefer using a verb as a name to indicate it will do something. Like `render`, `open` or `getData`.

### Variables, Properties, etc.

All non-functions should have a noun as a name, not a verb.

### Booleans

Should start with `is`, `has`, `will` or `should`. Like `isValid` or `hasValues`.

### Always Affirmative

Avoid negations. Prefer `isShown` over `isHidden` or
`isEnabled` over `isDisabled`. Do not use names like `notEditable`.

## Casing

### Classes, Interfaces, Types, Enums and Generics

**PascalCase** Every individual word start with an upper case character, no underscores, no dashes.

### Functions, Properties, Arguments and Variables

**camelCase** Starts with a lower case character, every following individual word start with an
upper case character, no underscores, no dashes.

### Globally used constants

**SNAKE_UPPER_CASE** Only use upper case characters, individual words must be separated with an underscore.

## File names

### Page files, data files and hook files

**camelCase** Starts with a lower case character, every following individual word start with an
upper case character, no underscores, no dashes.

### Component files

**PascalCase** Every individual word start with an upper case character, no underscores, no dashes.

## Coding

### Functions

Deconstruct props in the function parameters rather than inside the function body

```ts
interface IProps {
  propOne: string
  propTwo: string
}

const Component = ({ propOne, propTwo }: IProps) => { ... }

// rather than

const Component = (props: IProps) => {
  const { propOne, propTwo } = props
  ... 
}
```

Named export rather than default export

```ts
export const Component = () => { ... }

// rather than

const Component = () => { ... }

export default Component
```
### CSS

When in need to use a colour, use the defined variable from the `globals.ccs` file rather than adding hex codes.

```css
.class {
	color: var(--text);
}

/* rather than */

.class {
	color: #272727;
}
```




================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Accessible Web Dev

## Languages

This project is built with Next.JS, Typescript and CSS modules.

## Pre-requisites (these need to be installed on your machine)

[Node.js](https://nodejs.org/en/)

## Available packages

Icons - [React Icons Documentation]( https://react-icons.github.io/react-icons)  
Code Snippets - [React Syntax Highlighter Documentation](https://github.com/react-syntax-highlighter/react-syntax-highlighter)  
Translations - [next-i18next Documentation](https://next.i18next.com/)  

## How to contribute

1. Look through [Pre-existing issues](https://github.com/AccessibleForAll/AccessibleWebDev/issues) or [Raise a new issue](https://github.com/AccessibleForAll/AccessibleWebDev/issues/new/choose) and ask to be assigned. Pull requests made without a corresponding issue will likely be closed.
2. Please check the [coding standards](https://github.com/AccessibleForAll/AccessibleWebDev/blob/main/CODING_STANDARDS.md) page before start contributing.
3. [Fork](https://github.com/AccessibleForAll/AccessibleWebDev/fork) the project
4. Clone the project:

    ```bash
    git clone https://github.com/<your-github-username>/AccessibleWebDev
    ```

5. Navigate to the project directory:

    ```bash
    cd AccessibleWebDev
    ```

6. Set the upstream repository:

    ```bash
    git remote add upstream https://github.com/AccessibleForAll/AccessibleWebDev.git
    ```

7. Install dependencies:

    ```bash
    npm install
    ```

8. Create a new branch:

    ```bash
    git checkout -b <YourBranchName>
    ```

9. To run the whole project locally:

    ```bash
    npm run dev
    ```

10. Make your changes
11. Stage your changes:

    ```bash
    git add <NameOfFileChanged>
    ```

12. Commit your changes and provide a meaningful commit message:

    Unsure how to write a meaningful commit message? Check out this article about [How to Write a Good Git Commit Message](https://blog.ossph.org/how-to-write-a-good-git-commit-message/#:~:text=To%20set%20up%20a%20Git,t%20meet%20the%20specified%20format.)

    ```bash
    git commit -m "<Your commit message here>"
    ```

13. Push your commits to your local repository

    ```bash
    git push origin <YourBranchName>
    ```

14. Create a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
15. Wait for maintainers to review your pull request and suggest any changes

**Congratulations!** You made a contribution to the Accessible For All Community!

## Questions?

If at any time you need help with contributing, please reach out to the [maintainers](https://github.com/AccessibleForAll/Support/blob/main/README.md#our-maintainers)


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2022 Accessible For All

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================

# [Accessible Web Dev](https://accessibleweb.dev/) 🌐  

Welcome to **Accessible Web Dev**, a resource designed to help web developers learn the fundamentals of accessibility in a practical, easy-to-understand way. This site is an **entry point** into the world of accessibility, complementing current standards by breaking down complex concepts. While it doesn't replace existing standards like the [WCAG standards](https://www.w3.org/WAI/standards-guidelines/wcag/), it offers a beginner-friendly pathway into accessibility for developers of all experience levels.

![Screenshot of Accessible Web Dev homepage showing a clean, accessible interface with key topics and resources.](/public/images/websiteScreenshot.png)

---

## 🚀 Features  

- **Beginner-Friendly Content**: Step-by-step guides to start your accessibility journey.  
- **Practical Examples**: Real-world implementations of accessibility best practices.  
- **Resources & Tools**: Discover accessibility checkers, ARIA guides, and more.  
- **Community-Driven**: Contributions from developers worldwide to keep the content relevant and up-to-date.  

---

## 🤝 How to Contribute  

We welcome and encourage contributions! There are multiple ways to help improve this project:  

1. **Report Bugs:**  
   If you encounter a bug, please raise a [Bug Report](https://github.com/AccessibleForAll/AccessibleWebDev/issues/new?assignees=&labels=&template=bug_report.md&title=).  

2. **Request New Features:**  
   Have ideas for new features? Submit an [Issue](https://github.com/AccessibleForAll/AccessibleWebDev/issues/new?assignees=&labels=&template=feature_request.md&title=).  

3. **Contribute Code, Documentation, or Design:**  
   We are always looking to improve! Please follow our [Contributing Guidelines](https://github.com/AccessibleForAll/AccessibleWebDev/blob/main/CONTRIBUTING.md) to submit code, translations, or design updates.  

4. **Spread the Word:**  
   Share the project with your peers to help promote accessibility across the web.  

---

## 📄 License  

Accessible Web Dev is licensed under the **MIT License**. See the full [License](https://github.com/AccessibleForAll/AccessibleWebDev/blob/main/LICENSE) for more details.


================================================
FILE: components/CodeBlock/CodeBlock.module.css
================================================
.CodeBlockContainer {
	position: relative;
	width: 90vw;
	max-width: 850px;
	border: 1px solid var(--primaryLt);
	border-radius: 8px;
	background-color: var(--primaryLt);
	padding: 40px 8px 2px 8px;
	margin: 16px 0;
}

.CodeBlock {
	overflow-x: auto;
}



.codeLanguage {
	background-color: var(--dark);
	padding: 8px;
	color: var(--white);
	position: absolute;
	top: 10px;
	left: 8px;
	right: 8px;
	border-bottom: 1px solid var(--primaryLt);
}

@media only screen and (min-width: 800px) {
	.CodeBlockContainer {
		width: 61vw;
	}
}

@media only screen and (min-width: 1000px) {
	.CodeBlockContainer {
		width: 70vw;
	}
}



================================================
FILE: components/CodeBlock/CodeBlock.tsx
================================================
import { useEffect, useRef, useState } from "react"
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
import { nightOwl } from "react-syntax-highlighter/dist/cjs/styles/prism"
import CopyCodeBlock from "../CopyCodeBlock/CopyCodeBlock"
import styles from "./CodeBlock.module.css"

type TCodeLanguage =
	| "html"
	| "css"
	| "javascript"
	| "jsx"
	| "typescript"
	| "tsx"
interface ICodeBlockProps {
	codeSnippet: string
	languageType: TCodeLanguage
}

export const CodeBlock = ({ codeSnippet, languageType }: ICodeBlockProps) => {
	const [scrollableRegion, setScrollableRegion] = useState(false)

	const ref = useRef<HTMLPreElement>(null)
	const PreWithRef = (preProps: React.HTMLAttributes<HTMLPreElement>) => (
		<pre {...preProps} ref={ref} />
	)

	useEffect(() => {
		if (ref.current) {
			const element = ref.current
			setScrollableRegion(element.clientWidth < element.scrollWidth)
		}
	}, [])

	return (
		<div className={styles.CodeBlockContainer}>
			<div className={styles.codeLanguage}>{languageType}</div>
			<CopyCodeBlock code={codeSnippet} />
			<SyntaxHighlighter
				language={languageType}
				style={nightOwl}
				className={styles.CodeBlock}
				PreTag={PreWithRef}
				tabIndex={scrollableRegion ? 0 : -1}>
				{codeSnippet}
			</SyntaxHighlighter>
		</div>
	)
}


================================================
FILE: components/ContentTemplates/AlertsTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const AlertsTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/ContentTemplates/AnimationsTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const AnimationsTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/ContentTemplates/AudioTemplate.tsx
================================================
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { NavPage } from "../NavPage/NavPage"
import { PageUpdated } from "../PageUpdated/PageUpdated"
import { TemplateSection } from "../TemplateSection/TemplateSection"
import { audioPageNavigation } from "../../data/pageNavigationLists"

export const AudioTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={audioPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					Any form of audio on a website, whether prerecorded or live, audio
					only or as part of a video or animation, should be provided in an
					alternative form so that it can be perceived by people that can't
					access the audio. Such alternatives include transcripts, captions and
					sign language.
				</p>
			</TemplateSection>
			<TemplateSection sectionName={"transcripts"} title={"Transcripts"}>
				<p>
					An audio transcript is a text version of the audio in a prerecorded
					audio or video file. It should be located close to the audio or video
					file so that it is easy to find for anyone that wishes to read it. As
					a transcript can be long, it is adequate to provide a link to the
					transcript in close proximity to the audio or video file.
				</p>
				<p>
					Transcripts should identify who is speaking and include any relevant
					background sounds. Full verbatim transcripts include every sound, even
					ums and ahs, that occured in the original audio. Clean verbatim
					transcripts remove these extra sounds whilst leaving the rest of the
					audio as is. Nothing is paraphrased or summarised. They should include
					information about who is speaking and time stamps can also be useful,
					although not required, especially if the transcript is for a video.
				</p>
				<p>
					An added benefit of transcripts is that they can be more easily
					translated into other languages. This makes the audio content
					available to a wider range of people.
				</p>
			</TemplateSection>
			<TemplateSection sectionName={"captions"} title={"Captions"}>
				<p>
					Captions are a text version of audio displayed alongside video inside
					the media player. They should include all forms of audio such as
					dialogue, background music, sound effects and anything else relevant
					to the person watching. If the video is prerecorded the captions
					should be synced with the audio. If the video is live there can
					sometimes be a short delay as the captions are being added in real
					time by professional real-time captioners. Most online video services
					offer the ability to upload caption files alongside the video. It is
					important to choose a video upload service with these capabilities.
				</p>
				<p>
					There are two types of captions: Open Captions and Closed Captions.
				</p>
				<h3>Open Captions</h3>
				<p>
					Open captions are captions that are burned into the video track. They
					are always visible when the video is playing and there is no way to
					adjust the font size or style of the captions. They do however provide
					a consistent experience for everyone.
				</p>
				<h3>Closed Captions</h3>
				<p>
					Closed captions are provided on a separate audio track which means
					they can be switched on and off by the user. Often the user will also
					have some control over the size and style of the captions so they can
					be adjusted to suit their personal needs. However, closed caption
					support may differ between different media players. The closed
					captions should be easy to access. Ideally, the button to turn them on
					and off is at the same level as the play/pause button in the media
					player.
				</p>
				<h3>Auto-generated captions</h3>
				<p>
					When using captions within video-conferencing tools or for live events
					then auto-generated captions can provide some help. They are generally
					said to be around 80% accurate. However, this still means that 20% of
					information is lost. Auto-generated captions also become less accurate
					for people with accents and often are only available for English.
				</p>
				<p>
					Auto-generated captions are better than nothing but they are not
					sufficient to be WCAG compliant. If you have the possibility to
					provide real time captioning, or even sign language, for live events
					then that should be the preference. Auto-generated captions should
					also be edited if a recording of the live event is being uploaded to a
					video-sharing platform afterwards.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="howToAdd"
				title="How To Add Closed Captions To Your Audio?">
				<p>
					Whether you are adding an introductory video about yourself on
					websites or embedding an audio clip of your favorite song to a game
					you're building, it's important to add closed captions to them. This
					will ensure that users who need captions have an easier viewing
					experience.
				</p>
				<p>
					If using the video element within HTML you can specify a captions
					track by linking to a vtt file and specifying that the kind is
					captions. Multiple caption tracks in different languages can be added
					if necessary.
				</p>
				<CodeBlock
					languageType="html"
					codeSnippet={`<video controls width="200">
  <source src="video.mp4" type="video/mp4" />
  <track
    default
    kind="captions"
    src="https://youtube.com/captions.vtt"
    srclang="en"
  />
</video>
`}
				/>
				<p>
					Video upload services such as YouTube and Vimeo allow you to upload
					captions in various file formats including VTT, WebVTT and SRT.
				</p>
			</TemplateSection>
			<TemplateSection sectionName={"signLanguage"} title={"Sign Language"}>
				<p>
					There are over 300 different sign languages used around the world. For
					many deaf and hard of hearing people it is their primary method of
					communication and may be easier to understand or be less cognitively
					demanding than reading captions or transcripts.
				</p>
				<p>
					Sign language is more often used for live events as information can be
					conveyed more quickly than using live captions. Important information
					on a website could also be conveyed by embedding videos of the
					information being signed.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName={"accessibleMediaPlayers"}
				title={"Accessible Media Players"}>
				<p>
					The audio and video media players included in the HTML specification
					are very basic and will require some work to make them accessible.
					Many video upload/sharing services exist where work is well underway
					to provide an accessible experience for users so it is often
					beneficial to use such a service instead and embed the media player
					into your site. However, it's always important to check any third
					party tool you choose to use to make sure it is accessible.
				</p>
				<p>
					The key things to check when looking for a media player are that it is
					keyboard accessible and doesn't trap keyboard focus. It should also
					have the ability to add captions and the captions should be easy to
					find and operate with assistive technology.
				</p>
			</TemplateSection>
			<TemplateSection sectionName={"WCAGCriteria"} title={"WCAG Criteria"}>
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#audio-only-and-video-only-prerecorded"
							className="blockLink">
							1.2.1 Audio-only and Video-only (prerecorded)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#captions-prerecorded"
							className="blockLink">
							1.2.2 Captions (prerecorded)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#audio-description-or-media-alternative-prerecorded"
							className="blockLink">
							1.2.3 Audio Description or Media Alternative (prerecorded)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#captions-live"
							className="blockLink">
							1.2.4 Captions (live)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#audio-description-prerecorded"
							className="blockLink">
							1.2.5 Audio Description (prerecorded)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#sign-language-prerecorded"
							className="blockLink">
							1.2.6 Sign Language (prerecorded)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#media-alternative-prerecorded"
							className="blockLink">
							1.2.8 Media Alternative (prerecorded)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#audio-only-live"
							className="blockLink">
							1.2.9 Audio-only (live)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#sensory-characteristics"
							className="blockLink">
							1.3.3 Sensory characteristics
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#audio-control"
							className="blockLink">
							1.4.2 Audio Control
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#low-or-no-background-audio"
							className="blockLink">
							1.4.7 Low or No Background Audio
						</a>
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName={"resources"} title={"Resources"}>
				<ul className="list">
					<li>
						<a href="https://www.w3.org/WAI/media/av/" className="blockLink">
							WAI Making Audio and Video Media Accessible
						</a>
					</li>
				</ul>
			</TemplateSection>
			<PageUpdated date="7th October 2023" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/BreadcrumbsTemplate.module.css
================================================
.breadcrumbsExample {
  background-color: var(--highlight);
}

.breadcrumbsExample ol {
	list-style: none;
	margin: 0;
	padding: 1rem;
  display: flex;
  gap: 0.5rem;
}

.breadcrumbsExample ol li {
  display: flex;
  gap: 0.5rem;
}

.breadcrumbsExample p { 
  margin: 0;
}

================================================
FILE: components/ContentTemplates/BreadcrumbsTemplate.tsx
================================================
import { breadcrumbsPageNavigation } from "../../data/pageNavigationLists"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { NavPage } from "../NavPage/NavPage"
import { PageUpdated } from "../PageUpdated/PageUpdated"
import { TemplateSection } from "../TemplateSection/TemplateSection"
import styles from "./BreadcrumbsTemplate.module.css"

export const BreadcrumbsTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={breadcrumbsPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					Breadcrumbs are a type of navigation, designed to make it easy to see
					where you are within the structure of a website and easily navigate to
					different areas. The name refers to the story of Hansel and Gretel who
					left a trail of breadcrumbs in the hope to find their way back out of
					the forest. They are most useful when content is nested several layers
					deep.
				</p>
				<p>
					Breadcrumbs are most often found at the top of a page and should be
					placed just before the main content. There is no semantic HTML element
					for breadcrumbs but it can be made from a combination of semantic HTML
					elements plus a small amount of ARIA.
				</p>

				<nav
					aria-label="Breadcrumbs (example only)"
					className={styles.breadcrumbsExample}>
					<ol>
						<li>
							<a href="#">Website root</a>
							<p aria-hidden="true">{">"}</p>
						</li>
						<li>
							<a href="#">Website level 1</a>
							<p aria-hidden="true">{">"}</p>
						</li>
						<li>
							<a href="#" aria-current="page">
								Website level 2
							</a>
						</li>
					</ol>
				</nav>
			</TemplateSection>
			<TemplateSection sectionName="htmlStructure" title="HTML Structure">
				<p>
					Although there is not one HTML element that can be used to make
					breadcrumbs, there are a few elements available that, when used
					together, offer the semantics needed to make accessible breadcrumbs.
				</p>
				<p>What is needed:</p>
				<ul className="list">
					<li>
						A nav element will let users know that this is a navigation
						landmark. Landmarks make things easier to find, especially for
						screen reader users.
					</li>
					<li>
						An ordered list will let users know that the order of the items is
						important.
					</li>
					<li>
						Links within the list will let users know that they can click to
						navigate to that area of the website.
					</li>
					<li>
						Since the last element in a breadcrumb trail should represent the
						current page, making it a link is optional.
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection
				sectionName="aria"
				title="Add Extra Information with ARIA">
				<p>
					ARIA is used to add extra semantic information where HTML is not
					enough. In this case, there is probably another navigation present on
					the page. Therefore we will need to distinguish the breadcrumb
					navigation from any other navigation with an aria-label.
				</p>

				<p>
					If the last link in the breadcrumb trail is the current page, we can
					also use aria-current on that link to specify that it is the currently
					active page. If the last element is not a link then aria-current is
					optional.
				</p>

				<p>Aria-hidden can be used to hide any dividers between links.</p>
			</TemplateSection>

			<TemplateSection
				sectionName="breadcrumbsExample"
				title="Breadcrumbs Example">
				<CodeBlock
					languageType="html"
					codeSnippet={`<nav aria-label="Breadcrumbs" class="breadcrumbs">
	<ol>
		<li>
			<a href="#">Website root</a>
			<p aria-hidden="true">></p>
		</li>
		<li>
			<a href="#">Website level 1</a>
			<p aria-hidden="true">></p>
		</li>
		<li>
			<a href="#" aria-current="page">Website level 2</a>
		</li>
	</ol>
</nav>`}
				/>
			</TemplateSection>

			<TemplateSection
				sectionName="breadcrumbStyling"
				title="Styling Breadcrumbs">
				<p>
					Using an ordered list element within breadcrumbs causes each list item
					to be numbered. This styling can be removed with CSS and flexbox can
					be used to make list items sit side by side. CSS can also be used to
					create dividers between each link, or the divider can be added within
					the HTML and hidden with aria-hidden (as in the previous example).
				</p>
				<CodeBlock
					codeSnippet={`.breadcrumbs ol {
	list-style: none;
	margin: 0;
	padding: 1rem;
	display: flex;
	gap: 0.5rem;
}`}
					languageType="css"
				/>
				<p>
					Be aware that removing list styles from lists can cause the screen
					reader VoiceOver on Mac to stop announcing items as a list. If this
					happens, add role="list" to the ol element.
				</p>
			</TemplateSection>
			<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#info-and-relationships"
							className="blockLink">
							1.3.1 Info and Relationships
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#identify-purpose"
							className="blockLink">
							1.3.6 Identify Purpose
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#keyboard"
							className="blockLink">
							2.1.1 Keyboard
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#focus-order"
							className="blockLink">
							2.4.3 Focus Order
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#link-purpose-in-context"
							className="blockLink">
							2.4.4 Link Purpose
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#multiple-ways"
							className="blockLink">
							2.4.5 Multiple Ways
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#focus-visible"
							className="blockLink">
							2.4.7 Focus Visible
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#location"
							className="blockLink">
							2.4.8 Location
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#target-size"
							className="blockLink">
							2.5.5 Target Size
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#on-focus"
							className="blockLink">
							3.2.1 On Focus
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#consistent-navigation"
							className="blockLink">
							3.2.3 Consistent Navigation
						</a>
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName="otherResources" title="Other Resources">
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/examples/breadcrumb/"
							className="blockLink">
							ARIA Authoring Practices Guide Breadcrumb Example
						</a>
					</li>
					<li>
						<a
							href="https://design-system.service.gov.uk/components/breadcrumbs/"
							className="blockLink">
							Gov.uk Design System - Breadcrumbs
						</a>
					</li>
				</ul>
			</TemplateSection>
			<PageUpdated date="10th April 2023" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/ButtonsTemplate.module.css
================================================
.exampleButton {
	padding: 0.6rem 1.2rem;	
	cursor: pointer;
	background-color: var(--primaryLt);
  color: var(--text);
  font-size: 0.9rem;
  font-family: inherit;
	border: 1px solid var(--dark);
	border-radius: 5px;
	display: inline-block;
	margin: 0.5rem 0;
}

.exampleButton span {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: inherit;
}

.exampleButton:hover, .exampleButton:focus {
	background-color: var(--primary);
	color: var(--invertText)
}

.exampleHover {
	padding: 0.6rem 1.2rem;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	cursor: pointer;
	background-color: var(--primary);
	color:var(--invertText);
  font-size: 0.9rem;
  font-family: inherit;
	border: 1px solid var(--dark);
	border-radius: 5px;
	display: inline-block;
	margin: 0.5rem 0;
}

.exampleFocus {
	padding: 0.6rem 1.2rem;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	cursor: pointer;
	background-color: var(--primary);
	color:var(--invertText);
  font-size: 0.9rem;
  font-family: inherit;
	border: 1px solid var(--dark);
	border-radius: 5px;
	display: inline-block;
	outline: 2px transparent solid;
	box-shadow: 0 0 0 2px #000, 0 0 0 4px #fff;
	margin: 0.5rem 0;
}

.exampleActive {
	position: relative;
	top: 2px;
	left: 1px;
	padding: 0.6rem 1.2rem;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	cursor: pointer;
	background-color: var(--primary);
	color:var(--invertText);
  font-size: 0.9rem;
  font-family: inherit;
	border: 2px inset var(--primaryLt);
	border-radius: 5px;
	display: inline-block;
	
	margin: 0.5rem 0;
}

.exampleDisabled {
	padding: 0.6rem 1.2rem;
	display: flex;
	align-items: center;
	gap: 0.5rem;
	cursor: not-allowed;
	background-color: var(--primaryLt);
  font-size: 0.9rem;
  font-family: inherit;
	border: 1px solid var(--dark);
	border-radius: 5px;
	display: inline-block;
	margin: 0.5rem 0;
}

================================================
FILE: components/ContentTemplates/ButtonsTemplate.tsx
================================================
import { TemplateSection } from "../TemplateSection/TemplateSection"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { FaSave } from "react-icons/fa"
import { NavPage } from "../NavPage/NavPage"
import { buttonPageNavigation } from "../../data/pageNavigationLists"
import { PageUpdated } from "../PageUpdated/PageUpdated"
import styles from "./ButtonsTemplate.module.css"

export const ButtonsTemplate = () => {
	const handleTextButton = () => {
		alert("This is a Text button")
	}

	const handleAddToBasketButton = () => {
		alert("This is an example Add to Basket button")
	}

	const handleTextAndIconButton = () => {
		alert("This is an example Text and Icon button")
	}
	return (
		<>
			<NavPage pageNavigation={buttonPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					Buttons are interactive elements that perform an action when pressed.
					That action could be something like submitting a form or opening a
					menu.
				</p>
				<p>
					Buttons have their own semantic HTML element which comes with lots of
					inbuilt functionality. Using an HTML button means it can be reached by
					the tab key and activated with both a mouse and a keyboard
					automatically just by adding an onclick event. Using the semantic
					button element will save you lots of time.
				</p>

				<CodeBlock
					codeSnippet={`<button type="submit" onclick="handleClick()"></button>`}
					languageType={"html"}
				/>
				<p>
					If another element is used to create a button instead, such as a div,
					then functionality must be added to make the div behave exactly like a
					button. Adding the onclick event will not automatically make the
					element keyboard interactive. It also needs to:
				</p>
				<ul className="list">
					<li>Activate when a user presses the enter key</li>
					<li>Activate when a user presses the space key</li>
					<li>Be included in the tab sequence</li>
					<li>Be given the explicit role of button</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName="textButtons" title="Text Buttons">
				<p>A text button is a button which has only text inside it.</p>
				<button className={styles.exampleButton} onClick={handleTextButton}>
					Text here
				</button>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">Text here</button>`}
					languageType={"html"}
				/>
				<p>
					It gets its accessible name from the text between the opening and
					closing button tags. If your text clearly explains the button's
					purpose then this is an accessible button. However, if you have
					several text buttons with the same text you may need to do more to
					make them accessible.
				</p>
				<h3>Buttons with identical text</h3>
				<p>
					Let's say we have multiple products on a page, each with an "Add to
					basket" button. How do we help screen reader users and speech
					dictation users differentiate between the different buttons?
				</p>
				<ul>
					<li>
						Product 1{" "}
						<button
							className={styles.exampleButton}
							onClick={handleAddToBasketButton}>
							Add to basket
						</button>
					</li>
					<li>
						Product 2{" "}
						<button
							className={styles.exampleButton}
							onClick={handleAddToBasketButton}>
							Add to basket
						</button>
					</li>
					<li>
						Product 3{" "}
						<button
							className={styles.exampleButton}
							onClick={handleAddToBasketButton}>
							Add to basket
						</button>
					</li>
					<li>
						Product 4{" "}
						<button
							className={styles.exampleButton}
							onClick={handleAddToBasketButton}>
							Add to basket
						</button>
					</li>
					<li>
						Product 5{" "}
						<button
							className={styles.exampleButton}
							onClick={handleAddToBasketButton}>
							Add to basket
						</button>
					</li>
				</ul>
				<p>We could use CSS to visibly hide some extra text:</p>
				<CodeBlock
					codeSnippet={`.visibly-hidden {
	clip: rect(0 0 0 0); 
	clip-path: inset(50%);
	height: 1px;
	overflow: hidden;
	position: absolute;
	white-space: nowrap; 
	width: 1px;
}`}
					languageType={"css"}
				/>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">Add to basket
	<span class="visibly-hidden">Product 1</span>
</button>`}
					languageType={"html"}
				/>
				<p>
					This would then read out "Add to basket product 1" to screen reader
					users.
				</p>
				<p>
					However, it's important to be careful of word order when using this
					technique. If we had instead inserted the product name in the middle
					of the sentence, for example: "Add product 1 to basket" this can cause
					problems for users of speech input software.
				</p>
				<p>We could also use an aria-label.</p>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()" aria-label="Add to basket product 1">Add to basket</button>`}
					languageType={"html"}
				/>
				<p>
					Again, it is important that the start of the aria-label matches with
					the visible text on the button to help users of speech input software
					be able to activate the button.{" "}
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="textAndIconButtons"
				title="Text and Icon Buttons">
				<p>
					Some buttons have both text and icons inside. The icon can help
					complement the text and aid understanding. To prevent the accessible
					name from repetition, eg "Button, save icon, save", the icon should be
					given an empty(null) alt attribute or the state aria-hidden="true"
				</p>
				<button
					className={styles.exampleButton}
					type="button"
					onClick={handleTextAndIconButton}>
					<span>
						<FaSave size="1rem" aria-hidden="true" /> Save
					</span>
				</button>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">
<img src="icon-url.png" alt="" />
	Text
</button>`}
					languageType={"html"}
				/>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">
<img src="icon-url.png" aria-hidden="true" />
	Text
</button>`}
					languageType={"html"}
				/>
				<p>
					An empty alt attribute has the most wide-spread support, so that
					should be your go to choice when using icons. However, some icon
					libraries don't allow an alt attribute to be passed and that's where
					aria-hidden can be useful.
				</p>
			</TemplateSection>
			<TemplateSection sectionName="iconOnlyButtons" title="Icon-only buttons">
				<p>
					Some buttons use only an icon to convey their function. In this case
					it's important to choose icons that are widely recognised and
					understood, otherwise it can be difficult to know their function. The
					icons should also have a suitable label. This can be done with the alt
					attribute if using images or the aria-label attribute.
				</p>
				<button
					className={styles.exampleButton}
					type="button"
					onClick={handleTextAndIconButton}>
					<FaSave size="1rem" aria-label="Save" />
				</button>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">
	<img src="icon-url.png" alt="Save" />
</button>`}
					languageType={"html"}
				/>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">
	<i class="fa-solid fa-floppy-disk" aria-label="Save"></i>
</button>`}
					languageType={"html"}
				/>
				<p>
					Make sure that the label you give the icon matches the function of the
					button, not necessarily describing the actual icon.
				</p>
				<p>
					<strong>Do this:</strong>
				</p>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">
	<i class="fa-solid fa-magnifying-glass" aria-label="Search"></i>
</button>`}
					languageType={"html"}
				/>
				<p>
					<strong>Don't do this:</strong>
				</p>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()">
	<i class="fa-solid fa-magnifying-glass" aria-label="Magnifying glass"></i>
</button>`}
					languageType={"html"}
				/>
			</TemplateSection>
			<TemplateSection sectionName="buttonStates" title="Button States">
				<p>
					Buttons can be used to communicate different states. A toggle button
					can communicate both an on and off state. Buttons can also have
					default, hover, focus, active and disabled states.
				</p>
				<h3>Default, hover, focus and active states</h3>
				<p>These states can be handled with CSS.</p>
				<ul>
					<li>
						<strong>Default state: </strong>
						The normal state of a button when it's not being interacted with.
						Any text or icon should have a contrast ratio of 4.5:1 with the
						button background color. The button background color should have a
						3:1 contrast ratio with the background.
						<div>
							<button
								className={styles.exampleButton}
								type="button"
								onClick={handleTextButton}>
								Default
							</button>
						</div>
					</li>
					<li>
						<strong>Hover state: </strong>
						How the button looks when hovered over with a mouse cursor. This
						state is not visible on all devices, most notably touch screens.
						It's not a requirement to have a hover state but if used then normal
						color contrast ratios apply.
						<div>
							<button
								className={styles.exampleHover}
								type="button"
								onClick={handleTextButton}>
								Hover
							</button>
						</div>
					</li>
					<li>
						<strong>Focus state: </strong>A button in focus should have a focus
						indicator which makes it easy to see where focus is on the screen.
						This is often a thicker border or outline around the button and
						should have a contrast ratio of at least 3:1 with both the button
						background color and the background behind the button. If the
						button's colors change from default they should still meet the
						required color contrast ratio between text and background.
						<div>
							<button
								className={styles.exampleFocus}
								type="button"
								onClick={handleTextButton}>
								Focus
							</button>
						</div>
					</li>
					<li>
						<strong>Active state: </strong>A button is active in the moment it
						is pressed. It will often look like it's been pressed.
						<div>
							<button
								className={styles.exampleActive}
								type="button"
								onClick={handleTextButton}>
								Active
							</button>
						</div>
					</li>
				</ul>
				<h3>Disabled state</h3>
				<p>
					A disabled button is a button that is not focusable or clickable. It
					has been given the disabled attribute. The browser styling often greys
					out the text making the contrast lower than 3:1 which makes disabled
					buttons difficult to see for some people. Often they are also not
					discoverable by users of assistive technology. Therefore, it's best to
					avoid disabled buttons and add in logic that provides error messages
					instead if the button is pressed.
				</p>
				<button
					className={styles.exampleDisabled}
					type="button"
					disabled
					onClick={handleTextButton}>
					Disabled button
				</button>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()" disabled>Disabled button</button>`}
					languageType={"html"}
				/>
				<h3>Toggle buttons - pressed and unpressed states</h3>
				<p>
					You might have a button that turns something on or off, or only has
					two states. One example of this might be a light/dark mode.
				</p>
				<p>
					In this case you need to add the extra information by using the aria
					attribute aria-pressed which can either be true or false. This can be
					toggled with the use of JavaScript. This lets screen reader users know
					the state of the button.The button may also dynamically change the
					text/icon to visually convey the state too.
				</p>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()" aria-pressed="true">Toggle button</button>`}
					languageType={"html"}
				/>
				<h3>Menus and popups - expanded and collapsed state</h3>
				<p>
					If a button is used to open a menu or popup then it should also
					communicate to screen readers whether the popup is shown or not. This
					is done with the aria-expanded attribute which can take true or false
					values. If the popup is shown then aria-expanded="true". If the popup
					is not shown then aria-expanded="false" and the screen reader will
					announce that the popup is collapsed. The state of aria-expanded can
					be controlled with JavaScript.
				</p>
				<CodeBlock
					codeSnippet={`<button type="button" onclick="handleClick()" aria-expanded="true">Button with popup</button>`}
					languageType={"html"}
				/>
			</TemplateSection>
			<TemplateSection sectionName="buttonOrLink" title="Button or Link?">
				<p>
					How do you know when it's best to use a button and when it's best to
					use a link?
				</p>
				<p>
					Don't let CSS dictate which element you use. The styling can always be
					changed. A simple rule of thumb is to think about what the element
					should do. Buttons are for actions and links are to take you to new
					places.
				</p>
				<p>
					Is it performing an action like opening a modal, a menu or some other
					popup? Is it applying some styling to a page like a bold or italic
					button in a text editor? Is it allowing you to save something or
					search for something? Then you should probably use a button.
				</p>
				<p>
					Is it taking you to another page or another area of the page? Then it
					should probably be a link.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="touchTargetMinimum"
				title="Touch Target Minimum">
				<p>
					When it comes to creating accessible buttons for your websites and
					applications, it's important that they are easy to activate. To
					achieve this goal, WCAG suggests that buttons have a minimum target
					size of at least 24 by 24 CSS pixels. In doing so, users, especially
					those who suffer from mobility impairments like hand tremors or are
					amputees, have an easier time clicking on them.
				</p>
			</TemplateSection>
			<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#non-text-content"
							className="blockLink">
							1.1.1 Non-text content
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#info-and-relationships"
							className="blockLink">
							1.3.1 Info and Relationships
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#identify-purpose"
							className="blockLink">
							1.3.6 Identify Purpose
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#contrast-minimum"
							className="blockLink">
							1.4.3 Contrast (minimum)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#non-text-contrast"
							className="blockLink">
							1.4.11 Non-text Contrast
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#content-on-hover-or-focus"
							className="blockLink">
							1.4.13 Content on Hover or Focus
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#keyboard"
							className="blockLink">
							2.1.1 Keyboard
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#focus-visible"
							className="blockLink">
							2.4.7 Focus Visible
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#label-in-name"
							className="blockLink">
							2.5.3 Label in Name
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#target-size-enhanced"
							className="blockLink">
							2.5.5 Target Size (Enhanced)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#target-size-minimum"
							className="blockLink">
							2.5.8 Target Size (Minimum)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#on-focus"
							className="blockLink">
							3.2.1 On Focus
						</a>
					</li>
				</ul>
			</TemplateSection>

			<TemplateSection sectionName="otherResources" title="Other Resources">
				<ul className="list">
					<li>
						<a
							href="https://design-system.service.gov.uk/components/button/"
							className="blockLink">
							Gov.uk Design System Button
						</a>
					</li>
					<li>
						<a
							href="https://yatil.net/blog/buttons-vs-links"
							className="blockLink">
							Buttons vs. Links by Eric Eggert
						</a>
					</li>
				</ul>
			</TemplateSection>
			<PageUpdated date="18th February 2023" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/CaptchasTemplate.tsx
================================================
import { captchasPageNavigation } from "../../data/pageNavigationLists"
import { NavPage } from "../NavPage/NavPage"
import { PageUpdated } from "../PageUpdated/PageUpdated"
import { TemplateSection } from "../TemplateSection/TemplateSection"

export const CaptchasTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={captchasPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					CAPTCHA stands for Completely Automated Public Turing test to tell
					Computers and Humans Apart. CAPTCHAs are tests to prove you are human
					and not a bot, such as picking out objects from a set of images,
					listening to a garbled audio or trying to pick out letters and numbers
					from distorted text.
				</p>
				<p>
					CAPTCHAs are inherently not accessible by design. They rely on human
					senses and cognition which means that people with certain disabilities
					are unable to complete them.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName={"captchaIssues"}
				title={"What's the issue with CAPTCHAs?"}>
				<p>
					The easiest way to explain the issues with CAPTCHAs is with examples.
				</p>
				<h3>Visual</h3>
				<p>
					Any CAPTCHA relying on sight, such as picking all the traffic light
					images, or writing the letters in a distorted text, are not accessible
					to people who are blind, are deaf-blind, have low vision or have a
					reading disability such as dyslexia.
				</p>
				<h3>Audio</h3>
				<p>
					Any CAPTCHA relying on audio, such as picking out a word in the middle
					of a distorted soundtrack, are not accessible to people who are deaf,
					hard of hearing or those who have audio processing disorders.
				</p>
				<h3>Maths challenge</h3>
				<p>
					Any CAPTCHA that relies on doing calculations, even those considered
					simple such as 1 + 2, are not accessible to some people with cognitive
					disabilities, learning disabilities or those who have anxiety.
				</p>
				<h3>Alignment challenges</h3>
				<p>
					Any CAPTCHA relying on aligning two images are not accessible to
					people with vision disabilities or motor disabilities.
				</p>
				<h3>Click to prove you're not a robot</h3>
				<p>
					Even having a checkbox CAPTCHA can be difficult for some people
					because if they can't click it, sometimes another more complicated
					CAPTCHA is triggered instead.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName={"accessibleCAPTCHA"}
				title={"Accessible CAPTCHA"}>
				<p>
					The best way to make CAPTCHA accessible is to remove it. Unless you
					have a large problem with spam then CAPTCHA is probably not needed.
					You can try using things like honeypots for form submission. These are
					hidden form fields that only bots can find. Or consider two factor
					authentication for creating accounts and logging into services.
				</p>
				<p>
					If you must use CAPTCHA then you must provide multiple ways for people
					to attempt the CAPTCHA. This means that if people can't fill in a
					visual CAPTCHA due to a disability, they can attempt an audio CAPTCHA
					instead.
				</p>
				<p>
					Even having two types of CAPTCHA does not make your site accessible
					for everyone. If using CAPTCHA is the only way to get to a certain
					part of a website or perform a specific action, then you also need to
					provide a way for people who can't get past the CAPTCHAs to get help.
				</p>
			</TemplateSection>
			<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#non-text-content"
							className="blockLink">
							1.1.1 Non-text content
						</a>
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName={"otherResources"} title={"Other Resources"}>
				<ul>
					<li>
						<a href="https://www.w3.org/TR/turingtest/" className="blockLink">
							The inaccessibility of CAPTCHAS
						</a>
					</li>
				</ul>
			</TemplateSection>
			<PageUpdated date="28th June 2024" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/ChartsTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const ChartsTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/ContentTemplates/FormsTemplate.tsx
================================================
import { formsPageNavigation } from "../../data/pageNavigationLists"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { NavPage } from "../NavPage/NavPage"
import { PageUpdated } from "../PageUpdated/PageUpdated"
import { TemplateSection } from "../TemplateSection/TemplateSection"

export const FormsTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={formsPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					The web is filled with all types of digital forms. Digital forms are
					used to collect user information in an organized way. Whether
					inputting personal health information, completing a simple quiz, or
					placing an order for a local restaurant, forms are there to capture
					data.
				</p>
				<p>
					Examples of digital form elements include radio dial buttons, editable
					text fields, drop-down select elements, and text areas. When a form is
					not accessible, barriers are created that prevent the accurate input
					of data. Users may encounter difficulty using a keyboard to move
					through the forms, or they may miss information needed to complete
					data input accurately.
				</p>
				<p>
					Additionally, assistive technology such as screen readers may not be
					able to read the forms properly. It is imperative that users are able
					to interact with, understand, and complete forms on web pages with
					accuracy and without frustration.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="whatToConsider"
				title="What Should We Consider When Building Accessible Forms?">
				<p>
					There are some key considerations when it comes to building forms.
				</p>
				<ul className="list">
					<li>
						Forms should be simple, understandable and have clear labels and
						instructions on how to input data.
					</li>
					<li>
						Forms must be keyboard operable. Users should be able to use the tab
						key to navigate through all form controls.
					</li>
					<li>
						Forms must be programmatically labelled to match the form control.
					</li>
					<li>
						Forms should provide validation and error notifications that do not
						rely on just one sensory characteristic to alert users.
					</li>

					<li>
						Any time limits are communicated up front, and users are able to
						extend time limits if necessary.
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection
				sectionName="creatingForms"
				title="Creating Simple, Understandable Forms">
				<p>
					Users should be able to understand what the form is asking for and how
					to enter the data into these fields. A form should be demarcated with
					the &lt;form&gt; element. Inside the form element, there should be
					clearly identified sections and inputs with labels that ask for
					information in the required format.
				</p>
				<p>
					Provide simple instructions for filling out the form, including any
					required formatting guidelines. For example, if putting in a phone
					number or security number, the visual label before the text field
					should be:{" "}
				</p>
				<p>Phone number (XXX-XXX-XXXX): [text field]</p>
				<p>
					This is better than just having “Phone number” as the visual label, as
					it explicitly lets the user know the expected number format without
					having to guess.
				</p>
				<p>
					Additionally, forms should have good visual contrast between the text
					and background, as well as a clear delineation of the field input area
					and background area. This will make it easier for users to visually
					navigate, especially those with low vision or visual perceptual
					difficulties.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="labelsAndInputControls"
				title="Form Labels and Input Controls">
				<p>
					Inputs are created using the &lt;input&gt; element. This element takes
					a type which specifies to the user what kind of data should be
					entered. Use the appropriate &lt;input&gt; type for each field, such
					as “text”, “email”, or “number”.
				</p>
				<p>
					Placeholder text can be helpful for providing examples or additional
					information, but it should not be used as a substitute for a semantic
					label. This is because it disappears when the input is in focus, which
					causes an extra load on memory.
				</p>
				<p>
					Let’s revisit our phone number example. the example shows a simple
					code example of a form with an area to place your phone number.
				</p>
				<CodeBlock
					codeSnippet={`<form>
	<label for="phone">Phone Number (XXX-XXX-XXXX):</label>
	<input type="tel" id="phone" name="phone">
</form>
`}
					languageType={"html"}
				/>
				<p>
					This code will work and create a form with the text “Phone number:”
					and an editable text field next to it to place a number. In the edit
					field, there will be the text “enter phone number” as an additional
					visual cue thanks to the placeholder attribute (remember that screen
					readers do not read placeholder text, so important information should
					be placed elsewhere).
				</p>
				<p>
					With the code in this format, the description “Phone number” is
					*visually* determined, and it is *programmatically* determined.
					Meaning the text “Phone Number” is attached meaningfully to the input
					area.
				</p>
				<p>
					To make sure a label and input are programmatically linked as well as
					visually linked we need to use attributes. The &lt;label&gt; element
					should have a “for” attribute and the &lt;input&gt; element should
					have an “id” attribute. The values of the for attribute and id
					attribute must match to connect the label to the input. In this
					example, the label represents both the visual description users see on
					the page and the programmatic description that is read by a screen
					reader.
				</p>
				<p>
					When the label area is selected by a user, the focus of the browser
					goes to the input field. This makes the tap/ click area larger for the
					user, which is especially helpful for those with dexterity and
					cognitive impairments. It also makes explicitly clear that these two
					areas belong together.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="keyboardAccessibleForms"
				title="Keyboard Accessible Forms">
				<p>
					All forms should be navigable by using the keyboard only. Form
					controls are natively keyboard accessible when using the &lt;form&gt;
					element. Users should be able to press the tab or arrow buttons and
					move through all form elements and links. The form elements should be
					activated when the arrow or tab buttons are used (or given focus),
					then activated using the enter or spacebar key.
				</p>
				<p>
					When using JavaScript to create interactions and changes of state, the
					native keyboard accessibility of a form may become inoperable. Because
					there are interactions you can create that are only accessible by
					mouse, extra care should be taken to ensure they can also be accessed
					using the keyboard.
				</p>
				<p>
					Avoid using tables to style forms, instead use CSS. Placing a form in
					a &lt;table&gt; tag may cause navigation issues for assistive
					technology and those using a keyboard to move around the page.
					Manually testing your forms with a keyboard is imperative for catching
					errors caused by JavaScript and general layout issues.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="formErrors"
				title="Error Validation and Changes in State">
				<p>
					It is essential that users know when they have placed the wrong
					information in the form. Error messages and alerts should be clear,
					easy to understand, and given in multiple ways.
				</p>
				<p>
					This alert can be in the form of a popup box (navigable by keyboard)
					or an alert next to the form control. The alert should be perceivable
					by everyone. Therefore, alerts should not be limited to a sound, or
					text, or be conveyed by changing the element to a red color. The alert
					should also be readable by a screen reader.
				</p>
				{
					// INFO: move this section!
				}
				<p>
					Additionally, users should know when an input field is required. This
					can be done using the “required” attribute. An example using the Phone
					number form control would go as follows:
				</p>
				<CodeBlock
					codeSnippet={`<form>
	<label for="phone">Phone Number (XXX-XXX-XXXX):</label>
	<input type="tel" id="phone" name="phone" required>
</form>
`}
					languageType={"html"}
				/>
				<p>
					What would be a good way to convey an error if someone entered their
					phone number in an incorrect format? Preferably, the error message
					would appear close to the input, specifying what the error is in as
					much detail as possible. An icon next to the text would help
					differentiate it from other text. The error should also be added to a
					&lt;div&gt; element with role=alert in order to be read out to a
					screen reader user.
				</p>
			</TemplateSection>
			<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
				<ul className="list">
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#info-and-relationships">
							1.3.1 Info and Relationships
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#sensory-characteristics">
							1.3.3 Sensory Characteristics
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#identify-input-purpose">
							1.3.5 Identify Input Purpose
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#use-of-color">
							1.4.1 Use of Color
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#keyboard">2.1.1 Keyboard</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#timing-adjustable">
							2.2.1 Timing Adjustable
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#timeouts">2.2.6 Timeouts</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#headings-and-labels">
							2.4.6 Headings and Labels
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#focus-visible">
							2.4.7 Focus Visible
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#label-in-name">
							2.5.3 Label in Name
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#on-input">3.3.2 On Input</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#error-identification">
							3.3.1 Error Identification
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#labels-or-instructions">
							3.3.2 Labels or Instructions
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#error-suggestion">
							3.3.3 Error Suggestion
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#error-prevention-legal-financial-data">
							3.3.4 Error Prevention
						</a>
					</li>
					<li>
						<a href="https://www.w3.org/TR/WCAG21/#name-role-value">
							4.1.2 Name, Role, Value
						</a>
					</li>
				</ul>
			</TemplateSection>
			<PageUpdated date="25th July 2023" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/HeadingsTemplate.tsx
================================================
import Image from "next/legacy/image"
import { NavPage } from "../NavPage/NavPage"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { headingsPageNavigation } from "../../data/pageNavigationLists"
import { TemplateSection } from "../TemplateSection/TemplateSection"
import { PageUpdated } from "../PageUpdated/PageUpdated"

export const HeadingsTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={headingsPageNavigation} />
			<article>
				<TemplateSection sectionName="intro" title="Introduction">
					<p>
						HTML headings are tags that are used to hold titles and subheadings
						on a web page. They range from H1, which holds the overall title of
						the page, to H2 - H6, which hold subheadings. The importance of the
						heading decreases as the number increases.
					</p>
					<p>
						A good way to think about headings is to imagine a table of
						contents. The headings make up the important parts of your content
						that you would want users to find quickly.
					</p>
					<div className="imageContainer">
						<Image
							src="/images/headingsTemplate/contents.png"
							alt="screenshot of a table of contents for article about 20 coffee chats with developers, displaying headings for each section"
							width={400}
							height={400}
							layout="intrinsic"
						/>
					</div>
				</TemplateSection>
				<TemplateSection
					sectionName="whyHeadings"
					title="Why are HTML Headings Important?">
					<p>Headings are important for a number of reasons.</p>
					<ul className="list">
						<li>
							They give order and structure to the web page, making it easier
							for users to understand the layout and content of the page.
						</li>
						<li>
							They allow the browser to index and structure the page visually,
							which helps users find what they are looking for.
						</li>
						<li>
							They allow screen reader users to skip to specific sections of the
							page, so they can find the information they need quickly.
						</li>
					</ul>
				</TemplateSection>
				<TemplateSection
					sectionName="includedInHeadings"
					title="What Should Be Included in a Heading?">
					<p>
						When using headings, it is important to include descriptive titles
						and subheadings that accurately describe the content on the page.
						This will help users to find what they are looking for more easily.
						Headings should also be concise and to the point. They should
						clearly summarize the content that follows.
					</p>
				</TemplateSection>

				<TemplateSection
					sectionName="goodHeadings"
					title="How to Write a Good Heading">
					<p>
						Writing a good heading is all about being descriptive, and
						remembering how to nest heading sections within one another in
						sequential order.
					</p>
					<p>Below is a code snippet example with semantic section headings.</p>
					<CodeBlock
						languageType="html"
						codeSnippet={`<h1> Yoga for Developers </h1>
	<h2> What is Yoga? </h2>
		<h3> The History of Yoga </h3>
			<h4> Yoga's Origin </h4>
			<h4> Yoga in Modern Times </h4>
	<h2> The Benefit of Yoga </h2>
		<h3> Strength Conditioning </h3>
			<h4> Power Yoga </h4>
		<h3> Increasing Flexibility</h3>
			<h4> Gentle Stretches </h4>
				<h5> Stretches for the hands </h5>
					<h6> Prayer Pose </h6>
					<h6> Nerve Gliding Exercises </h6>`}
					/>
				</TemplateSection>

				<TemplateSection
					sectionName="avoidHeadings"
					title="What Should We Avoid When Using Headings?">
					<ul className="list">
						<li>
							Avoid using more than one H1 on a page, as this can confuse the
							structure and hierarchy of the page. Instead, the H1 should be
							used for the most important topic on the page.
						</li>
						<li>
							Headings should not be chosen for style purposes - use CSS to
							style sections instead.
						</li>
						<li>
							Headings should not be placed in non sequential order to ensure
							that the structure of the page makes sense.
						</li>
					</ul>
				</TemplateSection>
				<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
					<ul className="list">
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#section-headings"
								className="blockLink">
								2.4.10 Section Headings
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-descriptive.html"
								className="blockLink">
								2.4.6 Headings and Labels
							</a>
						</li>
					</ul>
				</TemplateSection>
				<TemplateSection
					sectionName="QuizQuestions"
					title="Test Your Knowledge">
					<ol className="list">
						<li>How many H1s should we have on our webpage?</li>
						<li>Why is heading order important?</li>
						<li>
							Why is it important to have accurate and descriptive headings?
						</li>
						<li>
							How does non-semantic headings affect users of screen readers?
						</li>
						<li>What should we use to change the style of our headings?</li>
						<li>
							If you wanted to add another subsection under an h2 heading that
							is directly related to the h2 subject, what heading level would
							you use?
						</li>
						<li>
							If you wanted to add a new subsection after an h2 that is not
							related to the current subsection of h2, which heading level would
							you use to make a new section?
						</li>
					</ol>
				</TemplateSection>
			</article>
			<PageUpdated date="8th April 2023" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/IconsTemplate.tsx
================================================
import Link from "next/link"

import { CodeBlock } from "../CodeBlock/CodeBlock"
import { NavPage } from "../NavPage/NavPage"
import { PageUpdated } from "../PageUpdated/PageUpdated"
import { TemplateSection } from "../TemplateSection/TemplateSection"
import { IPageNavigationItem } from "../../data/pageNavigationLists"

export const iconsPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "Decorative Icons", href: "#decorativeIcons" },
	{ linkName: "Informative Icons", href: "#informativeIcons" },
	{ linkName: "Text Alternatives", href: "#textAlternatives" },
	{ linkName: "Icon Links", href: "#iconLinks" },
	{ linkName: "Icon Buttons", href: "#iconButtons" },
	{ linkName: "Use of Colour", href: "#useOfColour" },
	{ linkName: "Target Size", href: "#targetSize" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	// { linkName: "Other Resources", href: "#otherResources" },
]

export const IconsTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={iconsPageNavigation} />
			<article>
				<TemplateSection sectionName="introduction" title="Introduction">
					<p>
						Icons are small stylized graphical images that are often used on
						webpages to complement text. They are also often used alone instead
						of text in order to save space. They are commonly included in
						buttons and links.
					</p>
					<p>
						Icons should be added to a page using the inbuilt HTML img element
						or as an svg. This way, alternative text can be added to the icon if
						needed.
					</p>
				</TemplateSection>
				<TemplateSection sectionName="decorativeIcons" title="Decorative Icons">
					<p>
						An icon is decorative if it doesn't add any information to a page.
						This is often the case when icons are used to complement text,
						especially as part of links and buttons. If a SAVE button included
						both the text "Save" and an icon of a floppy disk the icon is
						decorative. It should have an empty alternative text to avoid the
						word "Save" being announced twice by screen readers.
					</p>
				</TemplateSection>
				<TemplateSection
					sectionName="informativeIcons"
					title="Informative and Functional Icons">
					<p>
						If an icon is informative or functional it needs to have alternative
						text. Examples could include an envelope icon next to an email
						address, a magnifying glass used as a search button or a cog to
						stand for settings. In each case, the alternative text should
						describe the function, for example "search" rather than "magnifying
						glass".
					</p>
				</TemplateSection>
				<TemplateSection
					sectionName="textAlternatives"
					title="Text Alternatives">
					<p>
						The text alternative for an icon depends upon its purpose. Is the
						icon purely decorative? Or does it serve a functional role like an
						icon pointing to the homepage?
					</p>
					<p>
						In HTML the text alternative is added to the img element which takes
						an alt attribute. The alt attribute should be present on every img
						element even if the icon is decorative. If the icon is an svg it
						must be given the role of img and a title to make it accessible.
					</p>
					<p>
						The alternative text can be read out by screen readers or converted
						into braille for refreshable braille displays. Without it, screen
						reader users may hear the whole image url instead, which can often
						be a string of incomprehensible letters and numbers.
					</p>
					<p>
						An icon may need different alternative text depending on where it is
						placed on a webpage. For example, an icon button of a magnifying
						glass may serve as a search button in one place and as a zoom button
						in another.
					</p>
					<CodeBlock
						codeSnippet={`<img src="url" alt="The text alternative goes here" />`}
						languageType="html"
					/>

					<CodeBlock
						codeSnippet={`<svg role="img" height="210" width="400">
	<title>The text alternative goes here</title>
	<path d="M120 10 L55 200 L265 180 Z" />
</svg>`}
						languageType="html"
					/>
				</TemplateSection>
				<TemplateSection sectionName="iconLinks" title="Icon Links">
					<p>
						You can turn an icon into a clickable link that takes you to another
						webpage. Since icon links don't have a visible link text, you need
						to use a different method to give the link an accessible name. These
						methods can include adding an aria-label, using a visibly-hidden
						class or adding an alt attribute to the image wrapped inside the
						link. See the <Link href={"/links"}>Links Page</Link> for detail of
						how to use these techniques.
					</p>
					<p>
						The important thing to remember when using icons as links is to
						describe the link destination rather than the content of the image.
					</p>
					<CodeBlock
						codeSnippet={`<a href="https://google.com" aria-label="Google">
	<FaGoogle />
</a>

<a href="https://google.com">
	<FaGoogle />
	<span class="visibly-hidden">Google</span>
</a>

<a href="https://google.com">
	<img src="url" alt="Google" />
</a>`}
						languageType={"html"}
					/>
				</TemplateSection>
				<TemplateSection sectionName="iconButtons" title="Icon Buttons">
					<p>
						Some buttons use only an icon to convey their function. In this case
						it's important to choose icons that are widely recognised and
						understood, otherwise it can be difficult to know their function.
						The icons should also have a suitable label. This can be done with
						the alt attribute or the aria-label attribute on the button.
					</p>

					<CodeBlock
						codeSnippet={`<button type="button" onclick="handleClick()">
	<img src="icon-url.png" alt="Save" />
</button>`}
						languageType={"html"}
					/>
					<CodeBlock
						codeSnippet={`<button type="button" onclick="handleClick()">
	<i class="fa-solid fa-floppy-disk" aria-label="Save"></i>
</button>`}
						languageType={"html"}
					/>
				</TemplateSection>
				<TemplateSection sectionName={"useOfColour"} title={"Use of Colour"}>
					<p>
						Icons are often used to communicate status. The colour of the icon
						should not be the only way to do this. Instead, use different icons
						or complement the icon with text. For example, if you have an icon
						to indicate online status, avoid green for online and red for
						offline as people with red-green colour vision deficiencies will
						have difficulty telling the two colours apart.
					</p>
				</TemplateSection>
				<TemplateSection sectionName={"targetSize"} title={"Target Size"}>
					<p>
						Icons are often quite small and if used as icon buttons they can be
						difficult to press. Therefore, they should have a minimum target
						size to make sure they can be activated even for users with
						dexterity limitations.
					</p>
					<p>
						The minimum target size should be at least 24 x 24 CSS pixels unless
						the interactive element has enough space so that it does not
						intersect another element, it has an equivalent larger control
						elsewhere on the same page, it is inline, or the presentation is
						considered essential.
					</p>
					<p>
						Ideally, the target size is even larger than 24 CSS pixels, making
						it easier to press. On mobile devices, 44 x 44 CSS pixels is the
						recommended size. This allows for the reduced accuracy of touch.
					</p>
				</TemplateSection>
				<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
					<ul className="list">
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#non-text-content"
								className="blockLink">
								1.1.1 Non-text content
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#info-and-relationships"
								className="blockLink">
								1.3.1 Info and Relationships
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#identify-purpose"
								className="blockLink">
								1.3.6 Identify Purpose
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#use-of-color"
								className="blockLink">
								1.4.1 Use of Color
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#non-text-contrast"
								className="blockLink">
								1.4.11 Non-text Contrast
							</a>
						</li>

						<li>
							<a
								href="https://www.w3.org/TR/WCAG22/#link-purpose-in-context"
								className="blockLink">
								2.4.4 Link Purpose (in Context)
							</a>
						</li>

						<li>
							<a
								href="https://www.w3.org/TR/WCAG22/#link-purpose-link-only"
								className="blockLink">
								2.4.9 Link Purpose (Link Only)
							</a>
						</li>

						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#label-in-name"
								className="blockLink">
								2.5.3 Label in Name
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG22/#target-size-enhanced"
								className="blockLink">
								2.5.5 Target Size (Enhanced)
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG22/#target-size-minimum"
								className="blockLink">
								2.5.8 Target Size (Minimum)
							</a>
						</li>
					</ul>
				</TemplateSection>
				{/* <TemplateSection sectionName="otherResources" title="Other Resources">
					<ul className="list">
						<li>
							<a
								href="https://www.w3.org/WAI/tutorials/images/"
								className="blockLink">
								W3C Images Tutorial
							</a>
						</li>
					</ul>
				</TemplateSection> */}
			</article>
			<PageUpdated date="8th July 2024" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/ImagesTemplate.tsx
================================================
import Image from "next/legacy/image"
import { NavPage } from "../NavPage/NavPage"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { imagePageNavigation } from "../../data/pageNavigationLists"
import { TemplateSection } from "../TemplateSection/TemplateSection"
import { PageUpdated } from "../PageUpdated/PageUpdated"

export const ImagesTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={imagePageNavigation} />
			<article>
				<TemplateSection sectionName="introduction" title="Introduction">
					<p>
						A picture is worth more than a thousand words, as the old adage
						goes. Images help bring texts to life, they complement complex
						explanations and often lead to greater understanding and better web
						experiences. For many people they help make things easier to
						understand. However, not everyone can see images and therefore a
						text alternative is needed so that everyone has access to the
						information conveyed in the image.
					</p>
				</TemplateSection>
				<TemplateSection
					sectionName="textAlternatives"
					title="Text Alternatives">
					<p>
						The text alternative for an image depends upon its purpose. Is the
						image purely decorative? Does it help to describe or explain the
						text? Or does it serve a functional role like an icon pointing to
						the homepage?
					</p>
					<p>
						In HTML the text alternative is added to the image element which
						takes an alt attribute. The alt attribute should be present on every
						img element. If the image is an svg it must be given the role of
						image and a title to make it accessible.
					</p>
					<p>
						The alternative text can be read out by screen readers or converted
						into braille for refreshable braille displays. Without it, screen
						reader users may hear the whole image url instead, which can often
						be a string of incomprehensible letters and numbers.
					</p>
					<CodeBlock
						codeSnippet={`<img src="url" alt="The text alternative goes here" />`}
						languageType="html"
					/>

					<CodeBlock
						codeSnippet={`<svg role="img" height="210" width="400">
	<title>The text alternative goes here</title>
	<path d="M120 10 L55 200 L265 180 Z" />
</svg>`}
						languageType="html"
					/>
				</TemplateSection>
				<TemplateSection
					sectionName="decorativeImages"
					title="Decorative Images">
					<p>
						Decorative images usually add no extra information to a page and a
						person’s understanding is not hindered if the images are not
						visible. Background patterns and shapes are often decorative. Icons
						are also sometimes decorative if they are combined with a link and
						the link text describes the icon. Decorative images should have an
						empty (sometimes also called null) alt attribute.
					</p>
					<div className="imageContainer">
						<Image
							src="/images/imagesTemplate/oldPaperTexture.jpg"
							alt="Old brown paper texture"
							width={300}
							height={200}
							layout="intrinsic"
						/>

						<Image
							src="/images/imagesTemplate/hexagonsPattern.jpg"
							alt="Blue tiled hexagons"
							width={300}
							height={200}
							layout="intrinsic"
						/>
					</div>
					<CodeBlock
						codeSnippet={`<img src="/oldPaperTexture.jpg" alt="" />
<img src="/hexagonsPattern.jpg" alt="" />`}
						languageType="html"
					/>
				</TemplateSection>

				<TemplateSection
					sectionName="informativeImages"
					title="Informative Images">
					<p>
						Informative images compliment written information by illustrating
						concepts and examples visually. An image of a cake alongside a
						recipe, a diagram visualising an instruction and a telephone icon
						preceding a phone number are all examples of informative images.
						These should have a short and succinct text alternative.
					</p>
					<div className="imageContainer">
						<Image
							src="/images/imagesTemplate/cupcakes.jpg"
							alt="Cupcakes with pink icing and small sugar heart decorations"
							width={300}
							height={200}
							layout="intrinsic"
						/>
					</div>
					<CodeBlock
						codeSnippet={`<img src="/cupcakes.jpg" alt="Cupcakes with pink icing and small sugar heart decorations" />`}
						languageType="html"
					/>

					<h3>Complex Informative Images</h3>
					<p>
						Some informative images such as graphs can convey a lot of complex
						information. In such cases the text alternative needs to convey the
						same information which can be difficult to do in a short and
						succinct alt attribute. In this case the text alternative is split
						into two parts. The alt attribute should summarise the image and
						also explain where a longer form text explanation can be found. The
						longer text can be found on the same page or as a link to a separate
						page.
					</p>
					<p>
						The longer text should convey the same complex information as the
						image. In the case of graphs the data should be explained along with
						any trends or relationships. Avoid using colour as the only way of
						explaining the information as not everyone perceives colour in the
						same way.
					</p>
					<div className="imageContainer">
						<Image
							src="/images/imagesTemplate/drill-instruction.png"
							alt="Drawn instructions for how to use a handheld drill"
							width={200}
							height={175}
							layout="intrinsic"
						/>
					</div>
					<CodeBlock
						codeSnippet={`<img src="drill-instructions.png" alt="How to use a handheld drill. Further instructions below." />`}
						languageType="html"
					/>
				</TemplateSection>

				<TemplateSection
					sectionName="functionalImages"
					title="Functional Images">
					<p>
						If images are used as part of a link or button they are usually
						there to perform a function. Examples include using a magnifying
						glass to signify a search field, a floppy disk icon as a save button
						or a logo as a link back to the home page. The text alternative
						should match the action performed by the link or button.
					</p>
					<div className="imageContainer">
						<Image
							src="/images/imagesTemplate/searchBtn.png"
							alt="Magnifying glass used as search button example"
							width={150}
							height={150}
							layout="intrinsic"
						/>
						<Image
							src="/images/imagesTemplate/playBtn.png"
							alt="Triangle used as play button example"
							width={150}
							height={150}
							layout="intrinsic"
						/>
					</div>
					<CodeBlock
						codeSnippet={`<img src="searchBtn.png" alt="Search" />
<img src="playBtn.png" alt="Play" />`}
						languageType="html"
					/>
				</TemplateSection>

				<TemplateSection
					sectionName="goodAltText"
					title="How to write good alt text">
					<p>
						Writing good text alternatives is not always easy and there are many
						differing opinions about how to do it well. The text alternative
						should get across all the important information. A good rule of
						thumb is to imagine you are describing an image to someone over the
						phone. Which details would you tell them about? Which details would
						you leave out? The more complex the image, the more detailed your
						alternative text needs to be.
					</p>
					<p>Let's take a look at the following image:</p>
					<div className="imageContainer">
						<Image
							src="/images/imagesTemplate/vw-beetle-car.jpg"
							alt="VW Beetle Car in pale green in front of a pitched roof house painted in the same colour"
							width={600}
							height={400}
							layout="intrinsic"
						/>
					</div>
					<p>
						The focus of this image would depend on the context of where it's
						used. Is the focus the car or the house? Let's look at a couple of
						alternatives.
					</p>
					<p>
						<strong>Alternative 1: The house is for sale</strong>
					</p>
					<p>
						The main focus should be on describing the house. The car is
						probably not important as that won't be included in the house sale.
						Let's try it.
					</p>
					<p>
						<strong>Basic: </strong>House with pitched roof and brown front
						door.
					</p>
					<p>
						<strong>More detailed: </strong>Pale green, one storey house with
						pitched roof, large windows and steps up to a brown front door.
						Surrounded by a white picket fence.
					</p>
					<p>
						<strong>Too detailed? </strong>Pale green, one storey house of
						wooden construction. White painted trim surrounds large windows with
						3 panels on either side of a stained wood front door. The house is
						surrounded by a small garden and white picket fence with steps
						leading from the road to the porch. There is both on-road parking
						out the front and a driveway to the left of the house. The garden is
						well-established with palms, various trees, bushes and vines.
					</p>
					<p>
						<strong>Alternative 2: A car magazine</strong>
					</p>
					<p>
						This time the car is the main focus and the house needs less
						description. However, the house adds to the aesthetic and emotion of
						the image.
					</p>
					<p>
						<strong>Basic: </strong>Vintage car parked on a street.
					</p>
					<p>
						<strong>More detailed: </strong>Soft, pale green vintage VW Beetle
						parked in front of a house painted in the same pale green.
					</p>
					<p>
						<strong>Too detailed? </strong>Soft, pale green vintage VW Beetle in
						excellent condition with shiny silver trim and new tyres. The car is
						parked on a quiet street in front of a one storey house painted in
						the same color in a sleepy suburb.
					</p>
				</TemplateSection>

				<TemplateSection sectionName="imagesOfText" title="Images of Text">
					<p>
						Wherever possible, images of text should be avoided as the text
						can’t be enlarged in the same way as text in HTML. However, if you
						must have an image of text then the alt text should match the text
						in the image.
					</p>
					<div className="imageContainer">
						<Image
							src="/images/imagesTemplate/make-the-day-great.jpg"
							alt="Make the day great sign"
							width={300}
							height={200}
							layout="intrinsic"
						/>
					</div>
					<CodeBlock
						codeSnippet={`<img src="make-the-day-great.jpg" alt="Make the day great sign" />`}
						languageType="html"
					/>
				</TemplateSection>
				<TemplateSection
					sectionName="imagesAndColour"
					title="Images and Colour">
					<p>
						Colour should not be the only way to represent meaning in an image
						because not everyone perceives colour in the same way. If colour is
						used in graphs, charts and diagrams then there should also be
						another way to tell the colours apart, such as different patterns or
						symbols.
					</p>
					{
						// TODO: Add an example here of a pie chart or bar chart
					}
				</TemplateSection>
				<TemplateSection sectionName="imageMaps" title="Image Maps">
					<p>
						An image map is a larger image with clickable hotspots, each of
						which open a different section. An example could be a floor plan of
						a local building which opens up an enlarged map of each room when
						clicked. The hotspots are made with the area element and each area
						element should have its own alt attribute. The overall image should
						also have an alt attribute.
					</p>
					<p>
						Let's take a look at the image below. The image itself has an alt
						attribute which describes the whole image. Each area is clickable
						and leads to a Wikipedia article. Each area also has an alt
						attribute describing just that section of the image.
					</p>
					<map name="primary">
						<area
							shape="circle"
							coords="190,130,70"
							href="https://en.wikipedia.org/wiki/Doughnut"
							target="_blank"
							alt="Doughnut"
						/>
						<area
							shape="circle"
							coords="380,250,100"
							href="https://en.wikipedia.org/wiki/Coffee"
							target="_blank"
							alt="Coffee"
						/>
					</map>
					<Image
						useMap="#primary"
						src="/images/imagesTemplate/donut-coffee.png"
						width={600}
						height={400}
						alt="Illustration of a pink doughnut with sprinkles next to a cup of black coffee"
						layout="intrinsic"
					/>
					<CodeBlock
						codeSnippet={`<map name="primary">
	<area
		shape="circle"
		coords="190,130,70"
		href="url"
		alt="Doughnut"
	/>
	<area
		shape="circle"
		coords="380,250,100"
		href="url"
		alt="Coffee"
	/>
</map>
<img
	usemap="#primary"
	src="donut-coffee.png"
	alt="Illustration of a pink doughnut with sprinkles next to a cup of black coffee" 
/>`}
						languageType="html"
					/>
				</TemplateSection>
				{/* TODO: <TemplateSection sectionName="checklist"  title="Images Checklist">
					
					<p>Add some points here</p>
				</TemplateSection> */}
				<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
					<ul className="list">
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#non-text-content"
								className="blockLink">
								1.1.1 Non-text content
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#use-of-color"
								className="blockLink">
								1.4.1 Use of Color
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#images-of-text"
								className="blockLink">
								1.4.5 Images of Text
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/TR/WCAG21/#images-of-text-no-exception"
								className="blockLink">
								1.4.9 Images of Text (No Exception)
							</a>
						</li>
					</ul>
				</TemplateSection>
				<TemplateSection sectionName="otherResources" title="Other Resources">
					<ul className="list">
						<li>
							<a
								href="https://www.w3.org/WAI/tutorials/images/"
								className="blockLink">
								W3C Images Tutorial
							</a>
						</li>
						<li>
							<a
								href="https://www.w3.org/WAI/tutorials/images/decision-tree/"
								className="blockLink">
								W3C An alt decision tree
							</a>
						</li>
						<li>
							<a
								href="https://jakearchibald.com/2021/great-alt-text/"
								className="blockLink">
								Writing great alt text: Emotion matters
							</a>
						</li>
						<li>
							<a
								href="https://tink.uk/thoughts-on-skin-tone-and-text-descriptions.md-notes-on-synthetic-speech/"
								className="blockLink">
								Thoughts on skin tone and text descriptions
							</a>
						</li>
						<li>
							<a
								href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map"
								className="blockLink">
								MDN: The Image Map element
							</a>
						</li>
					</ul>
				</TemplateSection>
			</article>

			<PageUpdated date="26th November 2022" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/LinksTemplate.module.css
================================================
.srOnly{
	border: 0;
    clip: rect(0,0,0,0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}

================================================
FILE: components/ContentTemplates/LinksTemplate.tsx
================================================
import { TemplateSection } from "../TemplateSection/TemplateSection"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { NavPage } from "../NavPage/NavPage"
import { linkPageNavigation } from "../../data/pageNavigationLists"
import { PageUpdated } from "../PageUpdated/PageUpdated"

export const LinksTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={linkPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					Links, also known as hyperlinks, are a fundamental element in HTML.
					They connect different pages, or parts of pages, to one another.
				</p>

				<p>
					In HTML, links are created using the anchor element
					<strong>{`${" <a>"}`}</strong>. This element allows you to make text
					or images clickable, and has inbuilt interactivity allowing users to
					activate the link with a mouse click, a touch device or by pressing
					Enter on a keyboard. It is also automatically reachable with the tab
					key.
				</p>
				<p>
					The accessible name for links created using the anchor element comes
					from the content between the opening and closing tag. If the content
					between the opening and closing tags is not text, or the text is very
					generic the accessible name should be added in another way, for
					example with ARIA.
				</p>
				<p>
					An important attribute for accessibility is the href attribute. This
					specifies the destination of the link. If the href is not present then
					the link is not accessible.
				</p>
			</TemplateSection>

			<TemplateSection
				sectionName="accessibleLinkNames"
				title="Accessible Link Names">
				<div>
					<h3>Descriptive Link Text</h3>
					<p>
						Link text is the text between the opening and closing anchor tag
						that describes a hyperlink on a webpage. It's important to have
						descriptive link text to provide clear context about where the link
						leads and helps users understand the purpose of the link. This is
						helpful for people with cognitive disabilities, screen reader users
						and voice input users.
					</p>

					<CodeBlock
						codeSnippet={`<a href="https://accessibleweb.dev">Visit Accessible Web Dev</a> 
<!--The descriptive name in this case is "Visit Accessible Web Dev" -->`}
						languageType={"html"}
					/>
				</div>
				<div>
					<h3>Non-descriptive Link Text</h3>
					<p>
						If possible, avoid using vague, non-descriptive phrases as link text
						such as "Click Here" or "Read More". These phrases are difficult to
						understand without surrounding context and can pose problems for
						screen reader users and voice input users. It is also common to see
						these phrases repeated multiple times on a page, for example on an
						e-commerce site listing several product cards, making it more
						difficult to differentiate between the different link destinations.
					</p>
					<p>
						If you must use non-descriptive text, you can make it more
						accessible by using methods to overwrite the visible text. Two such
						methods are using aria-label or hiding additional text with CSS.
					</p>
					<h4>Aria-label</h4>
					<p>
						The first method is to use an aria-label. This will overwrite the
						visible text and be read out to screen reader users instead. It's
						important to keep in mind that the aria-label should start with the
						same text as shown in the visible text so that the link still works
						for voice input users. If the visible link says "Read more" the
						aria-label might be "Read more about accessible buttons"
					</p>
					<p>
						An aria-label can also be used to give an image or icon link an
						accessible name when there is no visible link text.
					</p>
					<CodeBlock
						codeSnippet={`<a href="https://accessibleweb.dev/buttons" aria-label="Read more about accessible buttons">Read more</a>`}
						languageType={"html"}
					/>
					<p>
						Some downsides to aria-label are that it doesn't always get
						translated by in-browser translation tools. It also completely
						overwrites the visible text which can be problematic if the two do
						not match.
					</p>
					<h4>Hiding elements with CSS</h4>
					<p>
						Another solution is to use CSS to hide some extra text. This can be
						done by adding a visibly hidden <strong>{`${"<span>"}`}</strong>{" "}
						element within the <strong>{`${"<a>"}`}</strong> element to provide
						descriptive text that gets read out to screen readers but is not
						visible to sighted users.
					</p>

					<CodeBlock
						codeSnippet={`<a href="https://accessibleweb.dev/buttons">Read more
	<span class="visibly-hidden">about accessible buttons</span>
</a>`}
						languageType={"html"}
					/>

					<CodeBlock
						codeSnippet={`.visibly-hidden {
    border: 0;
    clip: rect(0,0,0,0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
}
/* You may also see this class called screen-reader-only or sr-only in
other places on the web */`}
						languageType={"css"}
					/>
				</div>
			</TemplateSection>

			<TemplateSection sectionName="linkStates" title="Link State and Style">
				<p>
					To improve the accessibility of your website, it's crucial to make
					links easy to distinguish from non-interactive elements on a page.
				</p>

				<p>Here's how to achieve this:</p>

				<ul className="list">
					<li>
						<strong>Underline links by default: </strong>
						Links should be underlined by default. This provides a clear visual
						indicator that a piece of text or an element is clickable. It's a
						universal convention that helps all users understand what's
						clickable.
					</li>
					<li>
						<strong>Focus state: </strong>A focused link should have a focus
						indicator which makes it easy to see where focus is on the screen.
						This is often a thicker border or outline around the link and should
						have a contrast ratio of at least 3:1 with the background.
					</li>
					<li>
						<strong>Ensure sufficient color contrast: </strong>
						Make sure the color of your links contrasts well with the background
						color or surrounding text color. This ensures that people with
						visual impairments or color vision deficiencies can easily
						distinguish the links from the surrounding text. The contrast ratio
						should be at least 4.5:1 for WCAG level AA compliance. Color should
						not be the only way to distinguish links from surrounding text.
					</li>
					<li>
						<strong>Don't rely on hover state to convey links: </strong>
						Hover is not available on touch devices or for people navigating the
						web with keyboard, screen readers or other input devices. Therefore
						hover states only, such as underline or color change on hover,
						should not be relied upon to convey that something is a link.
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName="linkImage" title="Image and Icon Links">
				<p>
					You can turn an image or icon into a clickable link that takes you to
					another webpage. Since image and icon links don't have a visible link
					text, you need to use a different method to give the link an
					accessible name. These methods can include adding an aria-label, using
					a visibly-hidden class or adding an alt attribute to the image text
					wrapped inside the link.
				</p>
				<p>
					The important thing to remember when using images and icons as links
					is to describe the link destination rather than the content of the
					image.
				</p>
				<CodeBlock
					codeSnippet={`<a href="https://google.com" aria-label="Google">
	<FaGoogle />
</a>

<a href="https://google.com">
	<FaGoogle />
	<span class="visibly-hidden">Google</span>
</a>

<a href="https://google.com">
	<img src="url" alt="Google" />
</a>`}
					languageType={"html"}
				/>
			</TemplateSection>
			<TemplateSection
				sectionName="touchTargetMinimum"
				title="Touch Target Minimum">
				<p>
					When it comes to creating accessible links, it's important that they
					are easy to activate. To do this, WCAG recommends that links that are
					not within text have a target size of at least 24 x 24 CSS pixels.
					Doing this makes it easier for users who have motor dexterity issues
					to click them.
				</p>
			</TemplateSection>
			<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#non-text-content"
							className="blockLink">
							1.1.1 Non-text content
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#info-and-relationships"
							className="blockLink">
							1.3.1 Info and Relationships
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#identify-purpose"
							className="blockLink">
							1.3.6 Identify Purpose
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#contrast-minimum"
							className="blockLink">
							1.4.3 Contrast (minimum)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#non-text-contrast"
							className="blockLink">
							1.4.11 Non-text Contrast
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#content-on-hover-or-focus"
							className="blockLink">
							1.4.13 Content on Hover or Focus
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#keyboard"
							className="blockLink">
							2.1.1 Keyboard
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#link-purpose-in-context"
							className="blockLink">
							2.4.4 Link Purpose (in Context)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#focus-visible"
							className="blockLink">
							2.4.7 Focus Visible
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#link-purpose-link-only"
							className="blockLink">
							2.4.9 Link Purpose (Link Only)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#focus-not-obscured-minimum"
							className="blockLink">
							2.4.11 Focus Not Obscured (Minimum)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#focus-not-obscured-enhanced"
							className="blockLink">
							2.4.12 Focus Not Obscured (Enhanced)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#focus-appearance"
							className="blockLink">
							2.4.13 Focus Appearance
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#label-in-name"
							className="blockLink">
							2.5.3 Label in Name
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#target-size-enhanced"
							className="blockLink">
							2.5.5 Target Size (Enhanced)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG22/#target-size-minimum"
							className="blockLink">
							2.5.8 Target Size (Minimum)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#on-focus"
							className="blockLink">
							3.2.1 On Focus
						</a>
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName="otherResources" title="Other Resources">
				<ul className="list">
					<li>
						<a
							href="https://www.tpgi.com/well-color-us-surprised-this-sc-can-be-a-tricky-customer/"
							className="blockLink">
							Well Color Us Surprised - This SC Can Be a Tricky Customer
						</a>
					</li>
					<li>
						<a
							href="https://webaim.org/blog/wcag-2-0-and-link-colors/"
							className="blockLink">
							WCAG 2.0 and link colors
						</a>
					</li>
				</ul>
			</TemplateSection>

			<PageUpdated date="5th January 2024" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/ListsTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const ListsTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/ContentTemplates/MenusTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const MenusTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/ContentTemplates/ModalsTemplate.tsx
================================================
import { TemplateSection } from "../TemplateSection/TemplateSection"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { NavPage } from "../NavPage/NavPage"
import { modalPageNavigation } from "../../data/pageNavigationLists"
import { PageUpdated } from "../PageUpdated/PageUpdated"

export const ModalsTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={modalPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					Modals are elements of a website or application that are appear on top
					of the main window. They are usually activated by the click of a
					button or some event. The main window may still visible underneath
					although you should not be able to interact with it when the modal is
					open. Modals go by many names, including modal window, dialog, popup
					and even lightbox. On this page we will use the term modal throughout
					to describe this pattern.
				</p>
				<p>
					Before 2023, there was no semantic HTML element that could be used to
					create a modal. That means developers combined HTML elements to create
					their own modals. Many different patterns for modals exist out in the
					wild but unfortunately many are not accessible.
				</p>
				<p>
					In 2023, the dialog element was added to the HTML specification in an
					attempt to minimise the need for developers to build their own modals.
					On this page you will find examples of two accessible modals, one with
					the dialog element and one without.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName="howAModalShouldWork"
				title="How a modal should work">
				<ul className="list">
					<li>
						Things behind the modal should become inactive when the modal is
						open.
					</li>
					<li>
						The focus should move to an element within the modal when it opens.
					</li>
					<li>
						The focus should move back to the original activating element when
						the modal closes.
					</li>
					<li>
						The focus should be trapped within the modal when open - it should
						not be possible to tab to something outside of the modal when it is
						open.
					</li>
					<li>
						It should be possible to close the modal by pressing the Escape key.
					</li>
					<li>
						The modal should not be part of the tab order when it is closed.
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName="usingDialog" title={"Using <dialog>"}>
				<p>
					The HTML &lt;dialog&gt; element has full support since Chrome 37, Edge
					79, Firefox 98 and Safari 15.4. If you need to support browsers older
					than this then using a different method is suggested.
				</p>
				<h3>HTML</h3>
				<p>
					The &lt;dialog&gt; element will handle focus if using a keyboard to
					navigate without the need for additional JavaScript. On opening the
					modal, focus will be placed on the first interactive item. If no
					interactive item exists then the focus is placed on the modal itself.
					All content behind the modal is made inert. Using the Escape key
					closes the modal. However, clicking on the modal backdrop does not
					automatically close the modal.
				</p>

				<CodeBlock
					codeSnippet={`<button id="openDialogBtn">Open dialog</button>
<dialog id="dialog" aria-labelledby="dialog_heading">
  <h2 id="dialog_heading">This is a heading</h2>
  <p>This is some placeholder text within the dialog.</p>
  <button type="button" id="cancelBtn">Cancel</button>
</dialog>`}
					languageType={"html"}
				/>
				<h3>CSS</h3>
				<p>
					The modal comes with some basic built in styles. The backdrop can be
					customised using the ::backdrop pseudo-element. Dialog styles can be
					overwritten by styling the dialog element directly.
				</p>
				<CodeBlock
					codeSnippet={`dialog::backdrop {
  background: rgb(0 0 0 / 70%);
}

dialog {
  border: 1px solid #000;
  box-shadow: 0 19px 38px rgb(0 0 0 / 12%), 0 15px 12px rgb(0 0 0 / 22%);
}`}
					languageType={"css"}
				/>
				<h3>JavaScript</h3>
				<p>
					Using the showModal() method will open the dialog element in a modal
					window (on top of the other content) and apply an implicit state of
					aria-modal="true". The modal can be closed with the close() method. No
					extra JavaScript is needed to handle keyboard focus, making background
					elements inert or closing the modal with the Escape key.
				</p>
				<CodeBlock
					codeSnippet={`const openDialogBtn = document.getElementById("openDialogBtn");
const dialog = document.getElementById("dialog");
const cancelBtn = document.getElementById("cancelBtn");

openDialogBtn.addEventListener("click", () => dialog.showModal());
cancelBtn.addEventListener("click", () => dialog.close());`}
					languageType={"javascript"}
				/>
			</TemplateSection>
			<TemplateSection sectionName="customModals" title="Custom Modals">
				<p>
					If you need to support browsers older than those listed above, then
					you may need to build a custom modal component. In this case you will
					need to add accessible information yourself.
				</p>
				<h3>HTML</h3>
				<p>
					In this case, the div used to create the modal is given a
					role="dialog" to indicate that this is a modal. It is labelled with
					aria-labelledby so that it announces the heading when the modal
					appears. It is also given a tabindex="-1" so that focus can be
					manually handled with JavaScript.
				</p>
				<CodeBlock
					codeSnippet={`<div id="wrapper">  
  <button type="button" id="openModal">Open Modal</button>
</div>

<div class="modalBackground hidden"></div>
<div role="dialog" id="modal" aria-labelledby="modal_heading" class="hidden" tabindex="-1">
   <h2 id="modal_heading">This is a heading</h2>
   <p>This is some placeholder text within the modal.</p>
   <button type="button" id="cancelBtn">Cancel</button>
</div>`}
					languageType={"html"}
				/>
				<h3>CSS</h3>
				<p>
					For this modal we can use the [role="dialog] attribute to add the
					styling. All of the positioning needs to be added as none of it is
					inbuilt, unlike the dialog element.
				</p>
				<CodeBlock
					codeSnippet={`.hidden {
  display: none;
}

[role="dialog"] {
  position: absolute;
  padding: 15px;
  border: 1px solid #000;
  background-color: #fff;
  min-width: 300px;
  top: 2rem;
  left: 50vw; 
  transform: translateX(-50%); 
  overflow: hidden;
  box-shadow: 0 19px 38px rgb(0 0 0 / 12%), 0 15px 12px rgb(0 0 0 / 22%);
  }

.modalBackground {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: rgb(0 0 0 / 70%);
}
`}
					languageType={"css"}
				/>
				<h3>JavaScript</h3>
				<p>
					In a custom modal you need to handle focus and inert manually. When
					the modal is opened, focus moves from the button to something inside
					the modal. In this case it moves to the modal itself, but it could
					also move to the heading or the first interactive element. The page
					content is wrapped in a div with id="wrapper" so can be selected. Once
					the modal is open the inert attribute is applied to the main content
					so that focus is trapped within the modal.
				</p>
				<p>
					When the modal is closed, the inert attribute needs to be removed from
					the main content. This must happen before you set focus back to the
					opening button. If not, then the button won't be found. An event
					listener also needs adding for the Escape key so that it also runs the
					closeModal function. In this custom component it is also possible to
					add an event to the modal backdrop to close the modal on click.
				</p>
				<CodeBlock
					codeSnippet={`const wrapper = document.getElementById("wrapper")
const openModalBtn = document.getElementById("openModal");
const cancelBtn = document.getElementById("cancelBtn");
const modal = document.getElementById("modal");
const modalBackground = document.querySelector(".modalBackground");


const openModal = () => {
  modal.classList.remove("hidden");
  modalBackground.classList.remove("hidden");
  modal.focus();
  wrapper.setAttribute("inert", "");  
}

const closeModal = () => {
 modal.classList.add("hidden");
 modalBackground.classList.add("hidden");
 wrapper.removeAttribute("inert")
 openModalBtn.focus()
}

openModalBtn.addEventListener("click", openModal)
cancelBtn.addEventListener("click", closeModal)
modalBackground.addEventListener("click", closeModal)
window.addEventListener("keyup", (e) => {
  if (e.key === "Escape" && !modal.classList.contains("hidden")) {
    closeModal()
  }
})`}
					languageType={"javascript"}
				/>
			</TemplateSection>
			<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#keyboard"
							className="blockLink">
							2.1.1 Keyboard
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#no-keyboard-trap"
							className="blockLink">
							2.1.2 No Keyboard Trap
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#name-role-value"
							className="blockLink">
							4.1.2 Name, role, value
						</a>
					</li>
				</ul>
			</TemplateSection>
			<TemplateSection sectionName="otherResources" title="Other Resources">
				<ul className="list">
					<li>
						<a
							href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog"
							className="blockLink">
							MDN web docs - The Dialog element
						</a>
					</li>
					<li>
						<a
							href="https://adrianroselli.com/2020/10/dialog-focus-in-screen-readers.html"
							className="blockLink">
							Dialog Focus in Screen Readers by Adrian Roselli
						</a>
					</li>
					<li>
						<a
							href="https://www.scottohara.me/blog/2023/01/26/use-the-dialog-element.html"
							className="blockLink">
							Use the dialog element (reasonably) by Scott O'Hara
						</a>
					</li>
				</ul>
			</TemplateSection>
			<PageUpdated date="23rd June 2023" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/NavigationTemplate.tsx
================================================
import { navigationPageNavigation } from "../../data/pageNavigationLists"
import { CodeBlock } from "../CodeBlock/CodeBlock"
import { NavPage } from "../NavPage/NavPage"
import { PageUpdated } from "../PageUpdated/PageUpdated"
import { TemplateSection } from "../TemplateSection/TemplateSection"

// TODO: Add information about using aria-current
// TODO: Add working examples to complement the code examples

export const NavigationTemplate = () => {
	return (
		<>
			<NavPage pageNavigation={navigationPageNavigation} />
			<TemplateSection sectionName="introduction" title="Introduction">
				<p>
					A website navigation is a section of the page aimed at helping you
					find the main sections of a website. HTML has a semantic &lt;nav&gt;
					element which should be used around all navigations on the page. This
					element is a landmark element and can be used by screen reader users
					to more easily find their way around the page.
				</p>
			</TemplateSection>
			<TemplateSection sectionName="simpleNav" title="A Simple Navigation">
				<p>
					In its simplest form a navigation is a list of links to other pages
					within a larger website or to other regions of the same page. A nav
					element wraps an unordered list of links in order to communicate how
					long the navigation is.
				</p>

				<CodeBlock
					codeSnippet={`<nav>
	<ul>
		<li>
			<a href"/">Link 1</a>
		</li>
		<li>
			<a href"/">Link 2</a>
		</li>
		<li>
			<a href"/">Link 3</a>
		</li>
	</ul>
</nav>`}
					languageType={"html"}
				/>
			</TemplateSection>
			<TemplateSection sectionName={"hamburgerMenus"} title={"Hamburger Menus"}>
				<p>
					Often on mobile there is not space for a full navigation and a common
					pattern is to use a hamburger menu. This is usually a button with an
					icon that looks like three layers of a hamburger and represents the
					place to find the navigation. Pressing the button opens the navigation
					and often the icon will change to a cross to signify a close button.
				</p>
				<p>
					To make a hamburger menu accessible it must be reachable and operable
					by keyboard only. If a button element is used then this will happen
					automatically. It should have a clear label stating the function of
					the button and it should also announce whether it is opened or closed
					to screen reader users. For this, aria-label and aria-expanded are
					useful and JavaScript will be needed to toggle the navigation open and
					closed.
				</p>
				{
					// TODO: Fix this code block!
				}
				<CodeBlock
					codeSnippet={`<button id="hamburgerMenu" class="navButton" aria-label="Navigation menu" aria-expanded="false" aria-controls="primaryNav">
	Menu
</button>
<nav id="primaryNav" class="hidden">
	<ul class="primaryNavList">
		<li>
			<a href="#">Item 1</a>
		</li>
		<li>
			<a href="#">Item 2</a>
		</li>
		<li>
			<a href="#">Item 3</a>
		</li>
	</ul>
</nav>`}
					languageType={"html"}
				/>
				<CodeBlock
					codeSnippet={`.navButton {
  position: relative;
}

.primaryNavList {
  position: absolute;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid black;
  width: 10rem;
  z-index: 1;
}

.primaryNavList li {
  padding: 1rem;
}

.hidden {
  display: none;
}`}
					languageType={"css"}
				/>
				<CodeBlock
					codeSnippet={`const navButton = document.getElementById("hamburgerMenu");
const disclosure = document.getElementById("primaryNav");
const listItems = disclosure.querySelectorAll("li a");

function openNavigation() {
  navButton.setAttribute("aria-expanded", "true");
  disclosure.classList.remove("hidden");
}

function closeNavigation() {
  navButton.setAttribute("aria-expanded", "false");
  disclosure.classList.add("hidden");
}

function toggleNavigation() {
  const open = navButton.getAttribute("aria-expanded");
  open === "false" ? openNavigation() : closeNavigation();
}

// This function closes an open disclosure if a user tabs away from the last anchor element in the list. It is reliant on the ul container having a class to check whether the relatedTarget is within the disclosure. If not, it will close.
function handleBlur() {
  const navList = event.currentTarget.closest(".primaryNavList");
  if (!event.relatedTarget || !navList.contains(event.relatedTarget)) {
    closeNavigation();
  }
}

navButton.addEventListener("click", toggleNavigation);

// add event to the last item in the nav list to trigger the disclosure to close if the user tabs out of the disclosure
listItems[listItems.length - 1].addEventListener("blur", handleBlur);

// Close the disclosure if a user presses the escape key
window.addEventListener("keyup", (e) => {
  if (e.key === "Escape") {
    navButton.focus();
    closeNavigation();
  }
});`}
					languageType={"javascript"}
				/>
			</TemplateSection>
			<TemplateSection sectionName={"megaMenus"} title={"Mega Menus"}>
				<p>
					Mega menus are more complex navigations with nested links to different
					sections and pages. Examples can often be found on popular clothing
					chain websites.
				</p>
				<p>
					The top level of a mega menu is usually broken up into broad
					categories. These categories can be made with buttons that trigger a
					popup to open when pressed. The list of navigation links is then
					shown.
				</p>
				<p>
					In the example below a very simple "Mega Menu" is shown with only two
					sections. These can be extended as necessary.
				</p>
				<CodeBlock
					codeSnippet={`<nav>
  <ul class="nav-list">
    <li class="nav-group">
      <button id="navItem1" class="navItem" aria-expanded="false" aria-controls="disclosure1">Nav 1 &#9660;</button>
      <ul class="disclosure hidden" id="disclosure1">
        <li>
          <a href="#">Dropdown 1 - item 1</a>
        </li>
        <li>
          <a href="#">Dropdown 1 - item 2</a>
        </li>
        <li>
          <a href="#">Dropdown 1 - item 3</a>
        </li>
      </ul>
    </li>
    <li class="nav-group">
      <button id="navItem2" class="navItem" aria-expanded="false" aria-controls="disclosure2">Nav list 2 &#9660;</button>
      <ul class="disclosure hidden" id="disclosure2">
        <li>
          <a href="#">Dropdown 2 - item 1</a>
        </li>
        <li>
          <a href="#">Dropdown 2 - item 2</a>
        </li>
      </ul>
    </li>
  </ul>
</nav>`}
					languageType={"html"}
				/>
				<CodeBlock
					codeSnippet={`.disclosure {
  position: absolute;
  border: 1px solid black;
  width: 12rem;
  padding: 0.5rem 1rem;
  z-index: 1;
}

.disclosure li {
  margin: 0.5rem 0;
}

.hidden {
  display: none;
}`}
					languageType={"css"}
				/>
				<CodeBlock
					codeSnippet={`const navButtons = document.querySelectorAll(".navItem");
const disclosures = document.querySelectorAll(".disclosure");

function openNavigation(button) {
  button.setAttribute("aria-expanded", "true");
  // The ul is a direct sibling to the button
  const disclosure = button.nextElementSibling;
  disclosure.classList.remove("hidden");
}

function closeNavigation(button) {
  button.setAttribute("aria-expanded", "false");
  const disclosure = button.nextElementSibling;
  disclosure.classList.add("hidden");
}

function toggleNavigation(index) {
  // First we close any open dropdowns not related to the current button in focus by looping over all nav buttons
  navButtons.forEach((button, buttonIndex) => {
    if (buttonIndex != index) {
      closeNavigation(button);
    }
  });
  const currentButton = event.target;
  const open = currentButton.getAttribute("aria-expanded");
  open === "false"
    ? openNavigation(currentButton)
    : closeNavigation(currentButton);
}

// This function closes an open disclosure if a user tabs away from the last anchor element in the list. It is reliant on the top-level list item of the top level ul having a class to find the group containing button + disclosure it controls
function handleBlur(button) {
  const navList = event.currentTarget.closest(".nav-group");
  if (!event.relatedTarget || !navList.contains(event.relatedTarget)) {
    closeNavigation(button);
  }
}

// Adds the toggle event to every top level button
navButtons.forEach((button, index) => {
  button.addEventListener("click", () => toggleNavigation(index));
});

// This adds the handleBlur event to the last anchor element in each disclosure
disclosures.forEach((disclosure) => {
  const listItems = disclosure.querySelectorAll("li a");
  listItems[listItems.length - 1].addEventListener("blur", (event) => {
    handleBlur(disclosure.previousElementSibling);
  });
});

// This adds a global event listener to close any open disclosures when the escape key is pressed
window.addEventListener("keyup", (e) => {
  if (e.key === "Escape") {
    const navButtonsArr = Array.from(navButtons);
    const currentOpenButtonIndex = navButtonsArr.findIndex(
      (button) => button.getAttribute("aria-expanded") === "true"
    );
    // If there is an open disclosure, close it and send focus back to the button that controls it.
    if (currentOpenButtonIndex >= 0) {
      const currentOpenButton = navButtons[currentOpenButtonIndex];
      currentOpenButton.focus();
      closeNavigation(currentOpenButton);
    }
  }
});`}
					languageType={"javascript"}
				/>
			</TemplateSection>
			<TemplateSection sectionName={"linksOrder"} title={"Order of Links"}>
				<p>
					To help users find their way around easily, it's important that the
					relative order of links remains the same across all pages within a web
					site.
				</p>
			</TemplateSection>
			<TemplateSection
				sectionName={"multipleNavs"}
				title={"Multiple Navigations Per Page"}>
				<p>
					It is common to have more than one navigation per page, for example a
					primary navigation that takes people between different pages of the
					website and a secondary navigation that takes people to different
					sections within a page.
				</p>
				<p>
					When there are multiple navigations using the nav element it is
					important to differentiate them for screen reader users by labelling
					them. Use aria-label or aria-labelledby to let screen reader users
					know the different functions of the navigation elements.
				</p>

				<CodeBlock
					codeSnippet={`<nav aria-label="Site">
...
</nav>
`}
					languageType={"html"}
				/>
				<CodeBlock
					codeSnippet={`<nav aria-label="Within page">
...
</nav>`}
					languageType={"html"}
				/>
			</TemplateSection>
			<TemplateSection sectionName="WCAGCriteria" title="WCAG Criteria">
				<ul className="list">
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#info-and-relationships"
							className="blockLink">
							1.3.1 Info and Relationships
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#reflow"
							className="blockLink">
							1.4.10 Reflow
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#content-on-hover-or-focus"
							className="blockLink">
							1.4.13 Content on Hover and Focus
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#keyboard"
							className="blockLink">
							2.1.1 Keyboard
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#link-purpose-in-context"
							className="blockLink">
							2.4.4 Link Purpose (in Context)
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#focus-visible"
							className="blockLink">
							2.4.7 Focus visible
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#location"
							className="blockLink">
							2.4.8 Location
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#consistent-navigation"
							className="blockLink">
							3.2.3 Consistent Navigation
						</a>
					</li>
					<li>
						<a
							href="https://www.w3.org/TR/WCAG21/#name-role-value"
							className="blockLink">
							4.1.2 Name, Role, Value
						</a>
					</li>
				</ul>
			</TemplateSection>
			{/* <TemplateSection sectionName="otherResources" title="Other Resources">
				<ul className="list">
					<li>
						<a href="#" className="blockLink">
							###
						</a>
					</li>
				</ul>
			</TemplateSection> */}
			<PageUpdated date="27th August 2023" />
		</>
	)
}


================================================
FILE: components/ContentTemplates/PaginationTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const PaginationTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/ContentTemplates/TablesTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const TablesTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/ContentTemplates/VideoTemplate.tsx
================================================
import { WorkInProgress } from "../WorkInProgress/WorkInProgress"

export const VideoTemplate = () => {
	return <WorkInProgress />
}


================================================
FILE: components/CopyCodeBlock/CopyCodeBlock.module.css
================================================
.codeCopyBtn {
	color: var(--text);
	background-color: var(--primaryLt);
	padding: 4px 8px;
	position: absolute;
	display: flex;
	align-items: center;
	gap: 0.25rem;
	border: none;
	border-radius: var(--borderRadius);
	right: 14px;
	top: 18px;
	font-size: 0.8rem;
	cursor: pointer;
}


================================================
FILE: components/CopyCodeBlock/CopyCodeBlock.tsx
================================================
import { useState } from "react"
import { FaCopy, FaCheckSquare } from "react-icons/fa"
import styles from "./CopyCodeBlock.module.css"

interface CodeSnippet {
	code: string
}

const CopyCodeBlock = ({ code }: CodeSnippet) => {
	const [copyOk, setCopyOk] = useState(false)

	const handleClick = () => {
		navigator.clipboard.writeText(code)

		setCopyOk(true)
		setTimeout(() => {
			setCopyOk(false)
		}, 3000)
	}

	return (
		<button
			className={styles.codeCopyBtn}
			onClick={handleClick}
			aria-label="Copy code snippet to clipboard">
			{copyOk ? (
				<>
					<FaCheckSquare />
					Copied
				</>
			) : (
				<>
					<FaCopy />
					Copy
				</>
			)}
		</button>
	)
}

export default CopyCodeBlock


================================================
FILE: components/Footer/Footer.module.css
================================================
.footer {
    background-color: var(--bg);
    padding: 16px;
    color: var(--text);
    margin-top: 2rem;
    border-top: 1px solid var(--primaryLt);
}


.footerList {
    padding: 0;
    margin: 0;
    list-style: none;
    line-height: 1.6;
}

.footerList li {
    margin: 14px 0 14px 0;
}

.footerLink, .footerLink:visited {
    text-decoration: none;
    font-size: 0.9rem;
}

.footerLink:hover {
    text-decoration: underline;
}

.footerBottom {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: 0rem;
    padding: 16px 0 0 0;
}

.footerCopyrightText {
    margin: 0;
    font-size: 0.9rem;
}

.footerLogos {
    color: var(--text)
}

@media only screen and (min-width: 55rem) {

    .footerList {
        display: flex;
        flex-direction: row;
        justify-content: space-between;  
    }
    
    .footerList li {
        margin: 0;
    }
    
} 


================================================
FILE: components/Footer/Footer.tsx
================================================
import Link from "next/link"
import styles from "./Footer.module.css"
import { BsGithub, BsBoxArrowUpRight } from "react-icons/bs"

export const Footer = () => {
	return (
		<footer className={styles.footer}>
			<div className={styles.footerTop}>
				<ul className={styles.footerList}>
					<li>
						<Link href="/about" className={styles.footerLink}>
							About the maintainers
						</Link>
					</li>

					<li>
						<a
							href="https://github.com/AccessibleForAll/AccessibleWebDev/blob/main/CONTRIBUTING.md"
							className={styles.footerLink}>
							Become a Contributor
						</a>
					</li>
					<li>
						<a
							href="https://github.com/sponsors/EmmaDawsonDev"
							className={styles.footerLink}>
							Support Us
						</a>
					</li>
					<li>
						<a
							href="mailto:emma.l.dawson@gmail.com"
							className={styles.footerLink}>
							Contact Us
						</a>
					</li>
					<li>
						<Link href="/" className={styles.footerLink}>
							Accessibility Statement - coming soon
						</Link>
					</li>
				</ul>
			</div>
			<div className={styles.footerBottom}>
				<p className={styles.footerCopyrightText}>
					© Accessible Web Dev by <strong>Accessible For All</strong>. Making
					accessibility accessible for everyone!
				</p>

				<a href="https://github.com/AccessibleForAll">
					<BsGithub
						className={styles.footerLogos}
						size="1.5rem"
						aria-label="Github"
					/>
				</a>
			</div>
		</footer>
	)
}


================================================
FILE: components/Header/Header.module.css
================================================
.topBanner {
	background-color: var(--bg);
	color: var(--text);
	height: var(--headerHeight);
	width: 100%;
	padding: 0 16px;
	display: flex;
	justify-content: space-between;
	align-items: center;
	position: fixed;
	top: 0;
	border-bottom: 1px solid var(--primaryLt);
	z-index: 1;
}

.topBanner a {
	text-decoration: none;
	font-weight: bold;
}

.buttonsContainer {
	display: flex;
	gap: 0.5rem;
	align-items: center;
	position: relative;
}

.topBanner button {
	cursor: pointer;
}

.hamburgerBtn {
	display: grid;
	place-items: center;
	border: none;
	padding: 0;
	background-color: transparent;
	color: var(--text);
}



@media (min-width: 800px) {
	.topBanner .hamburgerBtn {
		display: none;
	}

}



================================================
FILE: components/Header/Header.tsx
================================================
import Link from "next/link"
import { IoMenuSharp, IoCloseSharp } from "react-icons/io5"
import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher"

import styles from "./Header.module.css"

export interface IHeaderProps {
	handleNavClick: () => void
	showNavMobile: boolean
}

export const Header = ({ handleNavClick, showNavMobile }: IHeaderProps) => {
	return (
		<>
			<header>
				<div className={styles.topBanner}>
					<Link href="/">AWD</Link>
					<div className={styles.buttonsContainer}>
						<ThemeSwitcher />
						<button
							className={styles.hamburgerBtn}
							onClick={handleNavClick}
							aria-label="Navigation menu"
							aria-expanded={showNavMobile}>
							{!showNavMobile && (
								<IoMenuSharp size="1.5rem" aria-hidden="true" />
							)}
							{showNavMobile && (
								<IoCloseSharp size="1.5rem" aria-hidden="true" />
							)}
						</button>
					</div>
				</div>
			</header>
		</>
	)
}


================================================
FILE: components/Layout/Layout.module.css
================================================
.layoutContainer {
  display: flex;
  min-height: calc(100vh - var(--headerHeight));
  margin-top: 3rem;
}

.layoutContainer main {
	padding: 16px;
  max-width: 1200px;
  margin: 0 auto;
}

.columnContainer {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  
  
}

@media (min-width: 800px) {
  .columnContainer {    
    flex-grow: 1; 
    margin-left: 15rem;  
  }
}

================================================
FILE: components/Layout/Layout.tsx
================================================
import { useState } from "react"
import { Footer } from "../Footer/Footer"
import { Header } from "../Header/Header"
import { NavPrimary } from "../Nav/NavPrimary"
import { NavPrimaryMobile } from "../Nav/NavPrimaryMobile"
import { SkipLink } from "../SkipLink/SkipLink"
import styles from "./Layout.module.css"

interface ILayoutProps {
	activeNavLink: string
	children: JSX.Element
}

export const Layout = ({ activeNavLink, children }: ILayoutProps) => {
	const [showNavMobile, setShowNavMobile] = useState<boolean>(false)

	const handleNavClick = () => {
		setShowNavMobile((prevState) => !prevState)
	}

	return (
		<>
			<SkipLink />
			<Header handleNavClick={handleNavClick} showNavMobile={showNavMobile} />
			<div className={styles.layoutContainer}>
				<NavPrimary activeNavLink={activeNavLink} />
				{showNavMobile && (
					<NavPrimaryMobile
						activeNavLink={activeNavLink}
						handleNavClick={handleNavClick}
					/>
				)}
				<div className={styles.columnContainer}>
					<main id="main">{children}</main>
					<Footer />
				</div>
			</div>
		</>
	)
}


================================================
FILE: components/MaintainerCard/MaintainerCard.module.css
================================================
.maintainerContainer {
    align-items: center;
    border: 0.15rem solid var(--primaryLt);
    border-radius: 0.5rem;
    display: flex;
    flex-direction: column;
    margin: 4.5rem 0 0 0;
    padding: 1rem;
    width: 20rem;
}

.maintainerImage {
    background-color: var(--primaryLt);
    border-radius: 50%;
    height: 8rem;
    margin-top: -5rem;
    position: absolute;
    width: 8rem;
}

.maintainerFullName {
    font-size: 2rem;
    margin-bottom: 0;
    margin-top: 3.5rem;
}

.maintainerDescription {
    font-size: 1rem;
    margin-top: 0.5rem;
    align-self: center;
}

.linkButton {
    background-color: var(--primaryLt);
    border-radius: 5px;
    cursor: pointer;
    font-size: 1rem;
    margin-top: 1rem;
    padding: 0.5rem 1rem;
    text-decoration: none;
}


================================================
FILE: components/MaintainerCard/MaintainerCard.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import styles from "./MaintainerCard.module.css"
import { IMaintainer } from "../../data/maintainers"

export interface IMaintainerCardProps {
	maintainer: IMaintainer
}

export const MaintainerCard = ({ maintainer }: IMaintainerCardProps) => {
	const { image, fullName, description, githubLink } = maintainer
	return (
		<section className={styles.maintainerContainer}>
			{image ? (
				<img className={styles.maintainerImage} src={image} alt={fullName} />
			) : (
				<p className={styles.maintainerImage}>{image}</p>
			)}

			<p className={styles.maintainerFullName}>{fullName}</p>
			<p className={styles.maintainerDescription}>{description}</p>

			<a className={styles.linkButton} href={githubLink}>
				{`${fullName}'s Github`}
			</a>
		</section>
	)
}


================================================
FILE: components/Nav/NavItem.tsx
================================================
import Link from "next/link"
import styles from "./NavPrimary.module.css"
import { IPage } from "../../data/pages"

export interface INavItemProps {
	page: IPage
	activeNavLink: string
	handleNavClick?: () => void
}

export const NavItem = ({
	page,
	activeNavLink,
	handleNavClick,
}: INavItemProps) => {
	const isLinkActive = activeNavLink === page.href
	return (
		<li className={`${styles.navListItem} ${isLinkActive ? "active" : ""}`}>
			<Link
				href={page.href}
				onClick={handleNavClick}
				aria-current={isLinkActive ? "page" : false}>
				{page.name}
			</Link>
		</li>
	)
}


================================================
FILE: components/Nav/NavPrimary.module.css
================================================
.navPrimary {
  display: none;  
}

.navPrimaryMobile {
  position: fixed;
  left: 0;
  right: 0;
  top: var(--headerHeight);
  bottom: 0;
  background-color: var(--bg);
  z-index: 1;
  overflow: scroll;
}

.navList {
  margin: 8px 0 0 0;
  padding: 0; 
}

.navListItem {
  list-style: none;
  margin: 2px;
  margin-left: 16px;
}

.navListItem a {
  text-decoration: none;
  padding: 8px;
  display: inline-block;
  border-radius: 5px;
}

.navListItem a:hover {
  background-color: var(--primaryLt);
  color: var(--text);
}

.navList a:focus {
  background-color: var(--primary);
  color: var(--invertText);
}

@media (min-width: 800px) {
  .navPrimary {
    width: 15rem;
    display: block;
    position: fixed;
    overflow-y: auto;
    height: calc(100vh - var(--headerHeight));
    top: var(--headerHeight);
    left: 0;
    border-right: 1px solid var(--primaryLt);
  }

  .navPrimaryMobile {
    display: none;
  }
}

================================================
FILE: components/Nav/NavPrimary.tsx
================================================
import { NavItem } from "./NavItem"
import { pages } from "../../data/pages"
import styles from "./NavPrimary.module.css"

export interface INavProps {
	activeNavLink: string
}

export const NavPrimary = ({ activeNavLink }: INavProps) => {

	return (
		<nav aria-label="Primary" className={styles.navPrimary}>
			<ul className={styles.navList}>
				{pages.map((page, index) =>(
					<NavItem
					        key={page.name + index}
					        page={page}
					        activeNavLink={activeNavLink}
					/>
				))}
			</ul>
		</nav>
	)
}


================================================
FILE: components/Nav/NavPrimaryMobile.tsx
================================================
import { NavItem } from "./NavItem"
import { pages } from "../../data/pages"
import styles from "./NavPrimary.module.css"

export interface INavProps {
	activeNavLink: string
	handleNavClick: () => void
}

export const NavPrimaryMobile = ({
	activeNavLink,
	handleNavClick,
}: INavProps) => {
	return (
		<nav aria-label="Primary" className={styles.navPrimaryMobile}>
			<ul className={styles.navList}>
				{pages.map((page, index) => (
					<NavItem
						key={page.name + index}
						page={page}
						activeNavLink={activeNavLink}
						handleNavClick={handleNavClick}
					/>
				))}
			</ul>
		</nav>
	)
}


================================================
FILE: components/NavPage/NavPage.module.css
================================================
.pageNav {
	background-color: var(--highlight);
	padding: 8px 16px;
}

.pageNavTitle {
	font-weight: bold;
	font-size: 1.1rem;
	cursor: pointer;
}

.pageNavList {
	list-style: none;
	margin: 8px 0;
	padding: 0;
	line-height: 1.6;
}

.pageNavList li {
	margin: 14px 0;
}


================================================
FILE: components/NavPage/NavPage.tsx
================================================
import styles from "./NavPage.module.css"
import { IPageNavigationItem } from "../../data/pageNavigationLists"

interface INavPageProps {
	pageNavigation: IPageNavigationItem[]
}

export const NavPage = ({ pageNavigation }: INavPageProps) => {
	return (
		<details className={styles.pageNav}>
			<summary className={styles.pageNavTitle}>On This Page</summary>

			<nav aria-label="On This Page">
				<ul className={styles.pageNavList}>
					{pageNavigation.map((item, index) => (
						<li key={index}>
							<a href={item.href}>{item.linkName}</a>
						</li>
					))}
				</ul>
			</nav>
		</details>
	)
}


================================================
FILE: components/PageUpdated/PageUpdated.module.css
================================================
.pageLastUpdated {
	margin-top: 5rem;
}

@media (min-width: 800px) {
	.pageLastUpdated {
		text-align: right;
	}
}

================================================
FILE: components/PageUpdated/PageUpdated.tsx
================================================
import styles from "./PageUpdated.module.css"
interface IPageUpdatedProps {
	date: string
}
export const PageUpdated = ({ date }: IPageUpdatedProps) => (
	<p className={styles.pageLastUpdated}>
		<strong>Page last updated: </strong>
		{date}
	</p>
)


================================================
FILE: components/SkipLink/SkipLink.module.css
================================================
.skipToMainContent {
  display: flex;
  justify-content: center;
}

.skipToMainContent a {
  position: absolute;
  color: var(--text);
	background-color: var(--bg);
  text-decoration: none;
  padding: 0.3rem;
  border: 1px solid var(--primary);
  z-index: 100;
  transform: translateY(-500px); 
  transition: all .4s ease-in-out;
}

.skipToMainContent a:focus {
  transform: translateY(8px);
}


================================================
FILE: components/SkipLink/SkipLink.tsx
================================================
import styles from "./SkipLink.module.css"

export const SkipLink = () => (
	<div className={styles.skipToMainContent}>
		<a href="#main">Skip to main content</a>
	</div>
)


================================================
FILE: components/TemplateSection/TemplateSection.module.css
================================================
.infoSection {
	margin-top: 2rem;
	width: 100%;
	max-width: 52rem;
}

================================================
FILE: components/TemplateSection/TemplateSection.tsx
================================================
import { ReactNode } from "react"
import styles from "./TemplateSection.module.css"

interface ITemplateSectionProps {
	sectionName: string
	title: string
	children: ReactNode
}

export const TemplateSection = ({
	sectionName,
	title,
	children,
}: ITemplateSectionProps) => {
	return (
		<section aria-labelledby={sectionName} className={styles.infoSection}>
			<h2 id={sectionName}>{title}</h2>
			{children}
		</section>
	)
}


================================================
FILE: components/ThemeSwitcher/ThemeSwitcher.module.css
================================================
.themeBtn {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	border: 1px solid var(--primaryLt);
	padding: 0.2rem 0.5rem;
	border-radius: var(--borderRadius);
	background-color: transparent;
	cursor: pointer;
	color: var(--text);
	font-size: .8rem;
}

.themeSwitcher {
	position: absolute;
	top: 8px;
	right: 32px;
	width: 10em;
	background-color: var(--bg);
	padding: 0.5rem;
	border: 1px solid var(--primaryLt);
	border-radius: var(--borderRadius);
	list-style: none;
}

.themeSwitcher li {
	margin-bottom: 0.25rem;
}

.themeSwitcherBtn {
	background-color: none;
	color: var(--text);
	display: flex;
	gap: 0.5rem;
	align-items: center;
	cursor: pointer;
	padding: 0.5rem;
	width: 100%;
	border: none;
	background-color: var(--bg);
	font-size: 0.8rem;
}

.themeSwitcher li.activeBtn {
	border-left: 3px solid var(--primary);
}

.themeSwitcherBtn:hover {
	background-color: var(--primaryLt);
	font-weight: bold;
}

.themeSwitcherBtn:focus {
	background-color: var(--primaryLt);
	font-weight: bold;
}

@media (min-width: 800px) {
	.themeSwitcher {
		top: 8px;
		right: 0;
	}
}


================================================
FILE: components/ThemeSwitcher/ThemeSwitcher.tsx
================================================
import { useState, useRef, useEffect, FocusEvent } from "react"
import { BsCircleHalf } from "react-icons/bs"
import { useTheme } from "next-themes"
import useOnClickOutside from "../../customHooks/useOnClickOutside"

import styles from "./ThemeSwitcher.module.css"
import { themes } from "./themes"

export const ThemeSwitcher = () => {
	const [showThemeSwitcher, setShowThemeSwitcher] = useState<boolean>(false)
	const { theme, setTheme } = useTheme()

	const buttonRef = useRef<HTMLButtonElement>(null)
	const divRef = useRef<HTMLDivElement>(null)

	const handleThemeSwitcher = () => {
		setShowThemeSwitcher((prevState) => !prevState)
	}

	const handleChangeTheme = (theme: string) => {
		setTheme(theme)
		handleThemeSwitcher()
		buttonRef.current?.focus()
	}

	const handleThemeSwitcherKB = (e: { key: string }) => {
		if (e.key === "Esc" || e.key === "Escape") {
			handleThemeSwitcher()
			buttonRef.current?.focus()
		}
	}

	const handleBlur = (e: FocusEvent) => {
		if (!e.currentTarget.contains(e.relatedTarget) && showThemeSwitcher) {
			setShowThemeSwitcher(false)
		}
	}

	const handleClickOutside = () => {
		setShowThemeSwitcher(false)
	}

	useOnClickOutside(divRef, handleClickOutside)

	useEffect(() => {
		document.addEventListener("keyup", handleThemeSwitcherKB)

		return () => document.removeEventListener("keyup", handleThemeSwitcherKB)
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [])

	return (
		<div ref={divRef}>
			<button
				className={styles.themeBtn}
				type="button"
				id="themeSwitcherBtn"
				aria-controls="themeSwitcherMenu"
				onClick={handleThemeSwitcher}
				aria-expanded={showThemeSwitcher}
				ref={buttonRef}>
				<BsCircleHalf
					className={styles.themeIcon}
					size="1rem"
					aria-hidden="true"
				/>
				Theme
			</button>
			{showThemeSwitcher && (
				<ul
					className={styles.themeSwitcher}
					id="themeSwitcherMenu"
					aria-labelledby="themeSwitcherBtn"
					onBlur={handleBlur}>
					{themes.map(({ label, value, Icon }) => (
						<li key={label} className={theme === value ? styles.activeBtn : ""}>
							<button
								className={styles.themeSwitcherBtn}
								onClick={() => handleChangeTheme(value)}
								aria-pressed={theme === value}>
								<Icon
									size="0.7rem"
									aria-hidden="true"
									className={styles.themeIcon}
								/>
								{label}
							</button>
						</li>
					))}
				</ul>
			)}
		</div>
	)
}


================================================
FILE: components/ThemeSwitcher/themes.ts
================================================
import { BsCircleHalf, BsFillSunFill, BsFillMoonFill } from "react-icons/bs"

export const themes = [
	{ label: "Device settings", value: "system", Icon: BsCircleHalf },
	{ label: "Light mode", value: "light", Icon: BsFillSunFill },
	{ label: "Dark mode", value: "dark", Icon: BsFillMoonFill },
]


================================================
FILE: components/TipOfTheDay/TipOfTheDay.module.css
================================================
.card {
	background-color: var(--bg);
	border: 1px solid var(--primaryLt);
	padding: 1rem;
	border-radius: 12px;
	color: var(--text);
	max-width: 100%;
}




================================================
FILE: components/TipOfTheDay/TipOfTheDay.tsx
================================================
import { useEffect, useState } from "react"
import styles from "./TipOfTheDay.module.css"
import { Tips } from "../../data/tipsOfTheDay"

interface ITip {
	title: string
	description: string
	tipLink: string
	tipLinkLabel: string
}

export const TipOfTheDay = () => {
	const [randomIndex, setRandomIndex] = useState<number>(0)
	const [loading, setLoading] = useState<boolean>(true)
	const tipIndex: ITip = Tips[randomIndex]

	useEffect(() => {
		const randomNumber = Math.floor(Math.random() * Tips.length)

		setRandomIndex(randomNumber)
		setLoading(false)
	}, [])

	const createTipOfTheDay = () => {
		return (
			<>
				<h2>Tip of the day: {tipIndex.title}</h2>
				<p>{tipIndex.description}</p>
				<a href={tipIndex.tipLink}>{tipIndex.tipLinkLabel}</a>
			</>
		)
	}
	const tip = loading ? null : createTipOfTheDay()

	return <div className={styles.card}>{tip}</div>
}


================================================
FILE: components/WorkInProgress/WorkInProgress.module.css
================================================
.WIPContainer {
  background-color: var(--highlight);
  padding: 32px;
}

================================================
FILE: components/WorkInProgress/WorkInProgress.tsx
================================================
import styles from "./WorkInProgress.module.css"

export const WorkInProgress = () => {
	return (
		<section className={styles.WIPContainer}>
			<h2>This section is a work in progress</h2>
			<p>Please come back at a later date.</p>
			<a href="https://github.com/AccessibleForAll/AccessibleWebDev/discussions">
				Let us know what information you're looking for.
			</a>
		</section>
	)
}


================================================
FILE: customHooks/useOnClickOutside.ts
================================================
import { RefObject } from "react"
import { useEventListener } from "usehooks-ts"

type Handler = (event: MouseEvent) => void

function useOnClickOutside<T extends HTMLElement = HTMLElement>(
	ref: RefObject<T>,
	handler: Handler,
	mouseEvent: "mousedown" | "mouseup" = "mousedown"
): void {
	useEventListener(mouseEvent, (event) => {
		const el = ref?.current

		// Do nothing if clicking ref's element or descendent elements
		if (!el || el.contains(event.target as Node)) {
			return
		}

		handler(event)
	})
}

export default useOnClickOutside


================================================
FILE: data/maintainers.ts
================================================
export interface IMaintainer {
	image: string
	fullName: string
	description: string
	githubLink: string
}

export const currentMaintainers: IMaintainer[] = [
	{
		image: "https://avatars.githubusercontent.com/u/57045550?v=4&s=150",
		fullName: "Emma Dawson",
		description:
			"Emma is a full stack developer from Stockholm with a passion for accessibility and open source. She wants to make web accessibility easy to learn for everyone.",
		githubLink: "https://github.com/EmmaDawsonDev",
	},
	{
		image: "https://avatars.githubusercontent.com/u/1682188?v=4&s=150",
		fullName: "Cristian Toffanin",
		description:
			"Cristian is a full stack developer based in the Netherlands. He's always curious and always learning. He's currently learning about accessibility (Emma's mentee).",
		githubLink: "https://github.com/ctoffanin",
	},
]


================================================
FILE: data/pageNavigationLists.ts
================================================
export interface IPageNavigationItem {
	linkName: string
	href: string
}

export const audioPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "Transcripts", href: "#transcripts" },
	{ linkName: "Captions", href: "#captions" },
	{ linkName: "How To Add Closed Captions To Your Video?", href: "#howToAdd" },
	{ linkName: "Sign Language", href: "#signLanguage" },
	{ linkName: "Accessible media players", href: "#accessibleMediaPlayers" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Other Resources", href: "#otherResources" },
]

export const breadcrumbsPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "HTML Structure", href: "#htmlStructure" },
	{ linkName: "Add Extra Information with ARIA", href: "#aria" },
	{ linkName: "Breadcrumbs Example", href: "#breadcrumbsExample" },
	{ linkName: "Styling Breadcrumbs", href: "#breadcrumbStyling" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Other Resources", href: "#otherResources" },
]

export const buttonPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "Text Buttons", href: "#textButtons" },
	{ linkName: "Text and Icon Buttons", href: "#textAndIconButtons" },
	{ linkName: "Icon-only Buttons", href: "#iconOnlyButtons" },
	{ linkName: "Button States", href: "#buttonStates" },
	{ linkName: "Button or Link?", href: "#buttonOrLink" },
	{ linkName: "Touch Target Minimum", href: "#touchTargetMinimum" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Other Resources", href: "#otherResources" },
]

export const captchasPageNavigation: IPageNavigationItem[] = [
	{
		linkName: "Introduction",
		href: "#introduction",
	},
	{ linkName: "What's the issue with CAPTCHAs?", href: "#captchaIssues" },
	{ linkName: "Accessible CAPTCHA", href: "#accessibleCAPTCHA" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Other Resources", href: "#otherResources" },
]

export const imagePageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "Text Alternatives", href: "#textAlternatives" },
	{ linkName: "Decorative Images", href: "#decorativeImages" },
	{ linkName: "Informative Images", href: "#informativeImages" },
	{ linkName: "Functional Images", href: "#functionalImages" },
	{ linkName: "How to write good alt text", href: "#goodAltText" },
	{ linkName: "Images of Text", href: "#imagesOfText" },
	{ linkName: "Images and Colour", href: "#imagesAndColour" },
	{ linkName: "Image Maps", href: "#imageMaps" },
	// { linkName: "Image Checklist", href: "#checklist" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Other Resources", href: "#otherResources" },
]

export const headingsPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#intro" },
	{ linkName: "Why are HTML Headings Important?", href: "#whyHeadings" },
	{
		linkName: "What Should Be Included in a Heading?",
		href: "#includedInHeadings",
	},
	{ linkName: "How to Write a Good Heading", href: "#goodHeadings" },
	{
		linkName: "What Should We Avoid When Using Headings?",
		href: "#avoidHeadings",
	},
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Test Your Knowledge", href: "#QuizQuestions" },
]

export const formsPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{
		linkName: "What Should We Consider When Building Accessible Forms?",
		href: "#whatToConsider",
	},
	{
		linkName: "Creating Simple, Understandable Forms",
		href: "#creatingForms",
	},
	{
		linkName: "Keyboard Accessible Forms",
		href: "#keyboardAccessibleForms",
	},
	{ linkName: "Error Validation and Changes in State", href: "#formErrors" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
]

export const linkPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "Accessible Link Names", href: "#accessibleLinkNames" },
	{ linkName: "Link State and Style", href: "#linkStates" },
	{ linkName: "Image and Icon Links", href: "#linkImage" },
	{ linkName: "Touch Target Minimum", href: "#touchTargetMinimum" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Other Resources", href: "#otherResources" },
]

export const modalPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "How a modal should work", href: "#howAModalShouldWork" },
	{ linkName: "Using <dialog>", href: "#usingDialog" },
	{ linkName: "Custom Modals", href: "#customModals" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	{ linkName: "Other Resources", href: "#otherResources" },
]

export const navigationPageNavigation: IPageNavigationItem[] = [
	{ linkName: "Introduction", href: "#introduction" },
	{ linkName: "A Simple Navigation", href: "#simpleNav" },
	{ linkName: "Hamburger Menus", href: "#hamburgerMenus" },
	{ linkName: "Mega Menus", href: "#megaMenus" },
	{ linkName: "Order of Links", href: "#linksOrder" },
	{ linkName: "Multiple Navigations Per Page", href: "#multipleNavs" },
	{ linkName: "WCAG Criteria", href: "#WCAGCriteria" },
	//{ linkName: "Other Resources", href: "#otherResources" },
]


================================================
FILE: data/pages.ts
================================================
export interface IPage {
	name: string
	href: string
	content?: string
}

export const pages: IPage[] = [
	{ name: "Home", href: "/" },
	// { name: "Alerts", href: "/alerts", content: "alerts" },
	// {
	// 	name: "Animations",
	// 	href: "/animations",
	// 	content: "animations",
	// },
	{ name: "Audio", href: "/audio", content: "audio" },
	{ name: "Breadcrumbs", href: "/breadcrumbs", content: "breadcrumbs" },
	{ name: "Buttons", href: "/buttons", content: "buttons" },
	{
		name: "CAPTCHAs",
		href: "/captchas",
		content: "captchas",
	},
	// {
	// 	name: "Charts",
	// 	href: "/charts",
	// 	content: "charts",
	// },
	{ name: "Forms", href: "/forms", content: "forms" },
	{ name: "Headings", href: "/headings", content: "headings" },
	{ name: "Icons", href: "/icons", content: "icons" },
	{ name: "Images", href: "/images", content: "images" },
	{ name: "Links", href: "/links", content: "links" },
	// { name: "Lists", href: "/lists", content: "lists" },
	// { name: "Menus", href: "/menus", content: "menus" },
	{ name: "Modals", href: "/modals", content: "modals" },
	{ name: "Navigation", href: "/navigation", content: "navigation" },
	// { name: "Pagination", href: "/pagination", content: "pagination" },
	// { name: "Tables", href: "/tables", content: "tables" },
	// { name: "Video", href: "/video", content: "video" },
]


================================================
FILE: data/tipsOfTheDay.ts
================================================
export interface ITips {
	title: string
	description: string
	tipLink: string
	tipLinkLabel: string
}

export const Tips: ITips[] = [
	{
		title: "Test with Assistive Technology",
		description:
			"Test your website using assistive technologies such as screen readers and keyboard-only navigation to identify and fix accessibility issues.",
		tipLink: "https://www.w3.org/WAI/test-evaluate/preliminary/",
		tipLinkLabel: "Read more about assistive technology...",
	},
	{
		title: "Make Forms Accessible",
		description:
			"Ensure that all form elements have labels, are navigable via keyboard, and provide clear instructions for users filling out the form.",
		tipLink: "https://www.w3.org/TR/WCAG21/#forms",
		tipLinkLabel: "Read more about forms...",
	},
	{
		title: "Provide Descriptive Links",
		description:
			"Use clear and descriptive link text that conveys the purpose and destination of the link, as screen readers often provide a list of links and users need to understand where each link will take them.",
		tipLink:
			"https://www.w3.org/WAI/tutorials/forms/labels/#descriptive-link-text",
		tipLinkLabel: "Read more about descriptive technologies...",
	},
	{
		title: "Use Sufficient Color Contrast",
		description:
			"Ensure that there is enough contrast between foreground and background colors to make text readable for users with low vision.",
		tipLink: "https://www.w3.org/TR/WCAG21/#contrast-minimum",
		tipLinkLabel: "Read more about color contrast...",
	},
	{
		title: "Ensure Keyboard Accessibility",
		description:
			"Make sure all interactive elements on your website can be accessed and used via keyboard alone, as some users may not be able to use a mouse or other pointing device.",
		tipLink: "https://www.w3.org/TR/WCAG21/#keyboard-accessible",
		tipLinkLabel: "Read more about keyboard accessibility...",
	},
	{
		title: "Use Semantic HTML",
		description:
			"Use appropriate HTML tags to help convey the meaning and structure of your content, which makes it easier for screen readers and other assistive technologies to navigate.",
		tipLink: "https://webaim.org/techniques/semanticstructure/",
		tipLinkLabel: "Read more about semantic HTML...",
	},
	{
		title: "Use Alt Text for Images",
		description:
			"Include descriptive text in the alt attribute of image tags to help screen readers and visually impaired users understand the content of the image.",
		tipLink: "https://www.w3.org/WAI/tutorials/images/",
		tipLinkLabel: "Read more about alt text...",
	},
]


================================================
FILE: docs-style-guide.md
================================================
# About this guide 👋

Welcome to our simple and straightforward style guide! We created this guide for our community of tech and non-tech experts to ensure we communicate effectively and inclusively. This guide is divided into four sections:

- 🌎 [Inclusive Language](inclusive-language)
- 📝 [Grammar & Mechanics](grammar-and-mechanics)
- 🤔 [Clarity](clarity)
- ♿ [Accessibility](accessibility)

## Inclusive Language 🌎

Inclusive language is an essential aspect of communication. It promotes equality, respects diversity, and avoids offense. Here are some best practices to follow:

- Use gender-neutral words for common terms
  - ❌ **Not this:** A maintainer should try to be kind yet constructive in **his** feedback.
  - ✅ **Use this:** A maintainer should try to be kind yet constructive in **their** feedback.

- Avoid using terms that have colonialistic or racist connotations.
  - ❌ **Not this:** Contributors should push their pull requests to the **master** branch.
  - ✅ **Use this:** Contributors should push their pull requests to the **main** branch.

## Grammar & Mechanics 📝

Grammar and mechanics help ensure that your writing is clear, concise, and easy to understand. Here are some best practices to follow:

### Commas

- Use commas when describing lists.
  - ❌ **Not this:** You can also add your **timeline testimonials and upcoming events** that you are participating in.
  - ✅ **Use this:** You can also add your **timeline, testimonials, and upcoming events** that you are participating in.

- Use commas in introductory elements.
  - ❌ **Not this:** **If you do not have one yet** you can create one for free with an email address and password.
  - ✅ **Use this:** **If you do not have one yet,** you can create one for free with an email address and password.

- Use commas before the seven, so-called, coordinating conjunctions (and, but, so, for, nor, yet, or) to separate two independent clauses.
  - ❌ **Not this:** There are 4 ways you can add your profile **but** for this Quickstart, we will use the GitHub UI.
  - ✅ **Use this:** There are 4 ways you can add your profile, **but** for this Quickstart, we will use the GitHub UI.

### Capitalisation

- Only capitalize terms that describe a product, its feature, the first letter of a sentence, or a person’s name.
  - ❌ **Not this:** There are 4 ways you can add your profile, but for this **quickstart** we will use the **github ui**.
  - ✅ **Use this:** There are 4 ways you can add your profile, but for this Quickstart, we will use the **GitHub UI**.

## Clarity 🤔

Clarity in writing helps ensure that your audience understands your message and intentions. Here are some best practices to follow:

### Active vs. Passive

Using the active voice in writing makes your message more direct and engaging.

- ❌ **Not this:** This repo is **maintained** by a team of people.
- ✅ **Use this:** A team of people **maintains** this repo.

### Jargon

Using technical and coding jargon can alienate non-technical readers.

- ❌ **Not this:** Before submitting your code review, it is always helpful to add comments such as **LGTM!** in the textbox.
- ✅ **Use this:** Before submitting your code review, it is always helpful to add comments such as **Great job!** in the textbox.

## Accessibility ♿

### Bullet Points

- Avoid describing things only by their color or position.
  - ❌ **Not this:** see **the** **image** above.
  - ✅ **Use this:** See **Image 2.2**.

### Emojis

- Avoid using emojis as bullet points or numbered lists.
- ❌ **Not this:** 1️⃣ Fork the repository
- 2️⃣ Visit the Accessibleforall repository
  - ✅ **Use this:** **1.** Fork the repository
- **2️.** Visit the Accessibleforall repository

- Avoid using emojis in the middle of a sentence.
  - ❌  **Not this:** There are 4️⃣ ways you can add your profile, but for this Quickstart we will use the GitHub UI.
- ✅ **Use this:** There are **4** ways you can fix your profile, but for this tutorial, we will use the GitHub UI.

- Use them sparingly at the end of a sentence.
  - ❌ **Not this:** Join the conversation on our Discord community! 😀 😄 🎉
  - ✅ **Use this:** Join the conversation on our Discord community! 😀

### Headings

- Use descriptive titles for headings.
  - ❌ **Not this:** `<h1> Yoga</h1>`
- ✅ **Use this:** `<h1>Yoga for Developers</h1>`

- Place headings in sequential order.
- ❌ **Not this:** `<h1>Yoga for Developers</h1>`
  `<h3>What is Yoga?</h3>`
  `<h2>The History of Yoga</h2>`
  - ✅ **Use this:**  `<h1>Yoga for Developers</h1>`
  `<h2>What is Yoga?</h2>`
  `<h3>The History of Yoga</h3>`

### Images

- Use descriptive alt text for images.
- ❌ **Not this:** `![Cat_2019-06-14.jpg](https://en.wikipedia.org/wiki/File:June_odd-eyed-cat.jpg)`
- ✅ **Use this:**  `![A white cat with a blue eye and golden eye is sitting on a grey couch](https://en.wikipedia.org/wiki/File:June_odd-eyed-cat.jpg)`

Have some ideas for improving the guide? Raise an issue on our [GitHub page](https://github.com/AccessibleForAll/AccessibleWebDev/issues/new/choose). We would love to receive your feedback!


================================================
FILE: next-env.d.ts
================================================
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.


================================================
FILE: next-i18next.config.js
================================================
module.exports = {
	i18n: {
		locales: ["en", "sv"],
		defaultLocale: "en",
	},
}


================================================
FILE: next.config.js
================================================
/** @type {import('next').NextConfig} */

const { i18n } = require("./next-i18next.config")

const nextConfig = {
	reactStrictMode: true,
	swcMinify: true,
	i18n,
}

module.exports = nextConfig


================================================
FILE: package.json
================================================
{
	"name": "accessible-web-dev",
	"version": "0.1.0",
	"private": true,
	"scripts": {
		"dev": "next dev",
		"build": "next build",
		"start": "next start",
		"lint": "next lint",
		"prepare": "husky install"
	},
	"dependencies": {
		"next": "^13.5.6",
		"next-i18next": "^12.1.0",
		"next-themes": "^0.2.1",
		"react": "^18.3.1",
		"react-dom": "^18.3.1",
		"react-icons": "^4.4.0",
		"react-syntax-highlighter": "^15.5.0",
		"usehooks-ts": "^2.7.2"
	},
	"devDependencies": {
		"@babel/core": "^7.19.3",
		"@types/node": "18.0.5",
		"@types/react": "18.0.15",
		"@types/react-dom": "18.0.6",
		"@types/react-syntax-highlighter": "^15.5.6",
		"@typescript-eslint/eslint-plugin": "^5.44.0",
		"babel-loader": "^8.2.5",
		"eslint": "8.20.0",
		"eslint-config-next": "^13.5.6",
		"eslint-config-prettier": "^8.5.0",
		"eslint-plugin-jsx-a11y": "^6.10.2",
		"husky": "^8.0.0",
		"lint-staged": "^13.0.3",
		"prettier": "^2.7.1",
		"typescript": "4.7.4"
	},
	"lint-staged": {
		"**/*.{js,jsx,ts,tsx}": [
			"eslint --fix",
			"prettier --write"
		]
	}
}


================================================
FILE: pages/404.tsx
================================================
/* eslint-disable @next/next/no-img-element */
import notFoundImage from "../public/404.png"
import Image from "next/legacy/image"
import Head from "next/head"
import { Layout } from "../components/Layout/Layout"
import { useTranslation } from "next-i18next"
import { serverSideTranslations } from "next-i18next/serverSideTranslations"
import { GetStaticProps } from "next"

const PageNotFound = () => {
	// eslint-disable-next-line @typescript-eslint/no-unused-vars
	const { t } = useTranslation("common")
	return (
		<>
			<Head>
				<title>{`Page Not Found - Accessible Web Dev`}</title>
				<meta name="description" content="404 - Page Not Found" />
			</Head>
			<Layout activeNavLink={""}>
				<>
					<h1>404 - Not Found</h1>
					<div className="center">
						<Image
							src={notFoundImage.src}
							alt="Page not found"
							width={800}
							height={600}
						/>
					</div>
				</>
			</Layout>
		</>
	)
}

export const getStaticProps: GetStaticProps = async (context) => {
	const locale: string = context?.locale || ""

	return {
		props: {
			...(await serverSideTranslations(locale, ["common"])),
			// Will be passed to the page component as props
		},
	}
}

export default PageNotFound


================================================
FILE: pages/[content].tsx
================================================
import type { GetStaticPaths, GetStaticProps, NextPage } from "next"

import { Layout } from "../components/Layout/Layout"
import Head from "next/head"
import { capitalizeRoute } from "../utils"
import { pages } from "../data/pages"
import { useTranslation } from "next-i18next"
import { serverSideTranslations } from "next-i18next/serverSideTranslations"

// Components
import { AlertsTemplate } from "../components/ContentTemplates/AlertsTemplate"
import { AnimationsTemplate } from "../components/ContentTemplates/AnimationsTemplate"
import { AudioTemplate } from "../components/ContentTemplates/AudioTemplate"
import { BreadcrumbsTemplate } from "../components/ContentTemplates/BreadcrumbsTemplate"
import { ButtonsTemplate } from "../components/ContentTemplates/ButtonsTemplate"
import { CaptchasTemplate } from "../components/ContentTemplates/CaptchasTemplate"
import { ChartsTemplate } from "../components/ContentTemplates/ChartsTemplate"
import { FormsTemplate } from "../components/ContentTemplates/FormsTemplate"
import { HeadingsTemplate } from "../components/ContentTemplates/HeadingsTemplate"
import { IconsTemplate } from "../components/ContentTemplates/IconsTemplate"
import { ImagesTemplate } from "../components/ContentTemplates/ImagesTemplate"
import { LinksTemplate } from "../components/ContentTemplates/LinksTemplate"
import { ListsTemplate } from "../components/ContentTemplates/ListsTemplate"
import { MenusTemplate } from "../components/ContentTemplates/MenusTemplate"
import { ModalsTemplate } from "../components/ContentTemplates/ModalsTemplate"
import { NavigationTemplate } from "../components/ContentTemplates/NavigationTemplate"
import { TablesTemplate } from "../components/ContentTemplates/TablesTemplate"
import { VideoTemplate } from "../components/ContentTemplates/VideoTemplate"
import { PaginationTemplate } from "../components/ContentTemplates/PaginationTemplate"

interface IProps {
	page: string
}

const ContentPage: NextPage<IProps> = ({ page }) => {
	const title = capitalizeRoute(page)

	// eslint-disable-next-line @typescript-eslint/no-unused-vars
	const { t } = useTranslation("common")

	return (
		<>
			<Head>
				<title>{`${title} - Accessible Web Dev`}</title>
				<meta
					name="description"
					content={`Learn how to make ${title} accessible`}
				/>
				<meta property="og:title" content={`${title} - Accessible Web Dev`} />
				<meta
					property="og:description"
					content={`Learn how to make ${title} accessible`}
				/>
				<meta property="og:url" content={`https://accessibleweb.dev/${page}`} />

				<meta
					property="twitter:url"
					content={`https://accessibleweb.dev/${page}`}
				/>
				<meta name="twitter:title" content={`${title} - Accessible Web Dev`} />
				<meta
					name="twitter:description"
					content={`Learn how to make ${title} accessible`}
				/>
			</Head>
			<Layout activeNavLink={`/${page}`}>
				<>
					<h1>{`Accessible ${title}`}</h1>
					{page === "alerts" && <AlertsTemplate />}
					{page === "animations" && <AnimationsTemplate />}
					{page === "audio" && <AudioTemplate />}
					{page === "breadcrumbs" && <BreadcrumbsTemplate />}
					{page === "buttons" && <ButtonsTemplate />}
					{page === "captchas" && <CaptchasTemplate />}
					{page === "charts" && <ChartsTemplate />}
					{page === "forms" && <FormsTemplate />}
					{page === "headings" && <HeadingsTemplate />}
					{page === "icons" && <IconsTemplate />}
					{page === "images" && <ImagesTemplate />}
					{page === "links" && <LinksTemplate />}
					{page === "lists" && <ListsTemplate />}
					{page === "menus" && <MenusTemplate />}
					{page === "modals" && <ModalsTemplate />}
					{page === "navigation" && <NavigationTemplate />}
					{page === "pagination" && <PaginationTemplate />}
					{page === "tables" && <TablesTemplate />}
					{page === "video" && <VideoTemplate />}
				</>
			</Layout>
		</>
	)
}

export const getStaticPaths: GetStaticPaths = async (context) => {
	const locales = context?.locales || []
	const paths = pages.filter((page) => page.content)

	const pathsWithLocales = paths.flatMap((path) => {
		return locales.map((locale) => {
			return {
				params: {
					content: path.content,
				},
				locale: locale,
			}
		})
	})

	return {
		paths: pathsWithLocales,
		fallback: false,
	}
}

export const getStaticProps: GetStaticProps = async (context) => {
	const content = context.params?.content || ""
	const locale: string = context?.locale || ""

	return {
		props: {
			...(await serverSideTranslations(locale, ["common"])),
			page: content,
		},
	}
}

export default ContentPage


================================================
FILE: pages/_app.tsx
================================================
import "../styles/globals.css"
import type { AppProps } from "next/app"
import Head from "next/head"
import { appWithTranslation } from "next-i18next"
import { ThemeProvider } from "next-themes"

function MyApp({ Component, pageProps }: AppProps) {
	return (
		<>
			<Head>
				<meta name="viewport" content="initial-scale=1.0, width=device-width" />
				<link rel="icon" href="/favicon.ico" />
				<link
					rel="apple-touch-icon"
					sizes="180x180"
					href="/apple-touch-icon.png"
				/>
				<link
					rel="icon"
					type="image/png"
					sizes="32x32"
					href="/favicon-32x32.png"
				/>
				<link
					rel="icon"
					type="image/png"
					sizes="16x16"
					href="/favicon-16x16.png"
				/>
				<link rel="manifest" href="/site.webmanifest" />

				<meta property="og:type" content="website" />
				<meta
					property="og:image"
					content="https://accessibleweb.dev/images/websiteScreenshot.png"
				/>

				<meta name="twitter:card" content="summary_large_image" />
				<meta property="twitter:domain" content="accessibleweb.dev" />
				<meta
					name="twitter:image"
					content="https://accessibleweb.dev/images/websiteScreenshot.png"
				/>
			</Head>
			<ThemeProvider attribute="class">
				<Component {...pageProps} />
			</ThemeProvider>
		</>
	)
}

export default appWithTranslation(MyApp)


================================================
FILE: pages/about.tsx
================================================
import type { GetStaticProps, NextPage } from "next"
import { Layout } from "../components/Layout/Layout"
import Head from "next/head"
import { useTranslation } from "next-i18next"
import { serverSideTranslations } from "next-i18next/serverSideTranslations"
import { MaintainerCard } from "../components/MaintainerCard/MaintainerCard"
import { currentMaintainers, IMaintainer } from "../data/maintainers"
import styles from "../styles/about.module.css"

interface IAboutProps {
	currentMaintainerData: IMaintainer[]
}

const About: NextPage<IAboutProps> = ({ currentMaintainerData }) => {
	// eslint-disable-next-line @typescript-eslint/no-unused-vars
	const { t } = useTranslation("common")
	return (
		<>
			<Head>
				<title>{`About - Accessible Web Dev`}</title>
				<meta
					name="description"
					content="About the Accessible Web Dev site & team"
				/>
				<meta property="og:title" content="Accessible Web Dev - About" />
				<meta property="og:description" content="About Accessible Web Dev" />
				<meta property="og:url" content="https://accessibleweb.dev/about" />

				<meta
					property="twitter:url"
					content="https://accessibleweb.dev/about"
				/>
				<meta name="twitter:title" content="Accessible Web Dev - About" />
				<meta name="twitter:description" content="About Accessible Web Dev" />
			</Head>
			<Layout activeNavLink="">
				<div>
					<h1>About Us</h1>
					<section>
						<h2>Current Maintainers</h2>
						<div className={styles.aboutRow}>
							{currentMaintainerData.map((maintainer, index) => (
								<MaintainerCard key={index} maintainer={maintainer} />
							))}
						</div>
					</section>
				</div>
			</Layout>
		</>
	)
}

export const getStaticProps: GetStaticProps = async (context) => {
	const locale: string = context?.locale || ""

	const currentMaintainerData = currentMaintainers

	return {
		props: {
			...(await serverSideTranslations(locale, ["common"])),
			// Will be passed to the page component as props
			currentMaintainerData: currentMaintainerData,
		},
	}
}

export default About


================================================
FILE: pages/api/hello.ts
================================================
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next"

type Data = {
	name: string
}

export default function handler(
	req: NextApiRequest,
	res: NextApiResponse<Data>
) {
	res.status(200).json({ name: "John Doe" })
}


================================================
FILE: pages/docs/Style Guide.md
================================================
# About this guide 👋

Welcome to our simple and straightforward style guide! We created this guide for our community of tech and non-tech experts to ensure we communicate effectively and inclusively. This guide is divided into four sections:

- 🌎 [Inclusive Language](inclusive-language)
- 📝 [Grammar & Mechanics](grammar-and-mechanics)
- 🤔 [Clarity](clarity)
- ♿ [Accessibility](accessibility)

## Inclusive Language 🌎

Inclusive language is an essential aspect of communication. It promotes equality, respects diversity, and avoids offense. Here are some best practices to follow:

- Use gender-neutral words for common terms
  - ❌ **Not this:** A maintainer should try to be kind yet constructive in **his** feedback.
  - ✅ **Use this:** A maintainer should try to be kind yet constructive in **their** feedback.

- Avoid using terms that have colonialistic or racist connotations.
  - ❌ **Not this:** Contributors should push their pull requests to the **master** branch.
  - ✅ **Use this:** Contributors should push their pull requests to the **main** branch.

## Grammar & Mechanics 📝

Grammar and mechanics help ensure that your writing is clear, concise, and easy to understand. Here are some best practices to follow:

### Commas

- Use commas when describing lists.
  - ❌ **Not this:** You can also add your **timeline testimonials and upcoming events** that you are participating in.
  - ✅ **Use this:** You can also add your **timeline, testimonials, and upcoming events** that you are participating in.

- Use commas in introductory elements.
  - ❌ **Not this:** **If you do not have one yet** you can create one for free with an email address and password.
  - ✅ **Use this:** If you do not have one yet, you can create one for free with an email address and password.

- Use commas before the seven, so-called, coordinating conjunctions (and, but, so, for, nor, yet, or) to separate two independent clauses.
  - ❌ **Not this:** There are 4 ways you can add your profile **but** for this Quickstart, we will use the GitHub UI.
  - ✅ **Use this:** There are 4 ways you can add your profile, **but** for this Quickstart, we will use the GitHub UI.

### Capitalisation

- Only capitalize terms that describe a product, its feature, the first letter of a sentence, or a person’s name.
  - ❌ **Not this:** There are 4 ways you can add your profile but****for this **quickstart**we will use the **github ui**.
  - ✅ **Use this:** There are 4 ways you can add your profile, **but** for this Quickstart, we will use the **GitHub UI**.

## Clarity 🤔

Clarity in writing helps ensure that your audience understands your message and intentions. Here are some best practices to follow:

### Active vs. Passive

Using the active voice in writing makes your message more direct and engaging.

- ❌ **Not this:** Gitpod **was** an open-source application that provides a prebuilt development environment in your browser - powered by VS Code.
- ✅ **Use this:** Gitpod **is** an open-source application that provides a prebuilt development envir
Download .txt
gitextract_u4kywwvh/

├── .eslintignore
├── .eslintrc.json
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows/
│       ├── appreciation.yml
│       └── axe.yaml
├── .gitignore
├── .gitpod.yml
├── .husky/
│   └── pre-commit
├── .prettierignore
├── .prettierrc.json
├── CODE_OF_CONDUCT.md
├── CODING_STANDARDS.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── components/
│   ├── CodeBlock/
│   │   ├── CodeBlock.module.css
│   │   └── CodeBlock.tsx
│   ├── ContentTemplates/
│   │   ├── AlertsTemplate.tsx
│   │   ├── AnimationsTemplate.tsx
│   │   ├── AudioTemplate.tsx
│   │   ├── BreadcrumbsTemplate.module.css
│   │   ├── BreadcrumbsTemplate.tsx
│   │   ├── ButtonsTemplate.module.css
│   │   ├── ButtonsTemplate.tsx
│   │   ├── CaptchasTemplate.tsx
│   │   ├── ChartsTemplate.tsx
│   │   ├── FormsTemplate.tsx
│   │   ├── HeadingsTemplate.tsx
│   │   ├── IconsTemplate.tsx
│   │   ├── ImagesTemplate.tsx
│   │   ├── LinksTemplate.module.css
│   │   ├── LinksTemplate.tsx
│   │   ├── ListsTemplate.tsx
│   │   ├── MenusTemplate.tsx
│   │   ├── ModalsTemplate.tsx
│   │   ├── NavigationTemplate.tsx
│   │   ├── PaginationTemplate.tsx
│   │   ├── TablesTemplate.tsx
│   │   └── VideoTemplate.tsx
│   ├── CopyCodeBlock/
│   │   ├── CopyCodeBlock.module.css
│   │   └── CopyCodeBlock.tsx
│   ├── Footer/
│   │   ├── Footer.module.css
│   │   └── Footer.tsx
│   ├── Header/
│   │   ├── Header.module.css
│   │   └── Header.tsx
│   ├── Layout/
│   │   ├── Layout.module.css
│   │   └── Layout.tsx
│   ├── MaintainerCard/
│   │   ├── MaintainerCard.module.css
│   │   └── MaintainerCard.tsx
│   ├── Nav/
│   │   ├── NavItem.tsx
│   │   ├── NavPrimary.module.css
│   │   ├── NavPrimary.tsx
│   │   └── NavPrimaryMobile.tsx
│   ├── NavPage/
│   │   ├── NavPage.module.css
│   │   └── NavPage.tsx
│   ├── PageUpdated/
│   │   ├── PageUpdated.module.css
│   │   └── PageUpdated.tsx
│   ├── SkipLink/
│   │   ├── SkipLink.module.css
│   │   └── SkipLink.tsx
│   ├── TemplateSection/
│   │   ├── TemplateSection.module.css
│   │   └── TemplateSection.tsx
│   ├── ThemeSwitcher/
│   │   ├── ThemeSwitcher.module.css
│   │   ├── ThemeSwitcher.tsx
│   │   └── themes.ts
│   ├── TipOfTheDay/
│   │   ├── TipOfTheDay.module.css
│   │   └── TipOfTheDay.tsx
│   └── WorkInProgress/
│       ├── WorkInProgress.module.css
│       └── WorkInProgress.tsx
├── customHooks/
│   └── useOnClickOutside.ts
├── data/
│   ├── maintainers.ts
│   ├── pageNavigationLists.ts
│   ├── pages.ts
│   └── tipsOfTheDay.ts
├── docs-style-guide.md
├── next-env.d.ts
├── next-i18next.config.js
├── next.config.js
├── package.json
├── pages/
│   ├── 404.tsx
│   ├── [content].tsx
│   ├── _app.tsx
│   ├── about.tsx
│   ├── api/
│   │   └── hello.ts
│   ├── docs/
│   │   └── Style Guide.md
│   └── index.tsx
├── public/
│   ├── locales/
│   │   ├── en/
│   │   │   ├── common.json
│   │   │   └── homepage.json
│   │   └── sv/
│   │       ├── common.json
│   │       └── homepage.json
│   └── site.webmanifest
├── styles/
│   ├── about.module.css
│   └── globals.css
├── tsconfig.json
└── utils.ts
Download .txt
SYMBOL INDEX (24 symbols across 21 files)

FILE: components/CodeBlock/CodeBlock.tsx
  type TCodeLanguage (line 7) | type TCodeLanguage =
  type ICodeBlockProps (line 14) | interface ICodeBlockProps {

FILE: components/CopyCodeBlock/CopyCodeBlock.tsx
  type CodeSnippet (line 5) | interface CodeSnippet {

FILE: components/Header/Header.tsx
  type IHeaderProps (line 7) | interface IHeaderProps {

FILE: components/Layout/Layout.tsx
  type ILayoutProps (line 9) | interface ILayoutProps {

FILE: components/MaintainerCard/MaintainerCard.tsx
  type IMaintainerCardProps (line 5) | interface IMaintainerCardProps {

FILE: components/Nav/NavItem.tsx
  type INavItemProps (line 5) | interface INavItemProps {

FILE: components/Nav/NavPrimary.tsx
  type INavProps (line 5) | interface INavProps {

FILE: components/Nav/NavPrimaryMobile.tsx
  type INavProps (line 5) | interface INavProps {

FILE: components/NavPage/NavPage.tsx
  type INavPageProps (line 4) | interface INavPageProps {

FILE: components/PageUpdated/PageUpdated.tsx
  type IPageUpdatedProps (line 2) | interface IPageUpdatedProps {

FILE: components/TemplateSection/TemplateSection.tsx
  type ITemplateSectionProps (line 4) | interface ITemplateSectionProps {

FILE: components/TipOfTheDay/TipOfTheDay.tsx
  type ITip (line 5) | interface ITip {

FILE: customHooks/useOnClickOutside.ts
  type Handler (line 4) | type Handler = (event: MouseEvent) => void
  function useOnClickOutside (line 6) | function useOnClickOutside<T extends HTMLElement = HTMLElement>(

FILE: data/maintainers.ts
  type IMaintainer (line 1) | interface IMaintainer {

FILE: data/pageNavigationLists.ts
  type IPageNavigationItem (line 1) | interface IPageNavigationItem {

FILE: data/pages.ts
  type IPage (line 1) | interface IPage {

FILE: data/tipsOfTheDay.ts
  type ITips (line 1) | interface ITips {

FILE: pages/[content].tsx
  type IProps (line 31) | interface IProps {

FILE: pages/_app.tsx
  function MyApp (line 7) | function MyApp({ Component, pageProps }: AppProps) {

FILE: pages/about.tsx
  type IAboutProps (line 10) | interface IAboutProps {

FILE: pages/api/hello.ts
  type Data (line 4) | type Data = {
  function handler (line 8) | function handler(
Condensed preview — 96 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (230K chars).
[
  {
    "path": ".eslintignore",
    "chars": 0,
    "preview": ""
  },
  {
    "path": ".eslintrc.json",
    "chars": 1935,
    "preview": "{\n\t\"extends\": [\n\t\t\"next/core-web-vitals\",\n\t\t\"prettier\",\n\t\t\"plugin:@typescript-eslint/recommended\",\n\t\t\"plugin:jsx-a11y/st"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 834,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 581,
    "preview": "## Describe your changes\n\n## Screenshots - If Any (Optional)\n\n## Link to issue\n<!-- Example: Closes #31 -->\nCloses #\n\n##"
  },
  {
    "path": ".github/workflows/appreciation.yml",
    "chars": 870,
    "preview": "name: 'Thank Contributors'\n\non:\n  issues:\n    types: [opened]\n  pull_request_target:\n    types: [opened]\n\njobs:\n  welcom"
  },
  {
    "path": ".github/workflows/axe.yaml",
    "chars": 568,
    "preview": "name: axe\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\njobs:\n  axe:\n    runs-on: ubuntu-latest\n"
  },
  {
    "path": ".gitignore",
    "chars": 410,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": ".gitpod.yml",
    "chars": 452,
    "preview": "# List the start up tasks. Learn more https://www.gitpod.io/docs/config-start-tasks/\ntasks:\n  - name: npm\n    init: npm "
  },
  {
    "path": ".husky/pre-commit",
    "chars": 69,
    "preview": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nnpx lint-staged\n"
  },
  {
    "path": ".prettierignore",
    "chars": 227,
    "preview": "# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.d"
  },
  {
    "path": ".prettierrc.json",
    "chars": 206,
    "preview": "{\n\t\"trailingComma\": \"es5\",\n\t\"useTabs\": true,\n\t\"tabWidth\": 2,\n\t\"semi\": false,\n\t\"singleQuote\": false,\n\t\"bracketSpacing\": t"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5225,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CODING_STANDARDS.md",
    "chars": 3030,
    "preview": "# Coding Standards\n\n## Naming\n\nChoosing good names is critical to creating code that is easy to use and easy to understa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2750,
    "preview": "# Contributing to Accessible Web Dev\n\n## Languages\n\nThis project is built with Next.JS, Typescript and CSS modules.\n\n## "
  },
  {
    "path": "LICENSE",
    "chars": 1075,
    "preview": "MIT License\n\nCopyright (c) 2022 Accessible For All\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "README.md",
    "chars": 2214,
    "preview": "\n# [Accessible Web Dev](https://accessibleweb.dev/) 🌐  \n\nWelcome to **Accessible Web Dev**, a resource designed to help "
  },
  {
    "path": "components/CodeBlock/CodeBlock.module.css",
    "chars": 623,
    "preview": ".CodeBlockContainer {\n\tposition: relative;\n\twidth: 90vw;\n\tmax-width: 850px;\n\tborder: 1px solid var(--primaryLt);\n\tborder"
  },
  {
    "path": "components/CodeBlock/CodeBlock.tsx",
    "chars": 1303,
    "preview": "import { useEffect, useRef, useState } from \"react\"\nimport { Prism as SyntaxHighlighter } from \"react-syntax-highlighter"
  },
  {
    "path": "components/ContentTemplates/AlertsTemplate.tsx",
    "chars": 134,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const AlertsTemplate = () => {\n\treturn <WorkIn"
  },
  {
    "path": "components/ContentTemplates/AnimationsTemplate.tsx",
    "chars": 138,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const AnimationsTemplate = () => {\n\treturn <Wo"
  },
  {
    "path": "components/ContentTemplates/AudioTemplate.tsx",
    "chars": 9743,
    "preview": "import { CodeBlock } from \"../CodeBlock/CodeBlock\"\nimport { NavPage } from \"../NavPage/NavPage\"\nimport { PageUpdated } f"
  },
  {
    "path": "components/ContentTemplates/BreadcrumbsTemplate.module.css",
    "chars": 272,
    "preview": ".breadcrumbsExample {\n  background-color: var(--highlight);\n}\n\n.breadcrumbsExample ol {\n\tlist-style: none;\n\tmargin: 0;\n\t"
  },
  {
    "path": "components/ContentTemplates/BreadcrumbsTemplate.tsx",
    "chars": 7167,
    "preview": "import { breadcrumbsPageNavigation } from \"../../data/pageNavigationLists\"\nimport { CodeBlock } from \"../CodeBlock/CodeB"
  },
  {
    "path": "components/ContentTemplates/ButtonsTemplate.module.css",
    "chars": 1846,
    "preview": ".exampleButton {\n\tpadding: 0.6rem 1.2rem;\t\n\tcursor: pointer;\n\tbackground-color: var(--primaryLt);\n  color: var(--text);\n"
  },
  {
    "path": "components/ContentTemplates/ButtonsTemplate.tsx",
    "chars": 16802,
    "preview": "import { TemplateSection } from \"../TemplateSection/TemplateSection\"\nimport { CodeBlock } from \"../CodeBlock/CodeBlock\"\n"
  },
  {
    "path": "components/ContentTemplates/CaptchasTemplate.tsx",
    "chars": 4100,
    "preview": "import { captchasPageNavigation } from \"../../data/pageNavigationLists\"\nimport { NavPage } from \"../NavPage/NavPage\"\nimp"
  },
  {
    "path": "components/ContentTemplates/ChartsTemplate.tsx",
    "chars": 134,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const ChartsTemplate = () => {\n\treturn <WorkIn"
  },
  {
    "path": "components/ContentTemplates/FormsTemplate.tsx",
    "chars": 11325,
    "preview": "import { formsPageNavigation } from \"../../data/pageNavigationLists\"\nimport { CodeBlock } from \"../CodeBlock/CodeBlock\"\n"
  },
  {
    "path": "components/ContentTemplates/HeadingsTemplate.tsx",
    "chars": 5540,
    "preview": "import Image from \"next/legacy/image\"\nimport { NavPage } from \"../NavPage/NavPage\"\nimport { CodeBlock } from \"../CodeBlo"
  },
  {
    "path": "components/ContentTemplates/IconsTemplate.tsx",
    "chars": 9724,
    "preview": "import Link from \"next/link\"\n\nimport { CodeBlock } from \"../CodeBlock/CodeBlock\"\nimport { NavPage } from \"../NavPage/Nav"
  },
  {
    "path": "components/ContentTemplates/ImagesTemplate.tsx",
    "chars": 14873,
    "preview": "import Image from \"next/legacy/image\"\nimport { NavPage } from \"../NavPage/NavPage\"\nimport { CodeBlock } from \"../CodeBlo"
  },
  {
    "path": "components/ContentTemplates/LinksTemplate.module.css",
    "chars": 160,
    "preview": ".srOnly{\n\tborder: 0;\n    clip: rect(0,0,0,0);\n    height: 1px;\n    margin: -1px;\n    overflow: hidden;\n    padding: 0;\n "
  },
  {
    "path": "components/ContentTemplates/LinksTemplate.tsx",
    "chars": 11944,
    "preview": "import { TemplateSection } from \"../TemplateSection/TemplateSection\"\nimport { CodeBlock } from \"../CodeBlock/CodeBlock\"\n"
  },
  {
    "path": "components/ContentTemplates/ListsTemplate.tsx",
    "chars": 133,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const ListsTemplate = () => {\n\treturn <WorkInP"
  },
  {
    "path": "components/ContentTemplates/MenusTemplate.tsx",
    "chars": 133,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const MenusTemplate = () => {\n\treturn <WorkInP"
  },
  {
    "path": "components/ContentTemplates/ModalsTemplate.tsx",
    "chars": 10012,
    "preview": "import { TemplateSection } from \"../TemplateSection/TemplateSection\"\nimport { CodeBlock } from \"../CodeBlock/CodeBlock\"\n"
  },
  {
    "path": "components/ContentTemplates/NavigationTemplate.tsx",
    "chars": 12298,
    "preview": "import { navigationPageNavigation } from \"../../data/pageNavigationLists\"\nimport { CodeBlock } from \"../CodeBlock/CodeBl"
  },
  {
    "path": "components/ContentTemplates/PaginationTemplate.tsx",
    "chars": 138,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const PaginationTemplate = () => {\n\treturn <Wo"
  },
  {
    "path": "components/ContentTemplates/TablesTemplate.tsx",
    "chars": 134,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const TablesTemplate = () => {\n\treturn <WorkIn"
  },
  {
    "path": "components/ContentTemplates/VideoTemplate.tsx",
    "chars": 133,
    "preview": "import { WorkInProgress } from \"../WorkInProgress/WorkInProgress\"\n\nexport const VideoTemplate = () => {\n\treturn <WorkInP"
  },
  {
    "path": "components/CopyCodeBlock/CopyCodeBlock.module.css",
    "chars": 284,
    "preview": ".codeCopyBtn {\n\tcolor: var(--text);\n\tbackground-color: var(--primaryLt);\n\tpadding: 4px 8px;\n\tposition: absolute;\n\tdispla"
  },
  {
    "path": "components/CopyCodeBlock/CopyCodeBlock.tsx",
    "chars": 712,
    "preview": "import { useState } from \"react\"\nimport { FaCopy, FaCheckSquare } from \"react-icons/fa\"\nimport styles from \"./CopyCodeBl"
  },
  {
    "path": "components/Footer/Footer.module.css",
    "chars": 907,
    "preview": ".footer {\n    background-color: var(--bg);\n    padding: 16px;\n    color: var(--text);\n    margin-top: 2rem;\n    border-t"
  },
  {
    "path": "components/Footer/Footer.tsx",
    "chars": 1463,
    "preview": "import Link from \"next/link\"\nimport styles from \"./Footer.module.css\"\nimport { BsGithub, BsBoxArrowUpRight } from \"react"
  },
  {
    "path": "components/Header/Header.module.css",
    "chars": 703,
    "preview": ".topBanner {\n\tbackground-color: var(--bg);\n\tcolor: var(--text);\n\theight: var(--headerHeight);\n\twidth: 100%;\n\tpadding: 0 "
  },
  {
    "path": "components/Header/Header.tsx",
    "chars": 939,
    "preview": "import Link from \"next/link\"\nimport { IoMenuSharp, IoCloseSharp } from \"react-icons/io5\"\nimport { ThemeSwitcher } from \""
  },
  {
    "path": "components/Layout/Layout.module.css",
    "chars": 398,
    "preview": ".layoutContainer {\n  display: flex;\n  min-height: calc(100vh - var(--headerHeight));\n  margin-top: 3rem;\n}\n\n.layoutConta"
  },
  {
    "path": "components/Layout/Layout.tsx",
    "chars": 1077,
    "preview": "import { useState } from \"react\"\nimport { Footer } from \"../Footer/Footer\"\nimport { Header } from \"../Header/Header\"\nimp"
  },
  {
    "path": "components/MaintainerCard/MaintainerCard.module.css",
    "chars": 786,
    "preview": ".maintainerContainer {\n    align-items: center;\n    border: 0.15rem solid var(--primaryLt);\n    border-radius: 0.5rem;\n "
  },
  {
    "path": "components/MaintainerCard/MaintainerCard.tsx",
    "chars": 811,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport styles from \"./MaintainerCard.module.css\"\nimport { IMaintainer } f"
  },
  {
    "path": "components/Nav/NavItem.tsx",
    "chars": 590,
    "preview": "import Link from \"next/link\"\nimport styles from \"./NavPrimary.module.css\"\nimport { IPage } from \"../../data/pages\"\n\nexpo"
  },
  {
    "path": "components/Nav/NavPrimary.module.css",
    "chars": 923,
    "preview": ".navPrimary {\n  display: none;  \n}\n\n.navPrimaryMobile {\n  position: fixed;\n  left: 0;\n  right: 0;\n  top: var(--headerHei"
  },
  {
    "path": "components/Nav/NavPrimary.tsx",
    "chars": 536,
    "preview": "import { NavItem } from \"./NavItem\"\nimport { pages } from \"../../data/pages\"\nimport styles from \"./NavPrimary.module.css"
  },
  {
    "path": "components/Nav/NavPrimaryMobile.tsx",
    "chars": 612,
    "preview": "import { NavItem } from \"./NavItem\"\nimport { pages } from \"../../data/pages\"\nimport styles from \"./NavPrimary.module.css"
  },
  {
    "path": "components/NavPage/NavPage.module.css",
    "chars": 270,
    "preview": ".pageNav {\n\tbackground-color: var(--highlight);\n\tpadding: 8px 16px;\n}\n\n.pageNavTitle {\n\tfont-weight: bold;\n\tfont-size: 1"
  },
  {
    "path": "components/NavPage/NavPage.tsx",
    "chars": 609,
    "preview": "import styles from \"./NavPage.module.css\"\nimport { IPageNavigationItem } from \"../../data/pageNavigationLists\"\n\ninterfac"
  },
  {
    "path": "components/PageUpdated/PageUpdated.module.css",
    "chars": 122,
    "preview": ".pageLastUpdated {\r\n\tmargin-top: 5rem;\r\n}\r\n\r\n@media (min-width: 800px) {\r\n\t.pageLastUpdated {\r\n\t\ttext-align: right;\r\n\t}\r"
  },
  {
    "path": "components/PageUpdated/PageUpdated.tsx",
    "chars": 250,
    "preview": "import styles from \"./PageUpdated.module.css\"\ninterface IPageUpdatedProps {\n\tdate: string\n}\nexport const PageUpdated = ("
  },
  {
    "path": "components/SkipLink/SkipLink.module.css",
    "chars": 394,
    "preview": ".skipToMainContent {\n  display: flex;\n  justify-content: center;\n}\n\n.skipToMainContent a {\n  position: absolute;\n  color"
  },
  {
    "path": "components/SkipLink/SkipLink.tsx",
    "chars": 173,
    "preview": "import styles from \"./SkipLink.module.css\"\n\nexport const SkipLink = () => (\n\t<div className={styles.skipToMainContent}>\n"
  },
  {
    "path": "components/TemplateSection/TemplateSection.module.css",
    "chars": 68,
    "preview": ".infoSection {\n\tmargin-top: 2rem;\n\twidth: 100%;\n\tmax-width: 52rem;\n}"
  },
  {
    "path": "components/TemplateSection/TemplateSection.tsx",
    "chars": 429,
    "preview": "import { ReactNode } from \"react\"\nimport styles from \"./TemplateSection.module.css\"\n\ninterface ITemplateSectionProps {\n\t"
  },
  {
    "path": "components/ThemeSwitcher/ThemeSwitcher.module.css",
    "chars": 1081,
    "preview": ".themeBtn {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 0.5rem;\n\tborder: 1px solid var(--primaryLt);\n\tpadding: 0.2rem 0."
  },
  {
    "path": "components/ThemeSwitcher/ThemeSwitcher.tsx",
    "chars": 2434,
    "preview": "import { useState, useRef, useEffect, FocusEvent } from \"react\"\nimport { BsCircleHalf } from \"react-icons/bs\"\nimport { u"
  },
  {
    "path": "components/ThemeSwitcher/themes.ts",
    "chars": 297,
    "preview": "import { BsCircleHalf, BsFillSunFill, BsFillMoonFill } from \"react-icons/bs\"\n\nexport const themes = [\n\t{ label: \"Device "
  },
  {
    "path": "components/TipOfTheDay/TipOfTheDay.module.css",
    "chars": 156,
    "preview": ".card {\n\tbackground-color: var(--bg);\n\tborder: 1px solid var(--primaryLt);\n\tpadding: 1rem;\n\tborder-radius: 12px;\n\tcolor:"
  },
  {
    "path": "components/TipOfTheDay/TipOfTheDay.tsx",
    "chars": 875,
    "preview": "import { useEffect, useState } from \"react\"\nimport styles from \"./TipOfTheDay.module.css\"\nimport { Tips } from \"../../da"
  },
  {
    "path": "components/WorkInProgress/WorkInProgress.module.css",
    "chars": 72,
    "preview": ".WIPContainer {\n  background-color: var(--highlight);\n  padding: 32px;\n}"
  },
  {
    "path": "components/WorkInProgress/WorkInProgress.tsx",
    "chars": 391,
    "preview": "import styles from \"./WorkInProgress.module.css\"\n\nexport const WorkInProgress = () => {\n\treturn (\n\t\t<section className={"
  },
  {
    "path": "customHooks/useOnClickOutside.ts",
    "chars": 548,
    "preview": "import { RefObject } from \"react\"\nimport { useEventListener } from \"usehooks-ts\"\n\ntype Handler = (event: MouseEvent) => "
  },
  {
    "path": "data/maintainers.ts",
    "chars": 837,
    "preview": "export interface IMaintainer {\n\timage: string\n\tfullName: string\n\tdescription: string\n\tgithubLink: string\n}\n\nexport const"
  },
  {
    "path": "data/pageNavigationLists.ts",
    "chars": 5361,
    "preview": "export interface IPageNavigationItem {\n\tlinkName: string\n\thref: string\n}\n\nexport const audioPageNavigation: IPageNavigat"
  },
  {
    "path": "data/pages.ts",
    "chars": 1338,
    "preview": "export interface IPage {\n\tname: string\n\thref: string\n\tcontent?: string\n}\n\nexport const pages: IPage[] = [\n\t{ name: \"Home"
  },
  {
    "path": "data/tipsOfTheDay.ts",
    "chars": 2506,
    "preview": "export interface ITips {\n\ttitle: string\n\tdescription: string\n\ttipLink: string\n\ttipLinkLabel: string\n}\n\nexport const Tips"
  },
  {
    "path": "docs-style-guide.md",
    "chars": 5066,
    "preview": "# About this guide 👋\n\nWelcome to our simple and straightforward style guide! We created this guide for our community of "
  },
  {
    "path": "next-env.d.ts",
    "chars": 201,
    "preview": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\n\n// NOTE: This file should not be edite"
  },
  {
    "path": "next-i18next.config.js",
    "chars": 82,
    "preview": "module.exports = {\n\ti18n: {\n\t\tlocales: [\"en\", \"sv\"],\n\t\tdefaultLocale: \"en\",\n\t},\n}\n"
  },
  {
    "path": "next.config.js",
    "chars": 194,
    "preview": "/** @type {import('next').NextConfig} */\n\nconst { i18n } = require(\"./next-i18next.config\")\n\nconst nextConfig = {\n\treact"
  },
  {
    "path": "package.json",
    "chars": 1049,
    "preview": "{\n\t\"name\": \"accessible-web-dev\",\n\t\"version\": \"0.1.0\",\n\t\"private\": true,\n\t\"scripts\": {\n\t\t\"dev\": \"next dev\",\n\t\t\"build\": \"n"
  },
  {
    "path": "pages/404.tsx",
    "chars": 1212,
    "preview": "/* eslint-disable @next/next/no-img-element */\nimport notFoundImage from \"../public/404.png\"\nimport Image from \"next/leg"
  },
  {
    "path": "pages/[content].tsx",
    "chars": 4593,
    "preview": "import type { GetStaticPaths, GetStaticProps, NextPage } from \"next\"\n\nimport { Layout } from \"../components/Layout/Layou"
  },
  {
    "path": "pages/_app.tsx",
    "chars": 1319,
    "preview": "import \"../styles/globals.css\"\nimport type { AppProps } from \"next/app\"\nimport Head from \"next/head\"\nimport { appWithTra"
  },
  {
    "path": "pages/about.tsx",
    "chars": 2058,
    "preview": "import type { GetStaticProps, NextPage } from \"next\"\nimport { Layout } from \"../components/Layout/Layout\"\nimport Head fr"
  },
  {
    "path": "pages/api/hello.ts",
    "chars": 303,
    "preview": "// Next.js API route support: https://nextjs.org/docs/api-routes/introduction\nimport type { NextApiRequest, NextApiRespo"
  },
  {
    "path": "pages/docs/Style Guide.md",
    "chars": 5257,
    "preview": "# About this guide 👋\n\nWelcome to our simple and straightforward style guide! We created this guide for our community of "
  },
  {
    "path": "pages/index.tsx",
    "chars": 1875,
    "preview": "import type { GetStaticProps, NextPage } from \"next\"\nimport { Layout } from \"../components/Layout/Layout\"\nimport Head fr"
  },
  {
    "path": "public/locales/en/common.json",
    "chars": 3,
    "preview": "{}\n"
  },
  {
    "path": "public/locales/en/homepage.json",
    "chars": 937,
    "preview": "{\n\t\"pageTitle\": \"Home - Accessible Web Dev\",\n\t\"metaContent\": \"Learn the basics about web accessibility in a clear and ea"
  },
  {
    "path": "public/locales/sv/common.json",
    "chars": 3,
    "preview": "{}\n"
  },
  {
    "path": "public/locales/sv/homepage.json",
    "chars": 941,
    "preview": "{\n\t\"pageTitle\": \"Hem - Accessible Web Dev\",\n\t\"metaContent\": \"Lär dig om webtillgänglighet på ett lätt och tydligt sätt.\""
  },
  {
    "path": "public/site.webmanifest",
    "chars": 263,
    "preview": "{\"name\":\"\",\"short_name\":\"\",\"icons\":[{\"src\":\"/android-chrome-192x192.png\",\"sizes\":\"192x192\",\"type\":\"image/png\"},{\"src\":\"/"
  },
  {
    "path": "styles/about.module.css",
    "chars": 68,
    "preview": ".aboutRow {\n    display:flex;\n    flex-wrap: wrap;\n    gap: 1rem;\n}\n"
  },
  {
    "path": "styles/globals.css",
    "chars": 1748,
    "preview": "@import url(\"https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;500;600;700;800;900&display=swap\");\n\n:root,\n:ro"
  },
  {
    "path": "tsconfig.json",
    "chars": 477,
    "preview": "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"es5\",\n\t\t\"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n\t\t\"allowJs\": true,\n\t\t\"skipLibChec"
  },
  {
    "path": "utils.ts",
    "chars": 112,
    "preview": "export const capitalizeRoute = (phrase: string) => {\n\treturn phrase.charAt(0).toUpperCase() + phrase.slice(1)\n}\n"
  }
]

About this extraction

This page contains the full source code of the AccessibleForAll/AccessibleWebDev GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 96 files (192.0 KB), approximately 54.8k tokens, and a symbol index with 24 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!