gbr/ui/theme

💎✨ GBR: UI Theme Module

🤺 theme.gleam = Vocabulário Visual e Design Token Algébrico.

Aqui temos um módulo muito especial cheio de tipos algébricos para representarmos matematicamente o mundo externo e como manipulamos o tema visual dos nossos componentes.

Aqui iremos encontrar as variantes do tema, a aparência dos componentes, o estado em que eles estão, seu tamanho, etc.

IDEIA: Que esta biblioteca e vocabulário sejam universais para desenvolver componentes UI para qualquer interface

Objetivos

Arquitetura: Type-Safe Styled Systems

CVA (Class Variance Authority)

🏆 Meta final para o theme.gleam

Se transformar em um motor gráfico capaz de descrever QUALQUER componente de interface no planeta. Estrutura final da nossa ontologia:

Teremos 8 dimensões base para representarmos visualmente um componente na interface do dispositivo.

A ordem no código para construir um elemento do zero até a pintura final:

Estrutura Base (Invisível): Display (flex, grid), alinhamento, transições (transition-all).

Regra da Propriedade do CSS

🔥 O Cálculo da Trindade (O Coração da Pintura)

A “Fusão” da pintura acontece cruzando as 3 dimensões:

✨ A Magia do Gleam: Graças ao curinga (_), você não precisa escrever 504 blocos de regras em CSS puro. Você mapeia apenas os 10 ou 15 caminhos felizes que o seu design aprova, e usa o _, _, _ -> fallback(...) para devorar as outras combinações impossíveis/indesejadas em uma linha só!

🌌 O Cálculo do Universo (As 8 Dimensões)

Se nós pegarmos um único elemento genérico (como um div atômico) e permitirmos que o desenvolvedor configure livremente as 8 dimensões, qual será o tamanho da nossa “Ontologia de UI”?

Mais de 5 MILHÕES de formas de desenhar um componente! 🤯

Explicando o sufixo Default e Ancestor

Para todos tipos de tema, inclusive os (size, shape, elevation, stacking), temos dois sufixos importantes Ancestor e Default, segue um exemplo usando o UIVariant:

Types

Direção de um elemento esquerda, direita, etc.

pub type UIAbsolute {
  Axis(horizontal: UIAlignment, vertical: UIAlignment)
  AxisX(UIAlignment)
  AxisY(UIAlignment)
}

Constructors

Representa as opções de alinhamento em um eixo genérico

pub type UIAlignment {
  Start
  End
  Center
  SpaceBetween
  SpaceAround
  SpaceEvenly
  Stretch
}

Constructors

  • Start

    e.g. flex-start

  • End

    e.g. flex-end

  • Center

    e.g. center

  • SpaceBetween

    e.g. space-between

  • SpaceAround

    e.g. space-around

  • SpaceEvenly

    e.g. space-evenly

  • Stretch

    e.g. stretch

Aparência de um elemento o seu estilo.

pub type UIAppearance {
  AppearanceDefault
  AppearanceFilled
  AppearanceGhost
  AppearanceLight
  AppearanceOutline
}

Constructors

  • AppearanceDefault
  • AppearanceFilled

    Apresentam fundo de cor sólida, ideal para ações primárias devido à alta visibilidade.

  • AppearanceGhost

    Tenha um fundo transparente sem borda e com rótulo de texto. Eles são adequados para ações secundárias, pois são menos proeminentes visualmente do que a aparencia sólida.

  • AppearanceLight

    Ao sobrepor várias sombras desfocadas com cores brilhantes, você pode criar um efeito luminoso

  • AppearanceOutline

    Tenha um fundo transparente com borda e rótulo de texto. Eles são adequados para ações secundárias, pois são menos proeminentes visualmente do que a aparencia sólida.

Como controlar a sensação de elevação dos elementos. (sombra)

