Skip to content

Commit 6884a3a

Browse files
committed
feat(progress): added a small state to the CircularProgress
Realized it would be really helpful to have the smaller version from `v1` available again as an option out of the box since the new one is a bit too big.
1 parent 46bd8b6 commit 6884a3a

File tree

13 files changed

+233
-18
lines changed

13 files changed

+233
-18
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The `CircularProgress` also supports a `small` state which defaults to the same
2+
size as icons from the #icon package.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, { ReactElement, useEffect } from "react";
2+
import { useTimeout, useToggle } from "@react-md/utils";
3+
import { Button } from "@react-md/button";
4+
import { CircularProgress } from "@react-md/progress";
5+
6+
export default function SmallCircularProgress(): ReactElement | null {
7+
const [loading, enable, disable] = useToggle(false);
8+
const [start] = useTimeout(disable, 10000);
9+
useEffect(() => {
10+
if (loading) {
11+
start();
12+
}
13+
}, [loading, start]);
14+
15+
return (
16+
<>
17+
<Button onClick={enable}>Show</Button>
18+
{loading && <CircularProgress id="small-circular-progress" small />}
19+
</>
20+
);
21+
}

packages/documentation/src/components/Demos/Progress/index.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import simpleIndeterminateExamples from "./SimpleIndeterminateExamples.md";
88
import SimpleDeterminateExamples from "./SimpleDeterminateExamples";
99
import simpleDeterminateExamples from "./SimpleDeterminateExamples.md";
1010

11+
import SmallCircularProgress from "./SmallCircularProgress";
12+
import smallCircularProgress from "./SmallCircularProgress.md";
13+
1114
import { WithSuspense, withSuspense } from "./WithSuspense";
1215

