United Kingdom: +44 (0)208 088 8978

The FluentUI design system

Isaac takes us on a quick spin of the Fluent UI F# wrapper for SAFE Stack apps.

We're hiring Software Developers

Click here to find out more

FluentUI is a design system by Microsoft. It comes with a set of UI components and layout features, built on top of React - not dissimilar from other UI toolkits such as Bootstrap or Ant Design.

Fluent UI now also has a fairly complete typesafe F# wrapper around it in the FS.FluentUI package. It's quick and easy to upgrade an existing SAFE Stack application to use it:

  1. Install the Femto tool if not already installed: dotnet tool install femto.
  2. Install FS.FluentUI using Femto from the ./src/client folder: dotnet femto install FS.FluentUI (this will also install the required NPM packages).
  3. Wrap your top-level element with the FluentProvider:
let view model dispatch =
    Fui.fluentProvider [
        fluentProvider.theme.webLightTheme
        fluentProvider.children [
            // your top-level React elements go here...
        ]
    ]

FluentUI has a wide variety of components that you can use, and it's possible to integrate them within other non-FluentUI components e.g. raw Tailwind elements etc. The following code shows the basic SAFE Stack Todo application with the input and button rewritten using FluentUI. Notice the use of a div with tailwind styles surrounding the Fluent UI input and button React elements.

let todoAction model dispatch =
    Html.div [
        prop.className "flex flex-col sm:flex-row mt-4 gap-4"
        prop.children [
            Fui.input [
                input.className "w-full"
                input.value model.Input
                input.placeholder "What needs to be done?"
                input.autoFocus true
                input.onChange (SetInput >> dispatch)
                input.onKeyPress (fun ev ->
                    if ev.key = "Enter" then
                        dispatch AddTodo)
            ]
            Fui.button [
                button.disabled (Todo.isValid model.Input |> not)
                button.onClick (fun _ -> dispatch AddTodo)
                button.text "Add"
            ]
        ]
    ]

which gives a UI as follows:

The package is being updated regularly and although like any design system will be subjective as to your preferences, it looks professional and slick with a good number of components - so is well worth checking out! We also have a sample repo here that you can download to check out yourself.