Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(skip-link): add <rh-skip-link> #1515

Merged
merged 32 commits into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d3f62e9
feat(skip-link): add `<rh-skip-link>`
adamjohnson Apr 5, 2024
6058a71
Merge branch 'staging/chansey' into feat/skip-link
adamjohnson Apr 5, 2024
7dcd074
chore(skip-link): add changeset
adamjohnson Apr 8, 2024
9c5cd97
docs(skip-link): add appropriate screenshot
adamjohnson Apr 8, 2024
e487165
fix: added lightdom-shim.css to export
adamjohnson Apr 10, 2024
a4bf360
chore: add Adam Johnson to contributors list
adamjohnson Apr 10, 2024
cc3cc5e
chore(skip-link): update readme
adamjohnson Apr 10, 2024
e26cc5d
fix(skip-link): implement lightdom-shim
adamjohnson Apr 10, 2024
cbb266a
docs(skip-link): added JSDoc
adamjohnson Apr 10, 2024
d4ae70d
docs(skip-link): enlarge screenshot
adamjohnson Apr 10, 2024
b36a9c3
test(skip-link): add tests
adamjohnson Apr 10, 2024
d868849
chore(skip-link): lint tests
adamjohnson Apr 10, 2024
98d5fc9
fix(skip-link): remove empty demo files
adamjohnson Apr 11, 2024
eadaec2
fix(skip-link): create container and move styles
adamjohnson Apr 11, 2024
83103f3
fix(skip-link): reformat `.changeset`
adamjohnson Apr 11, 2024
23aa5cc
fix(skip-link): add important to every CSS property
adamjohnson Apr 11, 2024
4b802c6
docs(skip-link): reformat `.changeset`.
adamjohnson Apr 11, 2024
a97bec0
fix(skip-link): Remove `!important` from lightdom shim.
adamjohnson Apr 11, 2024
26ce8e3
fix(skip-link): set `font-size`
adamjohnson Apr 11, 2024
b50e87f
refactor(skip-link): change container `id` name
adamjohnson Apr 11, 2024
40dc4ac
test(skip-link): refactor tests
adamjohnson Apr 11, 2024
0e311fd
feat: add more skip links docs content
marionnegp Apr 12, 2024
63ec5c3
feat: add images to accessibility page
marionnegp Apr 12, 2024
3135cb5
feat: add static image of skip link to Overview subpage
marionnegp Apr 12, 2024
a1c6718
docs(skip-link): add sample element
adamjohnson Apr 12, 2024
514cc1b
feat: add deprecation alert to skip navigation page
marionnegp Apr 12, 2024
93fdb62
Merge branch 'feat/skip-link' of github.com:RedHat-UX/red-hat-design-…
marionnegp Apr 12, 2024
24b9045
test(skip-link): use `aTimeout` for focus test
adamjohnson Apr 12, 2024
cdff319
feat: make the best practices more clear
marionnegp Apr 12, 2024
4ff8f47
Merge branch 'staging/chansey' into feat/skip-link
zeroedin Apr 13, 2024
8d7405b
docs(skip-link): add repoStatus
zeroedin Apr 13, 2024
49923c3
docs(skip-links): remove extraneous repoStatus shortcodes
zeroedin Apr 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slow-drinks-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rhds/elements": minor
---

Added the `<rh-skip-link>` element.
30 changes: 30 additions & 0 deletions elements/rh-skip-link/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Skip Link

A skip link is a link that allows the user to skip to a different
section on the same page. It allows assistive technology users to
skip repetitive content listed on every page.

## Installation

If using npm/bundlers:

```bash
npm install @rhds/elements
```

Then once installed, import it to your application:

```js
import '@rhds/elements/rh-skip-link/rh-skip-link.js';
```

## Usage

Generally, a skip link is placed as the first focusable item on a
page and targets the main content of a page.

```html
<rh-skip-link>
<a href="#main-content">Skip to main content</a>
</rh-skip-link>
```
3 changes: 3 additions & 0 deletions elements/rh-skip-link/demo/demo.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
rh-skip-link {
/* insert demo styles */
}
11 changes: 11 additions & 0 deletions elements/rh-skip-link/demo/rh-skip-link.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<rh-skip-link>
<a href="#main-content">Skip to main content</a>
</rh-skip-link>

<h1>Skip link</h1>
<p>To show the skip link, click the white background and press your tab key.</p>

