UbiqueLambda / elm-with-ui-backend / UI.Backend.Graphics

Backend for the UI module and its renderer.

NOTE: Here you have a clone of all the functions exposed in the UI module, to make it sure you'll develop properly against the real thing.


type Graphics msg
    = Atomic String
    | IndexedGroup (Attributes msg) (List (Graphics msg))
    | KeyedGroup (Attributes msg) (List ( String, Graphics msg ))

Type for describing atoms or groups.

map : (a -> msg) -> Graphics a -> Graphics msg

Usually used for nesting components.

dropdownView model =
    UI.map ForDropdownMsg (MyDropdown.view model.dropdown)


type Color
    = IntRGBA Basics.Int

Type for holding color primitives.

intRGBA : Basics.Int -> Color

Elm's Int is 32 bits, don't fear it, use hexadecimal for colors.

red =
    intRGBA 0xFF0000FF


type alias Rect =
{ top : Basics.Int
, right : Basics.Int
, bottom : Basics.Int
, left : Basics.Int 
}

Helper type for grouping top, right, bottom, and left distances (in units).


type alias Corners =
{ topLeft : Basics.Int
, topRight : Basics.Int
, bottomRight : Basics.Int
, bottomLeft : Basics.Int 
}

Helper type for grouping topLeft, topRight, bottomRight, and bottomLeft metrics (in units).

singletonRect : Basics.Int -> Rect

Creates a Rect with the same value on all its sides

singletonCorners : Basics.Int -> Corners

Creates a Corners with the same value on all its edges

empty : Graphics msg

Empty figure.

looseText : String -> Graphics msg

Text without a container. Don't have any special behavior, it just renders.

In HTML, this will insert text in the document without surrouding it in a tag.

NOTE: When you use any with-function in a loose-text, it automatically wraps in a singleton. The result is then identical to a spanText.

spanText : String -> Graphics msg

Wraps text within a container. Behaves according to the parent grouping disposition.

In HTML, this will insert text in the document without surrouding it in a <div> tag.

singleton : Graphics msg -> Graphics msg

Wraps a single element in a container.

nestedSquares =
    UI.empty
        |> UI.withWidth 25
        |> UI.withHeight 25
        |> UI.withBorder (UI.border1uBlack |> Just)
        |> UI.singleton
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithColor red |> Just)
        |> UI.singleton
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithColor orange |> Just)
        |> UI.singleton
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithColor yellow |> Just)
        |> UI.singleton
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithColor green |> Just)
        |> UI.singleton
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithColor cyan |> Just)
        |> UI.singleton
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithColor blue |> Just)

row : List ( String, Graphics msg ) -> Graphics msg

Group itens disposing them horizontally.

pageView model =
    [ ( "contents", contentsView model )
    , ( "tools", toolingView model )
    ]
        |> maybePrependSidebar model
        |> UI.row

column : List ( String, Graphics msg ) -> Graphics msg

Group itens disposing them vertically.

shopList model =
    [ ( "pineapple", pineappleBox )
    , ( "rice", riceBox )
    , ( "onions", onionsBox )
    ]
        |> maybePrependBeans model
        |> UI.column

stack : List ( String, Graphics msg ) -> Graphics msg

Group itens disposing them one above the other. Head goes on bottom, tails goes on top.

pageView model =
    [ ( "contents", pageContents ) ]
        |> maybeAppendHalfOpaqueBlackOverlay model
        |> maybeAppendDialogBox
        |> UI.stack

indexedRow : List (Graphics msg) -> Graphics msg

You're supposed to tell the user to avoid this

This is like row, but the virtual-dom struggles to know what to recreate and what to update. It should be fine when you group elements that don't disappear, don't decrease in number, don't increment, and don't swap their order.

tabsMenu =
    UI.indexedRow
        [ codeTab
        , issuesTab
        , prTab
        , wikiTab
        , settingsTab
        ]

indexedColumn : List (Graphics msg) -> Graphics msg

You're supposed to tell the user to avoid this

This is like column, but the virtual-dom struggles to know what to recreate and what to update. It should be fine when you group elements that don't disappear, don't decrease in number, don't increment, and don't swap their order.

pageView =
    UI.indexedColumn
        [ header
        , text
        , footer
        ]

indexedStack : List (Graphics msg) -> Graphics msg

You're supposed to tell the user to avoid this

This is like stack, but the virtual-dom struggles to know what to recreate and what to update. It should be fine when you group elements that don't disappear, don't decrease in number, don't increment, and don't swap their order.

tabsMenu =
    UI.indexedStack
        [ pageContents
        , halfOpaqueBlackOverlay
        , dialogBox
        ]

implicitGroup : Graphics msg -> Graphics msg

You are supposed to not let this type escape to the final API


