Make the dialog behave like a dialog

This commit is contained in:
Mariano Abel Coca 2022-11-07 12:02:04 -03:00
parent 76cc60d9a5
commit 0a9695073f
3 changed files with 59 additions and 47 deletions

View File

@ -121,7 +121,13 @@ type alias ButtonConfig =
type Purpose
= NavMenu
| Dialog { lastId : String }
| Dialog ExitFocusManager
type alias ExitFocusManager =
{ firstId : String
, lastId : String
}
@ -219,7 +225,7 @@ You will need to pass in the last focusable element in the dialog content in ord
- the dialog to close appropriately when the user tabs past all of the dialog content
-}
dialog : { lastId : String } -> Attribute msg
dialog : ExitFocusManager -> Attribute msg
dialog exitFocusManager =
Attribute (\config -> { config | purpose = Dialog exitFocusManager })
@ -456,47 +462,53 @@ viewCustom config =
in
div
(Attributes.id (config.buttonId ++ "__container")
:: Key.onKeyDown
(Key.escape
(config.focusAndToggle
{ isOpen = False
, focus = Just config.buttonId
}
)
:: (case config.purpose of
NavMenu ->
[ Key.tab
(config.focusAndToggle
{ isOpen = False
, focus = Nothing
}
)
, Key.tabBack
(config.focusAndToggle
{ isOpen = False
, focus = Nothing
}
)
]
Dialog { lastId } ->
[ WhenFocusLeaves.toDecoder
{ firstId = config.buttonId
, lastId = lastId
, tabBackAction =
config.focusAndToggle
{ isOpen = False
, focus = Nothing
}
, tabForwardAction =
config.focusAndToggle
{ isOpen = False
, focus = Nothing
}
:: (case config.purpose of
NavMenu ->
Key.onKeyDown
[ Key.escape
(config.focusAndToggle
{ isOpen = False
, focus = Just config.buttonId
}
]
)
)
)
, Key.tab
(config.focusAndToggle
{ isOpen = False
, focus = Nothing
}
)
, Key.tabBack
(config.focusAndToggle
{ isOpen = False
, focus = Nothing
}
)
]
Dialog { firstId, lastId } ->
Key.onKeyDownPreventDefault
[ Key.escape
(config.focusAndToggle
{ isOpen = False
, focus = Just config.buttonId
}
)
, WhenFocusLeaves.toDecoder
{ firstId = firstId
, lastId = lastId
, tabBackAction =
config.focusAndToggle
{ isOpen = True
, focus = Just lastId
}
, tabForwardAction =
config.focusAndToggle
{ isOpen = True
, focus = Just firstId
}
}
]
)
:: styleContainer
)
[ if config.isOpen then
@ -871,7 +883,7 @@ styleIconContainer config =
styleOuterContent : Bool -> MenuConfig msg -> Html.Attribute msg
styleOuterContent contentVisible config =
styleOuterContent _ config =
css
[ position absolute
, zIndex (int <| config.zIndex + 1)

View File

@ -267,7 +267,7 @@ view ellieLinkConfig state =
(menuAttributes
++ [ Menu.buttonId "with_controls__button"
, Menu.menuId "with_controls__menu"
, Menu.dialog { lastId = "login__button" }
, Menu.dialog { firstId = "username-input", lastId = "login__button"}
]
)
{ isOpen = isOpen "with_controls"

View File

@ -52,10 +52,10 @@ spec =
|> pressEscKey { targetId = Nothing }
|> ensureViewHasNot (menuContentSelector menuContent)
|> ProgramTest.done
, describe "disclosure" <|
, describe "dialog" <|
[ test "Close on esc key" <|
\() ->
program [ Menu.dialog { lastId = "last-button" } ]
program [ Menu.dialog { firstId = "hello-button", lastId = "last-button" } ]
-- Menu opens on mouse click and closes on esc key
|> clickMenuButton
|> ensureViewHas (menuContentSelector menuContent)
@ -64,7 +64,7 @@ spec =
|> ProgramTest.done
, test "Closes after tab on lastId" <|
\() ->
program [ Menu.dialog { lastId = "last-button" } ]
program [ Menu.dialog { firstId = "hello-button", lastId = "last-button" } ]
|> clickMenuButton
|> ensureViewHas (menuContentSelector menuContent)
-- NOTE: unable to simulate pressTabKey with other targetId since those decoders will fail