<link rel="stylesheet" href="../rh-skip-link-lightdom-shim.css">
<script type="module">
import '@rhds/elements/rh-skip-link/rh-skip-link.js';
</script>
1 change: 1 addition & 0 deletions elements/rh-skip-link/demo/rh-skip-link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@rhds/elements/rh-skip-link/rh-skip-link.js';
19 changes: 19 additions & 0 deletions elements/rh-skip-link/docs/00-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Overview
{{ tagName | getElementDescription }}

## Sample element
```html
<rh-skip-link>
<a href="#main-content">Skip to main content</a>
</rh-skip-link>
```

## Demo
{% playground tagName=tagName %}{% endplayground %}
{% cta href="./demo/", target="_blank" %}View the demo{% endcta %}

## When to use
-

{% repoStatus type="Element" %}

10 changes: 10 additions & 0 deletions elements/rh-skip-link/docs/30-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% renderInstall %}{% endrenderInstall %}

## Usage
```html
<rh-skip-link>
<a href="#main-content">Skip to main content</a>
</rh-skip-link>
```

{% renderCodeDocs hideDescription=true %}{% endrenderCodeDocs %}
Binary file added elements/rh-skip-link/docs/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions elements/rh-skip-link/rh-skip-link-lightdom-shim.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
rh-skip-link:not(:defined) {
display: block;
position: relative;
}

