all repos

onasty @ 8f21410f5a406eb22fba42206d10c63fea8151c7

a one-time notes service

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

Olexandr Smirnov Olexandr Smirnov
ss2316544@gmail.com
web: button component; improve code consistency (#168)..., 10 months ago
1
module Components.Form exposing (ButtonStyle(..), CanBeClicked, button, input, submitButton)
2
3
import Html as H exposing (Html)
4
import Html.Attributes as A
5
import Html.Events as E
6
7
8
9
-- INPUT
10
11
12
input :
13
    -- TODO: add `error : Maybe String`, to show that field is not correct and message
14
    { id : String
15
    , field : field
16
    , label : String
17
    , type_ : String
18
    , value : String
19
    , placeholder : String
20
    , required : Bool
21
    , helpText : Maybe String
22
    , prefix : Maybe String
23
    , onInput : String -> msg
24
    }
25
    -> Html msg
26
input opts =
27
    H.div [ A.class "space-y-2" ]
28
        [ H.label
29
            [ A.for opts.id
30
            , A.class "block text-sm font-medium text-gray-700"
31
            ]
32
            [ H.text opts.label ]
33
        , H.div
34
            [ A.class
35
                (if opts.prefix /= Nothing then
36
                    "flex items-center"
37
38
                 else
39
                    ""
40
                )
41
            ]
42
            [ case opts.prefix of
43
                Just prefix ->
44
                    H.span [ A.class "text-gray-500 text-md mr-2 whitespace-nowrap" ] [ H.text prefix ]
45
46
                Nothing ->
47
                    H.text ""
48
            , H.input
49
                [ 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"
50
                , A.type_ opts.type_
51
                , A.value opts.value
52
                , A.id opts.id
53
                , A.placeholder opts.placeholder
54
                , A.required opts.required
55
                , E.onInput opts.onInput
56
                ]
57
                []
58
            ]
59
        , case opts.helpText of
60
            Just help ->
61
                H.p [ A.class "text-xs text-gray-500 mt-1" ] [ H.text help ]
62
63
            Nothing ->
64
                H.text ""
65
        ]
66
67
68
69
-- BUTTON
70
71
72
type alias CanBeClicked =
73
    Bool
74
75
76
type ButtonStyle
77
    = Primary CanBeClicked
78
    | Secondary CanBeClicked
79
    | SecondaryDisabled CanBeClicked
80
    | SecondaryDanger
81
82
83
button : { text : String, disabled : Bool, onClick : msg, style : ButtonStyle } -> Html msg
84
button opts =
85
    H.button
86
        [ A.type_ "button"
87
        , E.onClick opts.onClick
88
        , A.class (buttonStyleToClass opts.style "")
89
        , A.disabled opts.disabled
90
        ]
91
        [ H.text opts.text ]
92
93
94
submitButton : { text : String, disabled : Bool, class : String, style : ButtonStyle } -> Html msg
95
submitButton opts =
96
    H.button
97
        [ A.type_ "submit"
98
        , A.class (buttonStyleToClass opts.style opts.class)
99
        , A.disabled opts.disabled
100
        ]
101
        [ H.text opts.text ]
102
103
104
buttonStyleToClass : ButtonStyle -> String -> String
105
buttonStyleToClass style appendClasses =
106
    case style of
107
        Primary canBeClicked ->
108
            getButtonClasses canBeClicked
109
                appendClasses
110
                "px-6 py-2 bg-gray-300 text-gray-500 rounded-md cursor-not-allowed transition-colors"
111
                "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"
112
113
        SecondaryDanger ->
114
            "text-gray-600 hover:text-red-600 transition-colors"
115
116
        Secondary canBeClicked ->
117
            getButtonClasses canBeClicked
118
                appendClasses
119
                "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"
120
                "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"
121
122
        SecondaryDisabled canBeClicked ->
123
            getButtonClasses canBeClicked
124
                appendClasses
125
                "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"
126
                "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"
127
128
129
getButtonClasses : Bool -> String -> String -> String -> String
130
getButtonClasses cond extend whenTrue whenFalse =
131
    let
132
        cls =
133
            if String.isEmpty extend then
134
                ""
135
136
            else
137
                " " ++ extend
138
    in
139
    if cond then
140
        whenTrue ++ cls
141
142
    else
143
        whenFalse ++ cls