+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut nisi eget dolor semper
+ luctus vitae a nulla. Cras semper eros sed lacinia tincidunt. Mauris dignissim ullamcorper dolor,
+ ut blandit dui ullamcorper faucibus. Interdum et malesuada fames ac ante ipsum.
+
+
+
+
+
+ Get Started
+
+
+
+
Get Started
+ Maecenas sed justo ac sapien venenatis ullamcorper. Sed maximus nunc non venenatis euismod.
+ Fusce vel porta ex, imperdiet molestie nisl. Vestibulum eu ultricies mauris, eget aliquam quam.
+
+
+
+
+
+ Set budget
+
+
+
+
Set budget
+ Phasellus quis augue convallis, congue velit ac, aliquam ex. In egestas porttitor massa
+ aliquet porttitor. Donec bibendum faucibus urna vitae elementum. Phasellus vitae efficitur
+ turpis, eget molestie ipsum.
+
+
+
+
+
+ Summary
+
+
+
+
Summary
+ Ut iaculis sed magna efficitur tempor. Vestibulum est erat, imperdiet in diam ac,
+ aliquam tempus sapien. Nam rutrum mi at enim mattis, non mollis diam molestie.
+ Cras sodales dui libero, sit amet cursus sapien elementum ac. Nulla euismod nisi sem.
+
+
+
+
+
+ @{
+ var index = context;
+ var lastStepIndex = 3;
+
+
+ @if (index > 0)
+ {
+ Go to first page
+ Previous
+ }
+
+
+
+ @if (index != lastStepIndex)
+ {
+ Next
+ Go to last page
+ }
+ else
+ {
+ Finish
+ }
+
+ }
+
+
+
+@code
+{
+ FluentWizard MyWizard = default!;
+ int Value = 0;
+
+ void OnStepChange(FluentWizardStepChangeEventArgs e)
+ {
+ }
+
+ async Task OnFinish()
+ {
+ await Task.CompletedTask;
+ }
+}
diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardDefault.razor b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardDefault.razor
new file mode 100644
index 0000000000..0c2ceceb99
--- /dev/null
+++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardDefault.razor
@@ -0,0 +1,56 @@
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut nisi eget dolor semper
+ luctus vitae a nulla. Cras semper eros sed lacinia tincidunt. Mauris dignissim ullamcorper dolor,
+ ut blandit dui ullamcorper faucibus. Interdum et malesuada fames ac ante ipsum.
+
+
+ Maecenas sed justo ac sapien venenatis ullamcorper. Sed maximus nunc non venenatis euismod.
+ Fusce vel porta ex, imperdiet molestie nisl. Vestibulum eu ultricies mauris, eget aliquam quam.
+
+
+ Nunc dignissim tortor eget lacus porta tristique. Nunc in posuere dui. Cras ligula ex,
+ ullamcorper in gravida in, euismod vitae purus. Lorem ipsum dolor sit amet, consectetur
+ adipiscing elit. Aliquam at velit leo. Suspendisse potenti. Cras dictum eu augue in laoreet.
+
+
+ Phasellus quis augue convallis, congue velit ac, aliquam ex. In egestas porttitor massa
+ aliquet porttitor. Donec bibendum faucibus urna vitae elementum. Phasellus vitae efficitur
+ turpis, eget molestie ipsum.
+
+
+ Ut iaculis sed magna efficitur tempor. Vestibulum est erat, imperdiet in diam ac,
+ aliquam tempus sapien. Nam rutrum mi at enim mattis, non mollis diam molestie.
+ Cras sodales dui libero, sit amet cursus sapien elementum ac. Nulla euismod nisi sem.
+
+
+
+
+@code
+{
+ void OnStepChange(FluentWizardStepChangeEventArgs e)
+ {
+ Console.WriteLine("Step changed to {0}", e.TargetIndex);
+ }
+
+ void OnFinished()
+ {
+ Console.WriteLine("Wizard has been finished");
+ }
+}
diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardEditForms.razor b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardEditForms.razor
new file mode 100644
index 0000000000..e5cd3cedc7
--- /dev/null
+++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardEditForms.razor
@@ -0,0 +1,140 @@
+@using System.ComponentModel.DataAnnotations
+
+@inject IDialogService DialogService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Phasellus quis augue convallis, congue velit ac, aliquam ex. In egestas porttitor massa
+ aliquet porttitor. Donec bibendum faucibus urna vitae elementum. Phasellus vitae efficitur
+ turpis, eget molestie ipsum.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@if (_overlayIsVisible)
+{
+
+
+
+}
+
+@code
+{
+ private FormData1 _formData1 = new FormData1();
+ private FormData2 _formData2 = new FormData2();
+ private FinishFormData _finishFormData = new FinishFormData();
+ private bool _overlayIsVisible = false;
+
+ void OnStepChange(FluentWizardStepChangeEventArgs e)
+ {
+ }
+
+ async Task OnFinishedAsync()
+ {
+ await DialogService.ShowInfoAsync("Wizard completed");
+ }
+
+ async Task OnValidSubmit()
+ {
+ _overlayIsVisible = true;
+ await Task.Delay(2000);
+ _overlayIsVisible = false;
+ }
+
+ void OnInvalidSubmit()
+ {
+ }
+
+ private class FormData1
+ {
+ [Required]
+ [MaxLength(3)]
+ public string? FirstName { get; set; }
+
+ [Required]
+ [MinLength(10)]
+ public string? LastName { get; set; }
+ }
+
+ private class FormData2
+ {
+ [Required]
+ public string? AddressLine1 { get; set; }
+
+ public string? AddressLine2 { get; set; }
+
+ [Required]
+ public string? City { get; set; }
+
+ [Required]
+ public string? StateOrProvince { get; set; }
+
+ [Required]
+ public string? Country { get; set; }
+
+ [Required]
+ public string? PostalCode { get; set; }
+ }
+
+ private class FinishFormData
+ {
+ [Required]
+ [MinLength(5)]
+ public string? Signature { get; set; }
+ }
+}
diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardPosition.razor b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardPosition.razor
new file mode 100644
index 0000000000..90de4bd2f3
--- /dev/null
+++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/Examples/WizardPosition.razor
@@ -0,0 +1,57 @@
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut nisi eget dolor semper
+ luctus vitae a nulla. Cras semper eros sed lacinia tincidunt. Mauris dignissim ullamcorper dolor,
+ ut blandit dui ullamcorper faucibus. Interdum et malesuada fames ac ante ipsum.
+
+
+ Maecenas sed justo ac sapien venenatis ullamcorper. Sed maximus nunc non venenatis euismod.
+ Fusce vel porta ex, imperdiet molestie nisl. Vestibulum eu ultricies mauris, eget aliquam quam.
+
+
+ Nunc dignissim tortor eget lacus porta tristique. Nunc in posuere dui. Cras ligula ex,
+ ullamcorper in gravida in, euismod vitae purus. Lorem ipsum dolor sit amet, consectetur
+ adipiscing elit. Aliquam at velit leo. Suspendisse potenti. Cras dictum eu augue in laoreet.
+
+
+ Phasellus quis augue convallis, congue velit ac, aliquam ex. In egestas porttitor massa
+ aliquet porttitor. Donec bibendum faucibus urna vitae elementum. Phasellus vitae efficitur
+ turpis, eget molestie ipsum.
+
+
+ Ut iaculis sed magna efficitur tempor. Vestibulum est erat, imperdiet in diam ac,
+ aliquam tempus sapien. Nam rutrum mi at enim mattis, non mollis diam molestie.
+ Cras sodales dui libero, sit amet cursus sapien elementum ac. Nulla euismod nisi sem.
+
+
+
+
+@code
+{
+ void OnStepChange(FluentWizardStepChangeEventArgs e)
+ {
+ Console.WriteLine("Step changed to {0}", e.TargetIndex);
+ }
+
+ void OnFinished()
+ {
+ Console.WriteLine("Wizard has been finished");
+ }
+}
diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/FluentWizard.md b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/FluentWizard.md
new file mode 100644
index 0000000000..725beddba9
--- /dev/null
+++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Wizard/FluentWizard.md
@@ -0,0 +1,67 @@
+---
+title: Wizard
+route: /Wizard
+icon: Steps
+---
+
+# Wizard
+
+**Wizards** are a step-by-step user interface used to break down complex tasks into digestible pieces.
+The simplified layout allows the reader to more easily understand the scope of a given task and the actions
+needed to complete the task.
+
+By default, steps are displayed on the left, but you can move them to the top of the component.
+They are in the form of circular bubbles, with a check mark indicating whether it has been processed or not.
+They are not numbered, but the **DisplayStepNumber** property can be used to add this numbering.
+It's also possible to customize these bubbles via the **IconPrevious**, **IconCurrent**
+and **IconNext** properties.
+
+The order of the steps must be defined when designing the Wizard.
+However, it is possible to enable or disable a step via the **Disabled** property.
+
+By default, the contents of all steps are hidden and displayed when the user arrives at that
+that step (for display performance reasons). But the **DeferredLoading** property
+property reverses this process and generates the contents of the active step only.
+
+The **Label** and **Summary** properties display the name and a small summary of the step below or next to the bubble.
+The **StepTitleHiddenWhen** property is used to hide this title and summary when the screen width
+is reduced, for example on mobile devices. By default, the value `XsAndDown` is applied
+to hide this data on cell phones (< 600px).
+
+All these areas (bubbles on the left/top and navigation buttons at the bottom) are fully customizable
+using the **StepTemplate** and **ButtonTemplate** properties (see the second example).
+You can customize button labels using the **ButtonTemplate** or by modifying
+the static properties **FluentWizard.LabelButtonPrevious / LabelButtonNext / LabelButtonDone**.
+
+> **note**: this FluentWizard is not yet fully compatible with accessibility.
+
+{{ WizardDefault }}
+
+## Positioning
+
+You can choose to display the steps on the left (default) or on the top of the component using the **StepperPosition** parameter.
+
+{{ WizardPosition }}
+
+## Customized
+
+You can customize the wizard with a **ButtonTemplate** to replace the default Previous/Next/Done buttons,
+and **StepTemplate** to fully control how each step indicator is rendered.
+
+{{ WizardCustomized }}
+
+## EditForms
+
+The wizard supports **EditForm** validation. When a step contains an `EditForm`, the wizard will
+automatically validate the form before navigating to the next step. If validation fails,
+the step change is cancelled.
+
+{{ WizardEditForms }}
+
+## API FluentWizard
+
+{{ API Type=FluentWizard }}
+
+## API FluentWizardStep
+
+{{ API Type=FluentWizardStep }}
diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/GetStarted/Migration/MigrationFluentWizard.md b/examples/Demo/FluentUI.Demo.Client/Documentation/GetStarted/Migration/MigrationFluentWizard.md
index 9469dc5470..5019745d07 100644
--- a/examples/Demo/FluentUI.Demo.Client/Documentation/GetStarted/Migration/MigrationFluentWizard.md
+++ b/examples/Demo/FluentUI.Demo.Client/Documentation/GetStarted/Migration/MigrationFluentWizard.md
@@ -4,80 +4,32 @@ route: /Migration/Wizard
hidden: true
---
-- ### Component removed 💥
+- ### Component re-introduced
- `FluentWizard` and `FluentWizardStep` have been **removed** in V5.
- There is no direct replacement component.
+ `FluentWizard` and `FluentWizardStep` have been **re-introduced** in V5.
+ The component preserves the same API and functionality from V4 with the following changes.
-- ### V4 FluentWizard parameters (removed)
+- ### Breaking changes 💥
- | Parameter | Type | Default |
- |-----------|------|---------|
- | `Height` | `string` | `"400px"` |
- | `Width` | `string` | `"100%"` |
- | `OnFinish` | `EventCallback` | — |
- | `StepperPosition` | `StepperPosition` | `Left` |
- | `StepperSize` | `string?` | — |
- | `StepperBulletSpace` | `string?` | — |
- | `Border` | `WizardBorder` | `None` |
- | `DisplayStepNumber` | `WizardStepStatus` | `None` |
- | `Value` / `ValueChanged` | `int` / `EventCallback` | `0` |
- | `ButtonTemplate` | `RenderFragment?` | — |
- | `Steps` | `RenderFragment?` | — |
- | `StepTitleHiddenWhen` | `GridItemHidden?` | `XsAndDown` |
- | `StepSequence` | `WizardStepSequence` | `Linear` |
+ | V4 | V5 |
+ |----|-----|
+ | `Appearance.Neutral` (in ButtonTemplate) | `ButtonAppearance.Default` |
+ | `Appearance.Accent` (in ButtonTemplate) | `ButtonAppearance.Primary` |
+ | `FluentLabel Typo="Typography.Body"` | `FluentLabel` (no `Typo` parameter; use `Size` / `Weight`) |
+ | `FluentLabel Typo="Typography.Header"` | `FluentLabel Weight="LabelWeight.Bold"` |
+ | `Icons.*.Size24.*` (icon defaults) | `CoreIcons.*.Size20.*` |
+ | `FluentTextField` | `FluentTextInput` |
+ | `FluentEditForm` | `EditForm` (standard Blazor) |
-- ### V4 FluentWizardStep parameters (removed)
+- ### Icon defaults changed
- | Parameter | Type | Default |
- |-----------|------|---------|
- | `Label` | `string` | `""` |
- | `Summary` | `string` | `""` |
- | `Disabled` | `bool` | `false` |
- | `DeferredLoading` | `bool` | `false` |
- | `OnChange` | `EventCallback` | — |
- | `IconPrevious` / `IconCurrent` / `IconNext` | `Icon` | — |
- | `StepTemplate` | `RenderFragment?` | — |
+ The default icons for wizard steps now use **Size20** instead of Size24:
+ - `IconPrevious` = `CoreIcons.Filled.Size20.CheckmarkCircle()`
+ - `IconCurrent` = `CoreIcons.Filled.Size20.Circle()`
+ - `IconNext` = `CoreIcons.Regular.Size20.Circle()`
-- ### Removed enums
+- ### Re-introduced enums
- `WizardBorder`
- `WizardStepSequence`
- `WizardStepStatus`
- `StepperPosition`
-
-- ### Migration strategy
-
- Build a custom wizard using `FluentTabs` for step navigation,
- or implement step-based logic with conditional rendering:
-
- ```xml
-
-
-
-
- @for (int i = 0; i < steps.Length; i++)
- {
-
- @(i + 1). @steps[i]
-
- }
-
-
-
- @switch (currentStep)
- {
- case 0: break;
- case 1: break;
- case 2: break;
- }
-
-
-
- Previous
-
- @(currentStep == steps.Length - 1 ? "Finish" : "Next")
-
-
-
- ```
diff --git a/src/Core/Components/Icons/CoreIcons.cs b/src/Core/Components/Icons/CoreIcons.cs
index 0f97af663c..bb0b42a1ee 100644
--- a/src/Core/Components/Icons/CoreIcons.cs
+++ b/src/Core/Components/Icons/CoreIcons.cs
@@ -95,6 +95,8 @@ public class PresenceTentative : Icon { public PresenceTentative() : base("Prese
public class PresenceUnknown : Icon { public PresenceUnknown() : base("PresenceUnknown", IconVariant.Regular, IconSize.Size20, "") { } }
+ public class Circle : Icon { public Circle() : base("Circle", IconVariant.Regular, IconSize.Size20, "") { } }
+
public class RadioButton : Icon { public RadioButton() : base("RadioButton", IconVariant.Regular, IconSize.Size20, "") { } };
public class Search : Icon { public Search() : base("Search", IconVariant.Regular, IconSize.Size20, "") { } }
@@ -133,6 +135,8 @@ public class PresenceBusy : Icon { public PresenceBusy() : base("PresenceBusy",
public class PresenceDnd : Icon { public PresenceDnd() : base("PresenceDnd", IconVariant.Filled, IconSize.Size20, "") { } }
+ public class Circle : Icon { public Circle() : base("Circle", IconVariant.Filled, IconSize.Size20, "") { } }
+
public class RadioButton : Icon { public RadioButton() : base("RadioButton", IconVariant.Regular, IconSize.Size20, "") { } };
public class Star : Icon { public Star() : base("Star", IconVariant.Filled, IconSize.Size20, "") { } };
diff --git a/src/Core/Components/Wizard/FluentWizard.razor b/src/Core/Components/Wizard/FluentWizard.razor
new file mode 100644
index 0000000000..e591d09f28
--- /dev/null
+++ b/src/Core/Components/Wizard/FluentWizard.razor
@@ -0,0 +1,64 @@
+@namespace Microsoft.FluentUI.AspNetCore.Components
+@inherits FluentComponentBase
+
+
+
+
+
+ @Steps
+
+
+
+ @foreach (var step in _steps.Where(i => i.Index == Value || !i.DeferredLoading))
+ {
+