-
Notifications
You must be signed in to change notification settings - Fork 158
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
fix(carousel): improved tab page navigation #5035
Changes from 6 commits
caea15c
e0827fd
d7c4f8b
370161c
7ac3c4e
b3bf936
a9d195d
d62d6d4
5392a08
90a961a
41fbdd5
95f4af5
a9a4511
671764b
e52de62
23c0161
81132f4
227309d
910a43c
1142e4d
00f46f5
c06974e
ad92d2f
889721a
baf1f3a
6a8689f
3a93494
cacd606
8abb24c
58ec236
7196136
3db21ec
b4cdb5a
aea7029
ef25a3a
5db8fe7
8ca1216
1b9e779
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,9 @@ import ddsSettings from '@carbon/ibmdotcom-utilities/es/utilities/settings/setti | |
import ifNonNull from 'carbon-web-components/es/globals/directives/if-non-null.js'; | ||
import CaretLeft20 from 'carbon-web-components/es/icons/caret--left/20.js'; | ||
import CaretRight20 from 'carbon-web-components/es/icons/caret--right/20.js'; | ||
import HostListener from 'carbon-web-components/es/globals/decorators/host-listener'; | ||
import HostListenerMixin from 'carbon-web-components/es/globals/mixins/host-listener'; | ||
import DDSCard from '../card/card'; | ||
import styles from './carousel.scss'; | ||
|
||
const { prefix } = settings; | ||
|
@@ -26,7 +29,7 @@ const { stablePrefix: ddsPrefix } = ddsSettings; | |
* @csspart next-button The button to go to the next page. | ||
*/ | ||
@customElement(`${ddsPrefix}-carousel`) | ||
class DDSCarousel extends LitElement { | ||
class DDSCarousel extends HostListenerMixin(LitElement) { | ||
/** | ||
* The scrolling contents node. | ||
*/ | ||
|
@@ -111,6 +114,36 @@ class DDSCarousel extends LitElement { | |
} | ||
} | ||
|
||
/** | ||
* Handles card focus throughout pages. | ||
* | ||
* @param event The event. | ||
*/ | ||
@HostListener('shadowRoot:focusin') | ||
// @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to | ||
private _handleFocus = async ({ target, relatedTarget }: FocusEvent) => { | ||
const currentContains = target !== this && this.contains(target as DDSCard); | ||
const oldNotContains = target !== this && !this.contains(relatedTarget as DDSCard); | ||
const currentCardIndex = Array.from(this.children).indexOf(target as HTMLElement); | ||
|
||
// keep current page if tabbing back into the carousel after previously moving pages | ||
if (currentContains && oldNotContains && currentCardIndex === 0) { | ||
(this.children[this.start] as HTMLElement).focus(); | ||
return; | ||
} | ||
|
||
if (currentContains) { | ||
// going forwards, change page depending on card index | ||
if (currentCardIndex >= this.start + this.pageSize) { | ||
this.start = currentCardIndex - (currentCardIndex % this.pageSize); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Considering the following condition:
And user keeps hitting tab key to reach to the code here. What should happen? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @asudo I see, wasn't aware the Now in the condition you provided |
||
|
||
// going backwards, change page depending on card index | ||
} else if (currentCardIndex < this.start) { | ||
this.start = Math.max(currentCardIndex + 1 - this.pageSize, 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want to apply your improvement to "page forward" logic to the "page backward" logic here, too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we'd use the same code going in either direction, the previous logic runs in both directions whenever the focus is out of the current page. |
||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Handles `click` event on the next button. | ||
*/ | ||
|
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.
Do we still need this logic?
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.
@asudoh Yes, we still need that logic to focus on the current starting card after having tabbed outside the carrousel. Without it, the focus will always go to the first card automatically, out of view. This will focus on the current page's starting card.
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.
I see, thank you for clarifying - I suggest preserving the "focused card index" in
_handleFocus()
. It can be done by "old contains but current node contains" detection and preservingevent.relatedTarget
. In this way we can setthis.start
according to the index of such "previously focused card".