Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
1 change: 1 addition & 0 deletions .config/cem.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
sourceControlRootUrl: https://github.com/patternfly/patternfly-elements/tree/main/
generate:
output: ./elements/custom-elements.json
Comment thread
zeroedin marked this conversation as resolved.
Outdated
files:
- ./elements/*/*.ts
- ./core/*/*.ts
Expand Down
1 change: 1 addition & 0 deletions elements/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"./pf-v5-progress/pf-v5-progress.js": "./pf-v5-progress/pf-v5-progress.js",
"./pf-v5-search-input/pf-v5-search-input.js": "./pf-v5-search-input/pf-v5-search-input.js",
"./pf-v5-spinner/pf-v5-spinner.js": "./pf-v5-spinner/pf-v5-spinner.js",
"./pf-v6-spinner/pf-v6-spinner.js": "./pf-v6-spinner/pf-v6-spinner.js",
Comment thread
zeroedin marked this conversation as resolved.
Outdated
"./pf-v5-switch/pf-v5-switch.js": "./pf-v5-switch/pf-v5-switch.js",
"./pf-v5-table/context.js": "./pf-v5-table/context.js",
"./pf-v5-table/pf-v5-caption.js": "./pf-v5-table/pf-v5-caption.js",
Expand Down
17 changes: 17 additions & 0 deletions elements/pf-v6-spinner/demo/basic.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: Basic
description: A basic spinner indicates that an action is in progress.
---
<section>
<pf-v6-spinner accessible-label="Loading contents">Loading...</pf-v6-spinner>
</section>

<script type="module">
import '@patternfly/elements/pf-v6-spinner/pf-v6-spinner.js';
</script>

<style>
section {
padding: 1em;
}
</style>
17 changes: 17 additions & 0 deletions elements/pf-v6-spinner/demo/custom-size.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: Custom size
description: A spinner can have a custom diameter using the `diameter` attribute.
---
<section>
<pf-v6-spinner diameter="80px" accessible-label="Custom size spinner">Loading...</pf-v6-spinner>
</section>

<script type="module">
import '@patternfly/elements/pf-v6-spinner/pf-v6-spinner.js';
</script>

<style>
section {
padding: 1em;
}
</style>
35 changes: 35 additions & 0 deletions elements/pf-v6-spinner/demo/inline-size.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: Inline size
description: An inline spinner inherits its font size, so its size will match the content around it.
---
<section>
<h1>
Heading
<pf-v6-spinner inline accessible-label="Spinner in a heading">Loading...</pf-v6-spinner>
</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed hendrerit nisi in cursus maximus.</p>
<h2>
Second level
<pf-v6-spinner inline accessible-label="Spinner in a subheading">Loading...</pf-v6-spinner>
</h2>
<p>
Curabitur accumsan turpis pharetra blandit. Quisque condimentum maximus mi,
<pf-v6-spinner inline accessible-label="Spinner in a paragraph">Loading...</pf-v6-spinner>
sit amet commodo arcu rutrum id. Proin pretium urna vel cursus venenatis.
Suspendisse potenti.
</p>
<small>
Sometimes you need small text
<pf-v6-spinner inline accessible-label="Spinner in small text">Loading...</pf-v6-spinner>
</small>
</section>

<script type="module">
import '@patternfly/elements/pf-v6-spinner/pf-v6-spinner.js';
</script>

<style>
section {
padding: 1em;
}
</style>
24 changes: 24 additions & 0 deletions elements/pf-v6-spinner/demo/size-variations.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: Size variations
description: Spinners can be sized using the `size` attribute with values `xs`, `sm`, `md`, `lg`, and `xl`.
---
<section>
<pf-v6-spinner size="xs" accessible-label="Extra small spinner">Loading...</pf-v6-spinner>
<pf-v6-spinner size="sm" accessible-label="Small spinner">Loading...</pf-v6-spinner>
<pf-v6-spinner size="md" accessible-label="Medium spinner">Loading...</pf-v6-spinner>
<pf-v6-spinner size="lg" accessible-label="Large spinner">Loading...</pf-v6-spinner>
<pf-v6-spinner size="xl" accessible-label="Extra large spinner">Loading...</pf-v6-spinner>
</section>

<script type="module">
import '@patternfly/elements/pf-v6-spinner/pf-v6-spinner.js';
</script>

<style>
section {
display: flex;
align-items: center;
gap: 1em;
padding: 1em;
}
</style>
112 changes: 112 additions & 0 deletions elements/pf-v6-spinner/pf-v6-spinner.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
:host {
display: inline-block;
width: min-content;
min-height: 0;
aspect-ratio: 1 / 1;
}

[hidden] {
display: none !important;
}

svg {
overflow: hidden;
width: var(--pf-v6-c-spinner--Width,
var(--pf-v6-c-spinner--diameter,
var(--pf-t--global--icon--size--2xl, 3.5rem)));
height: var(--pf-v6-c-spinner--Height,
var(--pf-v6-c-spinner--diameter,
var(--pf-t--global--icon--size--2xl, 3.5rem)));
animation:
rotate
calc(var(--pf-v6-c-spinner--AnimationDuration, 1.4s) * 2)
var(--pf-v6-c-spinner--AnimationTimingFunction, linear) infinite;
}

