Skip to content

Commit

Permalink
Merge pull request #133 from chasefleming/chasefleming/75
Browse files Browse the repository at this point in the history
Add Style Utilities
  • Loading branch information
chasefleming committed Mar 29, 2024
2 parents 78562e5 + e903d9c commit 74943ff
Show file tree
Hide file tree
Showing 3 changed files with 308 additions and 1 deletion.
106 changes: 105 additions & 1 deletion styles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ The `styles` subpackage within `elem-go` offers enhanced functionality for CSS s
- [Usage](#usage)
- [Styling Elements with `styles.Props`](#styling-elements-with-stylesprops)
- [Features](#features)
- [`Merge` Function](#merge-function)
- [`Style` and `CSS` Functions](#style-and-css-functions)
- [`Merge` Function](#merge-function)
- [Type-Safe CSS Values](#type-safe-css-values)

## Introduction

Expand Down Expand Up @@ -112,4 +113,107 @@ styleTag := elem.Style(nil, elem.CSS(cssContent))

// Incorporating the <style> tag in an HTML document
document := elem.Html(nil, elem.Head(nil, styleTag), /* ... */)
```

### Type-Safe CSS Values

This suite of functions provides a type-safe approach to defining CSS values, ensuring that only valid CSS values are used.

#### Length and Size Functions

##### `Em(value float64) string` and `Rem(value float64) string`

These functions return a string representation of the given value with the "em" and "rem" units, respectively.

```go
emValue := styles.Em(2.5) // Returns "2.5em"
remValue := styles.Rem(1.5) // Returns "1.5rem"
```

##### `Pixels(value int) string`

This function returns a string representation of the given value with the "px" unit.

```go
pxValue := styles.Pixels(10) // Returns "10px"
```

##### `Percent(value int) string`

This function returns a string representation of the given value with the "%" unit.

```go
percentValue := styles.Percent(50) // Returns "50%"
```

#### Viewport Functions

##### `ViewportHeight(value int) string` and `ViewportWidth(value int) string`

These functions return a string representation of the given value with the "vh" and "vw" units, respectively.

```go
vhValue := styles.ViewportHeight(50) // Returns "50vh"
vwValue := styles.ViewportWidth(25) // Returns "25vw"
```

##### `ViewportMin(value int) string` and `ViewportMax(value int) string`

These functions return a string representation of the given value with the "vmin" and "vmax" units, respectively.

```go
vminValue := styles.ViewportMin(10) // Returns "10vmin"
vmaxValue := styles.ViewportMax(20) // Returns "20vmax"
```

#### Color Functions

##### `RGB(r, g, b int) string`

This function returns a string representation of the given RGB color.

```go
rgbColor := styles.RGB(255, 0, 0) // Returns "rgb(255, 0, 0)"
```

##### `RGBA(r, g, b int, a float64) string`

This function returns a string representation of the given RGBA color.

```go
rgbaColor := styles.RGBA(255, 0, 0, 0.5) // Returns "rgba(255, 0, 0, 0.5)"
```

#### Other Functions

##### `Int(value int) string`

This function returns a string representation of the given integer value.

```go
intValue := styles.Int(100) // Returns "100"
```

##### `Float(value float64) string`

This function returns a string representation of the given float value.

```go
floatValue := styles.Float(3.14) // Returns "3.14"
```

##### `URL(url string) string`

This function returns a string representation as a formatted CSS URL.

```go
urlValue := styles.URL("https://example.com/image.jpg") // Returns "url('https://example.com/image.jpg')"
```

##### `Var(name string) string`

This function returns a string representation as a CSS variable.

```go
varValue := styles.Var("primary-color") // Returns "var(--primary-color)"
```
108 changes: 108 additions & 0 deletions styles/utils.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package styles

import (
"fmt"
"strconv"
"strings"
)

// Merge combines multiple styles.Props maps into one, with later styles overriding earlier ones.
func Merge(styleMaps ...Props) Props {
mergedStyles := Props{}
Expand All @@ -10,3 +16,105 @@ func Merge(styleMaps ...Props) Props {
}
return mergedStyles
}

// Em returns a string representation of the given float as an em value.
func Em(value float64) string {
return strconv.FormatFloat(value, 'f', 2, 64) + "em"
}

// Float returns a string representation of the float with 2 decimal places
func Float(value float64) string {
return fmt.Sprintf("%.2f", value)
}

// Int returns a string representation of the int
func Int(value int) string {
return strconv.Itoa(value)
}

// Percent returns a string representation of the given integer as a percentage.
func Percent(value int) string {
return strconv.Itoa(value) + "%"
}

// Pixels returns a string representation of the given integer as a pixel value.
func Pixels(value int) string {
if value == 0 {
return "0"
}
return strconv.Itoa(value) + "px"
}

// Rem returns a string representation of the given float as a rem value.
func Rem(value float64) string {
return strconv.FormatFloat(value, 'f', 2, 64) + "rem"
}

// RGB returns a string representation of the given RGB values as a CSS RGB value.
func RGB(r, g, b int) string {
var builder strings.Builder
builder.WriteString("rgb(")
builder.WriteString(strconv.Itoa(r))
builder.WriteString(",")
builder.WriteString(strconv.Itoa(g))
builder.WriteString(",")
builder.WriteString(strconv.Itoa(b))
builder.WriteString(")")
return builder.String()
}

// RGBA returns a string representation of the given RGBA values as a CSS RGBA value.
func RGBA(r, g, b int, a float64) string {
var builder strings.Builder
builder.WriteString("rgba(")
builder.WriteString(strconv.Itoa(r))
builder.WriteString(",")
builder.WriteString(strconv.Itoa(g))
builder.WriteString(",")
builder.WriteString(strconv.Itoa(b))
builder.WriteString(",")

// Convert the alpha float value to a string with desired precision
alphaStr := strconv.FormatFloat(a, 'f', 1, 64)
builder.WriteString(alphaStr)
builder.WriteString(")")
return builder.String()
}

// URL returns a string representation of the given string as a CSS URL value.
func URL(url string) string {
var builder strings.Builder
builder.WriteString("url('")
builder.WriteString(url)
builder.WriteString("')")
return builder.String()
}

// Var returns a string representation of the given string as a CSS var value.
func Var(name string) string {
var builder strings.Builder
builder.WriteString("var(--")
builder.WriteString(name)
builder.WriteString(")")
return builder.String()
}

// ViewportHeight returns a string representation of the given integer as a viewport height value.
func ViewportHeight(value int) string {
return strconv.Itoa(value) + "vh"
}

// ViewportWidth returns a string representation of the given integer as a viewport width value.
func ViewportWidth(value int) string {
return strconv.Itoa(value) + "vw"
}

// ViewportMin returns a string representation of the given integer as a viewport minimum value.
func ViewportMin(value int) string {
return strconv.Itoa(value) + "vmin"
}

// ViewportMax returns a string representation of the given integer as a viewport maximum value.
func ViewportMax(value int) string {
return strconv.Itoa(value) + "vmax"
}
95 changes: 95 additions & 0 deletions styles/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,98 @@ func TestMergeThreeStyles(t *testing.T) {

assert.Equal(t, expectedStyle, mergedStyle)
}

func TestEm(t *testing.T) {
assert.Equal(t, "100.00em", Em(100))
assert.Equal(t, "0.00em", Em(0))
assert.Equal(t, "50.00em", Em(50))
assert.Equal(t, "25.00em", Em(25))
}

func TestFloat(t *testing.T) {
assert.Equal(t, "100.00", Float(100))
assert.Equal(t, "0.00", Float(0))
assert.Equal(t, "50.00", Float(50))
assert.Equal(t, "25.00", Float(25))

// Longer float
assert.Equal(t, "100.12", Float(100.123456))
}

func TestInt(t *testing.T) {
assert.Equal(t, "100", Int(100))
assert.Equal(t, "0", Int(0))
assert.Equal(t, "50", Int(50))
assert.Equal(t, "25", Int(25))
}

func TestRem(t *testing.T) {
assert.Equal(t, "100.00rem", Rem(100))
assert.Equal(t, "0.00rem", Rem(0))
assert.Equal(t, "50.00rem", Rem(50))
assert.Equal(t, "25.00rem", Rem(25))
}

func TestPercent(t *testing.T) {
assert.Equal(t, "100%", Percent(100))
assert.Equal(t, "0%", Percent(0))
assert.Equal(t, "50%", Percent(50))
assert.Equal(t, "25%", Percent(25))
}

func TestPixels(t *testing.T) {
assert.Equal(t, "100px", Pixels(100))
assert.Equal(t, "0", Pixels(0))
assert.Equal(t, "50px", Pixels(50))
assert.Equal(t, "25px", Pixels(25))
}

func TestRGB(t *testing.T) {
assert.Equal(t, "rgb(100,100,100)", RGB(100, 100, 100))
assert.Equal(t, "rgb(0,0,0)", RGB(0, 0, 0))
assert.Equal(t, "rgb(50,50,50)", RGB(50, 50, 50))
assert.Equal(t, "rgb(25,25,25)", RGB(25, 25, 25))
}

func TestRGBA(t *testing.T) {
assert.Equal(t, "rgba(100,100,100,100.0)", RGBA(100, 100, 100, 100))
assert.Equal(t, "rgba(0,0,0,0.0)", RGBA(0, 0, 0, 0))
assert.Equal(t, "rgba(50,50,50,0.5)", RGBA(50, 50, 50, 0.5))
assert.Equal(t, "rgba(25,25,25,25.0)", RGBA(25, 25, 25, 25.0))
}

func TestURL(t *testing.T) {
assert.Equal(t, "url('https://example.com')", URL("https://example.com"))
}

func TestVar(t *testing.T) {
assert.Equal(t, "var(--primary-color)", Var("primary-color"))
}

func TestViewportHeight(t *testing.T) {
assert.Equal(t, "100vh", ViewportHeight(100))
assert.Equal(t, "0vh", ViewportHeight(0))
assert.Equal(t, "50vh", ViewportHeight(50))
assert.Equal(t, "25vh", ViewportHeight(25))
}

func TestViewportWidth(t *testing.T) {
assert.Equal(t, "100vw", ViewportWidth(100))
assert.Equal(t, "0vw", ViewportWidth(0))
assert.Equal(t, "50vw", ViewportWidth(50))
assert.Equal(t, "25vw", ViewportWidth(25))
}

func TestViewportMin(t *testing.T) {
assert.Equal(t, "100vmin", ViewportMin(100))
assert.Equal(t, "0vmin", ViewportMin(0))
assert.Equal(t, "50vmin", ViewportMin(50))
assert.Equal(t, "25vmin", ViewportMin(25))
}

func TestViewportMax(t *testing.T) {
assert.Equal(t, "100vmax", ViewportMax(100))
assert.Equal(t, "0vmax", ViewportMax(0))
assert.Equal(t, "50vmax", ViewportMax(50))
assert.Equal(t, "25vmax", ViewportMax(25))
}

0 comments on commit 74943ff

Please sign in to comment.