Skip to content

A fresh retake of the React API in Fable and a collection of high-quality components to build React applications in F#, optimized for happiness

License

Notifications You must be signed in to change notification settings

fable-hub/Feliz

Repository files navigation

Feliz Nuget

A fresh retake of the React API in Fable, optimized for happiness.

Here is how it looks like:

module App

open Feliz

[<ReactComponent>]
let Counter() =
    let (count, setCount) = React.useState(0)
    Html.div [
        Html.button [
            prop.style [ style.marginRight 5 ]
            prop.onClick (fun _ -> setCount(count + 1))
            prop.text "Increment"
        ]

        Html.button [
            prop.style [ style.marginLeft 5 ]
            prop.onClick (fun _ -> setCount(count - 1))
            prop.text "Decrement"
        ]

        Html.h1 count
    ]

open Browser.Dom

let root = ReactDOM.createRoot (document.getElementById "root")
root.render (Counter())

✨ Features

  • Flexible API design: Combine the reliability of F# type safety with the flexibility to interop easily with native JavaScript.
  • Discoverable attributes with no more functions, Html attributes or CSS properties globally available so they are easy to find.
  • Proper documentation: each attribute and CSS property
  • Full React API support: Feliz aims to support the React API for building components using hooks, context and more.
  • Fully Type-safe: no more Margin of obj but instead utilizing a plethora of overloaded functions to account for the overloaded nature of CSS attributes, covering 90%+ of the CSS styles, values and properties.
  • Compatible with Femto.
  • Approximately Zero bundle size increase where everything function body is erased from the generated JavaScript unless you actually use said function.

⚡Combine with Elmish "model-view-update" architecture

Feliz offers a React.useElmish hook to seamlessly integrate Elmish state machines with React components. You can use it by referencing the Feliz.UseElmish package.

You can read more on this topic in the documentation.

module App

open Fable.Core
open Feliz
open Feliz.UseElmish
open Elmish

type Msg =
    | Increment
    | Decrement

type State = { Count : int }

let init() = { Count = 0 }, Cmd.none

let update msg state =
    match msg with
    | Increment -> { state with Count = state.Count + 1 }, Cmd.none
    | Decrement -> { state with Count = state.Count - 1 }, Cmd.none

[<Erase; Mangle(false)>]
type Main =

    [<ReactComponent(true)>]
    static member Main() =
    
        let state, dispatch = React.useElmish(init, update, [| |])
        Html.div [
            Html.h1 state.Count
            Html.button [
                prop.text "Increment"
                prop.onClick (fun _ -> dispatch Increment)
            ]

            Html.button [
                prop.text "Decrement"
                prop.onClick (fun _ -> dispatch Decrement)
            ]
        ]

🚀 Quick Start

# install the template (if you haven't already)
dotnet new -i Feliz.Template
# create a new Feliz project from the installed template
dotnet new feliz -n MyProject
# navigate to the created project folder
cd MyProject
# install the npm dependencies
npm install
# install .NET tools
dotnet tool restore
# start the development server
npm start

📚 Documentation

Explore the full docs at https://fable-hub.github.io/Feliz/ — packed with live examples and practical guidance. Highlights:

If anything’s unclear or you’re missing an example, please open an issue or discussion — contributions are very welcome!

⌚ Changelog

Each project in Feliz has its own changelog file in the src folder. Check them out for the latest changes!

Here is a direct link to the Feliz changelog.