all repos

onasty @ 7a1da0f

a one-time notes service

onasty/web/src/Components/Form.elm(view raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
module Components.Form exposing (ButtonStyle(..), CanBeClicked, button, input, submitButton)

import Html as H exposing (Html)
import Html.Attributes as A
import Html.Events as E



-- INPUT


input :
    -- TODO: add `error : Maybe String`, to show that field is not correct and message
    { id : String
    , field : field
    , label : String
    , type_ : String
    , value : String
    , placeholder : String
    , required : Bool
    , helpText : Maybe String
    , prefix : Maybe String
    , onInput : String -> msg
    }
    -> Html msg
input opts =
    H.div [ A.class "space-y-2" ]
        [ H.label
            [ A.for opts.id
            , A.class "block text-sm font-medium text-gray-700"
            ]
            [ H.text opts.label ]
        , H.div
            [ A.class
                (if opts.prefix /= Nothing then
                    "flex items-center"

                 else
                    ""
                )
            ]
            [ case opts.prefix of
                Just prefix ->
                    H.span [ A.class "text-gray-500 text-md mr-2 whitespace-nowrap" ] [ H.text prefix ]

                Nothing ->
                    H.text ""
            , H.input
                [ A.class "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent"
                , A.type_ opts.type_
                , A.value opts.value
                , A.id opts.id
                , A.placeholder opts.placeholder
                , A.required opts.required
                , E.onInput opts.onInput
                ]
                []
            ]
        , case opts.helpText of
            Just help ->
                H.p [ A.class "text-xs text-gray-500 mt-1" ] [ H.text help ]

            Nothing ->
                H.text ""
        ]



-- BUTTON


type alias CanBeClicked =
    Bool


type ButtonStyle
    = Primary CanBeClicked
    | Secondary CanBeClicked
    | SecondaryDisabled CanBeClicked
    | SecondaryDanger


button : { text : String, disabled : Bool, onClick : msg, style : ButtonStyle } -> Html msg
button opts =
    H.button
        [ A.type_ "button"
        , E.onClick opts.onClick
        , A.class (buttonStyleToClass opts.style "")
        , A.disabled opts.disabled
        ]
        [ H.text opts.text ]


submitButton : { text : String, disabled : Bool, class : String, style : ButtonStyle } -> Html msg
submitButton opts =
    H.button
        [ A.type_ "submit"
        , A.class (buttonStyleToClass opts.style opts.class)
        , A.disabled opts.disabled
        ]
        [ H.text opts.text ]


buttonStyleToClass : ButtonStyle -> String -> String
buttonStyleToClass style appendClasses =
    case style of
        Primary canBeClicked ->
            getButtonClasses canBeClicked
                appendClasses
                "px-6 py-2 bg-gray-300 text-gray-500 rounded-md cursor-not-allowed transition-colors"
                "px-6 py-2 bg-black text-white rounded-md hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 transition-colors"

        SecondaryDanger ->
            "text-gray-600 hover:text-red-600 transition-colors"

        Secondary canBeClicked ->
            getButtonClasses canBeClicked
                appendClasses
                "px-4 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 transition-colors bg-green-100 border-green-300 text-green-700"
                "px-4 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 transition-colors border-gray-300 text-gray-700 hover:bg-gray-50"

        SecondaryDisabled canBeClicked ->
            getButtonClasses canBeClicked
                appendClasses
                "w-full px-4 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 transition-colors mt-3 border border-gray-300 text-gray-400 cursor-not-allowed"
                "w-full px-4 py-2 rounded-md focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 transition-colors mt-3 border border-gray-300 text-gray-700 hover:bg-gray-50"


getButtonClasses : Bool -> String -> String -> String -> String
getButtonClasses cond extend whenTrue whenFalse =
    let
        cls =
            if String.isEmpty extend then
                ""

            else
                " " ++ extend
    in
    if cond then
        whenTrue ++ cls

    else
        whenFalse ++ cls