github varabyte/kobweb v0.20.5

latest releases: v0.24.0, v0.23.3, v0.23.2...
13 months ago

Warning

We discovered some subtle issues in the color mode work we did after this release went out. You should skip this release and upgrade to v0.20.6 instead, as it is this same release plus fixes.

While a lot of significant work went into this release, the biggest feature we expect most people to care about is an under-the-hood color mode refactoring that lays the groundwork for fixing the export color flash issue. You can actually take manual steps today to fix this in your own site after updating to 0.20.5 (more information about this in the Notes section below).

Important

Planning to upgrade? Review instructions in the README.

Changes

Silk

  • 🚨 Laid the groundwork to eliminate the color flash issue that has plagued exported sites since forever.
    • See the notes for more details.
    • ⚠️ This is a major change. Please let us know if you notice anything weird with colors after this release.

Frontend

  • Modifier for scrollbar-width
  • Support for the color-mix function
    • Extend *-gradient (e.g. linear-gradeint) color functions with color interpolation modes
  • Add support for repeating-*-gradient (e.g. repeating-linear-gradient) methods
  • You can now specify a set of default headers that should get sent with every request (through window.fetch, window.http.*, and window.api.* methods)
    • This can be useful if you want to include some sort of site API key with every message, for example.
    • Set FetchDefaults.Headers to accomplish this.
  • Supporting inferred dynamic route names.
    • In a file called ProductDetails.kt, these two cases now do the same thing:
      • Before: @Page("{...product-details}")
      • After: @Page("{...}")
  • Allow indicating that a dynamic route is optional
    • In a file called Posts.kt...
      • Before: @Page("/posts/{post-id}")
        • Visiting /posts/123 works; post-id when queries will return "123"
        • Visiting /posts/ will result in a 404
      • After: @Page("/posts/{post-id?}")
        • Visiting /posts/123 works; post-id when queries will return "123"
        • Visiting /posts/ works; post-id when queried will be the empty string
  • Navigating between different values of the same dynamic route now causes a recomposition
    • e.g. navigating from /posts/123 to /posts/987
    • A recomposition here is a good thing -- it means any logic inside a LaunchedEffect or DisposableEffect will rerun for each page.
  • You can now add a PageContext parameter declaration to a @Page instead of calling rememberPageContext()
    • e.g. @Page fun ExamplePage(ctx: PageContext) { ... }
  • Fixed a bug where the self hosting feature didn't work when a site's basePath was set.

Backend

  • Before, if you tried to create multiple API streams on a single client connected to the same API stream endpoint, they would interfere with each other. This has been fixed.
    • In practice, it was unlikely a single client would ever create more than one stream per endpoint. But it's still nice to know the API will now work as expected!

Markdown

Documentation


Notes

Fixing the color flash!

One of the longest standing issues with Kobweb sites has been the dreaded color flash.

This is when you have a site that, at export time, snapshots a site in, say, light mode, but then a user visits it with an opposite preference (so, here, dark mode). The page renders in light mode briefly (the exported snapshot) before swapping to dark mode (the user's preference) after the page finishes loading and runs the page script. This often happens in about half a second or less, leading the user to see a color flash.

In this release, we have revisited how color modes work, taking advantage of a CSS feature called @scope blocks. Without going into detail, this allows us to include a script in the <head> tag which can run instantly, intercepting and fixing the color mode with what the user wants to see instead of what was exported.

In future releases of Kobweb, we plan to introduce helper methods for this, but if you'd like to opt-into this behavior now, you can add the code yourself. The most import thing is to add logic which mimics the code that sets the initialColorMode value.

A fairly common choice for setting the initial color mode is to read a value from local storage if it is present or, if not, use the user's system preference. That might look like this:

val COLOR_MODE_KEY = ColorMode.entries.createStorageKey("yourapp:colorMode")

@InitSilk
fun initSilk(ctx: InitSilkContext) {
    ctx.config.apply {
        initialColorMode = localStorage.getItem(COLOR_MODE_KEY) ?: ColorMode.systemPreference
   }
}

So, right below that, let's add code that gets inserted as a script onto your page at export time:

initialColorMode = localStorage.getItem(COLOR_MODE_KEY) ?: ColorMode.systemPreference
// Script must be kept in sync with `initialColorMode` above.
if (AppGlobals.isExporting) {
   document.head!!.appendChild(
      document.createElement("script").apply {
         textContent = """
            {
               const storedColor = localStorage.getItem('${COLOR_MODE_KEY.name}'); // 'LIGHT', 'DARK', or null
               const desiredColor = storedColor
                  ? `silk-${'$'}{storedColor.toLowerCase()}`
                  : (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'silk-dark' : 'silk-light');
               const oppositeColor = desiredColor === 'silk-dark' ? 'silk-light' : 'silk-dark';
               document.documentElement.classList.replace(oppositeColor, desiredColor);
            }
         """.trimIndent()
      }
   )
}

At this point, export your site and run the production version. If you check your DOM's head elements, you should find your script added there. Congratulations! You've eliminated the color flash for a significant number of your users!

Important

Firefox does not currently support the scope block feature, although work on it is planned. For Firefox (and any other browser that don't support scope blocks), Kobweb falls back to a legacy color mode so your site will still work there. However, users of those browsers will still see a color flash for now.


Thanks

  • @jakubmeysner for setting up our pipeline to publish API reference docs
  • @DennisTsar for his work on the color mode refactoring. Implementing it required insight and experimentation, and getting it to work in a way that supports legacy browsers and modern browsers at the same time required a clever approach.

Full Changelog: v0.20.4...v0.20.5

Don't miss a new kobweb release

NewReleases is sending notifications on new releases.