pub type UIElevation {
  ElevationFlat(option.Option(#(UISize, UILayout)))
  ElevationInner(option.Option(#(UISize, UILayout)))
  ElevationThin(option.Option(#(UISize, UILayout)))
  ElevationLow(option.Option(#(UISize, UILayout)))
  ElevationMedium(option.Option(#(UISize, UILayout)))
  ElevationHigh(option.Option(#(UISize, UILayout)))
}

Constructors

Representa a união de justify-content (main) e align-content (cross).

pub type UIFlow {
  Main(justify: UIAlignment)
  CrossItems(align: UIAlignment)
  CrossContent(align: UIAlignment)
  Flow(
    main: UIAlignment,
    cross_content: UIAlignment,
    cross_items: UIAlignment,
  )
  FlowItems(main: UIAlignment, cross_items: UIAlignment)
  FlowContent(main: UIAlignment, cross_content: UIAlignment)
}

Constructors

  • Main(justify: UIAlignment)

    Layout de fluxo principal referencia ao justify-*.

  • CrossItems(align: UIAlignment)

    Layout de fluxo principal referencia ao items-*.

  • CrossContent(align: UIAlignment)

    Layout de fluxo principal referencia ao content-*.

  • Flow(
      main: UIAlignment,
      cross_content: UIAlignment,
      cross_items: UIAlignment,
    )

    Layout de fluxo referenciando o eixo main, cross content e cross items.

  • FlowItems(main: UIAlignment, cross_items: UIAlignment)

    Layout de fluxo referenciando o eixo main e cross items.

  • FlowContent(main: UIAlignment, cross_content: UIAlignment)

    Layout de fluxo referenciando o eixo main e cross content.

Define a estratégia de posicionamento no layout.

pub type UILayout {
  LayoutFlow(UIFlow)
  LayoutAbsolute(UIAbsolute)
}

Constructors

Formato da superfície de um elemento.

O “quão redondo” é o elemento não depende do tamanho

pub type UIShape {
  Shape(#(UISize, UILayout))
  ShapeRounded
  ShapePill
  ShapeCircle
  ShapeSharp
}

Constructors

  • Shape(#(UISize, UILayout))

    Arredondamento

  • ShapeRounded

    Bordas arredondadas perfeito para botões

  • ShapePill

    Bordas totalmente arredondadas (Design iOS/Mobile)

  • ShapeCircle

    Círculo perfeito (Para avatares e icon_only)

  • ShapeSharp

    Quadrado perfeito (0px radius)

Escala do tamanho de um elemento.

  • Altura, Largura, Fonte e Espaçamento Interno (Padding).
pub type UISize {
  SizeXxl
  SizeXl
  SizeLg
  SizeMd
  SizeSm
  SizeXs
  SizeXxs
}

Constructors

  • SizeXxl

    2xl

  • SizeXl

    xl

  • SizeLg

    lg

  • SizeMd

    md

  • SizeSm

    sm

  • SizeXs

    xs

  • SizeXxs

    2xs

Tipo auxiliar para juntar tamanho e localização de um elemento visual.

pub type UISizeLayout =
  #(UISize, UILayout)

Controlar o empilhamento dos elementos no eixo Z.

pub type UIStacking {
  StackBase
  StackFloat
  StackSticky
  StackDropdown
  StackOverlay
  StackModal
  StackToast
  StackTooltip
}

Constructors

  • StackBase

    z-0

  • StackFloat

    z-10

  • StackSticky

    z-20

  • StackDropdown

    z-30

  • StackOverlay

    z-40

  • StackModal

    z-50

  • StackToast

    z-60

  • StackTooltip

    z-70

Estado de um elemento.

pub type UIState {
  StateIdle
  StateLoading
  StateDisabled
  StatePressed
}

Constructors

  • StateIdle

    Intocado ou parado (Padrão)

  • StateLoading

    Aguardando processamento

  • StateDisabled

    Desligado ou não acessível

  • StatePressed

    Sendo precionado

Dados para construir um tema a partir dos tipos de tema, os design tokens.

  • painter: Dados do pintor do tema, os design tokens em ADTs.
  • builder: Dados do motor para converter os tipos Gleam em design tokens específicos para a interface visual utilizada.

Exemplo

Abaixo temos um código utilizando o sistema de tipos Gleam para representar o tema de um elemento HTML <div>. Utilizamos como estrutura de dados para nossos design tokens finais, uma tupla List(#(String, True)), compatível com a função lustre attribute.classes(), que aplica os tokens tailwind

 import lustre/attribute as a
 import lustre/element/html as h

 import gbr/ui/theme

 pub fn main() {
   let builder_variant = fn (variant) {
     [
       #("bg-amber-700", theme.is_primary(variant)),
       #("bg-gray-500", theme.is_not_primary(variant)),
     ]
   }

   theme.new()
   |> theme.with_variant(theme.primary())
   |> theme.with_builder_variant(builder_variant)
   |> theme.view(fn (tokens) {
     h.div([a.classes(tokens)], [h.text("Olá mundo temático!")])
   })
 }
  • tokens: Representar os tokens finais, possibilita ser qualquer estrutura de dados, é um tipo genérico.
pub opaque type UITheme(tokens)

Variante semântica, conhecido como tema, de um elemento.

pub type UIVariant {
  VariantDefault
  VariantPrimary
  VariantSecondary
  VariantTertiary
  VariantSuccess
  VariantWarning
  VariantError
  VariantInfo
}

Constructors

  • VariantDefault
  • VariantPrimary

    A variante principal do tema.

  • VariantSecondary

    A variante secundaria do tema.

  • VariantTertiary

    A variante de fallback do tema.

  • VariantSuccess

    A variante de sucesso do tema.

  • VariantWarning

    A variante de alerta do tema.

  • VariantError

    A variante de erro do tema.

  • VariantInfo

    A variante de info do tema.

Values

pub fn alignment_rotate(align: UIAlignment) -> UIAlignment

Rotaciona o alinhamento de um tema de layout. (rotate-180)

pub fn disabled() -> UIState
pub fn error() -> UIVariant
pub fn filled() -> UIAppearance
pub fn ghost() -> UIAppearance
pub fn idle() -> UIState
pub fn info() -> UIVariant
pub fn is_not_primary(variant: UIVariant) -> Bool
pub fn is_primary(variant: UIVariant) -> Bool
pub fn layout_absolute(axis: UIAbsolute) -> UILayout
pub fn layout_absolute_axis(
  horizontal: UIAlignment,
  vertical: UIAlignment,
) -> UILayout
pub fn layout_flow(flow: UIFlow) -> UILayout
pub fn layout_flow_content(
  main: UIAlignment,
  cross_content: UIAlignment,
) -> UILayout
pub fn layout_flow_cross_content(main: UIAlignment) -> UILayout
pub fn layout_flow_cross_items(main: UIAlignment) -> UILayout
pub fn layout_flow_items(
  main: UIAlignment,
  cross_items: UIAlignment,
) -> UILayout
pub fn layout_flow_main(main: UIAlignment) -> UILayout
pub fn layout_rotate(layout: UILayout) -> UILayout

Rotaciona todo o tema de layout. (rotate-180)

pub fn light() -> UIAppearance
pub fn loading() -> UIState
pub fn new() -> UITheme(tokens)

NOVO THEME BUILDER

Criar novo tema e motor de elementos visuais estilizados.

  • theme: Cria um tema padrão.
  • builder: Cria um construtor de temas padrão, uma lista do tipo genérico.
pub fn paint(theme: UITheme(token)) -> List(token)

PAINT THEME

Converte o tema em tokens de design, utilizando o construtor de tokens.

  • theme: O tema que será convertido.
  • builder: O construtor de tokens que será utilizado.
  • with: O tema base que será utilizado.
pub fn pressed() -> UIState
pub fn primary() -> UIVariant
pub fn rounded_absolute(
  size: UISize,
  absolute: UIAbsolute,
) -> UIShape
pub fn secondary() -> UIVariant
pub fn shape_circle() -> UIShape
pub fn shape_pill() -> UIShape
pub fn shape_rounded() -> UIShape
pub fn shape_rounded_all(size: UISize) -> UIShape
pub fn shape_sharp() -> UIShape
pub fn size_decrement(size: UISize) -> UISize
pub fn size_decrement_count(size: UISize, count: Int) -> UISize
pub fn success() -> UIVariant
pub fn tertiary() -> UIVariant
pub fn view(
  apply theme: UITheme(token),
  in to_element: fn(List(token)) -> a,
) -> a

Construtor de uma visualização de um elemento injetado, aplicando o tema passado como argumento da função e a base dos tokens do estilo do elemento.

  • theme: Os dados do tema a ser aplicado ao elemento injetado.
  • build: Os dados de como construir os design tokens a partir do tema.
  • with: Base de estilos, design tokens, para ser aplicado ao elemento.
  • to: Função para injetar o construtor de um elemento visual genérico.

a: Tipo fantasma que representa o elemento sendo criado e estilizado.

pub fn warning() -> UIVariant
pub fn with_appearance(
  theme: UITheme(tokens),
  appearance appearance: UIAppearance,
) -> UITheme(tokens)
pub fn with_base_to_tokens(
  theme: UITheme(token),
  base_to_tokens: fn() -> List(token),
) -> UITheme(token)

Converte para tokens iniciais, padrão, de estilização.

pub fn with_design(
  theme: UITheme(tokens),
  variant variant: UIVariant,
  appearance appearance: UIAppearance,
  state state: UIState,
) -> UITheme(tokens)
pub fn with_design_to_tokens(
  theme: UITheme(token),
  design_to_tokens: fn(UIVariant, UIAppearance, UIState) -> List(
    token,
  ),
) -> UITheme(token)

Converte uma variante do tema em tokens.

pub fn with_elevation(
  theme: UITheme(tokens),
  elevation: option.Option(UIElevation),
) -> UITheme(tokens)
pub fn with_elevation_default(
  theme: UITheme(token),
  elevation: UIElevation,
) -> UITheme(token)

Elevação padrão, caso o tema não contenha um determinado.

pub fn with_elevation_to_tokens(
  theme: UITheme(token),
  elevation_to_tokens: fn(UIElevation) -> List(token),
) -> UITheme(token)

Converte uma elevação do tema em tokens.

pub fn with_layout(
  theme: UITheme(tokens),
  layout layout: option.Option(UILayout),
) -> UITheme(tokens)
pub fn with_layout_to_tokens(
  theme: UITheme(token),
  layout_to_tokens: fn(UILayout) -> List(token),
) -> UITheme(token)

Converte um tamanho do tema em tokens.

pub fn with_shape(
  theme: UITheme(tokens),
  shape shape: option.Option(UIShape),
) -> UITheme(tokens)
pub fn with_shape_default(
  theme: UITheme(token),
  shape: UIShape,
) -> UITheme(token)

Superfície padrão, caso o tema não contenha um determinado.

pub fn with_shape_to_tokens(
  theme: UITheme(token),
  shape_to_tokens: fn(UIShape) -> List(token),
) -> UITheme(token)

Converte uma superfície visual do tema em tokens.

pub fn with_size(
  theme: UITheme(tokens),
  size size: option.Option(UISize),
) -> UITheme(tokens)
pub fn with_size_default(
  theme: UITheme(token),
  size: UISize,
) -> UITheme(token)

Tamanho padrão, caso o tema não contenha um tamanho determinado.

pub fn with_size_to_tokens(
  theme: UITheme(token),
  size_to_tokens: fn(UISize) -> List(token),
) -> UITheme(token)

Converte um tamanho do tema em tokens.

pub fn with_stacking(
  theme: UITheme(tokens),
  stacking stacking: option.Option(UIStacking),
) -> UITheme(tokens)
pub fn with_stacking_default(
  theme: UITheme(token),
  stacking: UIStacking,
) -> UITheme(token)

Empilhamento padrão, caso o tema não contenha um determinado.

pub fn with_stacking_to_tokens(
  theme: UITheme(token),
  stacking_to_tokens: fn(UIStacking) -> List(token),
) -> UITheme(token)

Converte uma pilha visual do tema em tokens.

pub fn with_state(
  theme: UITheme(tokens),
  state state: UIState,
) -> UITheme(tokens)
pub fn with_variant(
  theme: UITheme(tokens),
  variant variant: UIVariant,
) -> UITheme(tokens)
pub fn without_elevation(
  theme: UITheme(tokens),
) -> UITheme(tokens)

Remove a elevação do elemento

pub fn without_shape(theme: UITheme(tokens)) -> UITheme(tokens)

Remove a superfície de um elemento

pub fn without_size(theme: UITheme(tokens)) -> UITheme(tokens)

Remove o tamanho de um elemento.

pub fn without_stacking(
  theme: UITheme(tokens),
) -> UITheme(tokens)

Remove o empilhamento do elemento.

✨ Search Document