-
Notifications
You must be signed in to change notification settings - Fork 233
feat(progress-circle): migrate progress circle component to second-generation architecture #5743
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,12 +11,19 @@ | |
*/ | ||
|
||
import { CSSResultArray, html, TemplateResult } from 'lit'; | ||
import { ifDefined } from 'lit/directives/if-defined.js'; | ||
import { classMap } from 'lit/directives/class-map.js'; | ||
|
||
import { ProgressCircleBase } from '@swc/core/components/progress-circle'; | ||
import { property } from '@spectrum-web-components/base/src/decorators.js'; | ||
|
||
import progressCircleStyles from './progress-circle.css'; | ||
|
||
function capitalize(str?: string): string { | ||
if (typeof str !== 'string') { | ||
return ''; | ||
} | ||
return str.charAt(0).toUpperCase() + str.slice(1); | ||
} | ||
/** | ||
* A progress circle component that visually represents the completion progress of a task. | ||
* Can be used in both determinate (with specific progress value) and indeterminate (loading) states. | ||
|
@@ -25,15 +32,16 @@ import progressCircleStyles from './progress-circle.css'; | |
* @since 2.0.0 | ||
* @status stable | ||
* @github https://github.com/adobe/spectrum-web-components/tree/main/second-gen/packages/swc/components/progress-circle | ||
* @figma https://spectrum.figma.com/file/progress-circle | ||
* | ||
* @slot - Optional content to display inside the progress circle (e.g., percentage text) | ||
* | ||
* @csspart track - The background track of the progress circle | ||
* @csspart fill - The filled portion of the progress circle | ||
* @figma https://www.figma.com/design/Mngz9H7WZLbrCvGQf3GnsY/S2-%2F-Desktop?node-id=13061-181 | ||
* | ||
* @fires progress-change - Dispatched when the progress value changes | ||
* | ||
* @prop {string} static-color - Static color variant for use on different backgrounds. | ||
* @prop {number} progress - Progress value between 0 and 100. | ||
* @prop {boolean} indeterminate - Indeterminate state for loading. | ||
* @prop {string} size - Size of the component. | ||
* @prop {string} label - Label for the component. | ||
* | ||
* @example | ||
* <swc-progress-circle progress="75" label="Loading progress"></swc-progress-circle> | ||
* | ||
|
@@ -45,30 +53,61 @@ export class ProgressCircle extends ProgressCircleBase { | |
return [progressCircleStyles]; | ||
} | ||
|
||
/** | ||
* Static color variant for use on different backgrounds. | ||
* When set to 'white', the component uses white styling for images with a dark tinted background. | ||
* When set to 'black', the component uses black styling for images with a light tinted background. | ||
*/ | ||
@property({ reflect: true, attribute: 'static-color' }) | ||
public staticColor?: 'white' | 'black'; | ||
|
||
protected override render(): TemplateResult { | ||
const styles = [ | ||
this.makeRotation(-180 + (180 / 50) * Math.min(this.progress, 50)), | ||
this.makeRotation( | ||
-180 + (180 / 50) * Math.max(this.progress - 50, 0) | ||
), | ||
]; | ||
const masks = ['Mask1', 'Mask2']; | ||
const strokeWidth = this.size === 's' ? 2 : this.size === 'l' ? 6 : 4; | ||
// SVG strokes are centered, so subtract half the stroke width from the radius to create an inner stroke. | ||
const radius = `calc(50% - ${strokeWidth / 2}px)`; | ||
|
||
return html` | ||
<slot @slotchange=${this.handleSlotchange}></slot> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the sake of simplifying this for S2, I've regressed some of this functionality by removing the slot and leveraging our SVG approach. Would love to have a larger conversation around this for S2 but this seemed sufficient for the base requirement of getting the S2 styles and rendering into the component. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I don't really see a good reason for us to continue supporting both the slot-based and attribute-based interfaces for providing accessible label text. That said, I would like to decouple that decision from the initial Barebones component migration, to keep Barebones scoped as minimally as possible. On the branch where I've been exploring the nuances of our layering / inheritance scheme, I experimentally re-added the slot to the new, SVG-based No need to reverse the change on this branch, but I will include the slot re-addition in my follow-up PR, along with a |
||
<div class="track"></div> | ||
<div class="fills"> | ||
${masks.map( | ||
(mask, index) => html` | ||
<div class="fill${mask}"> | ||
<div | ||
class="fillSub${mask}" | ||
style=${ifDefined(styles[index])} | ||
> | ||
<div class="fill"></div> | ||
</div> | ||
</div> | ||
` | ||
)} | ||
<div | ||
class=${classMap({ | ||
['spectrum-ProgressCircle']: true, | ||
[`spectrum-ProgressCircle--indeterminate`]: | ||
this.indeterminate, | ||
[`spectrum-ProgressCircle--static${capitalize(this.staticColor)}`]: | ||
typeof this.staticColor !== 'undefined', | ||
[`spectrum-ProgressCircle--size${this.size?.toUpperCase()}`]: | ||
typeof this.size !== 'undefined', | ||
})} | ||
> | ||
<svg | ||
fill="none" | ||
width="100%" | ||
height="100%" | ||
class="spectrum-outerCircle" | ||
> | ||
<circle | ||
class="spectrum-innerCircle" | ||
cx="50%" | ||
cy="50%" | ||
r=${`calc(50% - ${strokeWidth / 1}px)`} | ||
stroke-width=${strokeWidth} | ||
/> | ||
<circle | ||
cx="50%" | ||
cy="50%" | ||
class="spectrum-ProgressCircle-track" | ||
r=${radius} | ||
/> | ||
<circle | ||
cx="50%" | ||
cy="50%" | ||
r=${radius} | ||
class="spectrum-ProgressCircle-fill" | ||
pathLength="100" | ||
stroke-dasharray="100 200" | ||
stroke-dashoffset=${100 - this.progress} | ||
stroke-linecap="round" | ||
/> | ||
</svg> | ||
</div> | ||
`; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kind of liked this utility living separately but let me know how you want to handle this in the SWC infrastructure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, what you've done here looks great. Again, we can circle back after Barebones to discuss how we want to handle utilities like this more generally in 2nd-gen.