1316
import WithinButtons from "./WithinButtons";
@@ -24,6 +27,11 @@ const demos = [
2427
description: simpleDeterminateExamples,
2528
children: <SimpleDeterminateExamples />,
2629
},
30+
{
31+
name: "Small Circular Progress",
32+
description: smallCircularProgress,
33+
children: <SmallCircularProgress />,
34+
},
2735
{
2836
name: "With Suspense",
2937
description: withSuspense,

packages/documentation/src/constants/meta/search.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,14 @@ const metadata: ReadonlyArray<RouteMetadata> = [
16131613
pageUrl: "/packages/progress/demos#simple-determinate-examples-title",
16141614
pathname: "/packages/progress/demos#simple-determinate-examples-title",
16151615
},
1616+
{
1617+
title: "Progress Demo - Small Circular Progress",
1618+
summary:
1619+
"The CircularProgress also supports a small state which defaults to the same size as icons from the @react-md/icon package.",
1620+
type: "demo",
1621+
pageUrl: "/packages/progress/demos#small-circular-progress-title",
1622+
pathname: "/packages/progress/demos#small-circular-progress-title",
1623+
},
16161624
{
16171625
title: "Progress Demo - With Suspense",
16181626
summary:

packages/documentation/src/constants/meta/tocs.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2729,6 +2729,10 @@ const tocs: TOCRecord = {
27292729
anchor: "#simple-determinate-examples",
27302730
title: "Simple Determinate Examples",
27312731
},
2732+
{
2733+
anchor: "#small-circular-progress",
2734+
title: "Small Circular Progress",
2735+
},
27322736
{
27332737
anchor: "#with-suspense",
27342738
title: "With Suspense",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"public/index.html": {
3+
"content": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, shrink-to-fit=no\"\n />\n <meta name=\"theme-color\" content=\"#000000\" />\n <link\n rel=\"stylesheet\"\n href=\"https://fonts.googleapis.com/css?family=Material+Icons|Roboto:400,500,700|Source+Code+Pro\"\n />\n <link\n rel=\"stylesheet\"\n href=\"https://unpkg.com/react-md@{{RMD_VERSION}}/dist/css/react-md.teal-pink-200-light.min.css\"\n />\n <title>Progress Example - Small Circular Progress</title>\n </head>\n <body>\n <noscript>You need to enable JavaScript to run this app.</noscript>\n <div id=\"root\"></div>\n </body>\n</html>\n",
4+
"isBinary": false
5+
},
6+
"src/index.tsx": {
7+
"content": "import React from \"react\";\nimport { render } from \"react-dom\";\nimport { Configuration } from \"@react-md/layout\";\n\nimport Demo from \"./Demo\";\n\nconst App = () => (\n <Configuration>\n <Demo />\n </Configuration>\n);\n\nrender(<App />, document.getElementById(\"root\"));\n",
8+
"isBinary": false
9+
},
10+
"src/styles.scss": {
11+
"content": "@import \"variables\";\n@import \"~@react-md/button/dist/mixins\";\n@import \"~@react-md/layout/dist/mixins\";\n@import \"~@react-md/progress/dist/mixins\";\n@import \"~@react-md/states/dist/mixins\";\n@import \"~@react-md/theme/dist/mixins\";\n@import \"~@react-md/typography/dist/mixins\";\n@import \"~@react-md/utils/dist/mixins\";\n\n@include react-md-utils;\n",
12+
"isBinary": false
13+
},
14+
"src/_variables.scss": {
15+
"content": "@import \"~@react-md/theme/dist/color-palette\";\n\n$rmd-theme-light: true;\n$rmd-theme-primary: $rmd-teal-500;\n$rmd-theme-secondary: $rmd-pink-a-200;\n",
16+
"isBinary": false
17+
},
18+
"package.json": {
19+
"content": {
20+
"title": "Progress Example - Small Circular Progress",
21+
"description": "Example from https://react-md.dev/packages/progress/demos#small-circular-progress",
22+
"main": "src/index.tsx",
23+
"dependencies": {
24+
"@react-md/button": "latest",
25+
"@react-md/layout": "latest",
26+
"@react-md/progress": "latest",
27+
"@react-md/states": "latest",
28+
"@react-md/theme": "latest",
29+
"@react-md/typography": "latest",
30+
"@react-md/utils": "latest",
31+
"react": "latest",
32+
"react-dom": "latest"
33+
},
34+
"devDependencies": {
35+
"@types/jest": "latest",
36+
"@types/node": "latest",
37+
"@types/react": "latest",
38+
"@types/react-dom": "latest",
39+
"node-sass": "latest",
40+
"react-scripts": "latest",
41+
"typescript": "latest"
42+
},
43+
"scripts": {
44+
"start": "react-scripts start"
45+
}
46+
},
47+
"isBinary": false
48+
},
49+
"src/Demo.tsx": {
50+
"content": "import React, { ReactElement, useEffect } from \"react\";\nimport { useTimeout, useToggle } from \"@react-md/utils\";\nimport { Button } from \"@react-md/button\";\nimport { CircularProgress } from \"@react-md/progress\";\n\nexport default function SmallCircularProgress(): ReactElement | null {\n const [loading, enable, disable] = useToggle(false);\n const [start] = useTimeout(disable, 10000);\n useEffect(() => {\n if (loading) {\n start();\n }\n }, [loading, start]);\n\n return (\n <>\n <Button onClick={enable}>Show</Button>\n {loading && <CircularProgress id=\"small-circular-progress\" small />}\n </>\n );\n}\n",
51+
"isBinary": false
52+
}
53+
}

packages/documentation/src/constants/sandboxes/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ const sandboxes: Sandboxes = {
214214
resolve(import("./Progress-SimpleDeterminateExamples.json")),
215215
SimpleIndeterminateExamples: () =>
216216
resolve(import("./Progress-SimpleIndeterminateExamples.json")),
217+
SmallCircularProgress: () =>
218+
resolve(import("./Progress-SmallCircularProgress.json")),
217219
WithinButtons: () => resolve(import("./Progress-WithinButtons.json")),
218220
WithSuspense: () => resolve(import("./Progress-WithSuspense.json")),
219221
},

packages/documentation/src/constants/sassdoc/progress.ts

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ const sassdoc: PackageSassDoc = {
151151
{ name: "rmd-button", type: "mixin", packageName: "button" },
152152
{ name: "rmd-chip", type: "mixin", packageName: "chip" },
153153
{ name: "rmd-switch", type: "mixin", packageName: "form" },
154+
{
155+
name: "rmd-circular-progress",
156+
type: "mixin",
157+
packageName: "progress",
158+
},
154159
],
155160
requires: [
156161
{
@@ -347,18 +352,28 @@ const sassdoc: PackageSassDoc = {
347352
"rmd-circular-progress": {
348353
name: "rmd-circular-progress",
349354
description: "",
350-
source: "packages/progress/src/_mixins.scss#L221-L283",
355+
source: "packages/progress/src/_mixins.scss#L221-L289",
351356
usedBy: [
352357
{ name: "react-md-progress", type: "mixin", packageName: "progress" },
353358
],
354359
requires: [
355360
{ name: "rmd-progress-theme", type: "mixin", packageName: "progress" },
361+
{
362+
name: "rmd-progress-theme-update-var",
363+
type: "mixin",
364+
packageName: "progress",
365+
},
356366
{ name: "rmd-transition", type: "mixin", packageName: "transition" },
357367
{
358368
name: "rmd-progress-animation",
359369
type: "mixin",
360370
packageName: "progress",
361371
},
372+
{
373+
name: "rmd-circular-progress-small-size",
374+
type: "variable",
375+
packageName: "progress",
376+
},
362377
{
363378
name: "rmd-circular-progress-transition-duration",
364379
type: "variable",
@@ -383,13 +398,13 @@ const sassdoc: PackageSassDoc = {
383398
packageName: "progress",
384399
code: "@mixin rmd-circular-progress { … }",
385400
sourceCode:
386-
"@mixin rmd-circular-progress {\n .rmd-circular-progress {\n @include rmd-progress-theme(height, circular-size);\n @include rmd-progress-theme(width, circular-size);\n\n // add border radius and overflow-hidden so that different stroke-widths\n // are still circular. For some reason it isn't always the case.\n align-items: center;\n border-radius: 50%;\n display: inline-flex;\n justify-content: center;\n overflow: hidden;\n\n &--centered {\n display: flex;\n margin-left: auto;\n margin-right: auto;\n }\n\n &__svg {\n height: inherit;\n width: inherit;\n\n &--animate {\n @include rmd-transition(standard);\n\n transition: transform 0.1s;\n }\n\n &--indeterminate {\n animation: rmd-progress-rotate\n $rmd-circular-progress-transition-duration linear infinite;\n }\n }\n\n &__circle {\n @include rmd-progress-theme(stroke, color);\n @include rmd-progress-theme(stroke-width, circular-width);\n\n fill: none;\n stroke-dasharray: $rmd-circular-progress-dasharray;\n stroke-linecap: round;\n\n &--animate {\n @include rmd-transition(standard);\n\n transition: stroke-dashoffset 0.1s;\n }\n\n &--indeterminate {\n animation: rmd-circular-progress-size\n $rmd-circular-progress-transition-duration ease-in-out infinite;\n }\n }\n\n @keyframes rmd-progress-rotate {\n @include rmd-progress-animation($rmd-circular-progress-rotate-styles);\n }\n\n @keyframes rmd-circular-progress-size {\n @include rmd-progress-animation($rmd-circular-progress-dash-styles);\n }\n }\n}\n",
401+
"@mixin rmd-circular-progress {\n .rmd-circular-progress {\n @include rmd-progress-theme(height, circular-size);\n @include rmd-progress-theme(width, circular-size);\n\n // add border radius and overflow-hidden so that different stroke-widths\n // are still circular. For some reason it isn't always the case.\n align-items: center;\n border-radius: 50%;\n display: inline-flex;\n justify-content: center;\n overflow: hidden;\n\n &--centered {\n display: flex;\n margin-left: auto;\n margin-right: auto;\n }\n\n @if $rmd-circular-progress-small-size != null {\n &--small {\n @include rmd-progress-theme-update-var(\n circular-size,\n $rmd-circular-progress-small-size\n );\n }\n }\n\n &__svg {\n height: inherit;\n width: inherit;\n\n &--animate {\n @include rmd-transition(standard);\n\n transition: transform 0.1s;\n }\n\n &--indeterminate {\n animation: rmd-progress-rotate\n $rmd-circular-progress-transition-duration linear infinite;\n }\n }\n\n &__circle {\n @include rmd-progress-theme(stroke, color);\n @include rmd-progress-theme(stroke-width, circular-width);\n\n fill: none;\n stroke-dasharray: $rmd-circular-progress-dasharray;\n stroke-linecap: round;\n\n &--animate {\n @include rmd-transition(standard);\n\n transition: stroke-dashoffset 0.1s;\n }\n\n &--indeterminate {\n animation: rmd-circular-progress-size\n $rmd-circular-progress-transition-duration ease-in-out infinite;\n }\n }\n }\n\n @keyframes rmd-progress-rotate {\n @include rmd-progress-animation($rmd-circular-progress-rotate-styles);\n }\n\n @keyframes rmd-circular-progress-size {\n @include rmd-progress-animation($rmd-circular-progress-dash-styles);\n }\n}\n",
387402
type: "mixin",
388403
},
389404
"react-md-progress": {
390405
name: "react-md-progress",
391406
description: "Creates all the styles for the progress package.\n",
392-
source: "packages/progress/src/_mixins.scss#L286-L296",
407+
source: "packages/progress/src/_mixins.scss#L292-L302",
393408
usedBy: [{ name: "react-md-utils", type: "mixin", packageName: "utils" }],
394409
requires: [
395410
{
@@ -652,11 +667,29 @@ const sassdoc: PackageSassDoc = {
652667
value: "3rem",
653668
overridable: true,
654669
},
670+
"rmd-circular-progress-small-size": {
671+
name: "rmd-circular-progress-small-size",
672+
description:
673+
"The size for a small circular progress svg. This is really the same size as the `$rmd-icon-size` so it could be used instead if the `@react-md/icon` package has also been installed.",
674+
source: "packages/progress/src/_variables.scss#L217",
675+
since: "2.3.0",
676+
usedBy: [
677+
{
678+
name: "rmd-circular-progress",
679+
type: "mixin",
680+
packageName: "progress",
681+
},
682+
],
683+
packageName: "progress",
684+
type: "String|Number",
685+
value: "1.5rem",
686+
overridable: true,
687+
},
655688
"rmd-circular-progress-stroke-width": {
656689
name: "rmd-circular-progress-stroke-width",
657690
description:
658691
"The stroke width for the circular svg. I wouldn't change this value unless you also update the `viewbox` for the `CircularProgress` component.\n",
659-
source: "packages/progress/src/_variables.scss#L214",
692+
source: "packages/progress/src/_variables.scss#L222",
660693
packageName: "progress",
661694
type: "Number",
662695
value: "6",
@@ -666,7 +699,7 @@ const sassdoc: PackageSassDoc = {
666699
name: "rmd-circular-progress-dasharray",
667700
description:
668701
"The dasharray fro the circular svg. I don't really know how this works so good luck changing it to something else. If this value is changed, you'll aslo need to update the `dasharray` prop for the `CircularProgress` component.\n",
669-
source: "packages/progress/src/_variables.scss#L221",
702+
source: "packages/progress/src/_variables.scss#L229",
670703
usedBy: [
671704
{
672705
name: "rmd-circular-progress",
@@ -683,7 +716,7 @@ const sassdoc: PackageSassDoc = {
683716
name: "rmd-circular-progress-transition-duration",
684717
description:
685718
"The entire transition duration for the circular progress. This is really the full time for the change in the `stroke-dashoffset` as the default rotation will rotate `720deg` over this time.\n",
686-
source: "packages/progress/src/_variables.scss#L227",
719+
source: "packages/progress/src/_variables.scss#L235",
687720
usedBy: [
688721
{
689722
name: "rmd-circular-progress",
@@ -700,7 +733,7 @@ const sassdoc: PackageSassDoc = {
700733
name: "rmd-circular-progress-start-offset",
701734
description:
702735
"The starting dashoffset for the ciruclar progress animation. This will be used for the `0%` and `100%` values in the animation keyframes by default.\n",
703-
source: "packages/progress/src/_variables.scss#L232",
736+
source: "packages/progress/src/_variables.scss#L240",
704737
packageName: "progress",
705738
type: "Number",
706739
value: "$rmd-circular-progress-dasharray",
@@ -711,7 +744,7 @@ const sassdoc: PackageSassDoc = {
711744
name: "rmd-circular-progress-end-offset",
712745
description:
713746
"The ending dashoffset for the ciruclar progress animation. This will be used for the `50%` value in the animation keyframes by default.\n",
714-
source: "packages/progress/src/_variables.scss#L237",
747+
source: "packages/progress/src/_variables.scss#L245",
715748
packageName: "progress",
716749
type: "Number",
717750
value: "$rmd-circular-progress-dasharray / 4",
@@ -722,7 +755,7 @@ const sassdoc: PackageSassDoc = {
722755
name: "rmd-circular-progress-rotate-styles",
723756
description:
724757
"The circular progress styles to apply for the rotation transition. Each key in this map will be set immediately at the root of the `keyframes` and then each child map will be considered a map of property: value.\n",
725-
source: "packages/progress/src/_variables.scss#L243-L256",
758+
source: "packages/progress/src/_variables.scss#L251-L264",
726759
usedBy: [
727760
{
728761
name: "rmd-circular-progress",
@@ -740,7 +773,7 @@ const sassdoc: PackageSassDoc = {
740773
name: "rmd-circular-progress-dash-styles",
741774
description:
742775
"The circular progress styles to apply for the dashoffset transition. Each key in this map will be set immediately at the root of the `keyframes` and then each child map will be considered a map of property: value.\n",
743-
source: "packages/progress/src/_variables.scss#L262-L272",
776+
source: "packages/progress/src/_variables.scss#L270-L280",
744777
usedBy: [
745778
{
746779
name: "rmd-circular-progress",
@@ -760,7 +793,7 @@ const sassdoc: PackageSassDoc = {
760793
name: "rmd-progress-theme-values",
761794
description:
762795
'A Map of all the "themeable" parts of the progress package. Every key in this map will be used to create a css variable to dynamically update the values of the icon as needed.\n',
763-
source: "packages/progress/src/_variables.scss#L278-L284",
796+
source: "packages/progress/src/_variables.scss#L286-L292",
764797
usedBy: [
765798
{
766799
name: "rmd-progress-theme",

packages/progress/src/CircularProgress.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ export interface CircularProgressProps
7878
* margins.
7979
*/
8080
centered?: boolean;
81+
82+
/**
83+
* Boolean if the smaller size should be used instead.
84+
*
85+
* @since 2.3.0
86+
*/
87+
small?: boolean;
8188
}
8289

8390
const block = bem("rmd-circular-progress");
@@ -100,6 +107,7 @@ const CircularProgress = forwardRef<HTMLSpanElement, CircularProgressProps>(
100107
animate = true,
101108
centered = true,
102109
maxRotation = 360 * 1.75,
110+
small = false,
103111
...props
104112
},
105113
ref
@@ -144,7 +152,7 @@ const CircularProgress = forwardRef<HTMLSpanElement, CircularProgressProps>(
144152
aria-valuemin={min}
145153
aria-valuemax={max}
146154
aria-valuenow={value}
147-
className={cn(block({ centered }), className)}
155+
className={cn(block({ centered, small }), className)}
148156
>
149157
<svg
150158
style={svgStyle}
@@ -198,6 +206,7 @@ if (process.env.NODE_ENV !== "production") {
198206
centered: PropTypes.bool,
199207
maxRotation: PropTypes.number,
200208
dashoffset: PropTypes.number,
209+
small: PropTypes.bool,
201210
viewBox: PropTypes.string,
202211
};
203212
} catch (e) {}

packages/progress/src/__tests__/CircularProgress.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,21 @@ describe("CircularProgress", () => {
2929
expect(progress.style.transform).toContain(style.transform);
3030
expect(progress).toMatchSnapshot();
3131
});
32+
33+
it("should support a small variant", () => {
34+
const { getByRole, rerender } = render(
35+
<CircularProgress id="small=pgoress" small />
36+
);
37+
const progress = getByRole("progressbar");
38+
39+
expect(progress.className).toContain("rmd-circular-progress--small");
40+
expect(progress).toMatchSnapshot();
41+
42+
rerender(
43+
<CircularProgress id="small-circular-progress" small centered={false} />
44+
);
45+
46+
expect(progress.className).toContain("rmd-circular-progress--small");
47+
expect(progress).toMatchSnapshot();
48+
});
3249
});

packages/progress/src/__tests__/__snapshots__/CircularProgress.tsx.snap

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,47 @@ exports[`CircularProgress should render correctly 3`] = `
9797
</span>
9898
</div>
9999
`;
100+
101+
exports[`CircularProgress should support a small variant 1`] = `
102+
<span
103+
aria-valuemax="100"
104+
aria-valuemin="0"
105+
class="rmd-circular-progress rmd-circular-progress--centered rmd-circular-progress--small"
106+
id="small=pgoress"
107+
role="progressbar"
108+
>
109+
<svg
110+
class="rmd-circular-progress__svg rmd-circular-progress__svg--indeterminate"
111+
viewBox="0 0 66 66"
112+
>
113+
<circle
114+
class="rmd-circular-progress__circle rmd-circular-progress__circle--indeterminate"
115+
cx="33"
116+
cy="33"
117+
r="30"
118+
/>
119+
</svg>
120+
</span>
121+
`;
122+
123+
exports[`CircularProgress should support a small variant 2`] = `
124+
<span
125+
aria-valuemax="100"
126+
aria-valuemin="0"
127+
class="rmd-circular-progress rmd-circular-progress--small"
128+
id="small-circular-progress"
129+
role="progressbar"
130+
>
131+
<svg
132+
class="rmd-circular-progress__svg rmd-circular-progress__svg--indeterminate"
133+
viewBox="0 0 66 66"
134+
>
135+
<circle
136+
class="rmd-circular-progress__circle rmd-circular-progress__circle--indeterminate"
137+
cx="33"
138+
cy="33"
139+
r="30"
140+
/>
141+
</svg>
142+
</span>
143+
`;

0 commit comments

Comments
 (0)