circle {
width: 100%;
height: 100%;
transform-origin: 50% 50%;
stroke-linecap: round;
stroke-dasharray: 283;
stroke-dashoffset: 280;
stroke: var(--pf-v6-c-spinner--Color,
var(--pf-t--global--icon--color--brand--default, #0066cc));
stroke-width: var(--pf-v6-c-spinner--StrokeWidth, 10);
animation:
dash
var(--pf-v6-c-spinner--AnimationDuration, 1.4s)
var(--pf-v6-c-spinner__path--AnimationTimingFunction, ease-in-out) infinite;
}

:host([size="xs"]) svg {
--pf-v6-c-spinner--diameter: var(--pf-v6-c-spinner--m-xs--diameter,
var(--pf-t--global--icon--size--sm, 0.75rem));

& circle {
stroke-width: var(--pf-v6-c-spinner--StrokeWidth, 15);
}
}

:host([size="sm"]) svg {
--pf-v6-c-spinner--diameter: var(--pf-v6-c-spinner--m-sm--diameter,
var(--pf-t--global--icon--size--md, 0.875rem));
}

:host([size="md"]) svg {
--pf-v6-c-spinner--diameter: var(--pf-v6-c-spinner--m-md--diameter,
var(--pf-t--global--icon--size--lg, 1rem));
}

:host([size="lg"]) svg {
--pf-v6-c-spinner--diameter: var(--pf-v6-c-spinner--m-lg--diameter,
var(--pf-t--global--icon--size--xl, 1.5rem));
}

:host([size="xl"]) svg {
--pf-v6-c-spinner--diameter: var(--pf-v6-c-spinner--m-xl--diameter,
var(--pf-t--global--icon--size--2xl, 3.5rem));
}

:host([inline]) svg {
--pf-v6-c-spinner--diameter: var(--pf-v6-c-spinner--m-inline--diameter, 1em);
}

@keyframes rotate {
0% {
rotate: 0deg;
}

100% {
rotate: 360deg;
}
}

@keyframes dash {
0% {
stroke-dashoffset: 280;
rotate: 0deg;
}

15% {
stroke-width: calc(var(--pf-v6-c-spinner__path--StrokeWidth,
var(--pf-v6-c-spinner--StrokeWidth, 10)) - 4);
}

40% {
stroke-dasharray: 220;
stroke-dashoffset: 150;
}

100% {
stroke-dashoffset: 280;
rotate: 720deg;
}
}

@media (prefers-reduced-motion: reduce) {
svg,
circle {
animation-duration: 0s;
}
}
73 changes: 73 additions & 0 deletions elements/pf-v6-spinner/pf-v6-spinner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { LitElement, html, type TemplateResult } from 'lit';
import { customElement } from 'lit/decorators/custom-element.js';
import { property } from 'lit/decorators/property.js';

import { InternalsController } from '@patternfly/pfe-core/controllers/internals-controller.js';

import styles from './pf-v6-spinner.css';

export type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';

/**
* A **spinner** is an animated visual that indicates when a quick action is
* in progress. For actions that may take a long time, use a progress bar instead.
* @summary Indicates that an action is in progress.
* @cssprop {<length>} [--pf-v6-c-spinner--diameter] - Custom diameter of the spinner
* @cssprop {<color>} [--pf-v6-c-spinner--Color] - Color of the spinner stroke
* @cssprop {<time>} [--pf-v6-c-spinner--AnimationDuration=1.4s] - Duration of one animation cycle
* @cssprop {<number>} [--pf-v6-c-spinner--StrokeWidth=10] - Width of the spinner stroke
*/
@customElement('pf-v6-spinner')
export class PfV6Spinner extends LitElement {
static readonly styles: CSSStyleSheet[] = [styles];

/** Preset sizes for the spinner */
@property({ reflect: true }) size?: SpinnerSize;

/**
* When true, the spinner inherits its font size from the surrounding text,
* allowing it to display inline with content.
*/
@property({ type: Boolean, reflect: true }) inline = false;

/** Custom diameter of spinner set as CSS variable */
@property({ reflect: true }) diameter?: string;
Comment thread
zeroedin marked this conversation as resolved.
Outdated

/** Accessible label describing what is loading */
@property({ attribute: 'accessible-label' }) accessibleLabel?: string;

#internals = InternalsController.of(this, {
role: 'progressbar',
ariaValueText: 'Loading...',
ariaLabel: 'Loading...',
});

override willUpdate(changed: Map<PropertyKey, unknown>): void {
if (changed.has('accessibleLabel')) {
const label = this.accessibleLabel ?? 'Loading...';
this.#internals.ariaLabel = label;
this.#internals.ariaValueText = label;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be a separate public property

cc @adamjohnson

}
if (changed.has('diameter')) {
if (this.diameter) {
this.style.setProperty('--pf-v6-c-spinner--diameter', this.diameter);
} else {
this.style.removeProperty('--pf-v6-c-spinner--diameter');
}
}
}

override render(): TemplateResult {
return html`
<svg viewBox="0 0 100 100" aria-hidden="true">
<circle cx="50" cy="50" r="45" fill="none" />
</svg>
`;
}
}

declare global {
interface HTMLElementTagNameMap {
'pf-v6-spinner': PfV6Spinner;
}
}
Loading
Loading