Skip to content

Commit

Permalink
fix: Display of StepList with hidden items (#49734)
Browse files Browse the repository at this point in the history
- Use `displayIndex` prop to seperately track step numbers to display
  • Loading branch information
kiosion authored Dec 20, 2024
1 parent 4be8ef4 commit 92c1cec
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ export function StepItem<T>(props: {
return (
<StepsContainer active={isDone || isActive}>
<StepTitle>
<Bullet isDone={isDone} isActive={isActive} stepNumber={index + 1} />
<Bullet
isDone={isDone}
isActive={isActive}
stepNumber={props.view.displayIndex ?? index + 1}
/>
{props.view.title}
</StepTitle>
</StepsContainer>
Expand Down
8 changes: 6 additions & 2 deletions web/packages/teleport/src/components/Wizard/flow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,13 @@ test('computeViewChildrenSize', async () => {
},
{
title: 'Banana',
hide: true,
},
];
expect(computeViewChildrenSize(nestedViews)).toBe(3);
expect(computeViewChildrenSize({ views: nestedViews })).toBe(3);
expect(
computeViewChildrenSize({ views: nestedViews, constrainToVisible: true })
).toBe(2);

const notNestedViews = [
{
Expand All @@ -53,7 +57,7 @@ test('computeViewChildrenSize', async () => {
title: 'Banana',
},
];
expect(computeViewChildrenSize(notNestedViews)).toBe(2);
expect(computeViewChildrenSize({ views: notNestedViews })).toBe(2);
});

test('addIndexToViews and rendering correct steps', async () => {
Expand Down
64 changes: 55 additions & 9 deletions web/packages/teleport/src/components/Wizard/flow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,61 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/**
* BaseView is a recursive type representing a view in a Wizard flow.
*
* @template T - Any view-specific properties.
*/
export type BaseView<T> = T & {
/**
* Whether to hide the view from the list of views.
*/
hide?: boolean;
/**
* Current step index in the wizard.
*/
index?: number;
/**
* Current visible step index in the wizard (ignoring any hidden steps).
*/
displayIndex?: number;
/**
* Optional list of sub-views.
*/
views?: BaseView<T>[];
/**
* Title of this view in the wizard flow.
*/
title: string;
};

/**
* computeViewChildrenSize calculates how many children a view has, without counting the first
* child. This is because the first child shares the same index with its parent, so we don't
* need to count it as it's not taking up a new index
* need to count it as it's not taking up a new index.
*
* If `constrainToVisible` is true, then we only count the visible views.
*/
export function computeViewChildrenSize<T>(views: BaseView<T>[]) {
export function computeViewChildrenSize<T>({
views,
constrainToVisible = false,
}: {
views: BaseView<T>[];
constrainToVisible?: boolean;
}) {
let size = 0;
for (const view of views) {
if (constrainToVisible && view.hide) {
continue;
}

if (view.views) {
size += computeViewChildrenSize(view.views);
size += computeViewChildrenSize({
views: view.views,
constrainToVisible,
});
} else {
size += 1;
size++;
}
}

Expand All @@ -48,7 +84,8 @@ export function computeViewChildrenSize<T>(views: BaseView<T>[]) {
*/
export function addIndexToViews<T>(
views: BaseView<T>[],
index = 0
index = 0,
displayIndex = 1
): BaseView<T>[] {
const result: BaseView<T>[] = [];

Expand All @@ -60,11 +97,20 @@ export function addIndexToViews<T>(
};

if (view.views) {
copy.views = addIndexToViews(view.views, index);

index += computeViewChildrenSize(view.views);
copy.views = addIndexToViews(view.views, index, displayIndex);
index += computeViewChildrenSize({ views: view.views });
} else {
index += 1;
index++;
}

if (!view.hide) {
copy.displayIndex = displayIndex;
displayIndex += view.views
? computeViewChildrenSize({
views: view.views,
constrainToVisible: true,
})
: 1;
}

result.push(copy);
Expand Down

0 comments on commit 92c1cec

Please sign in to comment.