mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Issue number: Internal --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> The new picker component does not have a counterpart for the `prefix` and `suffix` properties on the old picker column. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - `prefix` and `suffix` slots added. - Picker items wrapped in a new `.picker-opts` element for positioning purposes, similar to the legacy picker column. This necessitated additional changes to functionality and styling, since previously the items were direct descendants of the host. - New `setFocus` method added. This gets around a browser bug in Firefox where calling `focus()` on the column doesn't correctly move focus, as the nearest focusable element (`.picker-opts`) is in the shadow DOM. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> While you can no longer call `focus()` on the column in Firefox and must use `setFocus()` instead, this isn't considered a breaking change because this component isn't public API yet. ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> --------- Co-authored-by: ionitron <hi@ionicframework.com>
519 lines
9.9 KiB
SCSS
519 lines
9.9 KiB
SCSS
@import "../../themes/ionic.globals";
|
|
|
|
// Datetime
|
|
// --------------------------------------------------
|
|
|
|
:host {
|
|
/**
|
|
* @prop --background: The primary background of the datetime component.
|
|
* @prop --background-rgb: The primary background of the datetime component in RGB format.
|
|
* @prop --title-color: The text color of the title.
|
|
*
|
|
* @prop --wheel-highlight-background: The background of the highlight under the selected
|
|
* item when using a wheel style layout, or in the month/year picker for grid style layouts.
|
|
* @prop --wheel-fade-background-rgb: The color of the gradient covering non-selected items
|
|
* when using a wheel style layout, or in the month/year picker for grid style layouts. Must
|
|
* be in RGB format, e.g. `255, 255, 255`.
|
|
*/
|
|
|
|
display: flex;
|
|
|
|
flex-flow: column;
|
|
|
|
background: var(--background);
|
|
|
|
overflow: hidden;
|
|
}
|
|
|
|
:host(.datetime-size-fixed) {
|
|
width: auto;
|
|
height: auto;
|
|
}
|
|
|
|
:host(.datetime-size-fixed:not(.datetime-prefer-wheel)) {
|
|
max-width: 350px;
|
|
}
|
|
|
|
/**
|
|
* This ensures that the picker is appropriately
|
|
* sized and never truncates the text.
|
|
*/
|
|
:host(.datetime-size-fixed.datetime-prefer-wheel) {
|
|
min-width: 350px;
|
|
max-width: max-content;
|
|
}
|
|
|
|
:host(.datetime-size-cover) {
|
|
width: 100%;
|
|
}
|
|
|
|
:host .calendar-body,
|
|
:host .datetime-year {
|
|
opacity: 0;
|
|
}
|
|
|
|
:host(:not(.datetime-ready)) .datetime-year {
|
|
position: absolute;
|
|
pointer-events: none;
|
|
}
|
|
|
|
:host(.datetime-ready) .calendar-body {
|
|
opacity: 1;
|
|
}
|
|
|
|
:host(.datetime-ready) .datetime-year {
|
|
display: none;
|
|
|
|
opacity: 1;
|
|
}
|
|
/**
|
|
* Changing the physical order of the
|
|
* picker columns in the DOM is added
|
|
* work, so we just use `order` instead.
|
|
*
|
|
* The picker automatically configures
|
|
* the text alignment, so when switching
|
|
* the order we need to manually switch
|
|
* the text alignment too.
|
|
*/
|
|
:host .wheel-order-year-first .day-column {
|
|
order: 3;
|
|
|
|
text-align: end;
|
|
}
|
|
|
|
:host .wheel-order-year-first .month-column {
|
|
order: 2;
|
|
|
|
text-align: end;
|
|
}
|
|
|
|
:host .wheel-order-year-first .year-column {
|
|
order: 1;
|
|
|
|
text-align: start;
|
|
}
|
|
|
|
// Calendar
|
|
// -----------------------------------
|
|
|
|
/**
|
|
* This allows the calendar to take
|
|
* up 100% of the remaining height.
|
|
* On iOS, if there are more than
|
|
* 5 rows of dates, the dates should
|
|
* be resized to fit into this
|
|
* container.
|
|
*/
|
|
:host .datetime-calendar,
|
|
:host .datetime-year {
|
|
display: flex;
|
|
|
|
flex: 1 1 auto;
|
|
|
|
flex-flow: column;
|
|
}
|
|
|
|
:host(.show-month-and-year) .datetime-year {
|
|
display: flex;
|
|
}
|
|
|
|
/**
|
|
* Safari 14 has an issue where a scroll event
|
|
* is incorrectly fired when unhiding the calendar content.
|
|
* To workaround this, we set the opacity
|
|
* of the content to 0 and hide it offscreen.
|
|
*
|
|
* -webkit-named-image is something only WebKit supports
|
|
* so we use this to detect general WebKit support.
|
|
* aspect-ratio is only supported in Safari 15+
|
|
* so by checking lack of aspect-ratio support, we know
|
|
* that we are in a pre-Safari 15 browser.
|
|
*
|
|
* TODO(FW-554): Remove when iOS 14 support is dropped.
|
|
*/
|
|
@supports (background: -webkit-named-image(apple-pay-logo-black)) and (not (aspect-ratio: 1/1)) {
|
|
:host(.show-month-and-year) .calendar-next-prev,
|
|
:host(.show-month-and-year) .calendar-days-of-week,
|
|
:host(.show-month-and-year) .calendar-body,
|
|
:host(.show-month-and-year) .datetime-time {
|
|
@include position(null, null, null, -99999px);
|
|
|
|
position: absolute;
|
|
|
|
/**
|
|
* Use visibility instead of
|
|
* opacity to ensure element
|
|
* cannot receive focus
|
|
*/
|
|
visibility: hidden;
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This support check two cases:
|
|
* 1. A WebKit browser that supports aspect-ratio (Safari 15+)
|
|
* 2. Any non-WebKit browser.
|
|
* Note that just overriding this display: none is not
|
|
* sufficient to resolve the issue mentioned above, which
|
|
* is why we do another set of @supports checks.
|
|
*/
|
|
@supports (not (background: -webkit-named-image(apple-pay-logo-black))) or ((background: -webkit-named-image(apple-pay-logo-black)) and (aspect-ratio: 1/1)) {
|
|
:host(.show-month-and-year) .calendar-next-prev,
|
|
:host(.show-month-and-year) .calendar-days-of-week,
|
|
:host(.show-month-and-year) .calendar-body,
|
|
:host(.show-month-and-year) .datetime-time {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
:host(.month-year-picker-open) .datetime-footer {
|
|
display: none;
|
|
}
|
|
|
|
:host(.datetime-disabled) {
|
|
pointer-events: none;
|
|
|
|
.calendar-days-of-week,
|
|
.datetime-time {
|
|
opacity: 0.4;
|
|
}
|
|
}
|
|
|
|
:host(.datetime-readonly) {
|
|
pointer-events: none;
|
|
|
|
/**
|
|
* Allow user to navigate months
|
|
* while in readonly mode
|
|
*/
|
|
.calendar-action-buttons,
|
|
.calendar-body,
|
|
.datetime-year {
|
|
pointer-events: initial;
|
|
}
|
|
|
|
/**
|
|
* Disabled buttons should have full opacity
|
|
* in readonly mode
|
|
*/
|
|
|
|
.calendar-day[disabled]:not(.calendar-day-constrained),
|
|
.datetime-action-buttons ion-button[disabled] {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Title should not wrap
|
|
* to the next line and should
|
|
* show ellipsis instead.
|
|
*/
|
|
:host .datetime-header .datetime-title {
|
|
text-overflow: ellipsis;
|
|
|
|
white-space: nowrap;
|
|
|
|
overflow: hidden;
|
|
}
|
|
|
|
// Calendar / Header / Action Buttons
|
|
// -----------------------------------
|
|
|
|
:host .datetime-action-buttons.has-clear-button {
|
|
width: 100%;
|
|
}
|
|
|
|
:host .datetime-action-buttons ion-buttons {
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
}
|
|
|
|
/**
|
|
* The confirm and clear buttons are grouped in a
|
|
* container so that they appear on the end opposite
|
|
* of the cancel button.
|
|
* We use display: flex so that the
|
|
* wrapper only takes up as much
|
|
* height as it needs.
|
|
*/
|
|
.datetime-action-buttons .datetime-action-buttons-container {
|
|
display: flex;
|
|
}
|
|
|
|
/**
|
|
* Date/Year button should be on
|
|
* the opposite side of the component
|
|
* as the Next/Prev buttons
|
|
*/
|
|
:host .calendar-action-buttons {
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
}
|
|
|
|
:host .calendar-action-buttons ion-button {
|
|
--background: transparent;
|
|
}
|
|
|
|
// Calendar / Header / Days of Week
|
|
// -----------------------------------
|
|
:host .calendar-days-of-week {
|
|
display: grid;
|
|
grid-template-columns: repeat(7, 1fr);
|
|
|
|
text-align: center;
|
|
}
|
|
|
|
.calendar-days-of-week .day-of-week {
|
|
/**
|
|
* Center the days of the week within each cell
|
|
* if the container size is changed as a result
|
|
* of Dynamic Type.
|
|
*/
|
|
@include margin(0, auto);
|
|
}
|
|
|
|
// Calendar / Body
|
|
// -----------------------------------
|
|
:host .calendar-body {
|
|
|
|
/**
|
|
* Show all calendar months inline
|
|
* and allow them to take up 100% of
|
|
* the free space. Do not use CSS Grid
|
|
* here as there are issues with nested grid
|
|
* on older browsers.
|
|
*/
|
|
display: flex;
|
|
|
|
flex-grow: 1;
|
|
|
|
scroll-snap-type: x mandatory;
|
|
|
|
/**
|
|
* Need to explicitly set overflow-y: hidden
|
|
* for older implementations of scroll snapping.
|
|
*/
|
|
overflow-x: scroll;
|
|
overflow-y: hidden;
|
|
|
|
// Hide scrollbars on Firefox
|
|
scrollbar-width: none;
|
|
|
|
/**
|
|
* Hide blue outline on calendar body
|
|
* when it is focused.
|
|
*/
|
|
outline: none;
|
|
}
|
|
|
|
:host .calendar-body .calendar-month {
|
|
display: flex;
|
|
|
|
flex-flow: column;
|
|
|
|
/**
|
|
* Swiping should snap to at
|
|
* most one month at a time.
|
|
*/
|
|
scroll-snap-align: start;
|
|
scroll-snap-stop: always;
|
|
|
|
flex-shrink: 0;
|
|
|
|
width: 100%;
|
|
}
|
|
|
|
:host .calendar-body .calendar-month-disabled {
|
|
/**
|
|
* Disables swipe gesture snapping for scroll-snap containers
|
|
*/
|
|
scroll-snap-align: none;
|
|
}
|
|
|
|
/**
|
|
* Hide scrollbars on Chrome and Safari
|
|
*/
|
|
:host .calendar-body::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
:host .calendar-body .calendar-month-grid {
|
|
/**
|
|
* Create 7 columns for
|
|
* 7 days in a week.
|
|
*/
|
|
display: grid;
|
|
grid-template-columns: repeat(7, 1fr);
|
|
}
|
|
|
|
:host .calendar-day-wrapper {
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
// Adding a min width and min height allows
|
|
// it to shrink smaller than its content
|
|
// which keeps the calendar day highlight
|
|
// larger while letting the grid items shrink
|
|
min-width: 0;
|
|
|
|
min-height: 0;
|
|
|
|
overflow: visible;
|
|
}
|
|
|
|
/**
|
|
* Center the day text vertically
|
|
* and horizontally within its grid cell.
|
|
*/
|
|
.calendar-day {
|
|
@include border-radius(50%);
|
|
@include padding(0px);
|
|
@include margin(0px);
|
|
|
|
display: flex;
|
|
|
|
position: relative;
|
|
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
border: none;
|
|
|
|
outline: none;
|
|
|
|
background: none;
|
|
color: currentColor;
|
|
|
|
font-family: $font-family-base;
|
|
|
|
cursor: pointer;
|
|
|
|
appearance: none;
|
|
|
|
z-index: 0;
|
|
}
|
|
|
|
:host .calendar-day[disabled] {
|
|
pointer-events: none;
|
|
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.calendar-day:focus {
|
|
background: current-color(base, 0.2);
|
|
|
|
box-shadow: 0px 0px 0px 4px current-color(base, 0.2);
|
|
}
|
|
|
|
// Time / Header
|
|
// -----------------------------------
|
|
|
|
:host .datetime-time {
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
}
|
|
|
|
:host(.datetime-presentation-time) .datetime-time {
|
|
@include padding(0);
|
|
}
|
|
|
|
:host ion-popover {
|
|
--height: 200px;
|
|
}
|
|
|
|
:host .time-header {
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
}
|
|
|
|
:host .time-body {
|
|
@include border-radius(8px);
|
|
@include padding(6px, 12px, 6px, 12px);
|
|
|
|
display: flex;
|
|
|
|
border: none;
|
|
|
|
background: var(--ion-color-step-300, #edeef0);
|
|
|
|
color: $text-color;
|
|
|
|
font-family: inherit;
|
|
font-size: inherit;
|
|
|
|
cursor: pointer;
|
|
|
|
appearance: none;
|
|
}
|
|
|
|
:host .time-body-active {
|
|
color: current-color(base);
|
|
}
|
|
|
|
:host(.in-item) {
|
|
position: static;
|
|
}
|
|
|
|
// Year Picker
|
|
// -----------------------------------
|
|
:host(.show-month-and-year) .calendar-action-buttons .calendar-month-year-toggle {
|
|
color: #{current-color(base)};
|
|
}
|
|
|
|
.calendar-month-year {
|
|
min-width: 0;
|
|
}
|
|
|
|
.calendar-month-year-toggle {
|
|
@include text-inherit();
|
|
|
|
position: relative;
|
|
|
|
border: 0;
|
|
|
|
outline: none;
|
|
|
|
background: transparent;
|
|
|
|
cursor: pointer;
|
|
|
|
z-index: 1;
|
|
|
|
&::after {
|
|
@include button-state();
|
|
|
|
transition: opacity 15ms linear, background-color 15ms linear;
|
|
|
|
z-index: -1;
|
|
}
|
|
|
|
&.ion-focused::after {
|
|
background: currentColor;
|
|
}
|
|
|
|
&:disabled {
|
|
opacity: 0.3;
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
|
|
.calendar-month-year-toggle ion-icon {
|
|
@include padding(0, 0, 0, 4px);
|
|
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.calendar-month-year-toggle #toggle-wrapper {
|
|
display: inline-flex;
|
|
|
|
align-items: center;
|
|
}
|