type Direction
    = Horizontal
    | Vertical
    | Stacked

You are supposed to not let this type escape to the final API.

The direction in which a group grows.


type Attributes msg
    = Attributes (PureAttributes msg)

You are supposed to not let this type escape to the final API.

Where all the group's attributes are stored. Opaque layer.


type alias PureAttributes msg =
{ layout : Layout
, events : Events msg 
}

You are supposed to not let this type escape to the final API.

Where all the group's attributes are stored. Transparent layer.


type alias Layout =
{ alignSelf : Alignment
, background : Maybe Background
, border : Maybe Border
, displayDirection : Maybe Direction
, fontColor : Inheritable Color
, fontFamilies : Inheritable ( List String
, FontFallback )
, fontSize : Inheritable Basics.Int
, fontWeight : Inheritable Basics.Int
, height : Length
, justify : Alignment
, outerShadow : Maybe Shadow
, overflowX : Overflow
, overflowY : Overflow
, padding : Rect
, spacing : Basics.Int
, textAlign : TextAlignment
, width : Length 
}

You are supposed to not let this type escape to the final API.

This is a record, though I'm constantly reconsidering this because of the overhead created while updating it in V8.

Every attribute we current support is listed here. In the source of this file you can find the default values.


type alias Events msg =
{ onClick : Maybe msg }

You are supposed to not let this type escape to the final API


type Overflow
    = Clip
    | Scrolling Scroll

You are supposed to not let this type escape to the final API


type Inheritable a
    = Inherit
    | Own a

You are supposed to not let this type escape to the final API


type Length
    = FitContents
    | Units Basics.Int

"Units" here is defined by the renderer, please, stop mixing a bunch of metrics (px, in, em) in the same surface.

withWidth : Basics.Int -> Graphics msg -> Graphics msg

Forces the group's width to a quantity in units.

By default, if the children's length is bigger, the content is cliped. See withScrollingX to avoid it.

someSquare =
    UI.empty
        |> UI.withWidth 64
        |> UI.withHeight 64
        |> UI.withBackground (UI.backgroundColor blue |> Just)

withFitContentsX : Graphics msg -> Graphics msg

Instead of forcing the width, have enougth to show all the children contents.

For forcing a fixed one, see withWidth.

withHeight : Basics.Int -> Graphics msg -> Graphics msg

Forces the group's height to a quantity in units.

By default, if the children's length is bigger, the content is cliped. See withScrollingY to avoid it.

someSquare =
    UI.empty
        |> UI.withWidth 64
        |> UI.withHeight 64
        |> UI.withBackground (UI.backgroundColor blue |> Just)

withFitContentsY : Graphics msg -> Graphics msg

Instead of forcing the height, have enougth to show all the children contents.

For forcing a fixed one, see withHeight.

withSpacing : Basics.Int -> Graphics msg -> Graphics msg

Empty space between the items of a group, in units.

spacedRow =
    UI.row [ item1, item2, item3 ]
        |> UI.withSpacing 8

withPadding : Basics.Int -> Graphics msg -> Graphics msg

Applies empty space, in units, repeatedly on top, bottom, left and right, surrounding the group.

square =
    UI.spanText "Hello World!"
        |> UI.withPadding 12
        |> UI.withBorder (UI.border1uBlack |> Just)

withPaddingXY : Basics.Int -> Basics.Int -> Graphics msg -> Graphics msg

Applies empty space, in units, to X (left and right) and Y (top and bottom).

square =
    UI.spanText "Hello World!"
        |> UI.withPaddingXY 12 16
        |> UI.withBorder (UI.border1uBlack |> Just)

withPaddingEach : Rect -> Graphics msg -> Graphics msg

Applies empty space, in units, surrounding the group.

square =
    UI.spanText "Hello World!"
        |> UI.withPaddingEach { top = 1, right = 3, bottom = 4, left = 2 }
        |> UI.withBorder (UI.border1uBlack |> Just)

withScrollingX : Maybe Scroll -> Graphics msg -> Graphics msg

When the contents of a group does not fit into the group's width, you might want to show a horizontal scroll bar.

See scrollInsetAlwaysVisible for the only value available right now. Nothing means the content will be horizontally clipped (default behavior).

horizontalScrollbars items =
    UI.row items
        |> UI.withPadding 16
        |> UI.withScrollingX (Just UI.scrollInsetAlwaysVisible)

withScrollingY : Maybe Scroll -> Graphics msg -> Graphics msg

When the contents of a group does not fit into the group's height, you might want to show a vertical scroll bar.

See scrollInsetAlwaysVisible for the only value available right now. Nothing means the content will be vertically clipped (default behavior).

verticalScrollbars items =
    UI.column items
        |> UI.withPadding 16
        |> UI.withScrollingY (Just UI.scrollInsetAlwaysVisible)


