Skip to content

Commit 9fb85ee

Browse files
authored
DragDropHalogen - Simplify input in label (#155)
* DragDropHalogen - Simplify input in label * Filter images
1 parent 3da51ba commit 9fb85ee

File tree

2 files changed

+47
-33
lines changed

2 files changed

+47
-33
lines changed

recipes/DragAndDropHalogenHooks/src/Main.purs

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ module DragAndDropHalogenHooks.Main where
22

33
import Prelude hiding (top)
44

5-
import CSS (alignItems, border, borderRadius, color, column, dashed, display, displayNone, flex, flexDirection, gray, height, justifyContent, margin, padding, purple, px, solid, width)
5+
import CSS (alignItems, backgroundColor, border, borderRadius, color, column, dashed, display, displayNone, flex, flexDirection, gray, height, justifyContent, lightblue, margin, padding, purple, px, solid, width)
66
import CSS as CSS
77
import CSS.Common (center)
8+
import DOM.HTML.Indexed.InputAcceptType (mediaType)
89
import DOM.HTML.Indexed.InputType (InputType(..))
910
import Data.Interpolate (i)
1011
import Data.Maybe (Maybe(..), maybe)
12+
import Data.MediaType (MediaType(..))
1113
import Data.String (toUpper)
1214
import Data.Tuple.Nested ((/\))
1315
import Effect (Effect)
@@ -69,40 +71,53 @@ hookComponent = Hooks.component \_ _ -> Hooks.do
6971
mbFileList = DataTransfer.files $ dataTransfer e
7072
fileArray = maybe [] FileList.items mbFileList
7173
Hooks.put filesIdx fileArray
74+
Hooks.put hoverIdx false
7275
]
73-
-- Note: Elm uses a button that, when clicked, will do the following:
74-
-- 1. create an input element
75-
-- 2. add it to the DOM
76-
-- 3. create a mouse event
77-
-- 4. dispatch the mouse event to the input element
78-
-- 5. (implication) file dialogue appears
79-
-- 6. user selects a file
80-
-- 7. input event handler runs a callback using user's selected file
81-
-- 8. input element is removed from DOM
82-
--
83-
-- The approach used below is based on this SO answer:
84-
-- https://stackoverflow.com/a/47094148
8576
[ HH.label
86-
[ HP.for "file-input" ]
87-
[ HH.div
88-
-- simulate button-like appearance
89-
[ HC.style do
90-
margin (px 4.0) (px 4.0) (px 4.0) (px 4.0)
91-
border solid (px 2.0) gray
92-
borderRadius (px 20.0) (px 20.0) (px 20.0) (px 20.0)
93-
padding (px 20.0) (px 20.0) (px 20.0) (px 20.0)
94-
, HP.class_ $ ClassName "otherCssNotInPurescript-Css"
95-
]
96-
[ HH.text "Upload images" ]
77+
-- simulate button-like appearance
78+
[ HC.style do
79+
margin (px 4.0) (px 4.0) (px 4.0) (px 4.0)
80+
border solid (px 2.0) gray
81+
borderRadius (px 20.0) (px 20.0) (px 20.0) (px 20.0)
82+
padding (px 20.0) (px 20.0) (px 20.0) (px 20.0)
83+
backgroundColor lightblue
84+
, HP.class_ $ ClassName "otherCssNotInPurescript-Css"
85+
]
86+
[ HH.text "Upload images"
87+
, HH.input
88+
[ HC.style $ display displayNone
89+
, HP.type_ InputFile
90+
, HP.multiple true
91+
, HP.accept $ mediaType $ MediaType "image/*"
92+
, HE.onFileUpload \fileArray -> Just $ Hooks.put filesIdx fileArray
93+
]
9794
]
98-
, HH.input
99-
[ HP.id_ "file-input"
100-
, HC.style $ display displayNone
101-
, HP.type_ InputFile
102-
, HP.multiple true
103-
, HE.onFileUpload \fileArray -> Just $ Hooks.put filesIdx fileArray
104-
]
10595
, HH.span
106-
[ HC.style $ color (CSS.fromInt 0xcccccc) ]
96+
[ HC.style $ color $ CSS.fromInt 0xcccccc ]
10797
[ HH.text $ i "{ files = "(show $ map File.name files)", hover = "(toUpper $ show hover)" }" ]
10898
]
99+
{-
100+
The easiest way to create a file input dialog is with the input element:
101+
102+
HH.input [ HP.type_ InputFile ]
103+
104+
However, this interface cannot be styled like a regular button - A common problem:
105+
https://stackoverflow.com/q/5813344
106+
https://stackoverflow.com/q/21842274
107+
https://stackoverflow.com/q/2048026
108+
109+
The workaround used in this recipe is to put the `input` within a `label`
110+
and style the label to appear as a button. Unfortunately, we can't just reuse
111+
default button styling.
112+
113+
Elm's workaround for custom file input styling is to use its runtime to
114+
let users call File.Select.files on button click, which performs the following:
115+
1. create an input element
116+
2. add it to the DOM
117+
3. create a mouse event
118+
4. dispatch the mouse event to the input element
119+
5. (implication) file dialogue appears
120+
6. user selects a file
121+
7. input event handler runs a callback using user's selected file
122+
8. input element is removed from DOM
123+
-}
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
.otherCssNotInPurescript-Css {
2-
background-color: lightblue;
32
cursor: pointer;
43
}

0 commit comments

Comments
 (0)