Skip to content
This repository was archived by the owner on Nov 20, 2025. It is now read-only.

Commit 6c0b317

Browse files
More Text updates
1 parent 31d6103 commit 6c0b317

10 files changed

Lines changed: 249 additions & 93 deletions

File tree

tyrian-ui/src/main/scala/tyrian/ui/Text.scala

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package tyrian.ui.datatypes
2+
3+
enum FontSize derives CanEqual:
4+
case XSmall, Small, Medium, Large, XLarge, XXLarge
5+
case Custom(value: String)
6+
7+
def toCSSValue: String = this match
8+
case XSmall => "0.75rem" // 12px at 16px base
9+
case Small => "0.875rem" // 14px at 16px base
10+
case Medium => "1rem" // 16px at 16px base
11+
case Large => "1.125rem" // 18px at 16px base
12+
case XLarge => "1.5rem" // 24px at 16px base
13+
case XXLarge => "2rem" // 32px at 16px base
14+
case Custom(value) => value
15+
16+
object FontSize:
17+
val default: FontSize = Medium
18+
19+
val heading1: FontSize = Custom("2rem") // 32px at 16px base
20+
val heading2: FontSize = Custom("1.75rem") // 28px at 16px base
21+
val heading3: FontSize = Custom("1.5rem") // 24px at 16px base
22+
val heading4: FontSize = Custom("1.25rem") // 20px at 16px base
23+
val heading5: FontSize = Custom("1.125rem") // 18px at 16px base
24+
val heading6: FontSize = Custom("1rem") // 16px at 16px base
25+
26+
val caption: FontSize = XSmall
27+
val button: FontSize = Medium
28+
val label: FontSize = Small
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package tyrian.ui.datatypes
2+
3+
/** Font weight options for text, from thinnest to boldest. */
4+
enum FontWeight derives CanEqual:
5+
case Thin, Light, Normal, Medium, SemiBold, Bold, ExtraBold, Black
6+
7+
/** Converts the font weight to its CSS numeric value. */
8+
def toCSSValue: String = this match
9+
case Thin => "100"
10+
case Light => "300"
11+
case Normal => "400"
12+
case Medium => "500"
13+
case SemiBold => "600"
14+
case Bold => "700"
15+
case ExtraBold => "800"
16+
case Black => "900"
17+
18+
object FontWeight:
19+
/** Default font weight for body text. */
20+
val default: FontWeight = Normal
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package tyrian.ui.datatypes
2+
3+
enum LineHeight derives CanEqual:
4+
case Tight, Normal, Relaxed, Loose
5+
case Custom(value: String)
6+
7+
def toCSSValue: String = this match
8+
case Tight => "1.2"
9+
case Normal => "1.4"
10+
case Relaxed => "1.5"
11+
case Loose => "1.7"
12+
case Custom(value) => value
13+
14+
object LineHeight:
15+
val default: LineHeight = Normal
16+
17+
val heading: LineHeight = Tight
18+
val body: LineHeight = Relaxed
19+
val caption: LineHeight = Normal
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package tyrian.ui.datatypes
2+
3+
enum TextAlignment derives CanEqual:
4+
case Left, Center, Right, Justify
5+
6+
def toCSSValue: String = this match
7+
case Left => "left"
8+
case Center => "center"
9+
case Right => "right"
10+
case Justify => "justify"
11+
12+
object TextAlignment:
13+
14+
val default: TextAlignment = Left
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package tyrian.ui.datatypes
2+
3+
enum TextDecoration derives CanEqual:
4+
case None, Underline, Strikethrough, Overline
5+
6+
def toCSSValue: String = this match
7+
case None => "none"
8+
case Underline => "underline"
9+
case Strikethrough => "line-through"
10+
case Overline => "overline"
11+
12+
object TextDecoration:
13+
14+
val default: TextDecoration = None
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package tyrian.ui.datatypes
2+
3+
enum TextStyle derives CanEqual:
4+
case Normal, Italic
5+
6+
def toCSSValue: String = this match
7+
case Normal => "normal"
8+
case Italic => "italic"
9+
10+
object TextStyle:
11+
12+
val default: TextStyle = Normal

tyrian-ui/src/main/scala/tyrian/ui/text/Text.scala

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ package tyrian.ui.text
22

33
import tyrian.ui.Theme
44
import tyrian.ui.UIElement
5+
import tyrian.ui.datatypes.FontSize
6+
import tyrian.ui.datatypes.FontWeight
7+
import tyrian.ui.datatypes.LineHeight
58
import tyrian.ui.datatypes.RGBA
9+
import tyrian.ui.datatypes.TextAlignment
10+
import tyrian.ui.datatypes.TextDecoration
11+
import tyrian.ui.datatypes.TextStyle
612

