Skip to content

Releases: varabyte/kobweb

v0.18.2

26 Jun 17:42
Compare
Choose a tag to compare

This is a minor release mostly to fix an accidental API ambiguity error we introduced for some users in v0.18.1. We also picked up a few misc. additions along the way.

If v0.18.1 is working fine for you, there is no urgency to upgrade.

Important

Planning to upgrade? Review instructions in the README.

Changes

Frontend

  • Fixed ambiguity error for people calling Modifier.background(color) without any other parameters.
  • Fixed an exception that would get fired if you used a design breakpoint inside a ctx.stylesheet.registerStyle block.
  • Added mixBlendMode modifier

Gradle

  • Refactored our Gradle code more compatible with configuration caching.

Full Changelog: v0.18.1...v0.18.2

v0.18.1

20 Jun 17:45
Compare
Choose a tag to compare

This release is a grab bag of miscellaneous features, including the addition of the long requested spacedBy arrangement method for Row and Column layouts (which comes thanks to a contribution from the community via @rafaeltonholo!). This release also features a handful of Markdown and CSS API fixes.

Important

Planning to upgrade? Review instructions in the README.

Note

Users are asking us when K2 support is going to land, but we are currently blocked due to a pretty major incremental compilation issue. You can learn more here and here. We are keeping a close eye on it and will support K2 as soon as we can!

Changes

Frontend

  • New spacedBy arrangement support
    • See notes below for more information
  • The boxShadow modifier can now take multiple shadow values
  • Add transformBox, transformOrigin, and transformStyle modifiers
  • Add overscrollBehavior modifier.

Silk

  • Support for CSS layers

    • Read more about the feature in the README
    • Support for CSS layers was actually quietly introduced in 0.18.0 but not officially announced, since we wanted a bit of time to battle test the API first
  • You can now pass in a callback letting you configure the look and feel of TOC header links

  • Added new descendants and children utility methods for use inside CssStyle

    • For example, CssStyle { children("div", "span") { /* ... */ } } which is more expressive and easier to remember than cssRule(" > :is(div,span)")
  • Link and Anchor widgets now accept an optional updateHistoryMode parameter

    • This is useful if you want a link to replace the current page rather than visit it (in other words, if you want to change the behavior when you press the "back" button)
  • ⚠️ Renamed onTextChanged to onTextChange and onValueChanged to onValueChange for relevant Silk widgest

    • This brings our naming in line with how Jetpack Compose names its callbacks. Apologies for catching it so late.

Markdown

  • You can now nest Kobweb Call blocks, supporting Kobweb code calling Kobweb code.
  • Fixed logic issue in markdown that was preventing markdown context from being created in certain situations.
  • Fixed a case where multiline markdown text had newlines getting swallowed

Backend

  • Cleaned up logic around detecting routes that represent routes vs. files
    • For example, we no longer erroneously detect 1.0.0 in https://site.com/path/to/1.0.0 as a file with a .0 extension.

Notes

spacedBy

In HTML / CSS, the normal way to put space between elements in a row, column, or table layout is using the gap CSS style, which we have actually recommended for the last two years. However, with spacedBy, you can now use that instead:

// Using gap
Row(Modifier.columnGap(2.cssRem)) { /* ... */ }

// Using spacedBy
Row(horizontalArrangement = Arrangement.spacedBy(2.cssRem)) { /* ... */ }

The spacedBy method can also take optional alignment parameters. Read the official Jetpack Compose documentation for more information about these new APIs.

Constructing Background, Transition, and Animation CSS style properties

Over the past year, we have been building up a consistent vocabularly for how we want our CSS style classes to behave.

A very common pattern that has emerged is the CssStyleClass.of(...) helper method, which is a useful way to construct many CSS style classes that have complex parameters.

For Background, Transition, and Animation classes, however, since those classes already had (incomplete) definitions inside Compose HTML, we extended them by introducing our own CSSBackground, CSSTransition, and CSSAnimation data classes.

We have since come to the conclusion that this is pretty inconsistent and confusing, so in this release, Kobweb has introduces its own Background, Transition, and Animation classes. Constructing them is now consistent with all other CSS styles.

This may result in you getting deprecation warnings to migrate code over. Fixing it should be relatively straightforward, as in the following code:

-import com.varabyte.kobweb.compose.css.CSSTransition
+import com.varabyte.kobweb.compose.css.Transition

-CSSTransition("color", 50.ms))
+Transition.of("color", 50.ms))

Gradle

We have been hard at work getting Kobweb tasks to play nicer with the Gradle configuration cache. Our changes so far have all been implementation fixes that will be invisible to users, but we may need to deprecate / migrate some APIs in near future releases.

Thanks

