@rdlabo/ionic-theme-ios27 1.2.0-1 → 1.2.0-beta.pr226.shaa2e125f11160

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- @property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}ion-split-pane.ios-theme-split-pane-half-open{--ios-theme-split-pane-width: 50vw}ion-app.ios-theme-vertical-bars{--ios-theme-vertical-bars-safe-area-left-resolved: var(--ios-theme-vertical-bars-safe-area-left, 0px);--ios-theme-vertical-bars-safe-area-right-resolved: var( --ios-theme-vertical-bars-safe-area-right, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-right, 0px))) )}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left{--ios-theme-vertical-bars-safe-area-left-resolved: var( --ios-theme-vertical-bars-safe-area-left, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-left, 0px))) );--ios-theme-vertical-bars-safe-area-right-resolved: var(--ios-theme-vertical-bars-safe-area-right, 0px)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(ion-menu-button,ion-button).ios-theme-vertical-bars-toolbar-projection{--ios26-glass-background-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-border-color-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-box-shadow-color-rgb: var(--ion-text-color-rgb, 0, 0, 0)}ion-app.ios-theme-vertical-bars .ios-transition-shade{clip-path:inset(0 var(--ios-theme-vertical-bars-safe-area-right-resolved) 0 var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *))::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl)::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *))::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *)):dir(rtl)::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px;--ios-theme-vertical-bars-fab-edge-gap: 16px;--ios-theme-vertical-bars-fab-start-offset: var(--ios-theme-menu-width, var(--ios26-menu-width, 0px))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):has(.fab-button-small){--ios-theme-vertical-bars-fab-edge-gap: 10px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-right:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-left: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-left:var(--ios-theme-vertical-bars-safe-area-left-resolved)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-tab-bar-width: 50px;--ios-theme-side-tab-bar-gap: 8px;--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-right-resolved);contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:46px;min-width:46px;max-width:46px;height:fit-content;min-height:0;padding:2px;border-radius:25px;left:auto;right:max(4px,(var(--ios-theme-side-safe-area) - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:calc(var(--ion-safe-area-bottom, 0px) + var(--ios-theme-side-tab-bar-gap))}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element){display:block;flex:none;width:46px;min-width:46px;height:52px;min-height:52px;border-radius:23px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)::part(native){justify-content:center}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:0;margin-inline-start:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;padding-block:4px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element) ion-label{position:static;width:auto;height:auto;max-width:44px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:.5rem;line-height:1;text-overflow:ellipsis;white-space:nowrap}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-left-resolved);right:auto;left:max(4px,(var(--ios-theme-side-safe-area) - var(--ios-theme-side-tab-bar-width))/2)}.ios-theme-native-ui-shell-prehidden{position:absolute !important;visibility:hidden !important}html.ios-theme-native-ui-shell-prehide ion-app.ios-theme-vertical-bars ion-back-button:not([icon],[color],.ios-theme-vertical-bars-back-web-owned,.ionic-theme-disabled,.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection):not(:where(ion-menu *,ion-modal *,ion-popover *,ion-header[collapse] *,ion-footer[collapse] *,ion-buttons.ios-theme-horizontal-only *,.ios-theme-shell-disabled *,.ionic-theme-disabled *,.ios-theme-disabled *,.ios26-disabled *)){position:absolute !important;visibility:hidden !important}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-shell]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-shell]))){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection{position:fixed;z-index:1001;top:var(--ios-theme-vertical-bars-toolbar-top, 220px);right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);display:block;width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{position:fixed;z-index:1001;top:calc(var(--ios-theme-vertical-bars-toolbar-top, 220px) + var(--ios-theme-vertical-bars-toolbar-offset, 0px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);width:46px;min-width:46px;height:46px;min-height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg){width:22px;height:22px;margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-radius:50%}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);--border-radius: 50%;--box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection::part(native){backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;box-shadow:var(--box-shadow);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection::part(native){border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{display:flex;flex-direction:column;height:auto;min-height:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action{display:block;width:44px;min-width:44px;height:46px;min-height:46px;margin:0 1px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native){margin-inline:auto}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{right:auto;left:max(4px,(var(--ios-theme-vertical-bars-safe-area-left-resolved) - 46px)/2)}
1
+ @property --ios-theme-split-pane-width{syntax:"<length>";inherits:false;initial-value:320px}ion-split-pane.ios-theme-split-pane-half-open{--ios-theme-split-pane-width: 50vw}ion-app.ios-theme-vertical-bars{--ios-theme-vertical-bars-safe-area-left-resolved: var(--ios-theme-vertical-bars-safe-area-left, 0px);--ios-theme-vertical-bars-safe-area-right-resolved: var( --ios-theme-vertical-bars-safe-area-right, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-right, 0px))) )}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left{--ios-theme-vertical-bars-safe-area-left-resolved: var( --ios-theme-vertical-bars-safe-area-left, var(--ios-theme-vertical-bars-native-inset, max(80px, env(safe-area-inset-left, 0px))) );--ios-theme-vertical-bars-safe-area-right-resolved: var(--ios-theme-vertical-bars-safe-area-right, 0px)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(ion-menu-button,ion-button).ios-theme-vertical-bars-toolbar-projection{--ios26-glass-background-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-border-color-rgb: var(--ion-background-color-rgb, 255, 255, 255);--ios26-glass-box-shadow-color-rgb: var(--ion-text-color-rgb, 0, 0, 0)}ion-app.ios-theme-vertical-bars .ios-transition-shade{clip-path:inset(0 var(--ios-theme-vertical-bars-safe-area-right-resolved) 0 var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *))::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-content:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl)::part(scroll){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *))::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):not(:where(ion-header.header-collapse-condense *,ion-footer.footer-collapse-fade *)):dir(rtl)::part(container){padding-inline-start:calc(var(--padding-start, 0px) + var(--ios-theme-vertical-bars-safe-area-right-resolved));padding-inline-end:calc(var(--padding-end, 0px) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)){--ion-safe-area-left: 0px;--ion-safe-area-right: 0px;--ios-theme-vertical-bars-fab-edge-gap: 16px;--ios-theme-vertical-bars-fab-start-offset: var(--ios-theme-menu-width, var(--ios26-menu-width, 0px))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-start{inset-inline-start:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-fab-start-offset) + var(--ios-theme-vertical-bars-safe-area-right-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):dir(rtl).fab-horizontal-end{inset-inline-end:calc(var(--ios-theme-vertical-bars-fab-edge-gap) + var(--ios-theme-vertical-bars-safe-area-left-resolved))}ion-app.ios-theme-vertical-bars ion-fab:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)):has(.fab-button-small){--ios-theme-vertical-bars-fab-edge-gap: 10px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-right: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-right:var(--ios-theme-vertical-bars-safe-area-right-resolved)}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled){--ion-safe-area-left: 0px}ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-start:not(:dir(rtl)):not(.ios-theme-disabled,.ios26-disabled)::part(container),ion-app.ios-theme-vertical-bars ion-menu:is(.ios,.md).menu-side-end:dir(rtl):not(.ios-theme-disabled,.ios26-disabled)::part(container){margin-left:var(--ios-theme-vertical-bars-safe-area-left-resolved)}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-tab-bar-width: 50px;--ios-theme-side-tab-bar-gap: 8px;--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-right-resolved);contain:layout style;position:absolute;z-index:2;display:flex;flex-direction:column;width:46px;min-width:46px;max-width:46px;height:fit-content;min-height:0;padding:2px;border-radius:25px;left:auto;right:max(4px,(var(--ios-theme-side-safe-area) - var(--ios-theme-side-tab-bar-width))/2);margin:0;top:auto;bottom:calc(var(--ion-safe-area-bottom, 0px) + var(--ios-theme-side-tab-bar-gap))}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled).ios27-enable-gesture{touch-action:pan-x pinch-zoom}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element){display:block;flex:none;width:46px;min-width:46px;height:52px;min-height:52px;border-radius:23px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)::part(native){justify-content:center;min-height:52px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:28px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled)>ion-tab-button:not(.ion-cloned-element)~ion-tab-button:not(.ion-cloned-element){margin-block-start:0;margin-inline-start:0}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element)::part(native){flex-direction:column;padding-block:4px}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element) ion-label{position:static;width:auto;height:auto;max-width:44px;padding:0;margin:1px 0 0;overflow:hidden;clip:auto;font-size:.5rem;line-height:1;text-overflow:ellipsis;white-space:nowrap}ion-app.ios-theme-vertical-bars ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):has(>ion-tab-button:is(.ion-activated,:active))>ion-tab-button:not(.ion-cloned-element) ion-icon{margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left ion-tabs:not(:where(ion-menu *,ion-modal *,ion-popover *))>ion-tab-bar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled){--ios-theme-side-safe-area: var(--ios-theme-vertical-bars-safe-area-left-resolved);right:auto;left:max(4px,(var(--ios-theme-side-safe-area) - var(--ios-theme-side-tab-bar-width))/2)}.ios-theme-native-ui-shell-prehidden{position:absolute !important;visibility:hidden !important}html.ios-theme-native-ui-shell-prehide ion-app.ios-theme-vertical-bars ion-back-button:not([icon],[color],.ios-theme-vertical-bars-back-web-owned,.ionic-theme-disabled,.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection):not(:where(ion-menu *,ion-modal *,ion-popover *,ion-header[collapse] *,ion-footer[collapse] *,ion-buttons.ios-theme-horizontal-only *,.ios-theme-shell-disabled *,.ionic-theme-disabled *,.ios-theme-disabled *,.ios26-disabled *)){position:absolute !important;visibility:hidden !important}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)) ion-back-button:is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-back-button-projection){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)) ion-buttons:is(.ios,.md)>:is(ion-button,ion-menu-button):is(.ios,.md)[data-native-ui-shell]:not(.ios-theme-disabled,.ios26-disabled,.ios-theme-vertical-bars-toolbar-action){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready ion-toolbar:is(.ios,.md):not(.ios-theme-disabled,.ios26-disabled):not(:where(ion-menu *,ion-modal *,ion-popover *)) ion-buttons:is(.ios,.md):has(>:is(ion-back-button,ion-button,ion-menu-button)[data-native-ui-shell]):not(:has(>:is(ion-back-button,ion-button,ion-menu-button):not([data-native-ui-shell]))){display:none}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-back-button.ios-theme-vertical-bars-back-button-projection{position:fixed;z-index:1001;top:var(--ios-theme-vertical-bars-toolbar-top, 220px);right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);display:block;width:46px;height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{position:fixed;z-index:1001;top:calc(var(--ios-theme-vertical-bars-toolbar-top, 220px) + var(--ios-theme-vertical-bars-toolbar-offset, 0px));right:max(4px,(var(--ios-theme-vertical-bars-safe-area-right-resolved) - 46px)/2);width:46px;min-width:46px;height:46px;min-height:46px;margin:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection :is(ion-icon,svg){width:22px;height:22px;margin:0;font-size:22px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-menu-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{border-radius:50%}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{--background: rgba(var(--ios-theme-glass-background-rgb, var(--ios26-glass-background-rgb)), 0.72);--border-radius: 50%;--box-shadow:inset 0 1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.25),inset 0 -1px 2px rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.3),0 -0.5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 .5px 0 rgba(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)), 0.65),0 0 0 .5px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.22),0 .5px 1px rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.08)}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection::part(native){backdrop-filter:blur(2px) saturate(360%);transform:translateZ(0);-webkit-transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden;box-shadow:var(--box-shadow);border:.5px solid rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)));background-image:linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%);background-origin:padding-box;background-clip:border-box;border-inline-color:rgba(0,0,0,0)}@supports(background-clip: border-area){ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-button:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection::part(native){border-color:rgba(0,0,0,0);background-image:linear-gradient(180deg, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb))), transparent 50%, rgb(var(--ios-theme-glass-border-color-rgb, var(--ios26-glass-border-color-rgb)))),linear-gradient(180deg, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 4%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.01) 8%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 16%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.027) 22%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.026) 28%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.018) 36%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 44%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 50%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.024) 58%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.008) 80%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.006) 88%, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0) 94%),linear-gradient(transparent, transparent);background-origin:border-box,padding-box,border-box;background-clip:border-area,padding-box,border-box}}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{display:flex;flex-direction:column;height:auto;min-height:0}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action{display:block;width:44px;min-width:44px;height:46px;min-height:46px;margin:0 1px}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-toolbar-ready>ion-buttons:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection>:is(ion-button,ion-menu-button):is(.ios,.md).ios-theme-vertical-bars-toolbar-action::part(native){margin-inline:auto}ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>ion-back-button.ios-theme-vertical-bars-back-button-projection,ion-app.ios-theme-vertical-bars.ios-theme-vertical-bars-left>:is(.ios,.md).ios-theme-vertical-bars-toolbar-projection{right:auto;left:max(4px,(var(--ios-theme-vertical-bars-safe-area-left-resolved) - 46px)/2)}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect{border-radius:23px}ion-tab-button.ios.ion-cloned-element.ios27-vertical-tab-effect::part(native){min-height:0;height:100%}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EACL,wBAAwB,IAAI,qBAAqB,EACjD,wBAAwB,IAAI,qBAAqB,GAClD,MAAM,2BAA2B,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,eAAO,MAAM,oBAAoB,GAAI,eAAe,WAAW,KAAG,gBAAgB,GAAG,SAgCpF,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EACL,wBAAwB,IAAI,qBAAqB,EACjD,wBAAwB,IAAI,qBAAqB,GAClD,MAAM,2BAA2B,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,eAAO,MAAM,oBAAoB,GAAI,eAAe,WAAW,KAAG,gBAAgB,GAAG,SA+DpF,CAAC"}
package/dist/index.js CHANGED
@@ -13,24 +13,43 @@ export const registerTabBarEffect = (targetElement) => {
13
13
  const reducedMotion = win.matchMedia('(prefers-reduced-motion: reduce)');
14
14
  const verticalBarsRoot = targetElement.closest('ion-app');
15
15
  let effect;
16
+ let placement;
16
17
  const update = () => {
18
+ const isVertical = !!verticalBarsRoot?.classList.contains('ios-theme-vertical-bars') &&
19
+ targetElement.matches('ion-tabs > ion-tab-bar:not(.ios-theme-disabled, .ios26-disabled)') &&
20
+ !targetElement.closest('ion-menu, ion-modal, ion-popover');
21
+ const disabled = reducedMotion.matches || !targetElement.matches('.ios:not(.ios-theme-disabled, .ios26-disabled)');
22
+ const nextPlacement = disabled
23
+ ? 'disabled'
24
+ : isVertical
25
+ ? verticalBarsRoot?.classList.contains('ios-theme-vertical-bars-left')
26
+ ? 'left'
27
+ : 'right'
28
+ : 'horizontal';
29
+ if (placement === nextPlacement)
30
+ return;
31
+ placement = nextPlacement;
17
32
  effect?.destroy();
18
- const isVertical = !!verticalBarsRoot?.classList.contains('ios-theme-vertical-bars') && !targetElement.closest('ion-menu, ion-modal, ion-popover');
19
- effect =
20
- reducedMotion.matches || isVertical
21
- ? undefined
22
- : registerEffect(targetElement, 'ion-tab-button', 'tab-selected', {
23
- small: 'scale(1.1, 1)',
24
- medium: 'scale(1.2)',
25
- large: 'scale(1.15, 1.4)',
26
- xlarge: 'scale(1.3)',
27
- });
33
+ effect = disabled
34
+ ? undefined
35
+ : registerEffect(targetElement, 'ion-tab-button', 'tab-selected', {
36
+ small: 'scale(1.1, 1)',
37
+ medium: 'scale(1.2)',
38
+ large: 'scale(1.15, 1.4)',
39
+ xlarge: 'scale(1.3)',
40
+ }, isVertical);
28
41
  };
29
42
  update();
30
43
  reducedMotion.addEventListener('change', update);
31
- const placementObserver = new win.MutationObserver(update);
44
+ const placementObserver = new win.MutationObserver((records) => {
45
+ if (records.some((record) => record.type === 'attributes'
46
+ ? record.target === targetElement || record.target === verticalBarsRoot
47
+ : [...Array.from(record.addedNodes), ...Array.from(record.removedNodes)].some((node) => node.contains(targetElement))))
48
+ update();
49
+ });
32
50
  if (verticalBarsRoot)
33
- placementObserver.observe(verticalBarsRoot, { attributes: true, attributeFilter: ['class'] });
51
+ placementObserver.observe(verticalBarsRoot, { attributes: true, attributeFilter: ['class'], childList: true, subtree: true });
52
+ placementObserver.observe(targetElement, { attributes: true, attributeFilter: ['class'] });
34
53
  return {
35
54
  destroy: () => {
36
55
  reducedMotion.removeEventListener('change', update);
@@ -1,14 +1,23 @@
1
1
  import type { Animation, AnimationKeyFrames } from '@ionic/core';
2
2
  import { AnimationPosition, EffectScales } from './interfaces';
3
3
  import { GestureDetail } from '@ionic/core';
4
+ export declare const animationRect: (element: Element, vertical?: boolean) => DOMRect | {
5
+ left: number;
6
+ top: number;
7
+ right: number;
8
+ width: number;
9
+ height: number;
10
+ x: number;
11
+ y: number;
12
+ };
4
13
  export declare const getScaleAnimation: (effectElement: Element) => Animation;
5
- export declare const createTabBarPressAnimation: (effect: HTMLElement, from: HTMLElement, to: HTMLElement, bar: HTMLElement) => Animation;
6
- export declare const createTabBarDragAnimation: (effect: HTMLElement, bar: HTMLElement, velocity: number) => Animation;
14
+ export declare const createTabBarPressAnimation: (effect: HTMLElement, from: HTMLElement, to: HTMLElement, bar: HTMLElement, vertical?: boolean) => Animation;
15
+ export declare const createTabBarDragAnimation: (effect: HTMLElement, bar: HTMLElement, velocity: number, vertical?: boolean) => Animation;
7
16
  export declare const createTabBarReleaseAnimation: (effectElement: Element, target: HTMLElement, tap?: {
8
17
  elapsed: number;
9
18
  distance: number;
10
- }) => Animation;
19
+ }, vertical?: boolean) => Animation;
11
20
  export declare const createPreMoveAnimation: (effectElement: Element, tabSelectedElement: Element, currentTouchedElement: Element, animationPosition: AnimationPosition) => Animation;
12
- export declare const createMoveAnimation: (effectElement: Element, detail: GestureDetail, tabSelectedElement: Element, animationPosition: AnimationPosition) => Animation;
21
+ export declare const createMoveAnimation: (effectElement: Element, detail: GestureDetail, tabSelectedElement: Element, animationPosition: AnimationPosition, vertical?: boolean) => Animation;
13
22
  export declare const getMoveAnimationKeyframe: (type: "moveRight" | "moveLeft" | "slowly", scales: EffectScales) => AnimationKeyFrames;
14
23
  //# sourceMappingURL=animations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"animations.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/animations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAG7D,eAAO,MAAM,iBAAiB,GAAI,eAAe,OAAO,KAAG,SAE1D,CAAC;AAyCF,eAAO,MAAM,0BAA0B,GAAI,QAAQ,WAAW,EAAE,MAAM,WAAW,EAAE,IAAI,WAAW,EAAE,KAAK,WAAW,KAAG,SAuCtH,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAAI,QAAQ,WAAW,EAAE,KAAK,WAAW,EAAE,UAAU,MAAM,KAAG,SAmBnG,CAAC;AAGF,eAAO,MAAM,4BAA4B,GACvC,eAAe,OAAO,EACtB,QAAQ,WAAW,EACnB,MAAM;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAC1C,SAgIF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,eAAe,OAAO,EACtB,oBAAoB,OAAO,EAC3B,uBAAuB,OAAO,EAC9B,mBAAmB,iBAAiB,KACnC,SA0BF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,eAAe,OAAO,EACtB,QAAQ,aAAa,EACrB,oBAAoB,OAAO,EAC3B,mBAAmB,iBAAiB,KACnC,SAiBF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,EAAE,QAAQ,YAAY,KAAG,kBAqD1G,CAAC"}
1
+ {"version":3,"file":"animations.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/animations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAI7D,eAAO,MAAM,aAAa,GAAI,SAAS,OAAO,EAAE,kBAAgB;;;;;;;;CAK/D,CAAC;AASF,eAAO,MAAM,iBAAiB,GAAI,eAAe,OAAO,KAAG,SAE1D,CAAC;AAyCF,eAAO,MAAM,0BAA0B,GACrC,QAAQ,WAAW,EACnB,MAAM,WAAW,EACjB,IAAI,WAAW,EACf,KAAK,WAAW,EAChB,kBAAgB,KACf,SAqCF,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAAI,QAAQ,WAAW,EAAE,KAAK,WAAW,EAAE,UAAU,MAAM,EAAE,kBAAgB,KAAG,SAmBrH,CAAC;AAGF,eAAO,MAAM,4BAA4B,GACvC,eAAe,OAAO,EACtB,QAAQ,WAAW,EACnB,MAAM;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC3C,kBAAgB,KACf,SAgIF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,eAAe,OAAO,EACtB,oBAAoB,OAAO,EAC3B,uBAAuB,OAAO,EAC9B,mBAAmB,iBAAiB,KACnC,SA0BF,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,eAAe,OAAO,EACtB,QAAQ,aAAa,EACrB,oBAAoB,OAAO,EAC3B,mBAAmB,iBAAiB,EACpC,kBAAgB,KACf,SAiBF,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,MAAM,WAAW,GAAG,UAAU,GAAG,QAAQ,EAAE,QAAQ,YAAY,KAAG,kBAqD1G,CAAC"}
@@ -1,5 +1,18 @@
1
1
  import { createAnimation } from '@ionic/core';
2
2
  import { getStep } from '../utils';
3
+ export const animationRect = (element, vertical = false) => {
4
+ const rect = element.getBoundingClientRect();
5
+ return vertical
6
+ ? { left: rect.top, top: rect.left, right: rect.bottom, width: rect.height, height: rect.width, x: rect.y, y: rect.x }
7
+ : rect;
8
+ };
9
+ const translate = (x, y, vertical) => `translate3d(${vertical ? y : x}px, ${vertical ? x : y}px, 0)`;
10
+ const stretchTransform = (x, y, vertical) => `scale(${vertical ? y : x}, ${vertical ? x : y})`;
11
+ const mainSize = (element, vertical) => (vertical ? element.offsetHeight : element.offsetWidth);
12
+ const axisScale = (transform, vertical) => {
13
+ const matrix = new DOMMatrixReadOnly(transform);
14
+ return vertical ? { a: matrix.d, d: matrix.a } : matrix;
15
+ };
3
16
  export const getScaleAnimation = (effectElement) => {
4
17
  return createAnimation().addElement(effectElement.shadowRoot.querySelector('[part="native"]')).easing('ease-out');
5
18
  };
@@ -37,21 +50,21 @@ const tabBarTapFrames = [
37
50
  [0.7, 1.003, -0.74, 0.59],
38
51
  [0.8, 1, 0, 0],
39
52
  ];
40
- export const createTabBarPressAnimation = (effect, from, to, bar) => {
41
- const box = bar.getBoundingClientRect();
53
+ export const createTabBarPressAnimation = (effect, from, to, bar, vertical = false) => {
54
+ const box = animationRect(bar, vertical);
42
55
  const center = box.left + box.width / 2;
43
- const left = center - bar.offsetWidth / 2;
44
- const fromBox = from.getBoundingClientRect();
45
- const toBox = to.getBoundingClientRect();
46
- const parentScale = box.width / bar.offsetWidth;
47
- const buttonScale = new DOMMatrixReadOnly(getComputedStyle(from).transform);
56
+ const left = center - mainSize(bar, vertical) / 2;
57
+ const fromBox = animationRect(from, vertical);
58
+ const toBox = animationRect(to, vertical);
59
+ const parentScale = box.width / mainSize(bar, vertical);
60
+ const buttonScale = axisScale(getComputedStyle(from).transform, vertical);
48
61
  const width = fromBox.width / parentScale / buttonScale.a;
49
62
  const height = fromBox.height / parentScale / buttonScale.d;
50
63
  const start = (fromBox.left + fromBox.width / 2 - box.left) / parentScale;
51
64
  const end = (toBox.left + toBox.width / 2 - box.left) / parentScale;
52
65
  const selected = from === to;
53
66
  const frames = tabBarPressFrames.map(([time, position, extraWidth, extraHeight, expansion]) => {
54
- const scale = 1 + (14.14 / bar.offsetWidth) * expansion;
67
+ const scale = 1 + (14.14 / mainSize(bar, vertical)) * expansion;
55
68
  const press = 1 - Math.exp(-18 * time) * (1 + 18 * time);
56
69
  return {
57
70
  offset: time / 0.9,
@@ -63,22 +76,22 @@ export const createTabBarPressAnimation = (effect, from, to, bar) => {
63
76
  const move = createAnimation()
64
77
  .addElement(effect)
65
78
  .beforeStyles({
66
- width: `${width}px`,
67
- height: `${height}px`,
79
+ width: `${vertical ? height : width}px`,
80
+ height: `${vertical ? width : height}px`,
68
81
  display: 'block',
69
82
  opacity: '1',
70
83
  })
71
- .keyframes(frames.map(({ offset, x }) => ({ offset, transform: `translate3d(${x}px, ${box.top + box.height / 2 - height / 2}px, 0)` })));
84
+ .keyframes(frames.map(({ offset, x }) => ({ offset, transform: translate(x, box.top + box.height / 2 - height / 2, vertical) })));
72
85
  const stretch = getScaleAnimation(effect)
73
86
  .easing('linear')
74
- .keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform: `scale(${sx}, ${sy})` })));
87
+ .keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform: stretchTransform(sx, sy, vertical) })));
75
88
  return createAnimation().duration(900).easing('linear').addAnimation([move, stretch]);
