Skip to content

Commit 579b57f

Browse files
authored
Add progress ring (#10)
* Add progress-ring * Fix tag naming in React * Improve some stories * Add snapshots
1 parent 4dcaee1 commit 579b57f

File tree

12 files changed

+194
-14
lines changed

12 files changed

+194
-14
lines changed

packages/components/src/breadcrumb-item/breadcrumb-item.stories.ts

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ export default {
99
href: { control: 'boolean' },
1010
startIcon: { control: 'boolean' },
1111
endIcon: { control: 'boolean' }
12+
},
13+
parameters: {
14+
actions: {
15+
disabled: true
16+
}
1217
}
1318
};
1419

packages/components/src/custom-elements.ts

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { jpBreadcrumbItem } from './breadcrumb-item/index';
88
import { jpButton } from './button/index';
99
import { jpOption } from './option/index';
1010
import { jpProgress } from './progress/index';
11+
import { jpProgressRing } from './progress-ring/index';
1112
import { jpSearch } from './search/index';
1213
import { jpSelect } from './select/index';
1314
import { jpSlider } from './slider/index';
@@ -26,6 +27,7 @@ import type { BreadcrumbItem } from './breadcrumb-item/index';
2627
import type { Button } from './button/index';
2728
import type { Option } from './option/index';
2829
import type { Progress } from './progress/index';
30+
import type { ProgressRing } from './progress-ring/index';
2931
import type { Search } from './search/index';
3032
import type { Select } from './select/index';
3133
import type { Slider } from './slider/index';
@@ -43,6 +45,7 @@ export {
4345
jpButton,
4446
jpOption,
4547
jpProgress,
48+
jpProgressRing,
4649
jpSearch,
4750
jpSelect,
4851
jpSlider,
@@ -67,6 +70,7 @@ export const allComponents = {
6770
jpButton,
6871
jpOption,
6972
jpProgress,
73+
jpProgressRing,
7074
jpSearch,
7175
jpSelect,
7276
jpSlider,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {
2+
BaseProgress as ProgressRing,
3+
ProgressRingOptions,
4+
progressRingTemplate as template
5+
} from '@microsoft/fast-foundation';
6+
import { progressRingStyles as styles } from '@microsoft/fast-components';
7+
8+
/**
9+
* A function that returns a {@link @microsoft/fast-foundation#BaseProgress} registration for configuring the component with a DesignSystem.
10+
* Implements {@link @microsoft/fast-foundation#progressRingTemplate}
11+
*
12+
*
13+
* @public
14+
* @remarks
15+
* Generates HTML Element: `<jp-progress-ring>`
16+
*/
17+
export const jpProgressRing = ProgressRing.compose<ProgressRingOptions>({
18+
baseName: 'progress-ring',
19+
template,
20+
styles,
21+
indeterminateIndicator: `
22+
<svg class="progress" part="progress" viewBox="0 0 16 16">
23+
<circle
24+
class="background"
25+
part="background"
26+
cx="8px"
27+
cy="8px"
28+
r="7px"
29+
></circle>
30+
<circle
31+
class="indeterminate-indicator-1"
32+
part="indeterminate-indicator-1"
33+
cx="8px"
34+
cy="8px"
35+
r="7px"
36+
></circle>
37+
</svg>
38+
`
39+
});
40+
41+
/**
42+
* Base class for ProgressRing
43+
* @public
44+
*/
45+
export { ProgressRing };
46+
47+
export { styles as progressRingStyles };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import { setTheme } from '../utilities/storybook';
5+
6+
export default {
7+
title: 'Progress Ring',
8+
argTypes: {
9+
min: { control: 'number', min: 0 },
10+
max: { control: 'number', min: 0 },
11+
value: { control: 'number', min: 0 },
12+
paused: { control: 'boolean' },
13+
height: { control: 'number', min: 4 }
14+
},
15+
parameters: {
16+
actions: {
17+
disabled: true
18+
}
19+
}
20+
};
21+
22+
const Template = (
23+
args,
24+
{ globals: { backgrounds, accent }, parameters }
25+
): string => {
26+
setTheme(accent, parameters.backgrounds, backgrounds);
27+
return `<jp-progress-ring
28+
${typeof args.min === 'number' ? `min="${args.min}"` : ''}
29+
${typeof args.max === 'number' ? `max="${args.max}"` : ''}
30+
${typeof args.value === 'number' ? `value="${args.value}"` : ''}
31+
${args.paused ? 'paused="true"' : ''}
32+
${
33+
typeof args.height === 'number' ? `style="height: ${args.height}px;"` : ''
34+
}
35+
>
36+
</jp-progress-ring>`;
37+
};
38+
39+
export const Default = Template.bind({});
40+
Default.args = {
41+
min: null,
42+
max: null,
43+
value: null,
44+
paused: false,
45+
height: null
46+
};
47+
48+
export const WithValue = Template.bind({});
49+
WithValue.args = {
50+
...Default.args,
51+
min: 0,
52+
max: 50,
53+
value: 30
54+
};
55+
56+
export const Paused = Template.bind({});
57+
Paused.args = {
58+
...WithValue.args,
59+
paused: true
60+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import { test, expect } from '@playwright/test';
5+
6+
test('With value', async ({ browserName, page }) => {
7+
// FIXME
8+
test.skip(browserName === 'webkit', 'Progress ring bar animation unstable.');
9+
10+
await page.goto('/iframe.html?id=progress-ring--with-value');
11+
12+
// Ensure the progress animation is finished
13+
await page.waitForTimeout(200);
14+
15+
expect(await page.locator('jp-progress-ring').screenshot()).toMatchSnapshot(
16+
'progress-ring-with-value.png'
17+
);
18+
});

packages/components/src/tabs/tabs.stories.ts

+20-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Jupyter Development Team.
22
// Distributed under the terms of the Modified BSD License.
33

4+
import { action } from '@storybook/addon-actions';
45
import { setTheme } from '../utilities/storybook';
56

67
export default {
@@ -9,23 +10,21 @@ export default {
910
activePanel: { control: 'select', options: [null, 'One', 'Two', 'Three'] },
1011
activeIndicator: { control: 'boolean' },
1112
orientation: { control: 'radio', options: ['horizontal', 'vertical'] }
12-
},
13-
parameters: {
14-
actions: {
15-
disabled: true
16-
}
1713
}
1814
};
1915

2016
const Template = (
2117
args,
2218
{ globals: { backgrounds, accent }, parameters }
23-
): string => {
19+
): HTMLElement => {
2420
setTheme(accent, parameters.backgrounds, backgrounds);
2521

26-
return `<jp-tabs
27-
${!args.activeIndicator && 'activeIndicator="false"'}
28-
${args.activePanel ? `activeId=Tab${args.activePanel}` : ''}
22+
const container = document.createElement('div');
23+
container.insertAdjacentHTML(
24+
'afterbegin',
25+
`<jp-tabs
26+
${!args.activeIndicator && 'activeindicator="false"'}
27+
${args.activePanel ? `activeid=Tab${args.activePanel}` : ''}
2928
orientation="${args.orientation}"
3029
>
3130
<jp-tab id="TabOne">Tab one</jp-tab>
@@ -40,14 +39,24 @@ const Template = (
4039
<jp-tab-panel id="TabPanelThree">
4140
Tab three content. This is for testing.
4241
</jp-tab-panel>
43-
</jp-tabs>`;
42+
</jp-tabs>`
43+
);
44+
45+
const tabs = container.firstChild as HTMLElement;
46+
47+
if (args.onChange) {
48+
tabs.addEventListener('change', args.onChange);
49+
}
50+
51+
return tabs;
4452
};
4553

4654
export const Default = Template.bind({});
4755
Default.args = {
4856
activePanel: null,
4957
activeIndicator: true,
50-
orientation: 'horizontal'
58+
orientation: 'horizontal',
59+
onChange: action('tabs-onchange')
5160
};
5261

5362
export const Vertical = Template.bind({});

packages/lab-example/src/index.tsx

+11-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Button,
66
Option,
77
Progress,
8+
ProgressRing,
89
Search,
910
Select,
1011
Slider,
@@ -160,6 +161,11 @@ function Artwork(): JSX.Element {
160161
<Progress></Progress>
161162
<Progress min={0} max={50} value={30}></Progress>
162163
</div>
164+
<div className="jp-FlexColumn">
165+
<label>Progress Ring</label>
166+
<ProgressRing></ProgressRing>
167+
<ProgressRing min={0} max={50} value={30}></ProgressRing>
168+
</div>
163169
</div>
164170
<div className="jp-FlexColumn" style={{ gridColumn: 3 }}>
165171
<Tabs>
@@ -191,7 +197,6 @@ function Artwork(): JSX.Element {
191197
<div>
192198
<Tag>Tag</Tag>
193199
</div>
194-
<ProgressRing></ProgressRing>
195200
</div> */}
196201
</div>
197202
);
@@ -249,7 +254,6 @@ function createNode(): HTMLElement {
249254
<jp-badge>1</jp-badge>
250255
<jp-tag>Tag</jp-tag>
251256
</div>
252-
<jp-progress-ring></jp-progress-ring>
253257
</div>
254258
-->
255259
<div class="jp-FlexColumn" style="grid-column: 2;">
@@ -264,6 +268,11 @@ function createNode(): HTMLElement {
264268
<jp-progress></jp-progress>
265269
<jp-progress min="0" max="50" value="30"></jp-progress>
266270
</div>
271+
<div class="jp-FlexColumn">
272+
<label>Progress Ring</label>
273+
<jp-progress-ring></jp-progress-ring>
274+
<jp-progress-ring min="0" max="50" value="30"></jp-progress-ring>
275+
</div>
267276
</div>
268277
<div class="jp-FlexColumn" style="grid-column: 3;">
269278
<!--

packages/react-components/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './breadcrumb-item';
44
export * from './button';
55
export * from './option';
66
export * from './progress';
7+
export * from './progress-ring';
78
export * from './search';
89
export * from './select';
910
export * from './slider';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import {
5+
provideJupyterDesignSystem,
6+
jpProgressRing
7+
} from '@jupyter-notebook/web-components';
8+
import { provideReactWrapper } from '@microsoft/fast-react-wrapper';
9+
import React from 'react';
10+
11+
const { wrap } = provideReactWrapper(React, provideJupyterDesignSystem());
12+
13+
export const ProgressRing: React.DetailedHTMLFactory<
14+
React.HTMLAttributes<HTMLElement> & {
15+
min?: number;
16+
max?: number;
17+
value?: number;
18+
paused?: boolean;
19+
},
20+
HTMLElement
21+
> = wrap(
22+
jpProgressRing(),
23+
// Name need to be exported otherwise a `jp-progress` element is instantiated
24+
{ name: 'jp-progress-ring' }
25+
) as any;
26+
// @ts-expect-error unknown property
27+
ProgressRing.displayName = 'Jupyter.ProgressRing';

packages/react-components/src/progress/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ export const Progress: React.DetailedHTMLFactory<
1818
paused?: boolean;
1919
},
2020
HTMLElement
21-
> = wrap(jpProgress()) as any;
21+
> = wrap(jpProgress(), { name: 'jp-progress' }) as any;
2222
// @ts-expect-error unknown property
2323
Progress.displayName = 'Jupyter.Progress';

0 commit comments

Comments
 (0)