@import "../themes/ionic.globals"; @import "../components/menu/menu.ios.vars"; @import "../components/menu/menu.md.vars"; // Ionic Font Family // -------------------------------------------------- html.ios { --ion-default-font: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Roboto", sans-serif; } html.md { --ion-default-font: "Roboto", "Helvetica Neue", sans-serif; } html { --ion-font-family: var(--ion-default-font); } body { background: var(--ion-background-color); } body.backdrop-no-scroll { overflow: hidden; } // Modal - Card Style // -------------------------------------------------- /** * Card style modal needs additional padding on the * top of the header. We accomplish this by targeting * the first toolbar in the header. * Footer also needs this. We do not adjust the bottom * padding though because of the safe area. */ html.ios ion-modal.modal-card ion-header ion-toolbar:first-of-type, html.ios ion-modal.modal-sheet ion-header ion-toolbar:first-of-type, html.ios ion-modal ion-footer ion-toolbar:first-of-type { padding-top: 6px; } /** * Card style modal needs additional padding on the * bottom of the header. We accomplish this by targeting * the last toolbar in the header. */ html.ios ion-modal.modal-card ion-header ion-toolbar:last-of-type, html.ios ion-modal.modal-sheet ion-header ion-toolbar:last-of-type { padding-bottom: 6px; } /** * Add padding on the left and right * of toolbars while accounting for * safe area values when in landscape. */ html.ios ion-modal ion-toolbar { padding-right: calc(var(--ion-safe-area-right) + 8px); padding-left: calc(var(--ion-safe-area-left) + 8px); } /** * Card style modal on iPadOS * should only have backdrop on first instance. */ @media screen and (min-width: 768px) { html.ios ion-modal.modal-card:first-of-type { --backdrop-opacity: 0.18; } } /** * Subsequent modals should not have a backdrop/box shadow * as it will cause the screen to appear to get progressively * darker. With Ionic 6, declarative modals made it * possible to have multiple non-presented modals in the DOM, * so we could no longer rely on ion-modal:first-of-type. * Here we disable the opacity/box-shadow for every modal * that comes after the first presented modal. * * Note: ion-modal:not(.overlay-hidden):first-of-type * does not match the first modal to not have * the .overlay-hidden class, it will match the * first modal in general only if it does not * have the .overlay-hidden class. * The :nth-child() pseudo-class has support * for selectors which would help us here. At the * time of writing it does not have great cross browser * support. * * Note 2: This should only apply to non-card and * non-sheet modals. Card and sheet modals have their * own criteria for displaying backdrops/box shadows. */ ion-modal.modal-default:not(.overlay-hidden) ~ ion-modal.modal-default { --backdrop-opacity: 0; --box-shadow: none; } /** * This works around a bug in WebKit where the * content will overflow outside of the bottom border * radius when re-painting. As long as a single * border radius value is set on .ion-page, this * issue does not happen. We set the top left radius * here because the top left corner will always have a * radius no matter the platform. * This behavior only applies to card modals. */ html.ios ion-modal.modal-card .ion-page { border-top-left-radius: var(--border-radius); } // Ionic Colors // -------------------------------------------------- // Generates the color classes and variables based on the // colors map @mixin generate-color($color-name) { $value: map-get($colors, $color-name); $base: map-get($value, base); $contrast: map-get($value, contrast); $shade: map-get($value, shade); $tint: map-get($value, tint); --ion-color-base: var(--ion-color-#{$color-name}, #{$base}) !important; --ion-color-base-rgb: var(--ion-color-#{$color-name}-rgb, #{color-to-rgb-list($base)}) !important; --ion-color-contrast: var(--ion-color-#{$color-name}-contrast, #{$contrast}) !important; --ion-color-contrast-rgb: var(--ion-color-#{$color-name}-contrast-rgb, #{color-to-rgb-list($contrast)}) !important; --ion-color-shade: var(--ion-color-#{$color-name}-shade, #{$shade}) !important; --ion-color-tint: var(--ion-color-#{$color-name}-tint, #{$tint}) !important; } @each $color-name, $value in $colors { .ion-color-#{$color-name} { @include generate-color($color-name); } } // Page Container Structure // -------------------------------------------------- .ion-page { @include position(0, 0, 0, 0); display: flex; position: absolute; flex-direction: column; justify-content: space-between; contain: layout size style; overflow: hidden; z-index: $z-index-page-container; } /** * When making custom dialogs, using * ion-content is not required. As a result, * some developers may wish to have dialogs * that are automatically sized by the browser. * These changes allow certain dimension values * such as fit-content to work correctly. */ ion-modal .ion-page:not(ion-nav .ion-page) { position: relative; contain: layout style; height: 100%; } .split-pane-visible > .ion-page.split-pane-main { position: relative; } ion-route, ion-route-redirect, ion-router, ion-select-option, ion-nav-controller, ion-menu-controller, ion-action-sheet-controller, ion-alert-controller, ion-loading-controller, ion-modal-controller, ion-picker-controller, ion-popover-controller, ion-toast-controller, .ion-page-hidden { /* stylelint-disable-next-line declaration-no-important */ display: none !important; } .ion-page-invisible { opacity: 0; } .can-go-back > ion-header ion-back-button { display: block; } // Ionic Safe Margins // -------------------------------------------------- html.plt-ios.plt-hybrid, html.plt-ios.plt-pwa { --ion-statusbar-padding: 20px; } @supports (padding-top: 20px) { html { --ion-safe-area-top: var(--ion-statusbar-padding); } } // TODO: remove once Safari 11.2 is no longer supported @supports (padding-top: constant(safe-area-inset-top)) { html { --ion-safe-area-top: constant(safe-area-inset-top); --ion-safe-area-bottom: constant(safe-area-inset-bottom); --ion-safe-area-left: constant(safe-area-inset-left); --ion-safe-area-right: constant(safe-area-inset-right); } } @supports (padding-top: env(safe-area-inset-top)) { html { --ion-safe-area-top: env(safe-area-inset-top); --ion-safe-area-bottom: env(safe-area-inset-bottom); --ion-safe-area-left: env(safe-area-inset-left); --ion-safe-area-right: env(safe-area-inset-right); } } // Global Card Styles // -------------------------------------------------- ion-card.ion-color .ion-inherit-color, ion-card-header.ion-color .ion-inherit-color { color: inherit; } // Menu Styles // -------------------------------------------------- .menu-content { @include transform(translate3d(0, 0, 0)); } .menu-content-open { cursor: pointer; touch-action: manipulation; // the containing element itself should be clickable but // everything inside of it should not clickable when menu is open pointer-events: none; } .ios .menu-content-reveal { box-shadow: $menu-ios-box-shadow-reveal; } [dir=rtl].ios .menu-content-reveal { box-shadow: $menu-ios-box-shadow-reveal-rtl; } .ios .menu-content-push { box-shadow: $menu-ios-box-shadow-push; } .md .menu-content-reveal { box-shadow: $menu-md-box-shadow; } .md .menu-content-push { box-shadow: $menu-md-box-shadow; } // Accordion Styles ion-accordion-group.accordion-group-expand-inset > ion-accordion:first-of-type { border-top-left-radius: 8px; border-top-right-radius: 8px; } ion-accordion-group.accordion-group-expand-inset > ion-accordion:last-of-type { border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; } ion-accordion-group > ion-accordion:last-of-type ion-item[slot="header"] { --border-width: 0px; } ion-accordion.accordion-animated > [slot="header"] .ion-accordion-toggle-icon { transition: 300ms transform cubic-bezier(0.25, 0.8, 0.5, 1); } @media (prefers-reduced-motion: reduce) { ion-accordion .ion-accordion-toggle-icon { /* stylelint-disable declaration-no-important */ transition: none !important; } } /** * The > [slot="header"] selector ensures that we do * not modify toggle icons for any nested accordions. The state * of one accordion should not affect any accordions inside * of a nested accordion group. */ ion-accordion.accordion-expanding > [slot="header"] .ion-accordion-toggle-icon, ion-accordion.accordion-expanded > [slot="header"] .ion-accordion-toggle-icon { transform: rotate(180deg); } ion-accordion-group.accordion-group-expand-inset.md > ion-accordion.accordion-previous ion-item[slot="header"] { --border-width: 0px; --inner-border-width: 0px; } ion-accordion-group.accordion-group-expand-inset.md > ion-accordion.accordion-expanding:first-of-type, ion-accordion-group.accordion-group-expand-inset.md > ion-accordion.accordion-expanded:first-of-type { margin-top: 0; } // Safari/iOS 15 changes the appearance of input[type="date"]. // For backwards compatibility from Ionic 5/Safari 14 designs, // we override the appearance only when using within an ion-input. ion-input input::-webkit-date-and-time-value { text-align: start; } /** * The .ion-datetime-button-overlay class contains * styles that allow any modal/popover to be * sized according to the dimensions of the datetime * when used with ion-datetime-button. */ .ion-datetime-button-overlay { --width: fit-content; --height: fit-content; } /** * The grid variant can scale down when inline. * When used in a `fit-content` overlay, this causes * the overlay to shrink when the month/year picker is open. * Explicitly setting the dimensions lets us have a consistently * sized grid interface. */ .ion-datetime-button-overlay ion-datetime.datetime-grid { width: 320px; min-height: 320px; }