freya
freya copied to clipboard
proposal: Unified text primitives/nestable text elements
Consider this a mini-RFC. I think I may have proposed it last year on discord, but it probably wasn't conveyed as well as it could have been.
Freya's Text Primitives
Currently freya has three elements (primitives) related to rendering text:
-
label
-
paragraph
-
text
These all render similar (or identical things), but serve slightly different purposes at the same time:
-
label
is generally used for "one-off" cases where you just need a single line of contigiously-styled text. It's simple and used for most things text-related where you just need one style.label
cannot take children other than a raw string. -
paragraph
/text
are used when you need differently styled text nodes in the same text layout at once. For example, if you wanted emphasized text, you would use a paragraph/text combo.
paragraph {
line_height: "2",
text {
font_size: "20",
font_style: "normal",
"Normal "
}
text {
font_size: "20",
font_style: "italic",
"Italic "
}
text {
font_size: "20",
font_style: "oblique",
"Oblique"
}
}
The case for a unified element
All three of these elements serve the same purpose -- drawing text, yet they have different arbitrary restrictions or API complexity. Currently, paragraph
could almost certainly replace label
in all cases, but that would be annoying to deal with due to having paragraph
split into a pair of elements. Instead, what if there was a single simplified text
primitive that served all the usecases. This would have some advantages:
- Freya wouldn't have to individually handle three elements in its native APIs, and all rendering and node-related code for text would be unified under a single primitive, reducing internal complexity.
- It's easier to teach to users. The difference between
label
andparagraph
wouldn't need to be explained. - It would remove any accidental differences in behavior or attributes between the elements as a result of feature additions to one element but not the other.
- It better fits the paradigm of having a set of "base elements". Generally most UI is visually comprised of text and rounded rectangles if you break it into its base parts, and this better fits that paradigm.
A new text
element
This proposal presents a new text
element that takes the place of paragraph
. In its simplest form, it looks a lot like the current label
.
text {
"Hi",
}
text
elements can contain bare strings or span
s as children.
text {
"Hello",
span {
font_weight: "bold",
"World"
}
}
The span
element
span
is basically a replacement for the previous text
element, and defines a styled span of text in SkParagraph
. Unlike the parent text
, they can only take inline text styling properties such as font_size
, font_weight
, etc...
- A span that is not a child of
text
is meaningless and does not render anything at all. -
span
s inherit the text styling properties of their parenttext
. - A bare string child of
text
is equivalent to aspan
with no styles.
This reduces the number of text elements from 3 to 2 and provides a clear distinction between a SkParagraph
and a text span in the paragraph. It also reduces the API complexity of using styled spanned text while also removing label
.
Past Work
This is very similar to the approaches of React Native and HTML:
<span>
I am
<span style="font-weight: bold;">
bold
</span>
</span>
Unlike HTML, there is a distinction between the text's block element (in Freya's case a SkParagraph
) and the inline children.
Remaining Questions
- Should
span
s be able to havespan
children to inherit styles? (probably not initially I guess...)