diff --git a/jest/jest-setup.js b/jest/jest-setup.js
index a92d4955a25..6545324c49b 100644
--- a/jest/jest-setup.js
+++ b/jest/jest-setup.js
@@ -135,3 +135,7 @@ if (!('matchMedia' in window)) {
})
window.matchMedia._mocked = true
}
+
+if (!('scrollIntoView' in window.HTMLElement.prototype)) {
+ window.HTMLElement.prototype.scrollIntoView = () => {}
+}
diff --git a/packages/canvas-planner/src/components/JumpToHeaderButton/index.js b/packages/canvas-planner/src/components/JumpToHeaderButton/index.js
new file mode 100644
index 00000000000..2bed4a2a3f1
--- /dev/null
+++ b/packages/canvas-planner/src/components/JumpToHeaderButton/index.js
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 - present Instructure, Inc.
+ *
+ * This file is part of Canvas.
+ *
+ * Canvas is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Affero General Public License as published by the Free
+ * Software Foundation, version 3 of the License.
+ *
+ * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Affero General Public License along
+ * with this program. If not, see .
+ */
+
+import React, {PureComponent} from 'react'
+import {Button} from '@instructure/ui-buttons'
+import formatMessage from '../../format-message'
+
+import {WEEKLY_PLANNER_ACTIVE_BTN_ID} from '../WeeklyPlannerHeader'
+
+export const WEEKLY_PLANNER_JUMP_TO_NAV_BUTTON = 'jump-to-weekly-nav-button'
+
+export default class JumpToHeaderButton extends PureComponent {
+ buttonRef = null
+
+ state = {focused: false}
+
+ setFocused = focused => () => {
+ this.setState({focused}, () => this.buttonRef.scrollIntoView(false))
+ }
+
+ focusHeader = () => {
+ document.getElementById(WEEKLY_PLANNER_ACTIVE_BTN_ID)?.focus()
+ }
+
+ render = () => (
+
+
+
+ )
+}
diff --git a/packages/canvas-planner/src/components/WeeklyPlannerHeader/index.js b/packages/canvas-planner/src/components/WeeklyPlannerHeader/index.js
index 8ecd0a7963f..aff8475e2d6 100644
--- a/packages/canvas-planner/src/components/WeeklyPlannerHeader/index.js
+++ b/packages/canvas-planner/src/components/WeeklyPlannerHeader/index.js
@@ -35,6 +35,8 @@ import {isInMomentRange} from '../../utilities/dateUtils'
import theme from './theme'
import styles from './styles.css'
+export const WEEKLY_PLANNER_ACTIVE_BTN_ID = 'weekly-header-active-button'
+
// Breaking our encapsulation by reaching outside our dom sub-tree
// I suppose we could wire up the event handlers in K5Dashboard.js
// and pass the height as a prop to all the pages. Maybe it will be
@@ -69,7 +71,6 @@ export class WeeklyPlannerHeader extends Component {
loadingError: PropTypes.string
}).isRequired,
visible: PropTypes.bool,
- isFooter: PropTypes.bool,
todayMoment: momentObj,
weekStartMoment: momentObj,
weekEndMoment: momentObj,
@@ -88,9 +89,7 @@ export class WeeklyPlannerHeader extends Component {
prevEnabled: true,
nextEnabled: true,
focusedButtonIndex: 1, // start with the today button
- buttons: [this.prevButtonRef, this.todayButtonRef, this.nextButtonRef],
- focused: false,
- activeButton: 0 // -1 for prev, 0 for today, 1 for next
+ buttons: [this.prevButtonRef, this.todayButtonRef, this.nextButtonRef]
}
handleStickyOffset = () => {
@@ -100,14 +99,14 @@ export class WeeklyPlannerHeader extends Component {
handlePrev = () => {
this.prevButtonRef.current.focus()
this.props.loadPastWeekItems()
- this.setState({focusedButtonIndex: 0, activeButton: -1})
+ this.setState({focusedButtonIndex: 0})
}
handleToday = () => {
this.todayButtonRef.current.focus()
this.props.loadThisWeekItems()
this.setState((state, _props) => {
- return {focusedButtonIndex: state.prevEnabled ? 1 : 0, activeButton: 0}
+ return {focusedButtonIndex: state.prevEnabled ? 1 : 0}
})
}
@@ -115,7 +114,7 @@ export class WeeklyPlannerHeader extends Component {
this.nextButtonRef.current.focus()
this.props.loadNextWeekItems({loadMoreButtonClicked: true})
this.setState((state, _props) => {
- return {focusedButtonIndex: state.prevEnabled ? 2 : 1, activeButton: 1}
+ return {focusedButtonIndex: state.prevEnabled ? 2 : 1}
})
}
@@ -133,14 +132,6 @@ export class WeeklyPlannerHeader extends Component {
this.setState({focusedButtonIndex: newFocusedIndex})
}
- handleFocus = () => {
- this.setState({focused: true})
- }
-
- handleBlur = () => {
- this.setState({focused: false})
- }
-
updateButtons() {
const buttons = []
@@ -187,7 +178,7 @@ export class WeeklyPlannerHeader extends Component {
// 2. the window becomes narrow enough for the tabs to wrap.
// We need to relocate the WeeklyPlannerHeader so it sticks
// to the bottom of the tabs panel.
- if (!this.props.isFooter && this.props.visible !== prevProps.visible) {
+ if (this.props.visible !== prevProps.visible) {
if (this.props.visible) {
const focusTarget = processFocusTarget()
this.handleStickyOffset()
@@ -215,7 +206,7 @@ export class WeeklyPlannerHeader extends Component {
) {
const buttons = this.updateButtons()
- if (!this.props.isFooter && prevState.buttons.length === 3 && buttons.length === 2) {
+ if (prevState.buttons.length === 3 && buttons.length === 2) {
// when prev or next buttons go away, move focus to Today
this.todayButtonRef.current.focus()
}
@@ -237,30 +228,21 @@ export class WeeklyPlannerHeader extends Component {
}
}
+ getButtonId(which) {
+ return this.getButtonTabIndex(which) === 0 ? WEEKLY_PLANNER_ACTIVE_BTN_ID : undefined
+ }
+
render() {
- let prevButtonId, todayButtonId, nextButtonId
- if (!this.props.isFooter) {
- prevButtonId = this.state.activeButton === -1 ? 'weekly-header-active-button' : undefined
- todayButtonId = this.state.activeButton === 0 ? 'weekly-header-active-button' : undefined
- nextButtonId = this.state.activeButton === 1 ? 'weekly-header-active-button' : undefined
- }
return (