Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flow-relative CSS properties #82

Open
raquo opened this issue Jul 7, 2022 · 2 comments
Open

Add flow-relative CSS properties #82

raquo opened this issue Jul 7, 2022 · 2 comments

Comments

@raquo
Copy link
Owner

raquo commented Jul 7, 2022

Such as:

  • margin-block, margin-block-start, margin-block-end
  • margin-inline, margin-inline-start, margin-inline-end
  • padding-block, padding-block-start, padding-block-end
  • padding-inline, padding-inline-start, padding-inline-end
  • inset
  • inset-block, inset-block-start, inset-block-end
  • inset-inline, inset-inline-start, inset-inline-end
  • etc

For example, margin-block-start is basically equivalent to margin-top except it's aware of flow direction and text direction.

There's more to these than just dimensional props, see this spec – note the TOC on the left, the new values for text-align, the new logical keyword, etc.

cc @Lasering

@raquo
Copy link
Owner Author

raquo commented Jul 7, 2022

Main question is how to encode these props. We could spell out each property like we do for e.g. marginTop, marginBottom, etc. but then the myriad of new props would "pollute" autocomplete.

Few people use these new props (and actually test their websites to make sure they work with the different text directions), so I'm not sure if that's a good tradeoff. And in general I loathe having to define repetitive props.

Alternatively, we could make those props nested, such as margin.blockStart or borderColor.inlineEnd. We would also need to add old ones like margin.top for consistency I guess. I don't think I'm ready to completely replace the existing props like marginTop with margin.top, both options might need to co-exist for a while.

@Lasering
Copy link
Contributor

Lasering commented Jul 8, 2022

Regarding the logical keyword, I think its best to not include it for now since issue 1 on the spec clearly defines it as unstable.

I don't see the autocomplete "pollution" as a problem but rather as a feature it helps with the discoverability. But I do understand why it isn't the most good looking option.

Making the props nested could be a very elegant solution. Here is a very rough idea (does not handle things like border-block-start-width):

object Setter {
  def instance[T](name: String): Setter[T] = (value: T) => s"$name: $value"
}
trait Setter[T] {
  def :=(value: T): String
}

class TopBottomLeftRight[T](prefix: String) {
  val top: Setter[T] = Setter.instance(s"$prefix-top")
  val bottom: Setter[T] = Setter.instance(s"$prefix-bottom")
  val left: Setter[T] = Setter.instance(s"$prefix-left")
  val right: Setter[T] = Setter.instance(s"$prefix-right")
  
  // (top and bottom, left and right).
  def :=(t: (T, T)): String = s"$prefix: ${t._1} ${t._2}"
  // (top, left and right, bottom).
  def :=(t: (T, T, T)): String = s"$prefix: ${t._1} ${t._2} ${t._3}"
  // (top, right, bottom, left)
  def :=(t: (T, T, T, T)): String = s"$prefix: ${t._1} ${t._2} ${t._3} ${t._4}"
}

class BlockInline[T](prefix: String) extends Setter[T] {
  override def :=(value: T): String = s"$prefix: $value"
  // (start, end)
  def :=(t: (T, T)): String = s"$prefix: ${t._1} ${t._2}"
  
  val start: Setter[T] = Setter.instance(s"$prefix-start")
  val end: Setter[T] = Setter.instance(s"$prefix-end")
}

class FourSidesProperty[T](prefix: String) extends TopBottomLeftRight[T](prefix) with Setter[T] {
  override def :=(value: T): String = s"$prefix: $value"
  
  val block: BlockInline[T] = new BlockInline(s"$prefix-block")
  val inline: BlockInline[T] = new BlockInline(s"$prefix-inline")
}

@main def main(): Unit =
  val margin: FourSidesProperty[Int] = new FourSidesProperty[Int]("margin")
  val padding: FourSidesProperty[Int] = new FourSidesProperty[Int]("padding")
  
  println(margin := 5)
  println(margin := (5, 25, 5))
  println(margin.top := 5)
  println(margin.block := 5)
  println(margin.block.start := 5)
  println(margin.inline.end := 5)
  println(padding.inline.end := 5)
margin: 5
margin: 5 25 5
margin-top: 5
margin-block: 5
margin-block-start: 5
margin-inline-end: 5
padding-inline-end: 5

Even the documentation could be easily done via interpolation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants