Add basic app steps.
+ Add basic app steps system and style. * Rename steps counter to avoid collision with app steps.
This commit is contained in:
		
							parent
							
								
									8c0c616f15
								
							
						
					
					
						commit
						8904ed741c
					
				
					 6 changed files with 458 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -23,6 +23,7 @@ import {AppItem, AppLink, AppsMenu} from "../src/Components/Menus/AppsMenu";
 | 
			
		|||
import {Application} from "../src/Application/Application";
 | 
			
		||||
import {Outlet} from "react-router-dom";
 | 
			
		||||
import {ToggleSwitch} from "../src/Components/Forms/ToggleSwitch";
 | 
			
		||||
import {Step, Steps} from "../src/Components/Steps/Steps";
 | 
			
		||||
 | 
			
		||||
export function DemoApp()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +63,6 @@ export function DemoApp()
 | 
			
		|||
			<h2>TODO</h2>
 | 
			
		||||
 | 
			
		||||
			<ul>
 | 
			
		||||
				<li>App steps</li>
 | 
			
		||||
				<li>Pagination</li>
 | 
			
		||||
				<li>Global states</li>
 | 
			
		||||
				<li>Async</li>
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +155,7 @@ export function DemoApp()
 | 
			
		|||
 | 
			
		||||
			<h2>Steps</h2>
 | 
			
		||||
 | 
			
		||||
			<div className={"steps"}>
 | 
			
		||||
			<div className={"steps-counter"}>
 | 
			
		||||
				<h3 className={"step"}>Step one</h3>
 | 
			
		||||
				<h3 className={"step"}>Step two</h3>
 | 
			
		||||
				<h3 className={"step"}>Step three</h3>
 | 
			
		||||
