PurpleKingdomGames / tyrian

Elm-inspired Scala UI library.
https://tyrian.indigoengine.io/
MIT License
350 stars 26 forks source link

Investigate: Is it possible to add support for ScalaCSS? #101

Open davesmith00000 opened 2 years ago

nigeleke commented 1 year ago

I'm having some success with this approach. I've only just started playing with Tyrian and Scalacss, so I'm not sure how flexible or "future-proof" this may be.

Use these conversions:

given Conversion[StyleA, tyrian.Attr[Nothing]] with
    def apply(style: StyleA): tyrian.Attr[Nothing] =
      tyrian.Html.styles(
        style.style.inspectCss
          .flatMap(
            _.content.toSet
              .map(kv => tyrian.Style(kv.key, kv.value))
          )
          .toList: _*
      )

  // Workaround for embedding ValueT types in strings. Target must be explicitly typed as String.
  import scalacss.internal.ValueT
  given Conversion[ValueT[_], String] with
    def apply(value: ValueT[_]): String = value.value

then a sample Stylesheet will be:

val CssSettings = scalacss.devOrProdDefaults
import CssSettings._

object Styles extends StyleSheet.Inline:
  import dsl.*

  // Place above code here

  private object Color:
    val themeL1 = rgb(0x70, 0x8d, 0xa2)
    val themeD2 = rgb(0x44, 0x59, 0x68)
    val textTheme   = themeL5

  private val verdana = fontFace("verdana")(_.src("url(verdana.woff2)"))

  val app =
    val from: String = Color.themeL1
    val to: String   = Color.themeD2
    style(
      display.flex,
      flexDirection := "column",
      height(100.%%),
      minHeight(100.vh),
      background := s"linear-gradient(45deg, $from, $to)",
      fontFamily(verdana),
      fontSize(1.5.rem),
      color(Color.textTheme)
    )

then this can be used in the Tyrian code:

@JSExportTopLevel("TyrianApp")
object Main extends TyrianApp[Main.Msg, Main.Model]:

  import Styles.given
  ...
  def view(model: Model): Html[Msg] =
    div(Styles.app)(
      div(
        header,
        content(model),
        footer
      )
    )