rh-skip-link:not(:defined) > a {
background-color: var(--rh-color-surface-lightest, #ffffff);
border-block-start-width: 0;
border-block-end:
var(--rh-border-width-sm, 1px)
solid
var(--rh-color-border-interactive-on-light, #0066cc);
border-inline-start:
var(--rh-border-width-sm, 1px)
solid
var(--rh-color-border-interactive-on-light, #0066cc);
border-inline-end:
var(--rh-border-width-sm, 1px)
solid
var(--rh-color-border-interactive-on-light, #0066cc);
border-end-start-radius: var(--rh-border-radius-default, 3px);
border-end-end-radius: var(--rh-border-radius-default, 3px);
clip: rect(0, 0, 0, 0);
color: var(--rh-color-interactive-blue-darker, #0066cc);
font-family: var(--rh-font-family-heading, RedHatDisplay, "Red Hat Display", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans JP", "Noto Sans KR", "Noto Sans Malayalam", "Noto Sans SC", "Noto Sans TC", "Noto Sans Thai", Helvetica, Arial, sans-serif);
font-weight: var(--rh-font-weight-heading-bold, 700);
height: 1px;
left: 50%;
margin: -1px;
outline: 0;
overflow: hidden;
padding: 0;
position: absolute;
text-decoration: none;
top: -40px;
transform: translateX(-50%);
transition: top 0.05s ease-in;
white-space: nowrap;
width: 1px;
}

rh-skip-link:not(:defined) > a:is(:active, :focus) {
border-width: var(--rh-border-width-md, 2px);
clip: auto;
height: auto;
margin: 0;
overflow: visible;
padding: var(--rh-space-lg, 16px) var(--rh-space-2xl, 32px);
top: 0;
white-space: inherit;
width: auto;
}

rh-skip-link:not(:defined) > a:is(:active, :hover) {
text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
rh-skip-link:not(:defined) > a {
transition-duration: 0.001ms;
}
}
62 changes: 62 additions & 0 deletions elements/rh-skip-link/rh-skip-link.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
:host {
display: block;
position: relative;
}

::slotted(a) {
background-color: var(--rh-color-surface-lightest, #ffffff);
border-block-start-width: 0;
border-block-end:
var(--rh-border-width-sm, 1px)
solid
var(--rh-color-border-interactive-on-light, #0066cc);
border-inline-start:
var(--rh-border-width-sm, 1px)
solid
var(--rh-color-border-interactive-on-light, #0066cc);
border-inline-end:
var(--rh-border-width-sm, 1px)
solid
var(--rh-color-border-interactive-on-light, #0066cc);
border-end-start-radius: var(--rh-border-radius-default, 3px);
border-end-end-radius: var(--rh-border-radius-default, 3px);
clip: rect(0, 0, 0, 0);
color: var(--rh-color-interactive-blue-darker, #0066cc);
font-family: var(--rh-font-family-heading, RedHatDisplay, "Red Hat Display", "Noto Sans Arabic", "Noto Sans Hebrew", "Noto Sans JP", "Noto Sans KR", "Noto Sans Malayalam", "Noto Sans SC", "Noto Sans TC", "Noto Sans Thai", Helvetica, Arial, sans-serif);
font-weight: var(--rh-font-weight-heading-bold, 700);
height: 1px;
left: 50%;
margin: -1px;
outline: 0;
overflow: hidden;
padding: 0;
position: absolute;
text-decoration: none;
top: -40px;
transform: translateX(-50%);
transition: top 0.05s ease-in;
white-space: nowrap;
width: 1px;
}

::slotted(a:is(:active, :focus)) {
border-width: var(--rh-border-width-md, 2px);
clip: auto;
height: auto;
margin: 0;
overflow: visible;
padding: var(--rh-space-lg, 16px) var(--rh-space-2xl, 32px);
top: 0;
white-space: inherit;
width: auto;
}

::slotted(a:is(:active, :hover)) {
text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
::slotted(a) {
transition-duration: 0.001ms;
}
}
30 changes: 30 additions & 0 deletions elements/rh-skip-link/rh-skip-link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators/custom-element.js';

import styles from './rh-skip-link.css';

/**
* A skip link is used to skip repetitive content on a page.
* It is hidden by default and can be activated by hitting
* the "Tab" key after loading/refreshing a page.
*
* @summary Skip to the main content of a page
*
* @slot - Place an anchor tag with an `href` that targets an ID of the main content on the page.
*/
@customElement('rh-skip-link')
export class RhSkipLink extends LitElement {
static readonly styles = [styles];

render() {
return html`
<slot></slot>
`;
}
}

declare global {
interface HTMLElementTagNameMap {
'rh-skip-link': RhSkipLink;
}
}
12 changes: 12 additions & 0 deletions elements/rh-skip-link/test/rh-skip-link.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { test } from '@playwright/test';
import { PfeDemoPage } from '@patternfly/pfe-tools/test/playwright/PfeDemoPage.js';

const tagName = 'rh-skip-link';

test.describe(tagName, () => {
test('snapshot', async ({ page }) => {
const componentPage = new PfeDemoPage(page, tagName);
await componentPage.navigate();
await componentPage.snapshot();
});
});
51 changes: 51 additions & 0 deletions elements/rh-skip-link/test/rh-skip-link.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { expect, html } from '@open-wc/testing';
import { createFixture } from '@patternfly/pfe-tools/test/create-fixture.js';
import { a11ySnapshot } from '@patternfly/pfe-tools/test/a11y-snapshot.js';
import { RhSkipLink } from '@rhds/elements/rh-skip-link/rh-skip-link.js';

describe('<rh-skip-link>', function() {
describe('simply instantiating', function() {
let element: RhSkipLink;
it('should upgrade', async function() {
element = await createFixture<RhSkipLink>(html`<rh-skip-link></rh-skip-link>`);
const klass = customElements.get('rh-skip-link');
expect(element)
.to.be.an.instanceOf(klass)
.and
.to.be.an.instanceOf(RhSkipLink);
});
});

describe('when the element loads', function() {
let element: RhSkipLink;
beforeEach(async function() {
element = await createFixture<RhSkipLink>(html`
<rh-skip-link>
<a href="#main-content">
Skip to main content
</a>
</rh-skip-link>
`);
await element.updateComplete;
});

it('should be accessible', async function() {
const snapshot = await a11ySnapshot();
expect(snapshot).to.deep.equal({
role: 'WebArea',
name: '',
children: [{ role: 'link', name: 'Skip to main content' }]
});
});

describe('when element receives focus', function() {
it('should be visible', async function() {
element.focus();
const elStyles = getComputedStyle(element);
expect(elStyles.getPropertyValue('clip')).to.equal('auto');
expect(elStyles.getPropertyValue('text-decoration')).to.not.equal('underline');
expect(elStyles.getPropertyValue('top')).to.equal('0px');
});
});
});
});
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"./*": "./elements/*"
},
"contributors": [
"Adam Johnson <adjohnso@redhat.com>",
"Benny Powers <bennyp@redhat.com>",
"Brian Ferry <bferry@redhat.com>",
"Corey Vickery <cvickery@redhat.com>",
Expand All @@ -33,6 +34,7 @@
"!*.{spec,e2e}.ts",
"elements/*/*.{js,md,map,txt,d.ts}",
"elements/*/*-lightdom.css",
"elements/*/*-lightdom-shim.css",
"elements/rh-audio-player/i18n/*.json",
"!elements/*/docs/**/*.{js,html,css,md}",
"!elements/*/demo/**/*.{js,html,css,md}",
Expand Down
Loading