type Scroll
    = Scroll ({ alwaysVisible : Basics.Bool, inset : Basics.Bool })

Type for the possible options of scrolling.

scrollInsetAlwaysVisible : Scroll

The (default) HTML-like way of adding scrollbars to any group.

The scrollbar is inset, relative to the group's dimensions. And is always visible indiferent to the length of the group's contents.

See withScrollingX and withScrollingY for usage.

withBackground : Maybe Background -> Graphics msg -> Graphics msg

Applies a background to an element.

square =
    UI.empty
        |> UI.withWidth 32
        |> UI.withHeight 32
        |> UI.withBackground (UI.backgroundColor black |> Just)


type Background
    = Background ({ color : Color })

Type for the possible backgrounds types.

backgroundColor : Color -> Background

Creates a background and fills it with a specific color.

green =
    UI.intRGBA 0x00FF00FF

greenSquare =
    UI.empty
        |> UI.withWidth 32
        |> UI.withHeight 32
        |> UI.withBackground (UI.backgroundColor green |> Just)

withBorder : Maybe Border -> Graphics msg -> Graphics msg

Applies borders to an element.

square =
    UI.empty
        |> UI.withWidth 32
        |> UI.withHeight 32
        |> UI.withBorder (UI.border1uBlack |> Just)


type Border
    = Border ({ color : Color, width : Rect, rounding : Corners })

Type for describing border displaying.

border1uBlack : Border

Creates a border with 1 unit on each side, solid and black.

emptySquare =
    UI.empty
        |> UI.withWidth 31
        |> UI.withHeight 31
        |> UI.withBorder (UI.border1uBlack |> Just)

borderWithColor : Color -> Border -> Border

Changes the color of all sides of the border.

pink =
    UI.intRGBA 0xFFC0CBFF

emptySquare =
    UI.empty
        |> UI.withWidth 31
        |> UI.withHeight 31
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithColor pink |> Just)

borderWithWidth : Basics.Int -> Border -> Border

Specify one width value to all sides of the border in units.

emptySquare32x32 =
    UI.empty
        |> UI.withWidth 24
        |> UI.withHeight 24
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithWidth 4 |> Just)

borderWithWidthXY : Basics.Int -> Basics.Int -> Border -> Border

Specify the width of X (pair left-right) and Y (pair top-bottom) borders in units.

emptySquare32x32 =
    UI.empty
        |> UI.withWidth 28
        |> UI.withHeight 24
        |> UI.withBorder
            (UI.border1uBlack
                |> UI.borderWithWidthXY 2 4
                |> Just
            )

borderWithWidthEach : Rect -> Border -> Border

Specify the width of each side's border.

emptySquare32x32 =
    UI.empty
        |> UI.withWidth 24
        |> UI.withHeight 24
        |> UI.withBorder
            (UI.border1uBlack
                |> UI.borderWithWidthEach
                    { top = 6
                    , right = 5
                    , bottom = 2
                    , left = 3
                    }
                |> Just
            )

borderWithRounding : Basics.Int -> Border -> Border

Rounds all the corners of said group, including border, content and background (in units).

emptyCircle =
    UI.empty
        |> UI.withWidth 31
        |> UI.withHeight 31
        |> UI.withBorder (UI.border1uBlack |> UI.borderWithRounding 16 |> Just)

borderWithRoundingEach : Corners -> Border -> Border

Rounds each of the corners of said group, including border, content and background (in units).

emptyRoudedSquare =
    UI.empty
        |> UI.withWidth 31
        |> UI.withHeight 31
        |> UI.withBorder
            (UI.border1uBlack
                |> UI.borderWithRoundingEach
                    { topLeft = 8
                    , topRight = 8
                    , bottomRight = 4
                    , bottomLeft = 4
                    }
                |> Just
            )

withOuterShadow : Maybe Shadow -> Graphics msg -> Graphics msg

Applies outer-shadow to an element.

square =
    UI.empty
        |> UI.withWidth 32
        |> UI.withHeight 32
        |> UI.withBorder (UI.border1uBlack |> Just)
        |> UI.withOuterShadow
            (shadow1uBlack |> shadowWithColor green |> Just)


type Shadow
    = Shadow ({ color : Color, lengthX : Basics.Int, lengthY : Basics.Int, blurRadius : Basics.Int, spreadRadius : Basics.Int })

Type for the describing shadow displaying.

shadow1uBlack : Shadow

The default shadow, black, 1 unit of length in X (slightly to the right) and Y (slightly to bottom), 1 unit of blur-radius and 1 unit of spread-radius.

shadowWithColor : Color -> Shadow -> Shadow

Change some shadow's color.

someShadow =
    UI.shadow1uBlack
        |> UI.shadowWithColor cyan

