---
title: "Firelight"
description: "Firelight's core package: define Lit web components in F# with reactive properties, scoped styles and html templates."
---

# Firelight

The core package: F# bindings for Lit. Define web components with reactive properties, scoped styles and `html` templates.

- [Lit docs: Components](https://lit.dev/docs/components/overview/)
- [NuGet 0.3.0](https://www.nuget.org/packages/Firelight/0.3.0)
- [Source](https://github.com/roboz0r/Firelight/tree/main/src/Firelight)

## Why use it

Web components are the browser's own component model. A custom element works in any page,
alongside any framework or none. Lit takes away the boilerplate: you declare properties and
return a template, and Lit updates only the parts of the page that changed.

Firelight lets you write those components in F#. Templates are F# interpolated strings, so the
values and event handlers in them are ordinary typed F# code. The bindings themselves compile
away: your component imports Lit directly, and there is no Firelight runtime to ship.

## Example

A star rating. `value` is a reactive property that also reads and writes the
`value` attribute, the styles are scoped to the component, and choosing a star raises
a `rating-changed` event. The message below comes from plain JavaScript on this page
listening for that event.

```fsharp
module Snippets.Rating

open Fable.Core
open Fable.Core.JsInterop
open Browser.Types
open Firelight
open type Firelight.Lit

// Each star is a button named "n out of 5"; the one matching the rating is pressed.
let private star (n: int) (value: int) (select: unit -> unit) =
    html
        $"""<button class={if n <= value then "on" else ""} aria-label="{n} out of 5"
                aria-pressed={n = value} @click={fun _ -> select ()}>{if n <= value then "★" else "☆"}</button>"""

/// <my-rating value="3"></my-rating>
/// Clicking a star sets `value` and raises a "rating-changed" event for the page to handle.
[<AttachMembers>]
type Rating() =
    inherit LitElement()

    static member properties =
        PropertyDeclarations.create [
            "value", PropertyDeclaration<int>(reflect = true)
        ]

    static member styles =
        css
            $$"""
        button { all: unset; cursor: pointer; font-size: 2rem; color: var(--muted); border-radius: 0.25rem; }
        button.on { color: var(--accent); }
        button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
        """

    member val value = 0 with get, set

    member this.Select(stars: int) =
        this.value <- stars
        this.dispatch (Event.customEvent ("rating-changed", stars))

    override this.render() =
        html $"""{[ for n in 1..5 -> star n this.value (fun () -> this.Select n) ]}"""

defineElement<Rating> "my-rating"
```

```html
<my-rating value="3"></my-rating>
<p id="rating-message">Pick a rating.</p>
```



## Install

```sh
dotnet add package Firelight
npm install lit
```

New to Firelight? The [Get started](https://roboz0r.github.io/Firelight/start/) tutorial creates an app from a template, then gives its component an attribute, an event, styles and a list.