This release we enjoyed first-time submissions from user @rafaeltonholo 🎉

They provided excellent PRs for the boxShadow and spacedBy changes. They also helped us identify inconsistencies in our codebase that we spent time tightening up.

Thank you Rafael for your contributions!


Full Changelog: v0.18.0...v0.18.1

v0.18.0

20 May 16:06
Compare
Choose a tag to compare

This release introduces the new CssStyle concept, which supersedes and obsoletes the previous ComponentStyle concept.

Important

Planning to upgrade? Review instructions in the README.

This release is one of the most significant changes we've made since we've started Kobweb development. These changes have been in discussion and development in the background for over eight months(!!!).

Caution

This release will likely introduce many deprecation warnings to your project. Please don't skip over the next section!

⚠️ Migrating your project

As authors of the framework, we're very excited about this release (and relieved to be finally getting it out there), but users should be prepared to hit anywhere from a handful to a bunch of warnings after upgrading. We've done everything we could to make the migration process as easy for users to do as possible, but we want to minimize surprise, which is why we're mentioning this up front.

If you are in the middle of a large change to your site, you probably want to hold off on upgrading until you can get your changes in.

After upgrading to Kobweb 0.18.0, users are encouraged to run ./gradlew kobwebMigrateToCssStyle in a clean git branch.

For most projects, the automigration task should just work; in rare cases, some projects using more advanced features may run into errors which should be easily resolvable.

Users can read the full story about Cssstyle here, including detailed migration support at the end of it.

A brief CssStyle overview

The short version is, this old pattern:

val ExampleStyle by ComponentStyle {
   /* ... */
}

has been replaced with

val ExampleStyle = CssStyle {
   /* ... */
}

"That's it?" you might be thinking. "You're so excited about a name change?"

Well, getting rid of the by keyword (a source of confusion for many new users) is already a nice win. But more importantly, we wrangled with a feature that organically grew out the constraints of its original design and fixed some of the longstanding issues with it.