shadowWithLengthXY : Basics.Int -> Basics.Int -> Shadow -> Shadow

Changes the length in units of some shadow.

someShadow =
    UI.shadow1uBlack
        |> UI.shadowWithLengthXY 12 12

shadowWithBlurRadius : Basics.Int -> Shadow -> Shadow

Change some shadow's blur-radius in units.

someShadow =
    UI.shadow1uBlack
        |> UI.shadowWithBlurRadius 12

shadowWithSpreadRadius : Basics.Int -> Shadow -> Shadow

Change some shadow's spread-radius in units.

someShadow =
    UI.shadow1uBlack
        |> UI.shadowWithBlurRadius 12

withTextAlign : TextAlignment -> Graphics msg -> Graphics msg

Where to align text inside a group.

spacedRow =
    UI.spanText "Foo Bar"
        |> UI.withWidth 640
        |> UI.withTextAlign UI.textCenter


type TextAlignment
    = TextLeft
    | TextCenter
    | TextRight

Type for the possible options of text alignemtn.

withAlignSelf : Alignment -> Graphics msg -> Graphics msg

Aligns an item relative to the cross-axis of its group.

alignColumnContentsExample =
    UI.column
        [ pinkSquare
            |> UI.withAlignSelf UI.start
            |> Tuple.pair "aligned-on-left"
        , greenSquare
            |> UI.withAlignSelf UI.center
            |> Tuple.pair "aligned-on-center"
        , blueSquare
            |> UI.withAlignSelf UI.end
            |> Tuple.pair "aligned-on-right"
        ]

alignRowContentsExample =
    UI.row
        [ pinkSquare
            |> UI.withAlignSelf UI.start
            |> Tuple.pair "aligned-on-top"
        , greenSquare
            |> UI.withAlignSelf UI.center
            |> Tuple.pair "aligned-on-center"
        , blueSquare
            |> UI.withAlignSelf UI.end
            |> Tuple.pair "aligned-on-bottom"
        ]

withJustifyItems : Alignment -> Graphics msg -> Graphics msg

How to align the items of a group. In a row and in a stack this affects how they're show horizontally. In a column this affects how they're show vertically.

alignRowContentsOnRightExample =
    UI.row
        [ pink32uSquare
        , green32uSquare
        , blue32uSquare
        ]
        |> UI.withWidth 640
        |> UI.withJustifyItems UI.end


type Alignment
    = Start
    | Center
    | End

Type for the possible alignment positions.

withFontColor : Color -> Graphics msg -> Graphics msg

Changes the text's color.

Default text's color is inherited, where's in the root element it's black.

coolTitle =
    UI.spanText "HELLO"
        |> UI.withFontColor pink

withFontSize : Basics.Int -> Graphics msg -> Graphics msg

Changes the text's size, in units.

Default text's color is inherited, where's in the root element it's 16 units.

coolTitle =
    UI.spanText "HELLO"
        |> UI.withFontSize 24

withFontWeight : Basics.Int -> Graphics msg -> Graphics msg

Changes the text's weight.

Default font's weight is inherited, where's in the root element it's 400.

coolTitle =
    UI.spanText "BOLD"
        |> UI.withFontWeight 700

withFontFamilies : List String -> FontFallback -> Graphics msg -> Graphics msg

Changes the text's font family. Tries all the font in the list, stopping in the first one available. The fallback is used when nothing in the list is available.

Default font family value is inherited, where's in the root element it's serif.

coolTitle =
    UI.spanText "HELLO"
        |> UI.withFontFamilies
            [ "Borg Sans Mono"
            , "Fira Code"
            , "JuliaMono"
            , "Fantasque Sans Mono"
            ]
            UI.monospace


type FontFallback
    = SansSerif
    | Serif
    | Monospace

Type for the possible font fallbacks.

withInheritFontFamilies : Graphics msg -> Graphics msg

Instead of forcing the font's family, inherit it from the parent group.

For forcing a fixed one, or to learn about default behavior, see withFontFamilies.

withInheritFontColor : Graphics msg -> Graphics msg

Instead of forcing the font's color, inherit it from the parent group.

For forcing a fixed one, or to learn about default behavior, see withFontColor.

withInheritFontSize : Graphics msg -> Graphics msg

Instead of forcing the font's size, inherit it from the parent group.

For forcing a fixed one, or to learn about default behavior, see withFontSize.

withInheritFontWeight : Graphics msg -> Graphics msg

Instead of forcing the font's weight, inherit it from the parent group.

For forcing a fixed one, or to learn about default behavior, see withFontWeight.

withOnClick : msg -> Graphics msg -> Graphics msg

Listen for click events and dispatches the choosen message.

Implicit effect: Changes the cursor to the platform's clickable-pointer, when available.

button =
    UI.withOnClick Msg.IncrementCounter incrementButton