Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
f84c2e4
Progress scaffold & implementation
tomi-msft Jul 21, 2022
2edb969
Update state styling and stories
tomi-msft Jul 21, 2022
e15e870
Merge branch 'master' of https://github.com/OfficeDev/office-ui-fabri…
tomi-msft Jul 21, 2022
1f2237a
update dependencies
tomi-msft Jul 21, 2022
96f8486
merge with master
tomi-msft Jul 22, 2022
b1be815
remove dup script from package.json
tomi-msft Jul 22, 2022
df8797e
Add appearance props and update styling
tomi-msft Jul 22, 2022
3e173de
Merge branch 'master' of https://github.com/OfficeDev/office-ui-fabri…
tomi-msft Jul 22, 2022
9507802
api update
tomi-msft Jul 22, 2022
622d491
add test to disabled conformance test array
tomi-msft Jul 25, 2022
58e9050
Add testOptions
tomi-msft Jul 25, 2022
771603d
Add size styling and stories
tomi-msft Aug 4, 2022
f58a3c7
Merge branch 'master' into react-progress-implementation
tomi-msft Aug 4, 2022
2b11456
api update
tomi-msft Aug 4, 2022
a7f1cc7
Merge branch 'react-progress-implementation' of https://github.com/to…
tomi-msft Aug 4, 2022
679f21e
Apply suggestions from code review
tomi-msft Aug 4, 2022
4bff1c8
react-label version update
tomi-msft Aug 4, 2022
96eb51c
merge with master
tomi-msft Aug 5, 2022
202fa99
merge with master
tomi-msft Sep 1, 2022
5ace35e
Merge branch 'master' of https://github.com/OfficeDev/office-ui-fabri…
tomi-msft Sep 1, 2022
52d74f3
Merge branch 'master' of https://github.com/OfficeDev/office-ui-fabri…
tomi-msft Sep 13, 2022
d44ddee
Update styling and package.json
tomi-msft Sep 15, 2022
858c591
change files
tomi-msft Sep 15, 2022
66074d3
Merge branch 'master' of https://github.com/OfficeDev/office-ui-fabri…
tomi-msft Sep 15, 2022
7b606d3
api update
tomi-msft Sep 15, 2022
e3fda55
fix dependency mismatch
tomi-msft Sep 15, 2022
adfe14c
Apply suggestions from code review
tomi-msft Sep 15, 2022
1655de0
Remove progressState file
tomi-msft Sep 26, 2022
f79f318
remove random spinbutton change
tomi-msft Sep 26, 2022
33a0119
change files
tomi-msft Sep 26, 2022
a3e86e6
fix dependency mismatch
tomi-msft Sep 26, 2022
e37a4ab
Add slots and update styling
tomi-msft Sep 26, 2022
96b480a
Update styling and add new slots
tomi-msft Sep 27, 2022
e3a9c72
add specificity to determinate style
tomi-msft Sep 27, 2022
0771d69
fix positioning
tomi-msft Sep 27, 2022
75243b1
remove unused file
tomi-msft Sep 27, 2022
d1bd42d
api update
tomi-msft Sep 27, 2022
c8a8e2f
Apply suggestions from code review
tomi-msft Sep 28, 2022
f7f3e98
Apply changes from code review
tomi-msft Sep 28, 2022
e6f3a9c
Clean up stories
tomi-msft Sep 29, 2022
3b567f3
Update snapshot
tomi-msft Sep 29, 2022
30b94ec
api update
tomi-msft Sep 29, 2022
387d030
Apply suggestions from code review
tomi-msft Sep 30, 2022
22d76d0
Remove animation from examples and cleanup
tomi-msft Sep 30, 2022
d81d803
cleanup
tomi-msft Sep 30, 2022
bf2697b
revert README.md
tomi-msft Sep 30, 2022
7c7b56b
update snapshot
tomi-msft Sep 30, 2022
b8d4e77
revert README.md
tomi-msft Sep 30, 2022
a28d531
Fix stories
tomi-msft Sep 30, 2022
884dd4a
api update
tomi-msft Sep 30, 2022
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Progress } from '@fluentui/react-progress';
Comment thread
tomi-msft marked this conversation as resolved.

console.log(Progress);

