- {prevButton && cloneButton(prevButton, this.handleMonthChange('prev'))}
- {renderNavigationLabel ? (
- callRenderProp(renderNavigationLabel)
- ) : (
-
- {visibleMonth.format('MMMM')}
- {visibleMonth.format('YYYY')}
-
- )}
- {nextButton && cloneButton(nextButton, this.handleMonthChange('next'))}
+
+
+ {prevButton &&
+ cloneButton(prevButton, this.handleMonthChange('prev'))}
+ {renderNavigationLabel ? (
+ callRenderProp(renderNavigationLabel)
+ ) : (
+
+ {visibleMonth.format('MMMM')}
+ {!withYearPicker ? (
+ {visibleMonth.format('YYYY')}
+ ) : null}
+
+ )}
+ {nextButton &&
+ cloneButton(nextButton, this.handleMonthChange('next'))}
+
+
+ {withYearPicker ? (
+
+
+ this.handleYearChange(e, Number(value))
+ }
+ >
+ {yearList.map((year) => (
+
+ {`${year}`}
+
+ ))}
+
+
+ ) : null}
)
}
diff --git a/packages/ui-calendar/src/Calendar/props.ts b/packages/ui-calendar/src/Calendar/props.ts
index c0f51f2b30..38b190fa01 100644
--- a/packages/ui-calendar/src/Calendar/props.ts
+++ b/packages/ui-calendar/src/Calendar/props.ts
@@ -152,6 +152,30 @@ type CalendarOwnProps = {
* Visible month for the rendered calendar. Formatted as an ISO date string.
*/
visibleMonth?: string
+
+ /**
+ * If set, years can be picked from a dropdown.
+ * It accepts an object.
+ * screenReaderLabel: string // e.g.: i18n("pick a year")
+ *
+ * maxHeight?: string // e.g.: 200px, Defaults to 300px. Sets the dropdown max height
+ *
+ * onRequestYearChange?:(e: React.MouseEvent,requestedYear: number): void // if set, on year change, only this will be called and no internal change will take place
+ *
+ * startYear?: number // e.g.: 2001, sets the start year of the selectable list
+ *
+ * endYear?: number // e.g.: 2030, sets the end year of the selectable list. If not provided with startYear, it'll default to the currentDate's year
+ *
+ * years?: number[] // e.g.: [2001,2002,2003,2010], if set, startYear and endYear will be ignored and this list will be used as selectable list
+ */
+ withYearPicker?: {
+ screenReaderLabel: string
+ maxHeight?: string
+ onRequestYearChange?: (e: any, requestedYear: number) => void
+ startYear?: number
+ endYear?: number
+ years?: never
+ }
}
type PropKeys = keyof CalendarOwnProps
@@ -163,7 +187,7 @@ type CalendarProps = CalendarOwnProps &
OtherHTMLAttributes
type CalendarStyle = ComponentStyle<
- 'navigation' | 'navigationWithButtons' | 'weekdayHeader'
+ 'navigation' | 'navigationWithButtons' | 'weekdayHeader' | 'yearPicker'
>
const propTypes: PropValidators = {
@@ -184,7 +208,8 @@ const propTypes: PropValidators = {
role: PropTypes.oneOf(['table', 'listbox']),
selectedDate: PropTypes.string,
timezone: PropTypes.string,
- visibleMonth: PropTypes.string
+ visibleMonth: PropTypes.string,
+ withYearPicker: PropTypes.object
}
const allowedProps: AllowedPropKeys = [
diff --git a/packages/ui-calendar/src/Calendar/styles.ts b/packages/ui-calendar/src/Calendar/styles.ts
index ff63c50d95..3d6e25d4ed 100644
--- a/packages/ui-calendar/src/Calendar/styles.ts
+++ b/packages/ui-calendar/src/Calendar/styles.ts
@@ -23,7 +23,7 @@
*/
import type { CalendarTheme } from '@instructure/shared-types'
-import type { CalendarStyle } from './props'
+import type { CalendarStyle, CalendarProps } from './props'
/**
* ---
@@ -33,7 +33,11 @@ import type { CalendarStyle } from './props'
* @param {Object} componentTheme The theme variable object.
* @return {Object} The final style object, which will be used in the component
*/
-const generateStyle = (componentTheme: CalendarTheme): CalendarStyle => {
+const generateStyle = (
+ componentTheme: CalendarTheme,
+ props: CalendarProps
+): CalendarStyle => {
+ const { withYearPicker } = props
return {
navigation: {
label: 'calendar__navigation',
@@ -43,7 +47,9 @@ const generateStyle = (componentTheme: CalendarTheme): CalendarStyle => {
fontFamily: componentTheme.fontFamily,
fontSize: componentTheme.fontSize,
fontWeight: componentTheme.fontWeight,
- marginBottom: componentTheme.navMargin
+ marginBottom: withYearPicker
+ ? componentTheme.navWithYearMargin
+ : componentTheme.navMargin
},
navigationWithButtons: {
label: 'calendar__navigation--withButtons',
@@ -55,6 +61,12 @@ const generateStyle = (componentTheme: CalendarTheme): CalendarStyle => {
label: 'calendar__weekdayHeader',
textAlign: 'center',
maxWidth: componentTheme.maxHeaderWidth
+ },
+ yearPicker: {
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: componentTheme.yearPickerMargin
}
}
}
diff --git a/packages/ui-calendar/src/Calendar/theme.ts b/packages/ui-calendar/src/Calendar/theme.ts
index c841af95bf..33e70b413c 100644
--- a/packages/ui-calendar/src/Calendar/theme.ts
+++ b/packages/ui-calendar/src/Calendar/theme.ts
@@ -48,6 +48,8 @@ const generateComponentTheme = (theme: Theme): CalendarTheme => {
background: colors?.backgroundLightest,
navMargin: spacing?.small,
+ navWithYearMargin: spacing?.xSmall,
+ yearPickerMargin: spacing?.mediumSmall,
maxHeaderWidth: spacing?.medium
}
diff --git a/packages/ui-calendar/tsconfig.build.json b/packages/ui-calendar/tsconfig.build.json
index f2ab0cb9bf..ff8dae0706 100644
--- a/packages/ui-calendar/tsconfig.build.json
+++ b/packages/ui-calendar/tsconfig.build.json
@@ -60,6 +60,9 @@
},
{
"path": "../ui-icons/tsconfig.build.json"
+ },
+ {
+ "path": "../ui-simple-select/tsconfig.build.json"
}
]
}
diff --git a/packages/ui-select/src/Select/index.tsx b/packages/ui-select/src/Select/index.tsx
index 6830ed0bfa..9429a35415 100644
--- a/packages/ui-select/src/Select/index.tsx
+++ b/packages/ui-select/src/Select/index.tsx
@@ -149,7 +149,7 @@ class Select extends Component {
placement: 'bottom stretch',
constrain: 'window',
shouldNotWrap: false,
- scrollToHighlightedOption: false
+ scrollToHighlightedOption: true
}
static Option = Option