713
final case class Text(
814
value: String,
@@ -25,21 +31,24 @@ final case class Text(
2531
def toCode: Text = this.copy(variant = TextVariant.Code)
2632
def toLabel: Text = this.copy(variant = TextVariant.Label)
2733

28-
// TODO: Add clearBold - or maybe just 'normal'?
29-
def bold: Text = modifyTextTheme(_.copy(fontWeight = "bold"))
30-
// TODO: Add clearItalic - or maybe just 'normal'?
31-
def italic: Text = modifyTextTheme(_.copy(fontStyle = Some("italic")))
32-
// TODO: Add clearUnderlined - or maybe just 'normal'?
33-
def underlined: Text = modifyTextTheme(_.copy(textDecoration = Some("underline")))
34-
// TODO: Strikethrough?
35-
def withColor(color: RGBA): Text = modifyTextTheme(_.copy(color = color))
36-
def withSize(size: String): Text = modifyTextTheme(_.copy(fontSize = size))
37-
def wrap: Text = modifyTextTheme(_.copy(wrap = true))
38-
def noWrap: Text = modifyTextTheme(_.copy(wrap = false))
39-
40-
def alignLeft: Text = modifyTextTheme(_.copy(textAlign = "left"))
41-
def alignCenter: Text = modifyTextTheme(_.copy(textAlign = "center"))
42-
def alignRight: Text = modifyTextTheme(_.copy(textAlign = "right"))
34+
def bold: Text = modifyTextTheme(_.withWeight(FontWeight.Bold))
35+
def italic: Text = modifyTextTheme(_.withStyle(TextStyle.Italic))
36+
def underlined: Text = modifyTextTheme(_.withDecoration(TextDecoration.Underline))
37+
def strikethrough: Text = modifyTextTheme(_.withDecoration(TextDecoration.Strikethrough))
38+
def withColor(color: RGBA): Text = modifyTextTheme(_.withColor(color))
39+
def withSize(size: FontSize): Text = modifyTextTheme(_.withFontSize(size))
40+
def withLineHeight(height: LineHeight): Text = modifyTextTheme(_.withLineHeight(height))
41+
def wrap: Text = modifyTextTheme(_.withWrap(true))
42+
def noWrap: Text = modifyTextTheme(_.withWrap(false))
43+
44+
def clearWeight: Text = modifyTextTheme(_.withWeight(FontWeight.Normal))
45+
def clearStyle: Text = modifyTextTheme(_.withStyle(TextStyle.Normal))
46+
def clearDecoration: Text = modifyTextTheme(_.withDecoration(TextDecoration.None))
47+
48+
def alignLeft: Text = modifyTextTheme(_.withAlignment(TextAlignment.Left))
49+
def alignCenter: Text = modifyTextTheme(_.withAlignment(TextAlignment.Center))
50+
def alignRight: Text = modifyTextTheme(_.withAlignment(TextAlignment.Right))
51+
def alignJustify: Text = modifyTextTheme(_.withAlignment(TextAlignment.Justify))
4352

4453
def modifyTheme(f: Theme => Theme): Text =
4554
this.copy(_modifyTheme = Some(f))

tyrian-ui/src/main/scala/tyrian/ui/text/TextTheme.scala

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,67 @@ package tyrian.ui.text
22

33
import tyrian.Style
44
import tyrian.ui.Theme
5+
import tyrian.ui.datatypes.FontSize
6+
import tyrian.ui.datatypes.FontWeight
7+
import tyrian.ui.datatypes.LineHeight
58
import tyrian.ui.datatypes.RGBA
9+
import tyrian.ui.datatypes.TextAlignment
10+
import tyrian.ui.datatypes.TextDecoration
11+
import tyrian.ui.datatypes.TextStyle
612

713
final case class TextTheme(
8-
fontSize: String,
9-
fontWeight: String,
14+
fontSize: FontSize,
15+
weight: FontWeight,
1016
color: RGBA,
11-
textAlign: String,
12-
lineHeight: String,
17+
alignment: TextAlignment,
18+
lineHeight: LineHeight,
1319
wrap: Boolean,
14-
fontStyle: Option[String],
15-
textDecoration: Option[String]
20+
style: TextStyle,
21+
decoration: TextDecoration
1622
):
1723

24+
def withFontSize(value: FontSize): TextTheme =
25+
this.copy(fontSize = value)
26+
27+
def withWeight(value: FontWeight): TextTheme =
28+
this.copy(weight = value)
29+
30+
def withColor(value: RGBA): TextTheme =
31+
this.copy(color = value)
32+
33+
def withAlignment(value: TextAlignment): TextTheme =
34+
this.copy(alignment = value)
35+
36+
def withLineHeight(value: LineHeight): TextTheme =
37+
this.copy(lineHeight = value)
38+
39+
def withWrap(value: Boolean): TextTheme =
40+
this.copy(wrap = value)
41+
def wrapText: TextTheme =
42+
this.copy(wrap = true)
43+
def noWrap: TextTheme =
44+
this.copy(wrap = false)
45+
46+
def withStyle(value: TextStyle): TextTheme =
47+
this.copy(style = value)
48+
49+
def withDecoration(value: TextDecoration): TextTheme =
50+
this.copy(decoration = value)
51+
1852
def toStyles(theme: Theme): Style =
1953
val baseStyle = Style(
2054
"font-family" -> theme.fonts.body,
21-
"font-size" -> fontSize,
22-
"font-weight" -> fontWeight,
55+
"font-size" -> fontSize.toCSSValue,
56+
"font-weight" -> weight.toCSSValue,
2357
"color" -> color.toHexString("#"),
24-
"text-align" -> textAlign,
25-
"line-height" -> lineHeight,
58+
"text-align" -> alignment.toCSSValue,
59+
"line-height" -> lineHeight.toCSSValue,
2660
"white-space" -> (if wrap then "normal" else "nowrap")
2761
)
2862

2963
val styleModifiers = List(
30-
fontStyle.map("font-style" -> _),
31-
textDecoration.map("text-decoration" -> _)
64+
if style != TextStyle.Normal then Some("font-style" -> style.toCSSValue) else None,
65+
if decoration != TextDecoration.None then Some("text-decoration" -> decoration.toCSSValue) else None
3266
).flatten
3367

3468
styleModifiers.foldLeft(baseStyle)((style, prop) => style |+| Style(prop))

0 commit comments

Comments
 (0)