Originally, ComponentStyle was meant to be a mechanism just for Silk to use internally when defining widgets, but it became the common and recommended approach for Kobweb users everywhere to create styles, even if the styles they were creating had nothing to do with any specific component. (For example, Silk even did this itself! It provides the SmoothColorStyle for smooth background color transitions; that's not really something that should be called a "component" style).

Note

In the context of Kobweb Silk, a style is Kotlin code that ultimately gets converted into / registered as a CSS stylesheet entry. Not too familiar with CSS stylesheet entries or why you should care about them? You can review the README section about them.

Moving forward, Kobweb now supports three broad categories of styles that we've identified across many users' projects: general styles, component styles, restricted styles.

General Styles

General styles are the most common type, and if you've been using ComponentStyle in your codebase, probably 95-100% of those declarations fall into this category. This case is just a block of related, open-ended, useful style values.

val HeaderTextStyle = CssStyle.base {
   Modifier.fontSize(32.px).fontWeight(FontWeight.Bold)
}

Starting in 0.18.0, you can now extend styles, which generate a new style that wraps its source style:

val TextStyle = CssStyle.base { Modifier.fontFamily("customfont") }

val HeaderTextStyle = TextStyle.extendedByBase {
   Modifier.fontSize(32.px).fontWeight(FontWeight.Bold)
}

val LoudHeaderTextStyle = HeaderTextStyle.extendedByBase {
   Modifier.color(Colors.Red).backgroundColor(Colors.Yellow)
}

With the above declared, LoudHeaderTextStyle.toModifier() would apply itself and its dependent styles, setting font family, font size, and colors all in a single invocation.

Component Styles

Component styles are the ones we originally designed -- styles with a niche purpose to back some widget and allow users to generates variants (i.e. style tweaks) on top of them.

As a bonus, starting in 0.18.0, they are now typed, so that you can no longer use a variant created by one of these styles with another style.

sealed interface ProgressKind : ComponentKind
val ProgressStyle = CssStyle<ProgressKind> { /* ... */ }
val IndeterminiteProgressVariant = ProgressStyle.addVariant { /* ... */ }

@Composable
fun Progress(
   modifier: Modifier = Modifier
   variant: CssStyleVariant<ProgressKind>? = null
) {
   val finalModifier = ProgressStyle.toModifier(variant).then(modifier)
   Box(finalModifier) { /* ... */ }
}

Restricted Styles

Restricted styles, the final category, are a way to create a class that exposes a limited set of constructor parameters, generating a style behind the scenes. We call it restricted because, unlike the other types of style declarations which are totally open-ended, these styles are constrained by the handful of constructor parameters that the class owner exposes.

class ProgressSize(size: CSSLengthNumericValue) :
   CssStyle.Restricted.Base(Modifier.size(size)) {
   companion object {
      val SM = ProgressSize(0.5.cssRem)
      val MD = ProgressSize(1.cssRem)
      val LG = ProgressSize(1.5.cssRem)
   }
}

CssStyle document

This concludes a brief overview of the new feature, but to see more details, read this document.


Thanks

I'd like to take a moment to express an incalculable amount of thanks to @DennisTsar, without whom this feature wouldn't exist. He did a ton of foundational exploration and work, but more than that, he identifyied and raised concerns about ComponentStyle in the first place.

I hope everyone working in open source is lucky enough to get to work with a core contributor of his generosity, good sense, and ability.


A final note

As library authors, we'd in general like very much not to make drastic changes like this, because we understand how disruptive it can be to our users who are just trying to get their work done.

Of course, it has been thanks to exposure from two years of some of the amazing projects that our users have created that has helped us improve our understanding of the domain. Normally, we can make incremental fixes here and there, but in this case, there was no way around ripping out the floor and installing a new one.

Still, we wanted to thank our users for their patience and understanding. We hope moving forward that people find CssStyle more convenient to use, due to its shorter name (easier to type!), improved type-safety, and extended feature set.


Full Changelog: v0.17.3...v0.18.0

v0.17.3

16 Apr 22:44
Compare
Choose a tag to compare

This small release fixes two regression with routes introduced in v0.17.2 -- one subtle dealing with trailing slashes, and another significant one that broke dynamic routes.

Important

Planning to upgrade? Review instructions in the README.

The release also adds a handful of misc. features that are coming along for the ride.

Changes

Frontend

  • Fixed regression where dynamic routes stopped capturing values correctly
    • For example, the dynamic route "/{folder}/{page}" should match "/example/route" providing params["folder"] == "example" and params["page"] == "route"
  • Fixed regression where missing slashes wouldn't get auto-appended.
    • For example, if you've registered the route "/a/b/" and the user visits "/a/b" (no trailing slash), Kobweb will automatically suffix the "/" for you at the end.
  • Added tests for route logic so that we don't break subtle route features again...
  • Added :focus-within psuedo-class
  • Updated FA icons to v6.5.2, which adds about a dozen or two new icons, including FaThreads for Meta's "Threads" logo.

Markdown

  • Added support for surfacing the optional title of an image link, e.g. ![example](/some-image.png 'This is a title')

Full Changelog: v0.17.2...v0.17.3

v0.17.2

12 Apr 20:44
Compare
Choose a tag to compare

This release adds a few features and has also migrated its dependencies to target Compose 1.6.2. (Projects using 1.6.1 should still work).

Important

Planning to upgrade? Review instructions in the README.

The biggest change is support for specifying route redirects, which you can read more about here.

server:
  redirects:
    - from: "/socials/facebook/([^/]+)"
      to: "/socials/meta/$1"

Changes

Frontend

  • Navigation logic updated to take redirects into account.
  • Users can now configure their site's lang setting, e.g. kobweb { app { index { lang.set("fr") } } } in your build script
    • If not set, defaults to "en"
    • You can use lang.set("") if you want to clear the language setting entirely.

Silk

  • Fixed an issue with the checkbox implementation that could occasionally mess up scrolling vertical layouts.
  • Modifier.backdropFilter now works on Safari targets

Backend

  • Added routing support for redirects. Visiting an old URL will now return a 301 redirect code.

Full Changelog: v0.17.1...v0.17.2

v0.17.1

15 Mar 21:31
Compare
Choose a tag to compare

This is a small release which adds a new feature to Kobweb Workers and has also migrated its dependencies to target Compose 1.6.1 and Kotlin 1.9.23.

Important

Planning to upgrade? Review instructions in the README.


Changes

Workers

  • Kobweb workers now support transferable objects
    • Transferable objects are a web solution to passing very large objects between an application and its workers
    • You can read more about them in the README
    • ⚠️ Backwards incompatible Unfortunately, this change will cause a compile error for anyone who is already using workers. The fix is easy, however. See the Notes section for more information.

Notes

The WorkerFactory interface has changed and will cause compile errors

In order to support transferable objects, the WorkerFactory interface has changed from using a lambda:

interface WorkerFactory<I, O> {
   fun createStrategy(postOutput: (O) -> Unit): WorkerStrategy<I>
}

to using a new class called OutputDispatcher:

interface WorkerFactory<I, O> {
   fun createStrategy(postOutput: OutputDispatcher<O>): WorkerStrategy<I>
}

Please update any implementations accordingly. Once the signature has been updated, your code should compile again as before.

For example, here is the diff in the empty template:

internal class EchoWorkerFactory : WorkerFactory<String, String> {
-  override fun createStrategy(postOutput: (String) -> Unit) = WorkerStrategy<String> { input ->
+  override fun createStrategy(postOutput: OutputDispatcher<String>) = WorkerStrategy<String> { input ->
      postOutput(input) // Add real worker logic here
   }
}

Deprecated code

We occasionally audit the codebase for deprecated code older than 6 months. In this case, we removed a lot. Hopefully, this won't affect you, if you already moved away from such code.

You can review this commit to see if a compile error you're getting was due to such a method


Full Changelog: v0.17.0...v0.17.1

v0.17.0

29 Feb 17:59
Compare
Choose a tag to compare

This release is identical to v0.16.3 but has migrated its dependencies to target Compose 1.6.0.

Important

Planning to upgrade? Review instructions in the README.


⚠️ ⚠️ ⚠️ If you see the androidx.collections error ⚠️ ⚠️ ⚠️

If after upgrading, you start getting this build error:

   > Could not find androidx.collection:collection:1.4.0.
     Searched in the following locations:
       - https://repo.maven.apache.org/maven2/androidx/collection/collection/1.4.0/collection-1.4.0.pom
       - https://maven.pkg.jetbrains.space/public/p/compose/dev/androidx/collection/collection/1.4.0/collection-1.4.0.pom
     Required by:
         project :site > org.jetbrains.compose.runtime:runtime:1.6.0 > org.jetbrains.compose.runtime:runtime-desktop:1.6.0 > org.jetbrains.compose.collection-internal:collection:1.6.0

make sure you have the google repository added to your list of project repositories. This requirement changed in 1.6.0!

Before

// build.gradle.kts
repositories {
     mavenCentral()
     maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
     maven("https://us-central1-maven.pkg.dev/varabyte-repos/public")
}

After

// build.gradle.kts
repositories {
     mavenCentral()
     maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
     // ↓↓↓↓↓
     google() // Add me!!!
     // ↑↑↑↑↑
     maven("https://us-central1-maven.pkg.dev/varabyte-repos/public")
}

Full Changelog: v0.16.3...v0.17.0

v0.16.3

29 Feb 16:25
Compare
Choose a tag to compare

This is a small release with some minor fixes. However, we're cutting it early in preparation for a follow-up release that will be compatible with a newer Compose version.

Important

Planning to upgrade? Review instructions in the README.

  • Fixed an issue with Markdown code generating incorrect output when links contained inline code formatting

    • For example, this used to break:
      [see `ExampleClass` docs for more information](https://mysite.com/docs/exampleclass)
  • Breakpoint types refactored to be more sensible

    • so you can now do e.g. Modifier.setWidth(Breakpoints.MD)
  • Added new PageContext parameters for convenience.

    • For a URL https://mysite.com/a/b/c?id=123#fragment
      • ctx.origin: https://mysite.com
      • ctx.pathQueryAndFragment: /a/b/c?id=123#fragment
    • These were values you could query JS's window.location property for, but they fit nicely inside PageContext as well for easy access.

Full Changelog: v0.16.2...v0.16.3

v0.16.2

11 Feb 22:05
Compare
Choose a tag to compare

This micro release contains a fix for a critical bug introduced in the v0.16.0 route generation algorithm that may apply to a small subset of users.

You will know if this is you if Kobweb v0.16.0 generates a site that won't start up, with the dev console complaining about an invalid path that doesn't start with a slash.

Important

Planning to upgrade? Review instructions in the README.

Due to the Compose / Kotlin target increase in v0.16.1, if you upgrade from v0.16.0 to this one, ensure that you also update to Compose v1.5.12 and Kotlin v1.9.22.

Who is affected? Specifically, if you use camel casing in your project's package, e.g. com.example.mySite, then v0.16.0 will break on your site.

// site/build.gradle.kts
plugins { /* ... */ }

group = "com.example.mySite" // <-- Camel casing here breaks in v0.16.0, fixed in v0.16.2+

// ...

Our new route generation algorithm should have only been constrained to the part of the package under the pages package, e.g. com.example.mySite.pages.exampleRoute should only have transformed exampleRoute and not mySite. Once we transformed the earlier part, however, we ended up generating a weird route that broke logic further down the line. Unfortunately, we missed this in our testing, and apologize for any inconvenience.

Thanks to @TheDome0 for their quick bug report, letting us turn around on this issue quickly.

If you were not affected by this issue, updating is not required but it otherwise harmless.


Full Changelog: v0.16.1...v0.16.2

v0.16.1

09 Feb 17:02
Compare
Choose a tag to compare

This release is identical to v0.16.0 but has migrated its dependencies to target Compose 1.5.12 and Kotlin 1.9.22.

Important

Planning to upgrade? Review instructions in the README.