mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 04:14:21 +08:00
feat(segment): implement iOS 13 segment with animation (#19036)
Changes Closes #18663 * Converts Segment to shadow * Enables gesture to swipe between segment buttons * Adds indicator transition to slide the indicator between buttons * Updates global theme variables * Removes activated state, now handled by the gesture * Updates iOS to latest iOS 13 UI * Ensures customization is working for the buttons and indicator * Updates the e2e tests
This commit is contained in:
committed by
Liam DeBeasi
parent
8e11f79fcc
commit
dc66ce48e1
@ -639,32 +639,33 @@ export const SegmentButtonExample: React.FC = () => (
|
||||
|
||||
## CSS Custom Properties
|
||||
|
||||
| Name | Description |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `--background` | Background of the segment button |
|
||||
| `--background-activated` | Background of the segment button when pressed |
|
||||
| `--background-checked` | Background of the checked segment button |
|
||||
| `--background-hover` | Background of the segment button on hover |
|
||||
| `--border-color` | Color of the segment button border |
|
||||
| `--border-radius` | Radius of the segment button border |
|
||||
| `--border-style` | Style of the segment button border |
|
||||
| `--border-width` | Width of the segment button border |
|
||||
| `--color` | Color of the segment button |
|
||||
| `--color-activated` | Color of the segment button when pressed |
|
||||
| `--color-checked` | Color of the checked segment button |
|
||||
| `--color-checked-disabled` | Color of the checked & disabled segment button |
|
||||
| `--color-disabled` | Color of the disabled segment button |
|
||||
| `--indicator-color` | Color of the indicator (highlight) under the segment button |
|
||||
| `--indicator-color-checked` | Color of the indicator (highlight) under the checked segment button |
|
||||
| `--margin-bottom` | Bottom margin of the segment button |
|
||||
| `--margin-end` | Right margin if direction is left-to-right, and left margin if direction is right-to-left of the segment button |
|
||||
| `--margin-start` | Left margin if direction is left-to-right, and right margin if direction is right-to-left of the segment button |
|
||||
| `--margin-top` | Top margin of the segment button |
|
||||
| `--padding-bottom` | Bottom padding of the segment button |
|
||||
| `--padding-end` | Right padding if direction is left-to-right, and left padding if direction is right-to-left of the segment button |
|
||||
| `--padding-start` | Left padding if direction is left-to-right, and right padding if direction is right-to-left of the segment button |
|
||||
| `--padding-top` | Top padding of the segment button |
|
||||
| `--transition` | Transition of the segment button |
|
||||
| Name | Description |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `--background` | Background of the segment button |
|
||||
| `--background-checked` | Background of the checked segment button |
|
||||
| `--background-disabled` | Background of the disabled segment button |
|
||||
| `--background-hover` | Background of the segment button on hover |
|
||||
| `--border-color` | Color of the segment button border |
|
||||
| `--border-radius` | Radius of the segment button border |
|
||||
| `--border-style` | Style of the segment button border |
|
||||
| `--border-width` | Width of the segment button border |
|
||||
| `--color` | Color of the segment button |
|
||||
| `--color-checked` | Color of the checked segment button |
|
||||
| `--color-disabled` | Color of the disabled segment button |
|
||||
| `--color-hover` | Color of the segment button on hover |
|
||||
| `--indicator-box-shadow` | Box shadow on the indicator for the checked segment button |
|
||||
| `--indicator-color` | Color of the indicator for the checked segment button |
|
||||
| `--indicator-transform` | Transform of the indicator for the checked segment button |
|
||||
| `--indicator-transition` | Transition of the indicator for the checked segment button |
|
||||
| `--margin-bottom` | Bottom margin of the segment button |
|
||||
| `--margin-end` | Right margin if direction is left-to-right, and left margin if direction is right-to-left of the segment button |
|
||||
| `--margin-start` | Left margin if direction is left-to-right, and right margin if direction is right-to-left of the segment button |
|
||||
| `--margin-top` | Top margin of the segment button |
|
||||
| `--padding-bottom` | Bottom padding of the segment button |
|
||||
| `--padding-end` | Right padding if direction is left-to-right, and left padding if direction is right-to-left of the segment button |
|
||||
| `--padding-start` | Left padding if direction is left-to-right, and right padding if direction is right-to-left of the segment button |
|
||||
| `--padding-top` | Top padding of the segment button |
|
||||
| `--transition` | Transition of the segment button |
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
@ -5,24 +5,73 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
:host {
|
||||
--background: #{$segment-button-ios-background-color};
|
||||
--background-checked: #{$segment-button-ios-background-color-checked};
|
||||
--background-hover: #{$segment-button-ios-background-color-hover};
|
||||
--border-radius: #{$segment-button-ios-border-radius};
|
||||
--border-width: #{$segment-button-ios-border-width};
|
||||
--border-color: #{$segment-button-ios-border-color};
|
||||
--border-style: solid;
|
||||
--indicator-box-shadow: #{$segment-button-ios-box-shadow-checked};
|
||||
--indicator-color: #{$segment-button-ios-indicator-color};
|
||||
--indicator-transition: #{$segment-button-ios-transition-animated};
|
||||
--indicator-transform: none;
|
||||
--transition: #{$segment-button-ios-transition};
|
||||
--padding-top: 0;
|
||||
--padding-end: 13px;
|
||||
--padding-bottom: 0;
|
||||
--padding-start: 13px;
|
||||
|
||||
min-height: #{$segment-button-ios-height};
|
||||
@include margin($segment-button-ios-margin, null, $segment-button-ios-margin, null);
|
||||
|
||||
position: relative;
|
||||
|
||||
flex-basis: 0;
|
||||
flex-direction: row;
|
||||
|
||||
min-width: #{$segment-button-ios-min-width};
|
||||
|
||||
min-height: #{$segment-button-ios-min-height};
|
||||
|
||||
// Necessary for the z-index to work properly
|
||||
transform: translate3d(0, 0, 0);
|
||||
|
||||
font-size: #{$segment-button-ios-font-size};
|
||||
|
||||
font-weight: 450;
|
||||
|
||||
line-height: #{$segment-button-ios-line-height};
|
||||
}
|
||||
|
||||
|
||||
// Segment Button: Indicator
|
||||
// Segment Button: Borders
|
||||
// --------------------------------------------------
|
||||
|
||||
.segment-button-indicator {
|
||||
display: none;
|
||||
:host::before {
|
||||
@include margin(5px, 0);
|
||||
|
||||
transition: 160ms opacity ease-in-out;
|
||||
|
||||
transition-delay: 100ms;
|
||||
|
||||
border-left: var(--border-width) var(--border-style) var(--border-color);
|
||||
|
||||
content: "";
|
||||
opacity: 1;
|
||||
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
:host(:first-of-type)::before {
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
// Segment Button: Disabled
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.segment-button-disabled) {
|
||||
opacity: $segment-button-ios-opacity-disabled;
|
||||
}
|
||||
|
||||
|
||||
@ -48,28 +97,52 @@
|
||||
}
|
||||
|
||||
|
||||
// Segment Button: Hover
|
||||
// Segment Button: Checked Indicator
|
||||
// --------------------------------------------------
|
||||
|
||||
@media (any-hover: hover) {
|
||||
:host(:hover:not(.segment-button-checked)) {
|
||||
background: var(--background-hover);
|
||||
}
|
||||
.segment-button-indicator {
|
||||
@include padding(null, $segment-button-ios-margin);
|
||||
@include position(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.segment-button-indicator-background {
|
||||
@include border-radius($segment-button-ios-border-radius);
|
||||
|
||||
background: var(--indicator-color);
|
||||
}
|
||||
|
||||
.segment-button-indicator-background {
|
||||
transition: var(--indicator-transition);
|
||||
}
|
||||
|
||||
|
||||
// Segment Button: Activated
|
||||
// Segment Button: Checked Borders
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.activated) {
|
||||
background: var(--background-activated);
|
||||
:host(.segment-button-checked)::before,
|
||||
:host(.segment-button-after-checked)::before {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
// Segment: Checked & Activated
|
||||
// Segment Button: Checked
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.segment-button-checked.activated) {
|
||||
background: var(--background-checked);
|
||||
color: var(--color-checked);
|
||||
:host(.segment-button-checked) {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
// Segment Button: Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
// Segment button indicator color should use the global variable with
|
||||
// a fallback to the local variable
|
||||
:host(.in-toolbar) .segment-button-indicator-background {
|
||||
background: #{var(--ion-toolbar-segment-indicator-color, var(--indicator-color))};
|
||||
}
|
||||
|
||||
// Do not use the global or local CSS variable if the toolbar has a color
|
||||
:host(.in-toolbar-color) .segment-button-indicator-background {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
@ -7,37 +7,37 @@
|
||||
$segment-button-ios-background-color: transparent !default;
|
||||
|
||||
/// @prop - Background of the checked segment button
|
||||
$segment-button-ios-background-color-checked: ion-color(primary, base) !default;
|
||||
$segment-button-ios-background-color-checked: transparent !default;
|
||||
|
||||
/// @prop - Background of the checked segment button indicator
|
||||
$segment-button-ios-indicator-color: var(--ion-color-step-350, $background-color) !default;
|
||||
|
||||
/// @prop - Margin of the segment button
|
||||
$segment-button-ios-margin: 2px !default;
|
||||
|
||||
/// @prop - Opacity of the segment button on hover
|
||||
$segment-button-ios-opacity-hover: .1 !default;
|
||||
|
||||
/// @prop - Opacity of the segment button when pressed
|
||||
$segment-button-ios-opacity-activated: .16 !default;
|
||||
$segment-button-ios-opacity-hover: .5 !default;
|
||||
|
||||
/// @prop - Opacity of the disabled segment button
|
||||
$segment-button-ios-opacity-disabled: .3 !default;
|
||||
|
||||
/// @prop - Background of the segment button on hover
|
||||
$segment-button-ios-background-color-hover: ion-color(primary, base, $segment-button-ios-opacity-hover) !default;
|
||||
$segment-button-ios-background-color-hover: transparent !default;
|
||||
|
||||
/// @prop - Background of the activated segment button
|
||||
$segment-button-ios-background-color-activated: ion-color(primary, base, $segment-button-ios-opacity-activated) !default;
|
||||
|
||||
/// @prop - Background of the disabled segment button
|
||||
$segment-button-ios-background-color-disabled: ion-color(primary, base, $segment-button-ios-opacity-disabled) !default;
|
||||
|
||||
/// @prop - Text color of the segment button
|
||||
$segment-button-ios-text-color: ion-color(primary, base) !default;
|
||||
|
||||
/// @prop - Text color of the checked segment button
|
||||
$segment-button-ios-text-color-checked: ion-color(primary, contrast) !default;
|
||||
/// @prop - Box shadow of the checked segment button
|
||||
$segment-button-ios-box-shadow-checked: 0 0 5px rgba(0, 0, 0, 0.16) !default;
|
||||
|
||||
/// @prop - Border width of the segment button
|
||||
$segment-button-ios-border-width: 1px !default;
|
||||
|
||||
/// @prop - Height of the segment button
|
||||
$segment-button-ios-height: 24px !default;
|
||||
/// @prop - Border color of the segment button
|
||||
$segment-button-ios-border-color: rgba($text-color-rgb, 0.12) !default;
|
||||
|
||||
/// @prop - Minimum width of the segment button
|
||||
$segment-button-ios-min-width: 70px !default;
|
||||
|
||||
/// @prop - Minimum height of the segment button
|
||||
$segment-button-ios-min-height: 28px !default;
|
||||
|
||||
/// @prop - Line height of the segment button
|
||||
$segment-button-ios-line-height: 37px !default;
|
||||
@ -46,31 +46,13 @@ $segment-button-ios-line-height: 37px !default;
|
||||
$segment-button-ios-font-size: 13px !default;
|
||||
|
||||
/// @prop - Border radius of the segment button
|
||||
$segment-button-ios-border-radius: 4px !default;
|
||||
|
||||
/// @prop - Border color of the segment button
|
||||
$segment-button-ios-border-color: ion-color(primary, base) !default;
|
||||
$segment-button-ios-border-radius: 7px !default;
|
||||
|
||||
/// @prop - Size of an icon in the segment button
|
||||
$segment-button-ios-icon-size: 24px !default;
|
||||
|
||||
/// @prop - Line height of an icon in the segment button
|
||||
$segment-button-ios-icon-line-height: 28px !default;
|
||||
|
||||
/// @prop - Transition of the segment button
|
||||
$segment-button-ios-transition: 100ms all linear !default;
|
||||
|
||||
/// @prop - Max width of the segment button in a toolbar
|
||||
$segment-button-ios-toolbar-button-max-width: 100px !default;
|
||||
|
||||
/// @prop - Line height of the segment button in a toolbar
|
||||
$segment-button-ios-toolbar-line-height: 22px !default;
|
||||
|
||||
/// @prop - Font size of the segment button in a toolbar
|
||||
$segment-button-ios-toolbar-font-size: 12px !default;
|
||||
|
||||
/// @prop - Size of an icon in the segment button in a toolbar
|
||||
$segment-button-ios-toolbar-icon-size: 22px !default;
|
||||
|
||||
/// @prop - Line height of an icon in the segment button in a toolbar
|
||||
$segment-button-ios-toolbar-icon-line-height: 24px !default;
|
||||
/// @prop - Transition of the animated segment button
|
||||
$segment-button-ios-transition-animated: transform 260ms cubic-bezier(0.4, 0, 0.2, 1) !default;
|
||||
|
||||
@ -5,6 +5,15 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
:host {
|
||||
--background: #{$segment-button-md-background};
|
||||
--background-checked: #{$segment-button-md-background-checked};
|
||||
--background-hover: #{$segment-button-md-background-hover};
|
||||
--color: #{$segment-button-md-text-color};
|
||||
--color-checked: #{$segment-button-md-text-color-checked};
|
||||
--indicator-box-shadow: none;
|
||||
--indicator-color: var(--color-checked);
|
||||
--indicator-transition: #{$segment-button-md-transition-animated};
|
||||
--indicator-transform: none;
|
||||
--padding-top: #{$segment-button-md-padding-top};
|
||||
--padding-end: #{$segment-button-md-padding-end};
|
||||
--padding-bottom: #{$segment-button-md-padding-bottom};
|
||||
@ -16,6 +25,10 @@
|
||||
max-width: $segment-button-md-max-width;
|
||||
min-height: $segment-button-md-min-height;
|
||||
|
||||
border-width: var(--border-width);
|
||||
border-style: var(--border-style);
|
||||
border-color: var(--border-color);
|
||||
|
||||
font-size: $segment-button-md-font-size;
|
||||
font-weight: $segment-button-md-font-weight;
|
||||
|
||||
@ -26,15 +39,6 @@
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
// Segment Button: Checked
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.activated),
|
||||
:host(.segment-button-checked) {
|
||||
--border-color: #{$segment-button-md-border-bottom-color-activated};
|
||||
|
||||
opacity: $segment-button-md-opacity-activated;
|
||||
}
|
||||
|
||||
// Segment Button: Disabled
|
||||
// --------------------------------------------------
|
||||
@ -93,20 +97,26 @@
|
||||
@include margin(12px, null, 12px, null);
|
||||
}
|
||||
|
||||
|
||||
// Segment: Checked & Activated
|
||||
// Segment Button: Indicator
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.segment-button-checked.activated) {
|
||||
color: var(--color-checked);
|
||||
.segment-button-indicator {
|
||||
@include position(null, 0, 0, 0);
|
||||
}
|
||||
|
||||
.segment-button-indicator-background {
|
||||
height: 2px;
|
||||
|
||||
// Segment Button: Hover
|
||||
// --------------------------------------------------
|
||||
|
||||
@media (any-hover: hover) {
|
||||
:host(:hover) {
|
||||
background: var(--background-hover);
|
||||
}
|
||||
background: var(--indicator-color);
|
||||
}
|
||||
|
||||
// Segment button indicator color should use the background checked variable with
|
||||
// a fallback to the default value of --indicator-color
|
||||
:host(.in-toolbar) .segment-button-indicator-background {
|
||||
background: #{var(--ion-toolbar-segment-indicator-color, var(--indicator-color))};
|
||||
}
|
||||
|
||||
// Do not use the global or local CSS variable if the toolbar has a color
|
||||
:host(.in-toolbar-color) .segment-button-indicator-background {
|
||||
background: #{current-color(contrast)};
|
||||
}
|
||||
|
||||
@ -18,24 +18,15 @@ $segment-button-md-background-checked: $segment-button-md-backgro
|
||||
/// @prop - Background of the hovered segment button
|
||||
$segment-button-md-background-hover: ion-color(primary, base, .04) !default;
|
||||
|
||||
/// @prop - Background of the activated segment button
|
||||
$segment-button-md-background-activated: ion-color(primary, base, .16) !default;
|
||||
|
||||
/// @prop - Width of the bottom border on the segment button
|
||||
$segment-button-md-border-bottom-width: 2px !default;
|
||||
|
||||
/// @prop - Color of the bottom border on the segment button
|
||||
$segment-button-md-border-bottom-color: transparent !default;
|
||||
|
||||
/// @prop - Text color of the activated segment button
|
||||
/// @prop - Text color of the checked segment button
|
||||
$segment-button-md-text-color-checked: ion-color(primary, base) !default;
|
||||
|
||||
/// @prop - Border color of the activated segment button
|
||||
$segment-button-md-border-bottom-color-activated: ion-color(primary, base) !default;
|
||||
|
||||
/// @prop - Opacity of the activated segment button
|
||||
$segment-button-md-opacity-activated: 1 !default;
|
||||
|
||||
/// @prop - Opacity of the disabled segment button
|
||||
$segment-button-md-opacity-disabled: .3 !default;
|
||||
|
||||
@ -75,6 +66,9 @@ $segment-button-md-font-weight: 500 !default;
|
||||
/// @prop - Transition of the segment button
|
||||
$segment-button-md-transition: color .15s linear 0s, opacity .15s linear 0s !default;
|
||||
|
||||
/// @prop - Transition of the animated segment button
|
||||
$segment-button-md-transition-animated: transform 250ms cubic-bezier(.4, 0, .2, 1) !default;
|
||||
|
||||
/// @prop - Size of an icon in the segment button
|
||||
$segment-button-md-icon-size: 24px !default;
|
||||
|
||||
|
||||
@ -6,15 +6,14 @@
|
||||
:host {
|
||||
/**
|
||||
* @prop --background: Background of the segment button
|
||||
* @prop --background-hover: Background of the segment button on hover
|
||||
* @prop --background-activated: Background of the segment button when pressed
|
||||
* @prop --background-checked: Background of the checked segment button
|
||||
* @prop --background-disabled: Background of the disabled segment button
|
||||
* @prop --background-hover: Background of the segment button on hover
|
||||
*
|
||||
* @prop --color: Color of the segment button
|
||||
* @prop --color-activated: Color of the segment button when pressed
|
||||
* @prop --color-checked: Color of the checked segment button
|
||||
* @prop --color-disabled: Color of the disabled segment button
|
||||
* @prop --color-checked-disabled: Color of the checked & disabled segment button
|
||||
* @prop --color-hover: Color of the segment button on hover
|
||||
*
|
||||
* @prop --border-radius: Radius of the segment button border
|
||||
* @prop --border-color: Color of the segment button border
|
||||
@ -33,26 +32,31 @@
|
||||
*
|
||||
* @prop --transition: Transition of the segment button
|
||||
*
|
||||
* @prop --indicator-color: Color of the indicator (highlight) under the segment button
|
||||
* @prop --indicator-color-checked: Color of the indicator (highlight) under the checked segment button
|
||||
*
|
||||
* @prop --indicator-box-shadow: Box shadow on the indicator for the checked segment button
|
||||
* @prop --indicator-color: Color of the indicator for the checked segment button
|
||||
* @prop --indicator-transition: Transition of the indicator for the checked segment button
|
||||
* @prop --indicator-transform: Transform of the indicator for the checked segment button
|
||||
*/
|
||||
--color: initial;
|
||||
--color-hover: initial;
|
||||
--color-checked: var(--color);
|
||||
--color-disabled: var(--color);
|
||||
--padding-start: 0;
|
||||
--padding-end: 0;
|
||||
--padding-top: 0;
|
||||
--padding-bottom: 0;
|
||||
|
||||
@include border-radius(var(--border-radius));
|
||||
|
||||
display: flex;
|
||||
|
||||
flex: 1 0 auto;
|
||||
position: relative;
|
||||
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
|
||||
height: auto;
|
||||
|
||||
border-width: var(--border-width);
|
||||
border-style: var(--border-style);
|
||||
border-color: var(--border-color);
|
||||
|
||||
background: var(--background);
|
||||
|
||||
color: var(--color);
|
||||
@ -62,32 +66,15 @@
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
overflow: hidden;
|
||||
font-kerning: none;
|
||||
}
|
||||
|
||||
:host(:first-of-type) {
|
||||
@include border-radius(var(--border-radius), 0, 0, var(--border-radius));
|
||||
}
|
||||
|
||||
:host(:not(:first-of-type)) {
|
||||
@include rtl() {
|
||||
border-right-width: 0;
|
||||
border-left-width: var(--border-width);
|
||||
}
|
||||
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
:host(:last-of-type) {
|
||||
@include border-radius(0, var(--border-radius), var(--border-radius), 0);
|
||||
}
|
||||
|
||||
.button-native {
|
||||
@include border-radius(inherit);
|
||||
@include border-radius(0);
|
||||
@include text-inherit();
|
||||
@include margin(var(--margin-top), var(--margin-end), var(--margin-bottom), var(--margin-start));
|
||||
@include padding(var(--padding-top), var(--padding-end), var(--padding-bottom), var(--padding-start));
|
||||
@include transform(translate3d(0,0,0));
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
@ -116,22 +103,8 @@
|
||||
|
||||
contain: content;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
// Segment Button: Indicator
|
||||
// --------------------------------------------------
|
||||
|
||||
.segment-button-indicator {
|
||||
align-self: flex-end;
|
||||
|
||||
width: 100%;
|
||||
|
||||
height: 2px;
|
||||
|
||||
background-color: var(--indicator-color);
|
||||
|
||||
opacity: 1;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
|
||||
@ -143,30 +116,28 @@
|
||||
color: var(--color-checked);
|
||||
}
|
||||
|
||||
:host(.segment-button-checked) .segment-button-indicator {
|
||||
background-color: var(--indicator-color-checked, var(--color-checked));
|
||||
}
|
||||
|
||||
// Segment Button: Activated
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.activated) {
|
||||
color: var(--color-activated, var(--color));
|
||||
}
|
||||
|
||||
|
||||
// Segment Button: Disabled
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.segment-button-disabled) {
|
||||
background: var(--background-disabled);
|
||||
color: var(--color-disabled);
|
||||
}
|
||||
|
||||
// Segment Button: Checked & Disabled
|
||||
|
||||
// Segment Button: Hover
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.segment-button-disabled.segment-button-checked) {
|
||||
color: var(--color-checked-disabled);
|
||||
@media (any-hover: hover) {
|
||||
:host(:hover) {
|
||||
background: var(--background-hover);
|
||||
color: var(--color-hover, var(--color));
|
||||
}
|
||||
|
||||
:host(.segment-button-checked:hover) {
|
||||
color: var(--color-hover, var(--color-checked));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -174,7 +145,11 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
::slotted(ion-icon) {
|
||||
flex-shrink: 0;
|
||||
|
||||
order: -1;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
@ -193,12 +168,19 @@
|
||||
white-space: nowrap;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
// Segment Button Layout
|
||||
// --------------------------------------------------
|
||||
|
||||
// Layout: icon top
|
||||
:host(.segment-button-layout-icon-top) .button-native {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// Layout: icon start
|
||||
:host(.segment-button-layout-icon-start) .button-native {
|
||||
flex-direction: row;
|
||||
@ -230,3 +212,49 @@
|
||||
ion-ripple-effect {
|
||||
color: var(--ripple-color, var(--color-checked));
|
||||
}
|
||||
|
||||
// Segment Button: Indicator
|
||||
// --------------------------------------------------
|
||||
|
||||
.segment-button-indicator {
|
||||
@include transform-origin(left);
|
||||
|
||||
position: absolute;
|
||||
|
||||
opacity: 0;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
.segment-button-indicator-background {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
transform: var(--indicator-transform);
|
||||
|
||||
box-shadow: var(--indicator-box-shadow);
|
||||
}
|
||||
|
||||
.segment-button-indicator-animated {
|
||||
transition: var(--indicator-transition);
|
||||
}
|
||||
|
||||
:host(.segment-button-checked) .segment-button-indicator {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
// Segment: Reduced Motion
|
||||
// --------------------------------------------------
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.segment-button-indicator-background {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.segment-button-indicator-animated {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { SegmentButtonLayout } from '../../interface';
|
||||
import { ButtonInterface } from '../../utils/element-interface';
|
||||
import { hostContext } from '../../utils/theme';
|
||||
|
||||
let ids = 0;
|
||||
|
||||
@ -18,7 +19,6 @@ let ids = 0;
|
||||
shadow: true
|
||||
})
|
||||
export class SegmentButton implements ComponentInterface, ButtonInterface {
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
/**
|
||||
@ -52,8 +52,10 @@ export class SegmentButton implements ComponentInterface, ButtonInterface {
|
||||
@Event() ionSelect!: EventEmitter<void>;
|
||||
|
||||
@Watch('checked')
|
||||
checkedChanged(checked: boolean, prev: boolean) {
|
||||
if (checked && !prev) {
|
||||
checkedChanged(newValue: boolean, oldValue: boolean) {
|
||||
// If the segment button is not already checked
|
||||
// emit the ionSelect event
|
||||
if (newValue && !oldValue) {
|
||||
this.ionSelect.emit();
|
||||
}
|
||||
}
|
||||
@ -79,6 +81,8 @@ export class SegmentButton implements ComponentInterface, ButtonInterface {
|
||||
aria-disabled={disabled ? 'true' : null}
|
||||
class={{
|
||||
[mode]: true,
|
||||
'in-toolbar': hostContext('ion-toolbar', this.el),
|
||||
'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
|
||||
'segment-button-has-label': hasLabel,
|
||||
'segment-button-has-icon': hasIcon,
|
||||
'segment-button-has-label-only': hasLabel && !hasIcon,
|
||||
@ -99,7 +103,16 @@ export class SegmentButton implements ComponentInterface, ButtonInterface {
|
||||
<slot></slot>
|
||||
{mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
|
||||
</button>
|
||||
<div class="segment-button-indicator"></div>
|
||||
<div
|
||||
part="indicator"
|
||||
class={{
|
||||
'segment-button-indicator': true,
|
||||
'segment-button-indicator-animated': true
|
||||
}}
|
||||
>
|
||||
<div part="indicator-background" class="segment-button-indicator-background"></div>
|
||||
</div>
|
||||
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user