| 
						 | 
				
			
			@ -332,6 +332,84 @@ export function DemoApp()
 | 
			
		|||
			</AppsMenu>
 | 
			
		||||
 | 
			
		||||
			<Outlet />
 | 
			
		||||
 | 
			
		||||
			<h2>App steps</h2>
 | 
			
		||||
 | 
			
		||||
			<h3>Basic</h3>
 | 
			
		||||
 | 
			
		||||
			<Steps>
 | 
			
		||||
				<Step stepKey={"abc"}>
 | 
			
		||||
					<Card>
 | 
			
		||||
						<h4>First step</h4>
 | 
			
		||||
 | 
			
		||||
						ABC STEP
 | 
			
		||||
					</Card>
 | 
			
		||||
				</Step>
 | 
			
		||||
 | 
			
		||||
				<Step stepKey={"def"} stepTitle={"Title"}>
 | 
			
		||||
					<Card>
 | 
			
		||||
						<h4>Big content</h4>
 | 
			
		||||
 | 
			
		||||
						<p>
 | 
			
		||||
							Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam id dignissim ligula, ut tempus sem. Sed
 | 
			
		||||
							faucibus tincidunt ante vel iaculis. Duis hendrerit, orci eu gravida interdum, nulla lacus congue augue,
 | 
			
		||||
							nec efficitur diam dui sollicitudin eros. Donec lacus lectus, aliquam nec feugiat non, gravida ac est.
 | 
			
		||||
							Suspendisse feugiat justo quis dui vehicula, sed auctor est mollis. Sed hendrerit nisi non lectus lacinia,
 | 
			
		||||
							id posuere dolor dignissim. Quisque commodo mi sit amet quam tincidunt auctor. Ut sit amet scelerisque
 | 
			
		||||
							sem. Nulla rhoncus, orci vitae cursus ullamcorper, ex odio rhoncus enim, et blandit elit libero quis est.
 | 
			
		||||
							Suspendisse lectus nunc, gravida sit amet vulputate eget, porta ac odio.
 | 
			
		||||
						</p>
 | 
			
		||||
 | 
			
		||||
						<p>
 | 
			
		||||
							Mauris egestas bibendum facilisis. Maecenas accumsan lorem arcu, ut faucibus dui euismod et. Nulla et
 | 
			
		||||
							dignissim est, interdum luctus diam. Aliquam condimentum ex augue, id porttitor enim vestibulum quis.
 | 
			
		||||
							Vivamus sed convallis leo. Duis finibus, ipsum sed condimentum viverra, ipsum sapien congue nunc, sed
 | 
			
		||||
							fermentum metus ante quis ligula. Fusce eleifend ante in leo molestie, at suscipit metus cursus. Class
 | 
			
		||||
							aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed laoreet justo ac
 | 
			
		||||
							lacus porta, sed ultricies est mattis. Integer finibus purus metus, quis posuere risus suscipit suscipit.
 | 
			
		||||
							Nulla facilisi. Duis tincidunt vitae enim eu sagittis.
 | 
			
		||||
						</p>
 | 
			
		||||
 | 
			
		||||
						<p>
 | 
			
		||||
							Donec rutrum tellus vitae vehicula tempor. Sed porta tempus leo, vel aliquam risus scelerisque nec.
 | 
			
		||||
							Pellentesque diam nibh, ultrices in rhoncus ut, rhoncus et ligula. Duis pellentesque diam purus, ut
 | 
			
		||||
							scelerisque turpis condimentum sit amet. Sed sit amet efficitur tortor, vitae aliquet quam. Nullam
 | 
			
		||||
							placerat dui eu sapien condimentum, placerat convallis sapien imperdiet. Suspendisse vitae laoreet ex.
 | 
			
		||||
							Etiam quis rhoncus ante. Ut egestas eget ipsum ultrices tempus. Vivamus non odio non nisl aliquet rhoncus.
 | 
			
		||||
							Ut et nisl placerat, interdum turpis a, condimentum mauris. In laoreet lobortis justo. Maecenas vehicula
 | 
			
		||||
							magna non libero posuere rutrum. Praesent eget lectus feugiat dui pellentesque vehicula a sed felis.
 | 
			
		||||
							Curabitur nunc orci, vehicula non gravida sed, suscipit sed diam. Nam semper, dui eu volutpat vulputate,
 | 
			
		||||
							metus mauris congue lectus, ultrices sollicitudin eros felis ac erat.
 | 
			
		||||
						</p>
 | 
			
		||||
 | 
			
		||||
						<p>
 | 
			
		||||
							Proin et rhoncus purus. Etiam nulla libero, dictum sed quam lacinia, consequat euismod ipsum. Donec quis
 | 
			
		||||
							tristique metus. Cras vitae pretium massa. Etiam laoreet, eros in rhoncus ultrices, nibh nibh bibendum
 | 
			
		||||
							diam, nec ultricies mi ante non ex. Pellentesque eget mattis dolor, eget pulvinar lorem. Nullam ante
 | 
			
		||||
							dolor, ultricies et malesuada in, efficitur sit amet diam. Duis ligula augue, vestibulum sit amet ligula
 | 
			
		||||
							ac, vestibulum tincidunt eros. Nullam commodo euismod vulputate. Morbi varius accumsan diam eu
 | 
			
		||||
							pellentesque. Nunc vehicula pretium risus dapibus cursus. Mauris sit amet est at ipsum scelerisque
 | 
			
		||||
							lobortis. Aenean eget quam sit amet arcu mattis interdum in at neque.
 | 
			
		||||
						</p>
 | 
			
		||||
 | 
			
		||||
						<p>
 | 
			
		||||
							Mauris efficitur, enim pellentesque maximus faucibus, nibh enim gravida urna, quis dignissim turpis velit
 | 
			
		||||
							quis nibh. Mauris eget vestibulum tellus. Duis mollis, ante in egestas lacinia, felis massa rutrum ante,
 | 
			
		||||
							vel placerat lectus neque in purus. Fusce sodales nunc vel ligula mollis tincidunt. Sed ac viverra ligula.
 | 
			
		||||
							Vestibulum ut velit sit amet ipsum cursus posuere in nec lacus. Praesent vel odio pellentesque,
 | 
			
		||||
							ullamcorper metus in, accumsan dolor. Donec vel mi ultrices, interdum arcu vel, pellentesque nunc.
 | 
			
		||||
						</p>
 | 
			
		||||
					</Card>
 | 
			
		||||
				</Step>
 | 
			
		||||
 | 
			
		||||
				<Step stepKey={"ghi"}>
 | 
			
		||||
					<Card>
 | 
			
		||||
						<h4>Third step</h4>
 | 
			
		||||
 | 
			
		||||
						GHI STEP
 | 
			
		||||
					</Card>
 | 
			
		||||
				</Step>
 | 
			
		||||
			</Steps>
 | 
			
		||||
		</Application>
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										109
									
								
								src/Components/Steps/Steps.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/Components/Steps/Steps.tsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
