-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Progress scaffold & implementation #24023
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 11 commits
f84c2e4
2edb969
e15e870
1f2237a
96f8486
b1be815
df8797e
3e173de
9507802
622d491
58e9050
771603d
f58a3c7
2b11456
a7f1cc7
679f21e
4bff1c8
96eb51c
202fa99
5ace35e
52d74f3
d44ddee
858c591
66074d3
7b606d3
e3fda55
adfe14c
1655de0
f79f318
33a0119
a3e86e6
e37a4ab
96b480a
e3a9c72
0771d69
75243b1
d1bd42d
c8a8e2f
f7f3e98
e6f3a9c
3b567f3
30b94ec
387d030
22d76d0
d81d803
bf2697b
7c7b56b
b8d4e77
a28d531
884dd4a
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 |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { Progress } from '@fluentui/react-progress'; | ||
|
|
||
| console.log(Progress); | ||
|
|
||
| export default { | ||
| name: 'Progress', | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| export const DefaultDiv = () => ( | ||
|
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 | ||||
|---|---|---|---|---|---|---|
| @@ -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>; | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
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'>; | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
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>; | ||||||
|
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 | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||||||
| * @defaultValue 2 | ||||||
|
Contributor
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.
Suggested change
|
||||||
| */ | ||||||
| barHeight?: number; | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
Contributor
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. Nit: I wonder if 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; | ||||||
|
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'>>; | ||||||
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; | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
Contributor
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. What's the value in using |
||||||
| const baseId = useId('Progress'); | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||||||
| const describedbyId = useId('Progress Description'); | ||||||
|
Contributor
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.
Suggested change
|
||||||
|
|
||||||
| const { role = 'progressbar', ...rest } = props; | ||||||
| const nativeRoot = getNativeElementProps('div', { ref, role, ...rest }); | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| const labelShorthand = resolveShorthand(props.label, { | ||||||
|
Contributor
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. Since you're calling resolveShorthand, the result is specifically not the shorthand value 🙂. Maybe just call this variable |
||||||
| defaultProps: { | ||||||
| id: baseId, | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||||||
| }, | ||||||
| required: false, | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||||||
| }); | ||||||
|
|
||||||
| const descriptionShorthand = resolveShorthand(props.description, { | ||||||
| defaultProps: { | ||||||
| id: describedbyId, | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||||||
| }, | ||||||
| required: false, | ||||||
| }); | ||||||
|
|
||||||
| const indicatorShortHand = resolveShorthand(props.indicator, { | ||||||
| required: true, | ||||||
|
khmakoto marked this conversation as resolved.
|
||||||
| defaultProps: { | ||||||
| children: <DefaultDiv />, | ||||||
| }, | ||||||
| }); | ||||||
|
|
||||||
| if (labelShorthand && nativeRoot && !nativeRoot['aria-labelledby']) { | ||||||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||||||
| nativeRoot['aria-labelledby'] = labelShorthand.id; | ||||||
| } | ||||||
|
Contributor
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. 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 | ||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||
| const ZERO_THRESHOLD = 0.01; | ||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||
|
|
||
| export const useProgressState_unstable = (state: ProgressState, props: ProgressProps) => { | ||
|
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; | ||
|
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', | ||
|
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; | ||
|
tomi-msft marked this conversation as resolved.
Outdated
|
||
| }; | ||
Uh oh!
There was an error while loading. Please reload this page.