diff --git a/ui/src/Layout.elm b/ui/src/Layout.elm index bd93c53..1c4ef2c 100644 --- a/ui/src/Layout.elm +++ b/ui/src/Layout.elm @@ -30,14 +30,16 @@ type Page type alias FrameControls msg = - { viewMailbox : String -> msg + { menuVisible : Bool + , toggleMenu : msg + , recentVisible : Bool + , showRecent : Bool -> msg + , viewMailbox : String -> msg , mailboxOnInput : String -> msg , mailboxValue : String , recentOptions : List String , recentActive : String , clearFlash : msg - , showMenu : Bool - , toggleMenu : msg } @@ -50,7 +52,7 @@ frame controls session activePage modal content = [ i [ class "fas fa-bars" ] [] ] , span [ class "navbar-brand" ] [ a [ Route.href Route.Home ] [ text "@ inbucket" ] ] - , ul [ classList [ ( "main-nav", True ), ( "active", controls.showMenu ) ] ] + , ul [ class "main-nav", classList [ ( "active", controls.menuVisible ) ] ] [ if session.config.monitorVisible then navbarLink Monitor Route.Monitor [ text "Monitor" ] activePage @@ -137,6 +139,7 @@ navbarLink page route linkContent activePage = navbarRecent : Page -> FrameControls msg -> Html msg navbarRecent page controls = let + -- Active means we are viewing a specific mailbox. active = page == Mailbox @@ -156,13 +159,41 @@ navbarRecent page controls = else controls.recentOptions + dropdownExpanded = + if controls.recentVisible then + "true" + + else + "false" + recentLink mailbox = a [ Route.href (Route.Mailbox mailbox) ] [ text mailbox ] in li - [ class "navbar-recent" - , classList [ ( "navbar-dropdown", True ), ( "navbar-active", active ) ] + [ class "navbar-recent navbar-dropdown" + , classList [ ( "navbar-active", active ) ] + , attribute "aria-haspopup" "true" + , ariaExpanded controls.recentVisible + , Events.onMouseOver (controls.showRecent True) + , Events.onMouseOut (controls.showRecent False) ] - [ span [ class "navbar-active-bg" ] [ text title ] + [ span [ class "navbar-active-bg" ] + [ text title + , button + [ class "navbar-dropdown-button" + , Events.onClick (controls.showRecent (not controls.recentVisible)) + ] + [ i [ class "fas fa-chevron-down" ] [] ] + ] , div [ class "navbar-dropdown-content" ] (List.map recentLink recentMailboxes) ] + + +ariaExpanded : Bool -> Attribute msg +ariaExpanded value = + attribute "aria-expanded" <| + if value then + "true" + + else + "false" diff --git a/ui/src/Main.elm b/ui/src/Main.elm index 10b50d9..858c781 100644 --- a/ui/src/Main.elm +++ b/ui/src/Main.elm @@ -25,7 +25,8 @@ import Url exposing (Url) type alias Model = { page : PageModel , mailboxName : String - , showMenu : Bool + , menuVisible : Bool + , recentVisible : Bool } @@ -64,7 +65,8 @@ init configValue location key = initModel = { page = Home subModel , mailboxName = "" - , showMenu = False + , menuVisible = False + , recentVisible = False } route = @@ -85,6 +87,7 @@ type Msg | OnMailboxNameInput String | ViewMailbox String | ToggleMenu + | ShowRecent Bool | HomeMsg Home.Msg | MailboxMsg Mailbox.Msg | MonitorMsg Monitor.Msg @@ -217,7 +220,10 @@ updateMain msg model session = ) ToggleMenu -> - ( { model | showMenu = not model.showMenu }, Cmd.none ) + ( { model | menuVisible = not model.menuVisible }, Cmd.none ) + + ShowRecent visible -> + ( { model | recentVisible = visible }, Cmd.none ) _ -> updatePage msg model @@ -256,7 +262,7 @@ changeRouteTo route model = getSession model newModel = - { model | showMenu = False } + { model | menuVisible = False, recentVisible = False } in case route of Route.Unknown path -> @@ -373,14 +379,16 @@ view model = "" controls = - { viewMailbox = ViewMailbox + { menuVisible = model.menuVisible + , toggleMenu = ToggleMenu + , recentVisible = model.recentVisible + , showRecent = ShowRecent + , viewMailbox = ViewMailbox , mailboxOnInput = OnMailboxNameInput , mailboxValue = model.mailboxName , recentOptions = session.persistent.recentMailboxes , recentActive = mailbox , clearFlash = ClearFlash - , showMenu = model.showMenu - , toggleMenu = ToggleMenu } framePage : diff --git a/ui/src/navbar.css b/ui/src/navbar.css index 3f1e09c..733d086 100644 --- a/ui/src/navbar.css +++ b/ui/src/navbar.css @@ -43,11 +43,16 @@ text-decoration: none; } +/* This takes precendence over .navbar a above */ .navbar-brand a { display: inline-block; padding: 12px 15px; } +.navbar-dropdown-button { + display: none; +} + .navbar li { color: var(--navbar-color); } @@ -131,6 +136,14 @@ li.navbar-active span, margin-top: 1px; } + .navbar-dropdown-button { + background: none; + border: none; + color: var(--navbar-color); + display: inline; + padding-right: 0; + } + .navbar-dropdown-content { background-color: var(--bg-color); border: 1px solid var(--border-color); @@ -143,7 +156,7 @@ li.navbar-active span, z-index: 1; } - .navbar-dropdown:hover .navbar-dropdown-content { + .navbar-dropdown[aria-expanded="true"] .navbar-dropdown-content { display: block; }