76
89
  };
77
- export const createTabBarDragAnimation = (effect, bar, velocity) => {
90
+ export const createTabBarDragAnimation = (effect, bar, velocity, vertical = false) => {
78
91
  const native = effect.shadowRoot.querySelector('[part="native"]');
79
- const current = new DOMMatrixReadOnly(native.style.transform || getComputedStyle(native).transform);
80
- const { width, height } = effect.getBoundingClientRect();
81
- const scale = 1 + 14.14 / bar.offsetWidth;
92
+ const current = axisScale(native.style.transform || getComputedStyle(native).transform, vertical);
93
+ const { width, height } = animationRect(effect, vertical);
94
+ const scale = 1 + 14.14 / mainSize(bar, vertical);
82
95
  const restX = ((width + 16) * scale) / width;
83
96
  const restY = ((height + 16) * scale) / height;
84
97
  const stretch = Math.min(16, 32 * velocity * velocity) * scale;
@@ -87,16 +100,16 @@ export const createTabBarDragAnimation = (effect, bar, velocity) => {
87
100
  .duration(500)
88
101
  .easing('linear')
89
102
  .keyframes([
90
- { offset: 0, transform: `scale(${current.a}, ${current.d})` },
91
- { offset: 0.2, transform: `scale(${restX + stretch / width}, ${restY - stretch / height})` },
92
- { offset: 0.44, transform: `scale(${restX - rebound / width}, ${restY + rebound / height})` },
93
- { offset: 1, transform: `scale(${restX}, ${restY})` },
103
+ { offset: 0, transform: stretchTransform(current.a, current.d, vertical) },
104
+ { offset: 0.2, transform: stretchTransform(restX + stretch / width, restY - stretch / height, vertical) },
105
+ { offset: 0.44, transform: stretchTransform(restX - rebound / width, restY + rebound / height, vertical) },
106
+ { offset: 1, transform: stretchTransform(restX, restY, vertical) },
94
107
  ]);
95
108
  };
96
- export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
109
+ export const createTabBarReleaseAnimation = (effectElement, target, tap, vertical = false) => {
97
110
  const tapElapsed = tap?.elapsed;
98
111
  const native = effectElement.shadowRoot.querySelector('[part="native"]');
99
- const scale = new DOMMatrixReadOnly(native.style.transform || getComputedStyle(native).transform);
112
+ const scale = axisScale(native.style.transform || getComputedStyle(native).transform, vertical);
100
113
  const samples = [
101
114
  [0, 1],
102
115
  [0.033, 0.85],
@@ -110,11 +123,11 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
110
123
  [0.45, 0],
111
124
  ];
112
125
  const bar = target.parentElement;
113
- const box = bar.getBoundingClientRect();
114
- const current = effectElement.getBoundingClientRect();
115
- const targetBox = target.getBoundingClientRect();
126
+ const box = animationRect(bar, vertical);
127
+ const current = animationRect(effectElement, vertical);
128
+ const targetBox = animationRect(target, vertical);
116
129
  const center = box.left + box.width / 2;
117
- const x = center + (targetBox.left + targetBox.width / 2 - center) / (box.width / bar.offsetWidth) - current.width / 2;
130
+ const x = center + (targetBox.left + targetBox.width / 2 - center) / (box.width / mainSize(bar, vertical)) - current.width / 2;
118
131
  const y = box.top + box.height / 2 - current.height / 2;
119
132
  const elapsed = (tapElapsed ?? 0) / 1000;
120
133
  const duration = tapElapsed === undefined ? 450 : 800 - tapElapsed;
@@ -136,7 +149,7 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
136
149
  ...tabBarTapFrames.slice(nextIndex).map(([time, position, width, height]) => ({
137
150
  offset: (time - elapsed) / (0.8 - elapsed),
138
151
  x: x + ((current.x - x) * (1 - position)) / Math.max(0.1, 1 - progress),
139
- y,
152
+ y: y + ((current.y - y) * (1 - position)) / Math.max(0.1, 1 - progress),
140
153
  sx: 1 + (width * (time >= 0.367 ? 1 + 0.75 * extraDistance : 1)) / current.width,
141
154
  sy: 1 + (height * (time >= 0.367 ? 1 + 0.5 * extraDistance : 1)) / current.height,
142
155
  })),
@@ -146,14 +159,14 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
146
159
  .addElement(native)
147
160
  .duration(duration)
148
161
  .easing('linear')
149
- .keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform: `scale(${sx}, ${sy})` })));
162
+ .keyframes(frames.map(({ offset, sx, sy }) => ({ offset, transform: stretchTransform(sx, sy, vertical) })));
150
163
  const move = createAnimation()
151
164
  .addElement(effectElement)
152
165
  .duration(duration)
153
166
  .easing('linear')
154
167
  .keyframes(frames.map(({ offset, x, y }) => ({
155
168
  offset,
156
- transform: `translate3d(${x}px, ${y}px, 0)`,
169
+ transform: translate(x, y, vertical),
157
170
  })));
158
171
  const offset = 1 - 200 / duration;
159
172
  const selectedBackground = 'var(--ios27-tab-selected-background, rgba(var(--ios-theme-button-color-selected-rgb, var(--ios26-button-color-selected-rgb, var(--ios27-button-color-selected-default-rgb))), 0.095))';
@@ -175,7 +188,7 @@ export const createTabBarReleaseAnimation = (effectElement, target, tap) => {
175
188
  ]);
176
189
  const release = createAnimation().duration(duration).addAnimation([stretch, move, glass, selected]);
177
190
  if (tapElapsed !== undefined) {
178
- const width = bar.offsetWidth;
191
+ const width = mainSize(bar, vertical);
179
192
  const expansion = box.width - width;
180
193
  const peak = Math.max(8.65, expansion);
181
194
  const platter = createAnimation()
@@ -236,7 +249,7 @@ export const createPreMoveAnimation = (effectElement, tabSelectedElement, curren
236
249
  },
237
250
  ]);
238
251
  };
239
- export const createMoveAnimation = (effectElement, detail, tabSelectedElement, animationPosition) => {
252
+ export const createMoveAnimation = (effectElement, detail, tabSelectedElement, animationPosition, vertical = false) => {
240
253
  return createAnimation()
241
254
  .duration(500)
242
255
  .addElement(effectElement)
@@ -247,7 +260,7 @@ export const createMoveAnimation = (effectElement, detail, tabSelectedElement, a
247
260
  opacity: '1',
248
261
  transform: 'none',
249
262
  })
250
- .fromTo('transform', `translate3d(${animationPosition.minPositionX}px, ${animationPosition.positionY}px, 0)`, `translate3d(${animationPosition.maxPositionX}px, ${animationPosition.positionY}px, 0)`)
263
+ .fromTo('transform', translate(animationPosition.minPositionX, animationPosition.positionY, vertical), translate(animationPosition.maxPositionX, animationPosition.positionY, vertical))
251
264
  .progressStep(getStep(detail.currentX, animationPosition));
252
265
  };
253
266
  export const getMoveAnimationKeyframe = (type, scales) => {
@@ -1,3 +1,3 @@
1
1
  import { EffectScales, registeredEffect } from './interfaces';
2
- export declare const registerEffect: (targetElement: HTMLElement, effectTagName: string, selectedClassName: string, scales: EffectScales) => registeredEffect | undefined;
2
+ export declare const registerEffect: (targetElement: HTMLElement, effectTagName: string, selectedClassName: string, scales: EffectScales, vertical?: boolean) => registeredEffect | undefined;
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAkBjF,eAAO,MAAM,cAAc,GACzB,eAAe,WAAW,EAC1B,eAAe,MAAM,EACrB,mBAAmB,MAAM,EACzB,QAAQ,YAAY,KACnB,gBAAgB,GAAG,SAqVrB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sheets-of-glass/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAmBjF,eAAO,MAAM,cAAc,GACzB,eAAe,WAAW,EAC1B,eAAe,MAAM,EACrB,mBAAmB,MAAM,EACzB,QAAQ,YAAY,EACpB,kBAAgB,KACf,gBAAgB,GAAG,SA0XrB,CAAC"}
@@ -1,10 +1,10 @@
1
1
  import { createGesture } from '@ionic/core';
2
2
  import { changeSelectedElement, cloneElement, getStep } from '../utils';
3
3
  import { isNativeUIShell } from '../native-integration';
4
- import { createMoveAnimation, createPreMoveAnimation, createTabBarDragAnimation, createTabBarPressAnimation, createTabBarReleaseAnimation, getMoveAnimationKeyframe, getScaleAnimation, } from './animations';
4
+ import { animationRect, createMoveAnimation, createPreMoveAnimation, createTabBarDragAnimation, createTabBarPressAnimation, createTabBarReleaseAnimation, getMoveAnimationKeyframe, getScaleAnimation, } from './animations';
5
5
  const GESTURE_NAME = 'ios27-enable-gesture';
6
6
  const ANIMATED_NAME = 'ios27-animated';
7
- export const registerEffect = (targetElement, effectTagName, selectedClassName, scales) => {
7
+ export const registerEffect = (targetElement, effectTagName, selectedClassName, scales, vertical = false) => {
8
8
  if (!targetElement.classList.contains('ios')) {
9
9
  return undefined;
10
10
  }
@@ -24,6 +24,8 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
24
24
  let destroyed = false;
25
25
  const originalTabBarScale = targetElement.style.getPropertyValue('--ios27-tab-bar-scale');
26
26
  const effectElement = cloneElement(effectTagName, false);
27
+ if (vertical)
28
+ effectElement.classList.add('ios27-vertical-tab-effect');
27
29
  const stopTabPress = () => {
28
30
  if (!tabPressAnimation)
29
31
  return;
@@ -98,17 +100,29 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
98
100
  document.addEventListener('pointercancel', onPointerCancel);
99
101
  };
100
102
  targetElement.addEventListener('pointerdown', onPointerDown);
103
+ const axisDetail = (detail) => vertical
104
+ ? {
105
+ ...detail,
106
+ currentX: detail.currentY,
107
+ currentY: detail.currentX,
108
+ startX: detail.startY,
109
+ startY: detail.startX,
110
+ velocityX: detail.velocityY,
111
+ velocityY: detail.velocityX,
112
+ }
113
+ : detail;
101
114
  const createAnimationGesture = () => {
102
115
  targetElement.classList.add(GESTURE_NAME);
103
116
  gesture = createGesture({
104
117
  el: targetElement,
105
118
  threshold: 0,
119
+ direction: vertical ? 'y' : 'x',
106
120
  gestureName: `${GESTURE_NAME}_${effectTagName}_${crypto.randomUUID()}`,
107
- onStart: (event) => onStartGesture(event),
108
- onMove: (event) => onMoveGesture(event),
121
+ onStart: (event) => onStartGesture(axisDetail(event)),
122
+ onMove: (event) => onMoveGesture(axisDetail(event)),
109
123
  onEnd: (detail) => {
110
124
  if (effectTagName === 'ion-tab-button' && tabDragging)
111
- onMoveGesture(detail);
125
+ onMoveGesture(axisDetail(detail));
112
126
  onEndGesture().then();
113
127
  },
114
128
  });
@@ -135,25 +149,29 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
135
149
  return false;
136
150
  currentTouchedElement = detail.event.target.closest(effectTagName) || undefined;
137
151
  const tabSelectedElement = targetElement.querySelector(`${effectTagName}.${selectedClassName}`);
138
- if (currentTouchedElement === undefined || tabSelectedElement === null) {
152
+ if (currentTouchedElement === undefined ||
153
+ currentTouchedElement.parentElement !== targetElement ||
154
+ currentTouchedElement.disabled ||
155
+ tabSelectedElement === null) {
156
+ currentTouchedElement = undefined;
139
157
  return false;
140
158
  }
141
159
  selectedElementBeforeGesture = tabSelectedElement;
142
160
  if (effectTagName === 'ion-tab-button') {
143
- targetElement.style.setProperty('--ios27-tab-bar-scale', String(1 + 14.14 / targetElement.offsetWidth));
161
+ targetElement.style.setProperty('--ios27-tab-bar-scale', String(1 + 14.14 / (vertical ? targetElement.offsetHeight : targetElement.offsetWidth)));
144
162
  }
145
163
  animationPosition = {
146
- minPositionX: targetElement.getBoundingClientRect().left,
147
- maxPositionX: targetElement.getBoundingClientRect().right - tabSelectedElement.clientWidth,
148
- width: tabSelectedElement.clientWidth,
149
- positionY: tabSelectedElement.getBoundingClientRect().top,
164
+ minPositionX: animationRect(targetElement, vertical).left,
165
+ maxPositionX: animationRect(targetElement, vertical).right - (vertical ? tabSelectedElement.clientHeight : tabSelectedElement.clientWidth),
166
+ width: vertical ? tabSelectedElement.clientHeight : tabSelectedElement.clientWidth,
167
+ positionY: animationRect(tabSelectedElement, vertical).top,
150
168
  };
151
169
  targetElement.classList.add(ANIMATED_NAME);
152
170
  changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
153
171
  if (effectTagName === 'ion-tab-button') {
154
- moveAnimation = createMoveAnimation(effectElement, detail, tabSelectedElement, animationPosition);
155
- moveAnimation.progressStart(true, getStep(tabSelectedElement.getBoundingClientRect().left + tabSelectedElement.clientWidth / 2, animationPosition));
156
- tabPressAnimation = createTabBarPressAnimation(effectElement, tabSelectedElement, currentTouchedElement, targetElement);
172
+ moveAnimation = createMoveAnimation(effectElement, detail, tabSelectedElement, animationPosition, vertical);
173
+ moveAnimation.progressStart(true, getStep(animationRect(tabSelectedElement, vertical).left + animationRect(tabSelectedElement, vertical).width / 2, animationPosition));
174
+ tabPressAnimation = createTabBarPressAnimation(effectElement, tabSelectedElement, currentTouchedElement, targetElement, vertical);
157
175
  tabPressStartedAt = performance.now();
158
176
  void tabPressAnimation.play();
159
177
  return true;
@@ -187,7 +205,7 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
187
205
  return;
188
206
  tabDragging = true;
189
207
  stopTabPress();
190
- tabPressAnimation = createTabBarDragAnimation(effectElement, targetElement, detail.velocityX);
208
+ tabPressAnimation = createTabBarDragAnimation(effectElement, targetElement, detail.velocityX, vertical);
191
209
  void tabPressAnimation.play();
192
210
  }
193
211
  else if (scaleAnimationPromise === undefined) {
@@ -211,10 +229,13 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
211
229
  }
212
230
  }
213
231
  const currentX = detail.currentX;
214
- const previousY = targetElement.getBoundingClientRect().top + targetElement.getBoundingClientRect().height / 2;
215
- const nextEl = targetElement.getRootNode().elementFromPoint(currentX, previousY);
232
+ const previousY = animationRect(targetElement, vertical).top + animationRect(targetElement, vertical).height / 2;
233
+ const nextEl = targetElement.getRootNode().elementFromPoint(vertical ? previousY : currentX, vertical ? currentX : previousY);
216
234
  const latestTouchedElement = nextEl?.closest(effectTagName) || undefined;
217
- if (latestTouchedElement && currentTouchedElement !== latestTouchedElement) {
235
+ if (latestTouchedElement &&
236
+ latestTouchedElement.parentElement === targetElement &&
237
+ !latestTouchedElement.disabled &&
238
+ currentTouchedElement !== latestTouchedElement) {
218
239
  currentTouchedElement = latestTouchedElement;
219
240
  changeSelectedElement(targetElement, currentTouchedElement, effectTagName, selectedClassName);
220
241
  }
@@ -268,7 +289,7 @@ export const registerEffect = (targetElement, effectTagName, selectedClassName,
268
289
  elapsed: tapElapsed,
269
290
  distance: Math.abs(tabs.indexOf(currentTouchedElement) - tabs.indexOf(selectedElementBeforeGesture)),
270
291
  }
271
- : undefined);
292
+ : undefined, vertical);
272
293
  currentTouchedElement.classList.remove('ion-activated');
273
294
  releaseAnimation = releasing;
274
295
  await releasing.play();
@@ -17,7 +17,7 @@ Available in `1.2.0-0` as an **experimental** feature. APIs and supported behavi
17
17
  This guide assumes an existing Ionic app with Ionic `>=8.8.1 <10` and Capacitor Core `>=8 <9`. Keep your existing Capacitor 8 installation. If your app uses another Capacitor major, migrate its Core, CLI, and platform packages together before following this guide. For a Web-only app without Capacitor, also install `@capacitor/core@^8`; the JavaScript entry point needs it even in Chrome.
18
18
 
19
19
  ```bash
20
- npm install @rdlabo/ionic-theme-ios27@1.2.0-0
20
+ npm install @rdlabo/ionic-theme-ios27@1.2.0-1
21
21
  ```
22
22
 
23
23
  Keep your existing theme imports. Add this to your global Sass file:
@@ -62,9 +62,23 @@ const ionicConfig = {
62
62
 
63
63
  Merge this option into your existing Ionic configuration before initialization: pass it to Angular's `provideIonicAngular()`, React's `setupIonicReact()`, or Vue's `IonicVue` plugin options. Keep your existing theme stylesheet imports. No iOS 27 theme stylesheet is required.
64
64
 
65
+ #### Use this package's iOS animation
66
+
67
+ If you already use the iOS 27 transition, keep this configuration. It includes the native adapter and excludes the horizontal back-button effect in vertical layouts; no additional wrapper is needed. Importing this JavaScript entry point does not load the theme stylesheets.
68
+
69
+ ```ts
70
+ import { iosTransitionAnimation } from '@rdlabo/ionic-theme-ios27';
71
+
72
+ const ionicConfig = {
73
+ navAnimation: iosTransitionAnimation,
74
+ };
75
+ ```
76
+
77
+ Apply this option to your existing iOS-mode configuration and keep your MD configuration.
78
+
65
79
  #### Keep your custom animation
66
80
 
67
- If your app already configures `navAnimation`, wrap that builder instead:
81
+ If your app uses another builder for `navAnimation`, wrap it:
68
82
 
69
83
  ```ts
70
84
  import type { AnimationBuilder } from '@ionic/core';
@@ -80,7 +94,7 @@ The adapter returns the original `Animation`, preserving its effects, duration,
80
94
 
81
95
  The adapter keeps the builder's animation targets, including any horizontal back-button effect. If you need the iOS 27 transition with that effect excluded in vertical layouts, use `iosTransitionAnimation` from `@rdlabo/ionic-theme-ios27` as your `navAnimation` instead. It already includes the adapter, so no wrapper is needed.
82
96
 
83
- The adapter is available after `1.2.0-0`. With `1.2.0-0`, use the package's `iosTransitionAnimation` for iOS mode and keep your existing MD configuration.
97
+ `withNativeUIShellTransition()` is available in `1.2.0-1` and later.
84
98
 
85
99
  ### 4. Start the controls after the app root is mounted
86
100
 
package/docs/migration.md CHANGED
@@ -8,8 +8,8 @@ title: Migration
8
8
 
9
9
  Use `withNativeUIShellTransition()` to keep your existing Ionic navigation animation while coordinating Native UI Shell controls.
10
10
 
11
- - If you already use this package's `iosTransitionAnimation`, no configuration change is needed. It now uses the shared adapter internally; do not add another wrapper.
12
- - If you use Ionic's default animation without a `navAnimation` option, follow [Keep Ionic's default animation](./iphone-duo-with-original-theme.md#keep-ionics-default-animation). The example selects Ionic's standard iOS or MD builder from the transition mode.
11
+ - If you already import `iosTransitionAnimation` from `@rdlabo/ionic-theme-ios27`, keep the [package animation setup](./iphone-duo-with-original-theme.md#use-this-package%27s-ios-animation); no configuration change is needed. It now uses the shared adapter internally; do not add another wrapper.
12
+ - If you use Ionic's default animation without a `navAnimation` option, follow [Keep Ionic's default animation](./iphone-duo-with-original-theme.md#keep-ionic%27s-default-animation). The example selects Ionic's standard iOS or MD builder from the transition mode.
13
13
  - If you use a custom navigation animation with Native UI Shell or the standalone Vertical Control Area, wrap your existing builder when configuring Ionic:
14
14
 
15
15
  ```diff
@@ -25,7 +25,7 @@ Merge this option into your existing Ionic configuration before initialization.
25
25
 
26
26
  Use the adapter only for navigation; leave modal and popover animations unchanged. Your builder must create a fresh `Animation` for each navigation because Ionic destroys it afterward. Keep lifecycle events for control registration and transitions without animation. If the custom builder animates a horizontal back button separately, exclude that effect while `.ios-theme-vertical-bars` is active.
27
27
 
28
- See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3-connect-your-navigation-animation) for the setup and supported scope.
28
+ See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3.-connect-your-navigation-animation) for the setup and supported scope.
29
29
 
30
30
  ## From the iOS 26 theme
31
31
 
@@ -116,7 +116,7 @@ FAB support covers the standard circular glass appearance, text and resolved sta
116
116
 
117
117
  Custom host animation or transition declarations on the FAB, list or button keep the group on the Web until removed. Button transforms support the standard identity and hidden-child scale(0), not custom scaling. For children inside a `display:none` list, browsers can report a computed transform of `none` even when a custom transform is declared. Such transforms are checked when layout becomes available; the whole FAB then returns to Web if needed. The plugin does not parse application stylesheets or temporarily open lists to predict hidden layout.
118
118
 
119
- The built-in `iosTransitionAnimation` waits for native retirement before starting the Web animation. Interactive progress and completion/cancellation are queued while that retirement is in progress. Stationary shared tabs are retained. First render and transitions without an animation builder are covered by the startup runtime and Ionic lifecycle events. Default Ionic and custom navigation builders can use the same integration through `withNativeUIShellTransition()`, exported from both the package root and `/vertical-bars`. See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3-connect-your-navigation-animation) for the setup.
119
+ The built-in `iosTransitionAnimation` waits for native retirement before starting the Web animation. Interactive progress and completion/cancellation are queued while that retirement is in progress. Stationary shared tabs are retained. First render and transitions without an animation builder are covered by the startup runtime and Ionic lifecycle events. Default Ionic and custom navigation builders can use the same integration through `withNativeUIShellTransition()`, exported from both the package root and `/vertical-bars`. See [Connect your navigation animation](./iphone-duo-with-original-theme.md#3.-connect-your-navigation-animation) for the setup.
120
120
 
121
121
  Tab switches skip the Web/native crossfade so a retiring UIKit snapshot cannot linger over the next tab. Detection uses the router URL versus the still-selected tab on `ionViewWillLeave` (and vanilla `ionTabsWillChange` / `ionTabsDidChange` DOM events). Stack pushes and pops keep the normal 180ms handoff.
122
122
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rdlabo/ionic-theme-ios27",
3
3
  "private": false,
4
- "version": "1.2.0-1",
4
+ "version": "1.2.0-beta.pr226.shaa2e125f11160",
5
5
  "description": "iOS27 Theme for Ionic Framework",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",