import React, {useEffect} from "react";
 | 
			
		||||
import {
 | 
			
		||||
	GlobalStateProvider,
 | 
			
		||||
	useGlobalStateReducers, useGlobalStateValue,
 | 
			
		||||
} from "../../GlobalState";
 | 
			
		||||
import {usePreviousValue} from "../../Utils";
 | 
			
		||||
import {StepKeyType, stepsGlobalState, useCurrentStepKey, useStepsNavigator} from "./StepsContext";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Main Steps component.
 | 
			
		||||
 */
 | 
			
		||||
export function Steps({children}: React.PropsWithChildren<{}>)
 | 
			
		||||
{
 | 
			
		||||
	return (
 | 
			
		||||
		<GlobalStateProvider globalState={stepsGlobalState}>
 | 
			
		||||
			<div className={"steps"}>
 | 
			
		||||
				<StepsNavigatorComponent />
 | 
			
		||||
 | 
			
		||||
				<div>
 | 
			
		||||
					{children}
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</GlobalStateProvider>
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Steps navigator component.
 | 
			
		||||
 */
 | 
			
		||||
export function StepsNavigatorComponent()
 | 
			
		||||
{
 | 
			
		||||
	// Get the steps navigator functions.
 | 
			
		||||
	const stepsNavigator = useStepsNavigator();
 | 
			
		||||
 | 
			
		||||
	// Get the current steps state.
 | 
			
		||||
	const stepsState = useGlobalStateValue(stepsGlobalState);
 | 
			
		||||
 | 
			
		||||
	// Get the current step.
 | 
			
		||||
	const currentStep = useCurrentStepKey();
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<nav className={"steps"}>
 | 
			
		||||
			<ul>
 | 
			
		||||
				{ // Showing a button for each step.
 | 
			
		||||
					stepsState.steps.map((step, index) => (
 | 
			
		||||
						// Rendering the current step button.
 | 
			
		||||
						<li key={step.key} className={currentStep == step.key ? "active" : undefined}>
 | 
			
		||||
							<button type={"button"} onClick={() => {
 | 
			
		||||
								stepsNavigator.set(step.key);
 | 
			
		||||
							}}>
 | 
			
		||||
								{step.title ?? (index + 1)}
 | 
			
		||||
							</button>
 | 
			
		||||
						</li>
 | 
			
		||||
					))
 | 
			
		||||
				}
 | 
			
		||||
			</ul>
 | 
			
		||||
		</nav>
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Component of a step.
 | 
			
		||||
 */
 | 
			
		||||
export function Step({stepKey, stepTitle, children}: React.PropsWithChildren<{
 | 
			
		||||
	/**
 | 
			
		||||
	 * The current step unique key.
 | 
			
		||||
	 */
 | 
			
		||||
	stepKey: StepKeyType;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The step title, to show in the navigator.
 | 
			
		||||
	 */
 | 
			
		||||
	stepTitle?: React.ReactNode;
 | 
			
		||||
}>)
 | 
			
		||||
{
 | 
			
		||||
	// Get the global state reducers class.
 | 
			
		||||
	const stepsGlobalStateReducers = useGlobalStateReducers(stepsGlobalState);
 | 
			
		||||
 | 
			
		||||
	// Get the previous step key.
 | 
			
		||||
	const previousStepKey = usePreviousValue(stepKey);
 | 
			
		||||
 | 
			
		||||
	useEffect(() => {
 | 
			
		||||
		// Remove the previous step key, if there is one.
 | 
			
		||||
		if (previousStepKey) stepsGlobalStateReducers.removeStep(previousStepKey);
 | 
			
		||||
 | 
			
		||||
		// Register the current step key.
 | 
			
		||||
		stepsGlobalStateReducers.registerStep(stepKey, stepTitle);
 | 
			
		||||
 | 
			
		||||
		// Remove the step key when component is removed.
 | 
			
		||||
		return () => stepsGlobalStateReducers.removeStep(stepKey);
 | 
			
		||||
	}, [stepsGlobalStateReducers, previousStepKey, stepTitle]);
 | 
			
		||||
 | 
			
		||||
	// Get the current step key.
 | 
			
		||||
	const currentStep = useCurrentStepKey();
 | 
			
		||||
 | 
			
		||||
	if (currentStep != stepKey)
 | 
			
		||||
		// If this step is not the current one, rendering nothing.
 | 
			
		||||
		return undefined;
 | 
			
		||||
 | 
			
		||||
	// Rendering the current step.
 | 
			
		||||
	return (
 | 
			
		||||
		<section className={"step"}>
 | 
			
		||||
			{children}
 | 
			
		||||
		</section>
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										165
									
								
								src/Components/Steps/StepsContext.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/Components/Steps/StepsContext.tsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,165 @@
 | 
			
		|||
import React, {useMemo} from "react";
 | 
			
		||||
import {GlobalState, GlobalStateReducers, useGlobalStateReducers, useGlobalStateValue} from "../../GlobalState";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Type of step key.
 | 
			
		||||
 */
 | 
			
		||||
export type StepKeyType = string;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Steps global state data type.
 | 
			
		||||
 */
 | 
			
		||||
export interface StepsGlobalStateType
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * Steps list, by their order of apparition.
 | 
			
		||||
	 */
 | 
			
		||||
	steps: { key: StepKeyType; title?: React.ReactNode; }[];
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * The index of the current step in the steps list.
 | 
			
		||||
	 */
 | 
			
		||||
	currentStepIndex: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The steps global state modification functions.
 | 
			
		||||
 */
 | 
			
		||||
class StepsGlobalStateReducers extends GlobalStateReducers<StepsGlobalStateType>
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * Register a new step with its step key.
 | 
			
		||||
	 * @param newStepKey The step key to register.
 | 
			
		||||
	 */
 | 
			
		||||
	registerStep(newStepKey: StepKeyType, newStepTitle?: React.ReactNode): void
 | 
			
		||||
	{
 | 
			
		||||
		this.setState({
 | 
			
		||||
			// Add the given step key to the steps array, ensuring that it will be there only once.
 | 
			
		||||
			steps: [...this.state.steps.filter(({key: currentStepKey}) => currentStepKey != newStepKey), { key: newStepKey, title: newStepTitle }]
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Remove an old step with its step key.
 | 
			
		||||
	 * @param oldStepKey The step key to remove.
 | 
			
		||||
	 */
 | 
			
		||||
	removeStep(oldStepKey: StepKeyType): void
 | 
			
		||||
	{
 | 
			
		||||
		this.setState({
 | 
			
		||||
			// Remove the given step key from the steps array.
 | 
			
		||||
			steps: this.state.steps.filter(({key: currentStepKey}) => currentStepKey != oldStepKey)
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Set the current step from its key.
 | 
			
		||||
	 * @param stepKey The step key to set as the current one.
 | 
			
		||||
	 */
 | 
			
		||||
	setCurrentStep(stepKey: StepKeyType): void
 | 
			
		||||
	{
 | 
			
		||||
		// Get the new step index.
 | 
			
		||||
		const stepIndex = this.state.steps.findIndex(({key: currentStep}) => currentStep == stepKey);
 | 
			
		||||
 | 
			
		||||
		if (stepIndex >= 0)
 | 
			
		||||
		{ // If the new step index has been found, setting it as the current one.
 | 
			
		||||
			this.setState({
 | 
			
		||||
				currentStepIndex: stepIndex,
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Get the next step key.
 | 
			
		||||
	 */
 | 
			
		||||
	getNextStep(): StepKeyType
 | 
			
		||||
	{
 | 
			
		||||
		return this.state.steps[this.state.currentStepIndex + 1]?.key ?? this.state.steps[0]?.key;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Get the previous step key.
 | 
			
		||||
	 */
 | 
			
		||||
	getPreviousStep(): StepKeyType
 | 
			
		||||
	{
 | 
			
		||||
		return this.state.steps[this.state.currentStepIndex - 1]?.key ?? this.state.steps[this.state.steps.length - 1]?.key;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The steps global state.
 | 
			
		||||
 */
 | 
			
		||||
export const stepsGlobalState = new GlobalState<StepsGlobalStateType, StepsGlobalStateReducers>({
 | 
			
		||||
	steps: [],
 | 
			
		||||
	currentStepIndex: 0,
 | 
			
		||||
}, new StepsGlobalStateReducers);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Hook of the current step key in a steps component.
 | 
			
		||||
 */
 | 
			
		||||
export function useCurrentStepKey(): StepKeyType
 | 
			
		||||
{
 | 
			
		||||
	// Get the current steps global state value.
 | 
			
		||||
	const stepsState = useGlobalStateValue(stepsGlobalState);
 | 
			
		||||
 | 
			
		||||
	// Get the current step from the global state value.
 | 
			
		||||
	return stepsState.steps.length > 0
 | 
			
		||||
		? ( // If there are steps, getting the current one.
 | 
			
		||||
			stepsState.currentStepIndex < stepsState.steps.length
 | 
			
		||||
				? ( // If the index is correctly defined, trying to get the corresponding state key
 | 
			
		||||
					stepsState.currentStepIndex >= 0 ? (stepsState.steps[stepsState.currentStepIndex]?.key) : stepsState.steps[0]?.key
 | 
			
		||||
				)
 | 
			
		||||
				// The current index is too high, taking the last step as the current one.
 | 
			
		||||
				: stepsState.steps[stepsState.steps.length - 1]?.key
 | 
			
		||||
		)
 | 
			
		||||
		// There are no steps, returning none.
 | 
			
		||||
		: undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Steps navigator
 | 
			
		||||
 */
 | 
			
		||||
export interface StepsNavigator
 | 
			
		||||
{
 | 
			
		||||
	/**
 | 
			
		||||
	 * Go to the next step.
 | 
			
		||||
	 */
 | 
			
		||||
	next(): void;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return to the previous step.
 | 
			
		||||
	 */
 | 
			
		||||
	previous(): void;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Go to the given step.
 | 
			
		||||
	 * @param stepKey The step key to join.
 | 
			
		||||
	 */
 | 
			
		||||
	set(stepKey: StepKeyType): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Hook of the steps' navigator.
 | 
			
		||||
 */
 | 
			
		||||
export function useStepsNavigator(): StepsNavigator
 | 
			
		||||
{
 | 
			
		||||
	// Get the steps reducers instance.
 | 
			
		||||
	const stepsReducers = useGlobalStateReducers(stepsGlobalState);
 | 
			
		||||
 | 
			
		||||
	// Create the steps navigator object.
 | 
			
		||||
	return useMemo(() => ({
 | 
			
		||||
		next()
 | 
			
		||||
		{
 | 
			
		||||
			stepsReducers.setCurrentStep(stepsReducers.getNextStep());
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		previous()
 | 
			
		||||
		{
 | 
			
		||||
			stepsReducers.setCurrentStep(stepsReducers.getPreviousStep());
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		set(stepKey: StepKeyType)
 | 
			
		||||
		{
 | 
			
		||||
			stepsReducers.setCurrentStep(stepKey);
 | 
			
		||||
		},
 | 
			
		||||
	}), [stepsReducers]);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -11,4 +11,5 @@
 | 
			
		|||
@import "components/_menus";
 | 
			
		||||
@import "components/_select";
 | 
			
		||||
@import "components/_steps";
 | 
			
		||||
@import "components/_steps-counter";
 | 
			
		||||
@import "components/_table";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								src/styles/components/_steps-counter.less
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/styles/components/_steps-counter.less
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
.steps-counter
 | 
			
		||||
{
 | 
			
		||||
	counter-reset: steps-count 0;
 | 
			
		||||
 | 
			
		||||
	.step
 | 
			
		||||
	{
 | 
			
		||||
		&::before
 | 
			
		||||
		{
 | 
			
		||||
			content: counter(steps-count);
 | 
			
		||||
 | 
			
		||||
			display: inline-block;
 | 
			
		||||
			margin: 0 0.2em;
 | 
			
		||||
 | 
			
		||||
			color: var(--primary);
 | 
			
		||||
 | 
			
		||||
			font-family: @monospace-fonts;
 | 
			
		||||
			font-size: 1.5em;
 | 
			
		||||
			font-weight: 700;
 | 
			
		||||
			vertical-align: baseline;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		counter-increment: steps-count;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,24 +1,90 @@
 | 
			
		|||
.steps
 | 
			
		||||
div.steps
 | 
			
		||||
{
 | 
			
		||||
	counter-reset: steps-count 0;
 | 
			
		||||
	display: flex;
 | 
			
		||||
	flex-direction: row;
 | 
			
		||||
 | 
			
		||||
	.step
 | 
			
		||||
	> nav.steps
 | 
			
		||||
	{
 | 
			
		||||
		&::before
 | 
			
		||||
		position: sticky;
 | 
			
		||||
		top: 1em;
 | 
			
		||||
		bottom: 1em;
 | 
			
		||||
 | 
			
		||||
		display: flex;
 | 
			
		||||
		flex-direction: column;
 | 
			
		||||
		align-items: center;
 | 
			
		||||
		justify-content: center;
 | 
			
		||||
 | 
			
		||||
		margin: auto 0.5em;
 | 
			
		||||
 | 
			
		||||
		> ul
 | 
			
		||||
		{
 | 
			
		||||
			content: counter(steps-count);
 | 
			
		||||
			margin: 0;
 | 
			
		||||
			padding: 0;
 | 
			
		||||
			list-style: none;
 | 
			
		||||
 | 
			
		||||
			display: inline-block;
 | 
			
		||||
			margin: 0 0.2em;
 | 
			
		||||
			> li
 | 
			
		||||
			{
 | 
			
		||||
				margin: auto;
 | 
			
		||||
				padding: 0;
 | 
			
		||||
				text-align: center;
 | 
			
		||||
 | 
			
		||||
			color: var(--primary);
 | 
			
		||||
				> button
 | 
			
		||||
				{
 | 
			
		||||
					padding: 0;
 | 
			
		||||
 | 
			
		||||
			font-family: @monospace-fonts;
 | 
			
		||||
			font-size: 1.5em;
 | 
			
		||||
			font-weight: 700;
 | 
			
		||||
			vertical-align: baseline;
 | 
			
		||||
					box-shadow: 0 0 0 0 transparent;
 | 
			
		||||
					outline: none;
 | 
			
		||||
					border: none;
 | 
			
		||||
					background: none;
 | 
			
		||||
					color: var(--foreground-lightest);
 | 
			
		||||
 | 
			
		||||
					&:focus::before
 | 
			
		||||
					{
 | 
			
		||||
						outline-color: var(--primary);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					&::before
 | 
			
		||||
					{
 | 
			
		||||
						transition: all 0.2s ease;
 | 
			
		||||
 | 
			
		||||
						content: "";
 | 
			
		||||
 | 
			
		||||
						display: block;
 | 
			
		||||
						margin: auto auto 0.4em auto;
 | 
			
		||||
						width: 2em;
 | 
			
		||||
						height: 2em;
 | 
			
		||||
						border-radius: 2em;
 | 
			
		||||
 | 
			
		||||
						box-shadow: 0 0 0 0 transparent;
 | 
			
		||||
						outline: solid 2px transparent;
 | 
			
		||||
						outline-offset: 2px;
 | 
			
		||||
						border: solid var(--background-darkest) thin;
 | 
			
		||||
						background: var(--background-lightest);
 | 
			
		||||
 | 
			
		||||
						transform: scale(0.75);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				&.active
 | 
			
		||||
				{
 | 
			
		||||
					> button
 | 
			
		||||
					{
 | 
			
		||||
						&::before
 | 
			
		||||
						{
 | 
			
		||||
							box-shadow: 0 0 0.3em 0 var(--foreground-shadow);
 | 
			
		||||
							border-color: var(--primary-darker);
 | 
			
		||||
							background: var(--primary);
 | 
			
		||||
 | 
			
		||||
							transform: scale(1);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		counter-increment: steps-count;
 | 
			
		||||
	> :not(nav)
 | 
			
		||||
	{
 | 
			
		||||
		flex: 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue