-
Notifications
You must be signed in to change notification settings - Fork 55
fix: enable Tab focus for staging area buttons in notification center #1383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
- Added keyboard focus handling for staging notification buttons - Implemented Tab cycling between staging area, header, and notification list - Fixed button unloading issue during Tab navigation Log: enable Tab focus for staging area buttons in notification center pms: BUG-345531
Reviewer's GuideImplements full keyboard Tab/Shift+Tab focus cycling between the staging area, header, and notification list in the notification center, and fixes the staging close button loader being unloaded while focused by refactoring hover/focus handling in notification item content. Sequence diagram for Tab navigation from staging item to headersequenceDiagram
actor User
participant NotifyStaging_root as NotifyStaging
participant ListView_view as ListView_view
participant OverlapNotify as OverlapNotify
participant NotifyCenter_root as NotifyCenter
participant Header as Header
User->>OverlapNotify: Press Tab key
OverlapNotify->>OverlapNotify: Keys.onTabPressed(event)
OverlapNotify->>OverlapNotify: overlapNotify.focusFirstButton()
alt InternalButtonFocused
OverlapNotify-->>User: event.accepted = true
else NoInternalButton
OverlapNotify->>OverlapNotify: Qt.callLater(focusFirstButtonAgain)
OverlapNotify->>NotifyStaging_root: navigateToNextItem(index)
NotifyStaging_root->>ListView_view: Update currentIndex
NotifyStaging_root->>NotifyStaging_root: Qt.callLater(focus next item)
alt NextItemExists
NotifyStaging_root->>ListView_view: nextItem.forceActiveFocus()
ListView_view-->>User: Focus moves to next staging item
else LastItemReached
NotifyStaging_root->>NotifyCenter_root: gotoHeaderFirst()
NotifyCenter_root->>Header: focusFirstButton()
Header-->>User: Focus moves to header first button
end
end
Sequence diagram for Shift+Tab navigation from header to staging or listsequenceDiagram
actor User
participant Header as Header
participant NotifyCenter_root as NotifyCenter
participant NotifyStaging_root as NotifyStaging
participant NotifyView as NotifyView
User->>Header: Press Shift+Tab
Header->>NotifyCenter_root: gotoStagingLast()
alt StagingHasItems (notifyStaging.viewCount > 0)
NotifyCenter_root->>NotifyStaging_root: focusLastButton()
NotifyStaging_root-->>User: Focus moves to last button in last staging item
else NoStagingItems
alt ViewHasItems (notifyCenter.viewCount > 0)
NotifyCenter_root->>NotifyView: focusViewLastItem()
NotifyView-->>User: Focus moves to last notification item
else NoViewItems
NotifyCenter_root->>NotifyCenter_root: focusHeaderLast()
NotifyCenter_root-->>User: Focus remains on header last button
end
end
Class diagram for updated notification center focus logicclassDiagram
class NotifyStaging {
property var model
readonly property int viewCount
signal gotoHeaderFirst()
signal gotoHeaderLast()
function focusFirstItem()
function focusLastButton()
function navigateToNextItem(currentIndex)
function navigateToPrevItem(currentIndex)
}
class NotifyCenter {
property alias viewPanelShown
property int maxViewHeight
property int stagingViewCount
readonly property int viewCount
signal gotoStagingLast()
signal gotoStagingFirst()
function focusHeaderFirst()
function focusHeaderLast()
function focusViewLastItem()
}
class NotifyItemContent {
implicitHeight
readonly property int maxFocusRetries
property bool parentHovered
property bool closeVisible
property int miniContentHeight
property bool enableDismissed
property alias clearButton
}
class OverlapNotify {
property bool activeFocus
property bool impl_hovered
}
class NormalNotify {
property bool activeFocus
property bool impl_hovered
}
class ClearLoader {
property bool active
property var item
}
NotifyCenter "1" o-- "1" NotifyStaging : contains
NotifyCenter "1" o-- "1" Header : uses
NotifyCenter "1" o-- "1" NotificationListView : uses
NotifyStaging "1" o-- "1" ListView : manages
NotifyStaging "1" --> "many" OverlapNotify : items
OverlapNotify "1" o-- "1" NotifyItemContent : wraps
NormalNotify "1" o-- "1" NotifyItemContent : wraps
NotifyItemContent "1" o-- "1" ClearLoader : owns
class Header {
function focusFirstButton()
function focusLastButton()
}
class NotificationListView {
readonly property int viewCount
function focusLastItem()
function focusItemAtIndex(index)
}
class ListView {
property int count
property int currentIndex
function itemAtIndex(index)
}
ClearLoader : active depends on closeVisible
NotifyItemContent : closeVisible = activeFocus || impl.hovered || parentHovered || clearLoader.item.activeFocus
OverlapNotify : parentHovered = impl.hovered || activeFocus
NormalNotify : parentHovered = impl.hovered || activeFocus
Flow diagram for focus routing between staging, header, and notification listflowchart LR
subgraph Window_main
subgraph NotifyCenter
Header[Header]
View[NotificationListView]
Staging[NotifyStaging]
end
end
StagingFirst[Staging first item]
StagingLastButton[Staging last button]
ViewFirst[List first item]
ViewLast[List last item]
HeaderFirst[Header first button]
HeaderLast[Header last button]
StagingFirst -->|Shift+Tab| HeaderLast
StagingLastButton -->|Tab when last item| HeaderFirst
HeaderFirst -->|Tab| ViewFirst
HeaderLast -->|Shift+Tab| StagingLastButton
ViewLast -->|Tab| StagingFirst
ViewFirst -->|Shift+Tab| HeaderLast
HeaderFirst -->|Tab when no list items| StagingFirst
HeaderLast -->|Shift+Tab when no staging items and list has items| ViewLast
HeaderLast -->|Shift+Tab when no staging items and no list items| HeaderLast
ViewLast -->|Tab when no staging items| HeaderFirst
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - I've left some high level feedback:
- The focus management helpers in
NotifyStaging.qml(focusFirstItem,focusLastButton,navigateToNextItem,navigateToPrevItem) useQt.callLaterin several places; consider consolidating the focus-change logic into a single utility or reducing nestedcallLatercalls to avoid hard-to-debug timing issues when the model changes quickly. focusFirstItemchecksfirstItem.enabledbefore focusing, butnavigateToNextItem/navigateToPrevItemdo not skip disabled items; if disabled notifications are possible, it would be more robust to mirror that check (and potentially loop to the next enabled item) so keyboard navigation never lands on an unusable control.- The naming of signals like
gotoHeaderFirst/gotoHeaderLastinNotifyCenter.qmlandNotifyStaging.qmlno longer fully matches their behavior (sometimes they route to staging instead of the header); consider renaming or adding brief comments near the signal definitions to clarify the actual navigation path and reduce confusion for future maintainers.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The focus management helpers in `NotifyStaging.qml` (`focusFirstItem`, `focusLastButton`, `navigateToNextItem`, `navigateToPrevItem`) use `Qt.callLater` in several places; consider consolidating the focus-change logic into a single utility or reducing nested `callLater` calls to avoid hard-to-debug timing issues when the model changes quickly.
- `focusFirstItem` checks `firstItem.enabled` before focusing, but `navigateToNextItem`/`navigateToPrevItem` do not skip disabled items; if disabled notifications are possible, it would be more robust to mirror that check (and potentially loop to the next enabled item) so keyboard navigation never lands on an unusable control.
- The naming of signals like `gotoHeaderFirst`/`gotoHeaderLast` in `NotifyCenter.qml` and `NotifyStaging.qml` no longer fully matches their behavior (sometimes they route to staging instead of the header); consider renaming or adding brief comments near the signal definitions to clarify the actual navigation path and reduce confusion for future maintainers.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Log: enable Tab focus for staging area buttons in notification center
pms: BUG-345531
Summary by Sourcery
Improve keyboard Tab navigation and focus handling across the notification center, staging area, and notification items.
Bug Fixes:
Enhancements: