From f95e1d193bd8f6eb9ff3ad945ddcc9843a970f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8jberg?= Date: Tue, 7 Jan 2025 12:13:27 -0500 Subject: [PATCH] Update toolbar icons with tooltips Add a new "refresh codebase" button in the lower left toolbar and add tooltips with keyboard shortcut indicators for all toolbar actions --- elm-git.json | 2 +- src/Ucm/WorkspaceScreen.elm | 127 ++++++++++++++++++++++++++++-------- src/Window.elm | 29 +++++--- src/css/window.css | 33 +++++++++- 4 files changed, 153 insertions(+), 38 deletions(-) diff --git a/elm-git.json b/elm-git.json index 7588386..0d74968 100644 --- a/elm-git.json +++ b/elm-git.json @@ -1,7 +1,7 @@ { "git-dependencies": { "direct": { - "https://github.com/unisonweb/ui-core": "b172cbdb17eba02f64edfef92a4e4e3d117ea636" + "https://github.com/unisonweb/ui-core": "08ef7e8e1d1fa718f7bd7d0d83a2841099ffe5d2" }, "indirect": {} } diff --git a/src/Ucm/WorkspaceScreen.elm b/src/Ucm/WorkspaceScreen.elm index 2de49b2..a9755f9 100644 --- a/src/Ucm/WorkspaceScreen.elm +++ b/src/Ucm/WorkspaceScreen.elm @@ -4,16 +4,17 @@ import Browser import Code.BranchRef as BranchRef import Code.CodebaseTree as CodebaseTree import Code.Config -import Html exposing (Html, div) +import Html exposing (Html, div, text) import Html.Attributes exposing (class) import RemoteData exposing (RemoteData(..)) import UI.AnchoredOverlay as AnchoredOverlay import UI.Button as Button import UI.Icon as Icon import UI.KeyboardShortcut as KeyboardShortcut exposing (KeyboardShortcut(..)) -import UI.KeyboardShortcut.Key exposing (Key(..)) +import UI.KeyboardShortcut.Key as Key exposing (Key(..)) import UI.KeyboardShortcut.KeyboardEvent as KeyboardEvent import UI.Modal as Modal +import UI.Tooltip as Tooltip import Ucm.AppContext as AppContext exposing (AppContext) import Ucm.CommandPalette as CommandPalette import Ucm.SwitchBranch as SwitchBranch @@ -86,6 +87,7 @@ type Msg | CloseModal | ToggleSidebar | ToggleRightPane + | RefreshCodebase | Keydown KeyboardEvent.KeyboardEvent | CodebaseTreeMsg CodebaseTree.Msg | WorkspacePanesMsg WorkspacePanes.Msg @@ -175,6 +177,18 @@ update appContext msg model = in ( { model | panes = panes }, Cmd.none, None ) + RefreshCodebase -> + let + ( codebaseTree, codebaseTreeCmd ) = + CodebaseTree.init model.config + in + ( { model + | codebaseTree = codebaseTree + } + , Cmd.map CodebaseTreeMsg codebaseTreeCmd + , None + ) + Keydown event -> let ( keyboardShortcut, kCmd ) = @@ -192,6 +206,9 @@ update appContext msg model = toggleSidebar = ( { model_ | sidebarVisible = not model_.sidebarVisible }, Cmd.none ) + toggleSplitPanes = + ( { model_ | panes = WorkspacePanes.toggleRightPane model_.panes }, Cmd.none ) + focusLeft = ( { model_ | panes = WorkspacePanes.focusLeft model_.panes }, Cmd.none ) @@ -218,6 +235,9 @@ update appContext msg model = ( NoModal, Chord Ctrl (B _) ) -> toggleSidebar + ( NoModal, Sequence (Just (W _)) (R _) ) -> + toggleSplitPanes + ( NoModal, Sequence (Just (W _)) ArrowLeft ) -> focusLeft @@ -393,6 +413,21 @@ subscriptions model = -- VIEW +controlBarTooltip : Model -> String -> Maybe KeyboardShortcut.KeyboardShortcut -> Tooltip.Tooltip msg +controlBarTooltip model label shortcut = + let + content = + case shortcut of + Just s -> + Tooltip.rich + (div [ class "label-with-shortcut" ] [ text label, KeyboardShortcut.view model.keyboardShortcut s ]) + + Nothing -> + Tooltip.text label + in + Tooltip.tooltip content + + titlebarLeft : Model -> List (Html Msg) titlebarLeft { switchProject, switchBranch, workspaceContext } = [ SwitchProject.toAnchoredOverlay workspaceContext.projectName switchProject @@ -404,16 +439,65 @@ titlebarLeft { switchProject, switchBranch, workspaceContext } = ] -titlebarRight : List (Html Msg) -titlebarRight = - [ Button.icon ShowCommandPalette Icon.search - |> Button.small - |> Button.subdued - |> Button.view - , Button.icon ToggleRightPane Icon.windowSplit - |> Button.small - |> Button.subdued - |> Button.view +titlebarRight : Model -> List (Html Msg) +titlebarRight model = + let + tooltip label shortcut = + controlBarTooltip model label (Just shortcut) + |> Tooltip.below + |> Tooltip.withArrow Tooltip.End + in + [ tooltip "Search" (KeyboardShortcut.single Key.ForwardSlash) + |> Tooltip.view + (Button.icon ShowCommandPalette Icon.search + |> Button.small + |> Button.subdued + |> Button.view + ) + , tooltip "Toggle split panes" (KeyboardShortcut.Sequence (Just (Key.W Key.Lower)) (Key.R Key.Lower)) + |> Tooltip.view + (Button.icon ToggleRightPane Icon.windowSplit + |> Button.small + |> Button.subdued + |> Button.view + ) + ] + + +footerLeft : Model -> List (Html Msg) +footerLeft model = + let + sidebarIcon = + if model.sidebarVisible then + Icon.leftSidebarOff + + else + Icon.leftSidebarOn + + tooltip label shortcut = + controlBarTooltip model label shortcut + |> Tooltip.above + |> Tooltip.withArrow Tooltip.Start + + toggleSidebarSequence = + KeyboardShortcut.Sequence + (Just (Key.W Key.Lower)) + (Key.S Key.Lower) + in + [ tooltip "Toggle sidebar" (Just toggleSidebarSequence) + |> Tooltip.view + (Button.icon ToggleSidebar sidebarIcon + |> Button.small + |> Button.subdued + |> Button.view + ) + , tooltip "Refresh codebase" Nothing + |> Tooltip.view + (Button.icon RefreshCodebase Icon.refresh + |> Button.small + |> Button.subdued + |> Button.view + ) ] @@ -433,21 +517,12 @@ view appContext model = window = Window.window "workspace-screen" - ( sidebarIcon, window_ ) = + window_ = if model.sidebarVisible then - ( Icon.leftSidebarOff - , Window.withLeftSidebar (viewLeftSidebar model.codebaseTree) window - ) + Window.withLeftSidebar (viewLeftSidebar model.codebaseTree) window else - ( Icon.leftSidebarOn, window ) - - footerLeft = - [ Button.icon ToggleSidebar sidebarIcon - |> Button.small - |> Button.subdued - |> Button.view - ] + window footerRight = [ UcmConnectivity.view appContext.ucmConnectivity ] @@ -467,8 +542,8 @@ view appContext model = in window__ |> Window.withTitlebarLeft (titlebarLeft model) - |> Window.withTitlebarRight titlebarRight - |> Window.withFooterLeft footerLeft + |> Window.withTitlebarRight (titlebarRight model) + |> Window.withFooterLeft (footerLeft model) |> Window.withFooterRight footerRight |> Window.withContent content |> Window.view WindowMsg model.window diff --git a/src/Window.elm b/src/Window.elm index 52c18d7..b74cda0 100644 --- a/src/Window.elm +++ b/src/Window.elm @@ -20,6 +20,7 @@ import UI.Button as Button import UI.Click as Click import UI.Icon as Icon import UI.Modal as Modal exposing (Modal) +import UI.Tooltip as Tooltip import Ucm.Link as Link @@ -447,7 +448,15 @@ viewWindowTitlebar settingsMenu id_ titlebar_ = WindowTitlebar cfg -> { left = cfg.left , center = cfg.center - , right = cfg.right ++ [ settingsMenu ] + , right = + cfg.right + ++ [ Tooltip.text "Settings" + |> Tooltip.tooltip + |> Tooltip.below + |> Tooltip.withArrow Tooltip.End + |> Tooltip.view + settingsMenu + ] , transparent = False , border = cfg.border } @@ -470,9 +479,9 @@ viewWindowTitlebar settingsMenu id_ titlebar_ = , ( "window-titlebar_borderless", not border ) ] ] - [ div [ class "window-control-bar-group" ] left - , div [ class "window-control-bar-group" ] center - , div [ class "window-control-bar-group" ] right + [ div [ class "window-control-bar-group window-titlebar_left" ] left + , div [ class "window-control-bar-group window-titlebar_center" ] center + , div [ class "window-control-bar-group window-titlebar_right" ] right ] @@ -487,9 +496,9 @@ viewWindowFooter id_ footer_ = [ id (id_ ++ "_window-footer") , class "window-control-bar window-footer" ] - [ div [ class "window-control-bar-group" ] left - , div [ class "window-control-bar-group" ] center - , div [ class "window-control-bar-group" ] right + [ div [ class "window-control-bar-group window-footer_left" ] left + , div [ class "window-control-bar-group window-footer_center" ] center + , div [ class "window-control-bar-group window-footer_right" ] right ] @@ -505,11 +514,11 @@ view toMsg model win = , ActionMenu.dividerItem , ActionMenu.titleItem "Resources" , ActionMenu.optionItem Icon.graduationCap "Unison Docs" Link.docs - , ActionMenu.optionItem Icon.browse "Unison Share" Link.share + , ActionMenu.optionItem Icon.browse "Unison Share (libraries)" Link.share , ActionMenu.dividerItem , ActionMenu.titleItem "Debug" - , ActionMenu.optionItem Icon.refresh "Reload" (Click.onClick ReloadApp) - , ActionMenu.optionItem Icon.x "Reset to factory settings" (Click.onClick ResetToFactorySettings) + , ActionMenu.optionItem Icon.refresh "Reload app" (Click.onClick ReloadApp) + , ActionMenu.optionItem Icon.factory "Reset to factory settings" (Click.onClick ResetToFactorySettings) ] |> ActionMenu.fromIconButton ToggleSettingsMenu Icon.cog |> ActionMenu.withButtonColor Button.Subdued diff --git a/src/css/window.css b/src/css/window.css index 1174f5a..9661be6 100644 --- a/src/css/window.css +++ b/src/css/window.css @@ -36,6 +36,13 @@ body:has(.window-footer) { padding: 0.5rem 0.5rem; } +.window-control-bar .label-with-shortcut { + display: flex; + flex-direction: row; + gap: 1rem; + align-items: center; +} + .window-control-bar-group { display: flex; flex-direction: row; @@ -45,7 +52,22 @@ body:has(.window-footer) { .window-titlebar { padding-left: 0.5rem; border-bottom: 1px solid var(--u-color_chrome_border); - background: var(--u-color_chrome_emphasized) + background: var(--u-color_chrome_emphasized); + + & .window-titlebar_right { + position: relative; + + & .tooltip { + margin-top: 0.7rem; + margin-left: 1.8rem; + } + } + + & .window-titlebar_right:has(.action-menu_sheet) { + & .tooltip { + display: none; + } + } } .macos .window-titlebar { @@ -112,4 +134,13 @@ body:has(.window-footer) { .window-footer { border-top: 1px solid var(--u-color_chrome_border); background: var(--u-color_chrome); + + & .window-footer_left { + position: relative; + + & .tooltip { + margin-top: 0.75rem; + margin-left: -0.3rem; + } + } }