export default {
name: 'Progress',
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import { Label } from '@fluentui/react-label';
import * as React_2 from 'react';
import type { Slot } from '@fluentui/react-utilities';
import type { SlotClassNames } from '@fluentui/react-utilities';
Expand All @@ -18,15 +19,22 @@ export const Progress: ForwardRefComponent<ProgressProps>;
export const progressClassNames: SlotClassNames<ProgressSlots>;

// @public
export type ProgressProps = ComponentProps<ProgressSlots> & {};
export type ProgressProps = Omit<ComponentProps<ProgressSlots>, 'size'> & {
appearance?: 'primary' | 'inverted';
barHeight?: number;
percentComplete?: number;
};

// @public (undocumented)
export type ProgressSlots = {
root: Slot<'div'>;
root: NonNullable<Slot<'div'>>;
label?: Slot<typeof Label>;
indicator?: Slot<'span'>;
description?: Slot<typeof Label>;
};

// @public
export type ProgressState = ComponentState<ProgressSlots>;
export type ProgressState = ComponentState<ProgressSlots> & Required<Pick<ProgressProps, 'appearance' | 'barHeight' | 'percentComplete'>>;

// @public
export const renderProgress_unstable: (state: ProgressState) => JSX.Element;
Expand Down
8 changes: 5 additions & 3 deletions packages/react-components/react-progress/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
"code-style": "just-scripts code-style",
"just": "just-scripts",
"lint": "just-scripts lint",
"start": "yarn storybook",
"test": "jest --passWithNoTests",
"docs": "api-extractor run --config=config/api-extractor.local.json --local",
"build:local": "tsc -p ./tsconfig.lib.json --module esnext --emitDeclarationOnly && node ../../../scripts/typescript/normalize-import --output ./dist/types/packages/react-components/react-progress/src && yarn docs",
"type-check": "tsc -b tsconfig.json",
"storybook": "node ../../../scripts/storybook/runner",
"start": "yarn storybook"
"build:local": "tsc -p ./tsconfig.lib.json --module esnext --emitDeclarationOnly && node ../../../scripts/typescript/normalize-import --output ./dist/types/packages/react-components/react-progress/src && yarn docs",
"type-check": "tsc -b tsconfig.json"
},
"devDependencies": {
"@fluentui/eslint-plugin": "*",
Expand All @@ -32,8 +32,10 @@
"@fluentui/scripts": "^1.0.0"
},
"dependencies": {
"@fluentui/react-label": "^9.0.3",
"@fluentui/react-theme": "^9.0.0",
"@fluentui/react-utilities": "^9.0.2",
"@fluentui/react-shared-contexts": "^9.0.0",
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
"@griffel/react": "^1.2.0",
"tslib": "^2.1.0"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as React from 'react';

export const DefaultDiv = () => (
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
<div className="fui-Progress__Container">
<div className="fui-Progress__Track" />
<div className="fui-Progress__Bar" />
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ describe('Progress', () => {
Component: Progress,
displayName: 'Progress',
disabledTests: ['component-has-static-classname', 'component-has-static-classname-exported'],
testOptions: {
'has-static-classnames': [
{
props: {
label: 'Test Label',
description: 'Test Description',
},
},
],
},
});

// TODO add more tests here, and create visual regression tests in /apps/vr-tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { ProgressProps } from './Progress.types';
import type { ForwardRefComponent } from '@fluentui/react-utilities';

/**
* Progress component - TODO: add more docs
* Converged Progress component for the fluentui repo
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
*/
export const Progress: ForwardRefComponent<ProgressProps> = React.forwardRef((props, ref) => {
const state = useProgress_unstable(props, ref);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,52 @@
import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
import { Label } from '@fluentui/react-label';

export type ProgressSlots = {
root: Slot<'div'>;
/**
* The root of the Progress
* The root slot receives the `className` and `style` specified directly on the `<Progress>`.
*/
root: NonNullable<Slot<'div'>>;
/**
* The title of the Progress.
* The label slot receives the styling related to the title associated with the Progress.
*/
label?: Slot<typeof Label>;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
/**
* The animated slot of the Progress
* The indicator slot receives the styling related to the loading bar associated with the Progress
*/
indicator?: Slot<'span'>;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
/**
* The description slot of the Progress
* The description slot receives the styling related to the description associated with the Progress
*/
description?: Slot<typeof Label>;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
};

/**
* Progress Props
*/
export type ProgressProps = ComponentProps<ProgressSlots> & {};
export type ProgressProps = Omit<ComponentProps<ProgressSlots>, 'size'> & {
/**
* The appearance of the Progress.
* @default 'primary'
*/
appearance?: 'primary' | 'inverted';
/**
* The height of the Progress bar
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
* @defaultValue 2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @defaultValue 2
* @default 2

*/
barHeight?: number;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: I wonder if barThickness is a better name here? I don't really ever expect us to have a vertically oriented progress bar but I think avoiding terms like width and height in our APIs is probably good practice for globalization.

Feel free to completely disregard this comment though :)

/**
* Percentage of the operation's completeness, numerically between 0 and 1. If this is not set,
* the indeterminate progress animation will be shown instead.
*/
percentComplete?: number;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
};

/**
* State used in rendering Progress
*/
export type ProgressState = ComponentState<ProgressSlots>;
// TODO: Remove semicolon from previous line, uncomment next line, and provide union of props to pick from ProgressProps
// & Required<Pick<ProgressProps, 'propName'>>
export type ProgressState = ComponentState<ProgressSlots> &
Required<Pick<ProgressProps, 'appearance' | 'barHeight' | 'percentComplete'>>;
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,23 @@ exports[`Progress renders a default state 1`] = `
<div>
<div
class="fui-Progress"
role="progressbar"
>
Default Progress
<span
class="fui-Progress__indicator"
style="--fui-Progress--percentage: 0; --fui-Progress--transition: width .3s ease;"
>
<div
class="fui-Progress__Container"
>
<div
class="fui-Progress__Track"
/>
<div
class="fui-Progress__Bar"
/>
</div>
</span>
</div>
</div>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { getSlots } from '@fluentui/react-utilities';
import type { ProgressState, ProgressSlots } from './Progress.types';

/**
* Render the final JSX of Progress
* Render the final JSX of Spinner
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
*/
export const renderProgress_unstable = (state: ProgressState) => {
const { slots, slotProps } = getSlots<ProgressSlots>(state);

// TODO Add additional slots in the appropriate place
return <slots.root {...slotProps.root} />;
return (
<slots.root {...slotProps.root}>
{slots.label && <slots.label {...slotProps.label} />}
{slots.indicator && <slots.indicator {...slotProps.indicator} />}
{slots.description && <slots.description {...slotProps.description} />}
</slots.root>
);
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as React from 'react';
import { getNativeElementProps, resolveShorthand, useId } from '@fluentui/react-utilities';
import type { ProgressProps, ProgressState } from './Progress.types';
import { Label } from '@fluentui/react-label';
import { DefaultDiv } from './DefaultDiv';
import { useProgressState_unstable } from './useProgressState';

/**
* Create the state required to render Progress.
*
* The returned state can be modified with hooks such as useProgressStyles_unstable,
* before being passed to renderProgress_unstable.
*
* @param props - props from this instance of Progress
* @param ref - reference to root HTMLElement of Progress
*/
export const useProgress_unstable = (props: ProgressProps, ref: React.Ref<HTMLElement>): ProgressState => {
// Props
const { appearance = 'primary', barHeight = 2, percentComplete = -1 } = props;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What's the value in using -1 rather than just propagating undefined for percentComplete?

const baseId = useId('Progress');
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
const describedbyId = useId('Progress Description');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
const describedbyId = useId('Progress Description');
const describedbyId = useId('ProgressDescription');

ids cannot contain whitespace.


const { role = 'progressbar', ...rest } = props;
const nativeRoot = getNativeElementProps('div', { ref, role, ...rest });
Comment thread
tomi-msft marked this conversation as resolved.
Outdated

const labelShorthand = resolveShorthand(props.label, {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since you're calling resolveShorthand, the result is specifically not the shorthand value 🙂. Maybe just call this variable label? Same for the other slots as well.

defaultProps: {
id: baseId,
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
},
required: false,
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
});

const descriptionShorthand = resolveShorthand(props.description, {
defaultProps: {
id: describedbyId,
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
},
required: false,
});

const indicatorShortHand = resolveShorthand(props.indicator, {
required: true,
Comment thread
khmakoto marked this conversation as resolved.
defaultProps: {
children: <DefaultDiv />,
},
});

if (labelShorthand && nativeRoot && !nativeRoot['aria-labelledby']) {
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
nativeRoot['aria-labelledby'] = labelShorthand.id;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do you also need to add aria-describedby for the description?


const state: ProgressState = {
appearance,
barHeight,
percentComplete,
components: {
root: 'div',
indicator: 'span',
label: Label,
description: Label,
},
root: nativeRoot,
indicator: indicatorShortHand,
label: labelShorthand,
description: descriptionShorthand,
};

useProgressState_unstable(state, props);
return state;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { ProgressState, ProgressProps } from './Progress.types';
import { progressCssVars } from './useProgressStyles';

// if the percentComplete is near 0, don't animate it.
// This prevents animations on reset to 0 scenarios
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
const ZERO_THRESHOLD = 0.01;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated

export const useProgressState_unstable = (state: ProgressState, props: ProgressProps) => {
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
const { percentComplete = -1 } = props;

const determinate = percentComplete > -1 ? true : false;

const valuePercent = determinate ? Math.min(100, Math.max(0, percentComplete)) : undefined;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated

const progressBarStyles = {
[`${progressCssVars.percentageCssVar}`]: determinate ? valuePercent + '%' : '0',
[`${progressCssVars.transitionCssVar}`]:
valuePercent && determinate && valuePercent < ZERO_THRESHOLD ? 'none' : 'width .3s ease',
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
};

const ariaValueMin = determinate ? 0 : undefined;
const ariaValueMax = determinate ? 100 : undefined;
const ariaValueNow = determinate ? Math.floor(percentComplete!) : undefined;

if (state.indicator) {
state.indicator.style = {
...progressBarStyles,
...state.indicator.style,
};
state.indicator['aria-valuemin'] = ariaValueMin;
state.indicator['aria-valuemax'] = ariaValueMax;
state.indicator['aria-valuenow'] = ariaValueNow;
}
//return state;
Comment thread
tomi-msft marked this conversation as resolved.
Outdated
};
Loading