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:
Brandy Carney
2020-01-14 11:51:28 -05:00
committed by Liam DeBeasi
parent 8e11f79fcc
commit dc66ce48e1
27 changed files with 1278 additions and 481 deletions

View File

@ -443,7 +443,7 @@ export const SegmentExample: React.FC = () => (
| `color` | `color` | The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). | `string \| undefined` | `undefined` |
| `disabled` | `disabled` | If `true`, the user cannot interact with the segment. | `boolean` | `false` |
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
| `scrollable` | `scrollable` | If `true`, the segment buttons will overflow and the user can swipe to see them. | `boolean` | `false` |
| `scrollable` | `scrollable` | If `true`, the segment buttons will overflow and the user can swipe to see them. In addition, this will disable the gesture to drag the indicator between the buttons in order to swipe to see hidden buttons. | `boolean` | `false` |
| `value` | `value` | the value of the segment. | `null \| string \| undefined` | `undefined` |
@ -454,6 +454,13 @@ export const SegmentExample: React.FC = () => (
| `ionChange` | Emitted when the value property has changed. | `CustomEvent<SegmentChangeEventDetail>` |
## CSS Custom Properties
| Name | Description |
| -------------- | -------------------------------- |
| `--background` | Background of the segment button |
----------------------------------------------
*Built with [StencilJS](https://stenciljs.com/)*

View File

@ -5,92 +5,78 @@
// --------------------------------------------------
:host {
--background: #{$segment-button-ios-background-color};
--background-hover: #{$segment-button-ios-background-color-hover};
--background-activated: #{$segment-button-ios-background-color-activated};
--background-checked: #{$segment-button-ios-background-color-checked};
--color: #{$segment-button-ios-text-color};
--color-checked: #{$segment-button-ios-text-color-checked};
--color-disabled: #{ion-color(primary, base, $segment-button-ios-opacity-disabled)};
--color-checked-disabled: #{ion-color(primary, contrast, $segment-button-ios-opacity-disabled)};
--border-color: #{$segment-button-ios-border-color};
--indicator-color: transparent;
--background: #{$segment-ios-background-color};
@include border-radius($segment-ios-border-radius);
overflow: hidden;
z-index: 0;
}
:host(.segment-disabled) {
opacity: $segment-ios-opacity-disabled;
opacity: $segment-button-ios-opacity-disabled;
}
// Segment: Color
// --------------------------------------------------
:host(.ion-color)::slotted(ion-segment-button) {
--border-color: #{current-color(base)};
background: transparent;
color: #{current-color(base)};
:host(.ion-color) {
background: #{current-color(base, 0.065)};
}
:host(.ion-color)::slotted(.activated) {
background: #{current-color(base, .16)};
color: #{current-color(base)};
:host(.ion-color) ::slotted(.segment-button-checked) {
color: #000;
}
:host(.ion-color)::slotted(.segment-button-checked.activated),
:host(.ion-color)::slotted(.segment-button-checked) {
background: #{current-color(base)};
color: #{current-color(contrast)};
}
:host(.ion-color)::slotted(.segment-button-disabled) {
color: #{current-color(base, $segment-ios-opacity-disabled)};
}
// Segment: Activated
// --------------------------------------------------
:host(.ion-color)::slotted(.segment-button-checked.segment-button-disabled) {
color: #{current-color(contrast, $segment-ios-opacity-disabled)};
}
@media (any-hover: hover) {
:host(.ion-color)::slotted(ion-segment-button:hover:not(.segment-button-checked)) {
background: #{current-color(base, .1)};
}
:host(.segment-activated) ::slotted(ion-segment-button) {
--indicator-transform: scale(0.95);
}
// Segment: Default Toolbar
// --------------------------------------------------
:host-context(ion-toolbar)::slotted(ion-segment-button) {
max-width: $segment-button-ios-toolbar-button-max-width;
:host(.in-toolbar) {
@include margin(0, auto);
font-size: $segment-button-ios-toolbar-font-size;
line-height: $segment-button-ios-toolbar-line-height;
width: auto;
}
:host-context(ion-toolbar:not(.ion-color)):not(.ion-color)::slotted(ion-segment-button) {
border-color: #{var(--ion-toolbar-color-checked, var(--border-color))};
color: #{var(--ion-toolbar-color-unchecked, var(--color))};
// Default Segment, In a Toolbar
:host(.in-toolbar:not(.ion-color)) {
background: var(--ion-toolbar-segment-background, $segment-ios-background-color);
color: var(--ion-toolbar-segment-color, var(--color));
}
:host-context(ion-toolbar:not(.ion-color)):not(.ion-color)::slotted(.segment-button-checked) {
background: #{var(--ion-toolbar-color-checked, var(--background-checked))};
color: #{var(--ion-toolbar-background, var(--color-checked))};
// Default Segment, In a Toolbar, Checked
:host(.in-toolbar:not(.ion-color)) ::slotted(.segment-button-checked) {
color: var(--ion-toolbar-segment-color-checked, var(--color-checked));
}
// Segment: Color Toolbar
// --------------------------------------------------
:host-context(ion-toolbar.ion-color):not(.ion-color)::slotted(ion-segment-button) {
--color: #{current-color(contrast)};
--color-disabled: #{current-color(contrast, $segment-button-ios-opacity-disabled)};
--color-checked: #{current-color(base)};
--color-checked-disabled: #{current-color(contrast, $segment-button-ios-opacity-disabled)};
--background-hover: #{current-color(contrast, $segment-button-ios-opacity-hover)};
--background-activated: #{current-color(contrast, $segment-button-ios-opacity-activated)};
--background-checked: #{current-color(contrast)};
--border-color: #{current-color(contrast)};
// Toolbar with Color, Default Segment
:host(.in-toolbar-color:not(.ion-color)) {
background: #{current-color(contrast, 0.11)};
color: #{current-color(contrast)};
}
// Toolbar with Color, Default Segment, Checked
:host(.in-toolbar-color:not(.ion-color)) ::slotted(.segment-button-checked) {
color: #{current-color(base)};
}
@media (any-hover: hover) {
// Toolbar with Color, Default Segment, Checked / Hover
:host(.in-toolbar-color:not(.ion-color)) ::slotted(.segment-button-checked:hover) {
color: #{current-color(base)};
}
}

View File

@ -4,5 +4,11 @@
// iOS Segment
// --------------------------------------------------
/// @prop - Opacity of the disabled segment
$segment-ios-opacity-disabled: .3 !default;
/// @prop - Alpha of the segment for use in the backgrounds
$segment-ios-background-alpha: 0.065 !default;
/// @prop - Background color of the segment
$segment-ios-background-color: rgba($text-color-rgb, $segment-ios-background-alpha) !default;
/// @prop - Border radius of the segment
$segment-ios-border-radius: 8px !default;

View File

@ -5,14 +5,7 @@
// --------------------------------------------------
:host {
--background: #{$segment-button-md-background};
--background-checked: #{$segment-button-md-background-checked};
--background-hover: #{$segment-button-md-background-hover};
--background-activated: #{$segment-button-md-background-activated};
--color: #{$segment-button-md-text-color};
--color-checked: #{$segment-button-md-text-color-checked};
--color-checked-disabled: var(--color-checked);
--indicator-color: transparent;
--background: transparent;
}
:host(.segment-disabled) {
@ -22,25 +15,20 @@
// Segment: Color
// --------------------------------------------------
:host(.ion-color)::slotted(ion-segment-button) {
--background-activated: #{current-color(base, .16)};
:host(.ion-color) ::slotted(ion-segment-button) {
--ripple-color: #{current-color(base)};
--indicator-color: #{current-color(base)};
background: transparent;
color: $segment-button-md-text-color;
}
:host(.ion-color)::slotted(.segment-button-checked) {
--indicator-color-checked: #{current-color(base)};
color: #{current-color(base)};
}
:host(.ion-color)::slotted(.segment-button-checked.activated) {
:host(.ion-color) ::slotted(.segment-button-checked) {
color: #{current-color(base)};
}
@media (any-hover: hover) {
:host(.ion-color)::slotted(ion-segment-button:hover) {
:host(.ion-color) ::slotted(ion-segment-button:hover) {
background: #{current-color(base, .04)};
}
}
@ -48,24 +36,49 @@
// Segment: Default Toolbar
// --------------------------------------------------
:host-context(ion-toolbar:not(.ion-color)):not(.ion-color)::slotted(ion-segment-button) {
color: #{var(--ion-toolbar-color-unchecked, var(--color))};
// Default Segment, In a Toolbar
:host(.in-toolbar:not(.ion-color)) ::slotted(ion-segment-button) {
--indicator-color: #{var(--ion-toolbar-segment-color-checked, var(--color-checked))};
background: #{var(--ion-toolbar-segment-background, var(--background))};
color: #{var(--ion-toolbar-segment-color, var(--color))};
}
:host-context(ion-toolbar:not(.ion-color)):not(.ion-color)::slotted(.segment-button-checked) {
--indicator-color-checked: #{var(--ion-toolbar-color-checked, var(--color-checked))};
color: #{var(--ion-toolbar-color-checked, var(--color-checked))};
// Default Segment, In a Toolbar, Checked
:host(.in-toolbar:not(.ion-color)) ::slotted(.segment-button-checked) {
background: #{var(--ion-toolbar-segment-background-checked, var(--background-checked))};
color: #{var(--ion-toolbar-segment-color-checked, var(--color-checked))};
}
// Segment: Toolbar Color
// --------------------------------------------------
:host-context(ion-toolbar.ion-color):not(.ion-color)::slotted(ion-segment-button) {
--background-hover: #{current-color(contrast, .04)};
--background-activated: #{current-color(base)};
--color: #{current-color(contrast, .6)};
--color-checked: #{current-color(contrast)};
--indicator-color-checked: #{current-color(contrast)};
// Default Segment, In a Toolbar with Color
:host(.in-toolbar-color:not(.ion-color)) ::slotted(ion-segment-button) {
color: #{current-color(contrast, .6)};
}
// Default Segment, In a Toolbar with Color, Checked
:host(.in-toolbar-color:not(.ion-color)) ::slotted(.segment-button-checked) {
color: #{current-color(contrast)};
}
// Segment: Toolbar Hover
// --------------------------------------------------
@media (any-hover: hover) {
// Default Segment, In a Toolbar with Color, Hover
:host(.in-toolbar-color:not(.ion-color)) ::slotted(ion-segment-button:hover) {
background: #{ion-color(primary, contrast, .04)};
}
}
// Segment: Scrollable
// --------------------------------------------------
:host(.segment-scrollable) ::slotted(ion-segment-button) {
min-width: $segment-button-md-min-width;
}

View File

@ -4,22 +4,29 @@
// --------------------------------------------------
:host {
--indicator-color-checked: initial;
/**
* @prop --background: Background of the segment button
*/
--ripple-color: currentColor;
--color-activated: initial;
@include font-smoothing();
display: flex;
position: relative;
align-items: stretch;
justify-content: center;
width: 100%;
background: var(--background);
font-family: $font-family-base;
text-align: center;
contain: paint;
}
@ -46,3 +53,19 @@
:host(.segment-scrollable::-webkit-scrollbar) {
display: none;
}
// Segment Button: Hover
// --------------------------------------------------
@media (any-hover: hover) {
// Default Segment, In a Default Toolbar, Hover
:host(.in-toolbar:not(.ion-color)) ::slotted(ion-segment-button:hover) {
background: var(--ion-toolbar-segment-background-hover, var(--background-hover));
color: var(--ion-toolbar-segment-color-hover, var(--color-hover, var(--ion-toolbar-segment-color, var(--color))));
}
// Default Segment, In a Default Toolbar, Checked / Hover
:host(.in-toolbar:not(.ion-color)) ::slotted(.segment-button-checked:hover) {
color: var(--ion-toolbar-segment-color-hover, var(--color-hover, var(--ion-toolbar-segment-color-checked, var(--color-checked))));
}
}

View File

@ -1,8 +1,10 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Listen, Prop, Watch, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Listen, Prop, State, Watch, h, writeTask } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color, SegmentChangeEventDetail, StyleEventDetail } from '../../interface';
import { createColorClasses } from '../../utils/theme';
import { Gesture, GestureDetail } from '../../utils/gesture';
import { pointerCoord } from '../../utils/helpers';
import { createColorClasses, hostContext } from '../../utils/theme';
/**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
@ -13,13 +15,16 @@ import { createColorClasses } from '../../utils/theme';
ios: 'segment.ios.scss',
md: 'segment.md.scss'
},
scoped: true
shadow: true
})
export class Segment implements ComponentInterface {
private gesture?: Gesture;
private didInit = false;
private checked?: HTMLIonSegmentButtonElement;
@Element() el!: HTMLElement;
@Element() el!: HTMLIonSegmentElement;
@State() activated = false;
/**
* The color to use from your application's color palette.
@ -35,6 +40,8 @@ export class Segment implements ComponentInterface {
/**
* If `true`, the segment buttons will overflow and the user can swipe to see them.
* In addition, this will disable the gesture to drag the indicator between the buttons
* in order to swipe to see hidden buttons.
*/
@Prop() scrollable = false;
@ -43,14 +50,6 @@ export class Segment implements ComponentInterface {
*/
@Prop({ mutable: true }) value?: string | null;
@Watch('value')
protected valueChanged(value: string | undefined) {
if (this.didInit) {
this.updateButtons();
this.ionChange.emit({ value });
}
}
/**
* Emitted when the value property has changed.
*/
@ -62,10 +61,32 @@ export class Segment implements ComponentInterface {
*/
@Event() ionStyle!: EventEmitter<StyleEventDetail>;
@Watch('value')
protected valueChanged(value: string | undefined) {
if (this.didInit) {
this.updateButtons();
this.ionChange.emit({ value });
}
}
@Watch('disabled')
disabledChanged() {
if (this.gesture && !this.scrollable) {
this.gesture.enable(!this.disabled);
}
}
@Listen('ionSelect')
segmentClick(ev: CustomEvent) {
const selectedButton = ev.target as HTMLIonSegmentButtonElement;
this.value = selectedButton.value;
const current = ev.target as HTMLIonSegmentButtonElement;
const previous = this.checked;
this.value = current.value;
if (previous && this.scrollable) {
this.checkButton(previous, current);
}
this.checked = current;
}
connectedCallback() {
@ -78,11 +99,219 @@ export class Segment implements ComponentInterface {
this.emitStyle();
}
componentDidLoad() {
componentWillLoad() {
this.emitStyle();
}
async componentDidLoad() {
this.updateButtons();
this.setCheckedClasses();
this.gesture = (await import('../../utils/gesture')).createGesture({
el: this.el,
gestureName: 'segment',
gesturePriority: 100,
threshold: 0,
passive: false,
onStart: ev => this.onStart(ev),
onMove: ev => this.onMove(ev),
onEnd: ev => this.onEnd(ev),
});
this.gesture.enable(!this.scrollable);
this.disabledChanged();
this.didInit = true;
}
onStart(detail: GestureDetail) {
this.activate(detail);
}
onMove(detail: GestureDetail) {
this.setNextIndex(detail);
}
onEnd(detail: GestureDetail) {
this.activated = false;
this.setNextIndex(detail, true);
detail.event.preventDefault();
detail.event.stopImmediatePropagation();
this.addRipple(detail);
}
/**
* The gesture blocks the segment button ripple. This
* function adds the ripple based on the checked segment
* and where the cursor ended.
*/
private addRipple(detail: GestureDetail) {
const buttons = this.getButtons();
const checked = buttons.find(button => button.checked === true);
const ripple = checked!.shadowRoot!.querySelector('ion-ripple-effect');
if (!ripple) { return; }
const { x, y } = pointerCoord(detail.event);
ripple.addRipple(x, y).then(remove => remove());
}
private activate(detail: GestureDetail) {
const clicked = detail.event.target as HTMLIonSegmentButtonElement;
const buttons = this.getButtons();
const checked = buttons.find(button => button.checked === true);
// Make sure we are only checking for activation on a segment button
// since disabled buttons will get the click on the segment
if (clicked.tagName !== 'ION-SEGMENT-BUTTON') {
return;
}
// If there are no checked buttons, set the current button to checked
if (!checked) {
clicked.checked = true;
}
// If the gesture began on the clicked button with the indicator
// then we should activate the indicator
if (clicked.checked) {
this.activated = true;
}
}
private getIndicator(button: HTMLIonSegmentButtonElement): HTMLDivElement | null {
return button.shadowRoot && button.shadowRoot.querySelector('.segment-button-indicator');
}
private checkButton(previous: HTMLIonSegmentButtonElement, current: HTMLIonSegmentButtonElement) {
const previousIndicator = this.getIndicator(previous);
const currentIndicator = this.getIndicator(current);
if (previousIndicator === null || currentIndicator === null) {
return;
}
const previousClientRect = previousIndicator.getBoundingClientRect();
const currentClientRect = currentIndicator.getBoundingClientRect();
const widthDelta = previousClientRect.width / currentClientRect.width;
const xPosition = previousClientRect.left - currentClientRect.left;
// Scale the indicator width to match the previous indicator width
// and translate it on top of the previous indicator
const transform = `translate3d(${xPosition}px, 0, 0) scaleX(${widthDelta})`;
writeTask(() => {
// Remove the transition before positioning on top of the previous indicator
currentIndicator.classList.remove('segment-button-indicator-animated');
currentIndicator.style.setProperty('transform', transform);
// Force a repaint to ensure the transform happens
currentIndicator.getBoundingClientRect();
// Add the transition to move the indicator into place
currentIndicator.classList.add('segment-button-indicator-animated');
// Remove the transform to slide the indicator back to the button clicked
currentIndicator.style.setProperty('transform', '');
});
current.checked = true;
this.setCheckedClasses();
}
private setCheckedClasses() {
const buttons = this.getButtons();
const index = buttons.findIndex(button => button.checked === true);
const next = index + 1;
// Keep track of the currently checked button
this.checked = buttons.find(button => button.checked === true);
for (const button of buttons) {
button.classList.remove('segment-button-after-checked');
}
if (next < buttons.length) {
buttons[next].classList.add('segment-button-after-checked');
}
}
private setNextIndex(detail: GestureDetail, isEnd = false) {
const isRTL = document.dir === 'rtl';
const activated = this.activated;
const buttons = this.getButtons();
const index = buttons.findIndex(button => button.checked === true);
const previous = buttons[index];
let current;
let nextIndex;
if (index === -1) {
return;
}
// Get the element that the touch event started on in case
// it was the checked button, then we will move the indicator
const rect = previous.getBoundingClientRect() as DOMRect;
const left = rect.left;
const width = rect.width;
// Get the element that the gesture is on top of based on the currentX of the
// gesture event and the Y coordinate of the starting element, since the gesture
// can move up and down off of the segment
const currentX = detail.currentX;
const previousY = rect.y;
const nextEl = document.elementFromPoint(currentX, previousY) as HTMLIonSegmentButtonElement;
const decreaseIndex = isRTL ? currentX > (left + width) : currentX < left;
const increaseIndex = isRTL ? currentX < left : currentX > (left + width);
// If the indicator is currently activated then we have started the gesture
// on top of the checked button so we need to slide the indicator
// by checking the button next to it as we move
if (activated && !isEnd) {
// Decrease index, move left in LTR & right in RTL
if (decreaseIndex) {
const newIndex = index - 1;
if (newIndex >= 0) {
nextIndex = newIndex;
}
// Increase index, moves right in LTR & left in RTL
} else if (increaseIndex) {
if (activated && !isEnd) {
const newIndex = index + 1;
if (newIndex < buttons.length) {
nextIndex = newIndex;
}
}
}
if (nextIndex !== undefined && !buttons[nextIndex].disabled) {
current = buttons[nextIndex];
}
}
// If the indicator is not activated then we will just set the indicator
// to the element where the gesture ended
if (!activated && isEnd) {
current = nextEl;
}
if (!current) {
return;
}
if (previous !== current) {
this.checkButton(previous, current);
}
}
private emitStyle() {
this.ionStyle.emit({
'segment': true
@ -102,15 +331,20 @@ export class Segment implements ComponentInterface {
render() {
const mode = getIonMode(this);
return (
<Host
class={{
...createColorClasses(this.color),
[mode]: true,
'in-toolbar': hostContext('ion-toolbar', this.el),
'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
'segment-activated': this.activated,
'segment-disabled': this.disabled,
'segment-scrollable': this.scrollable
}}
>
<slot></slot>
</Host>
);
}

View File

@ -4,12 +4,14 @@
<head>
<meta charset="UTF-8">
<title>Segment - Basic</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script></head>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body onload="listenForEvent()">
<ion-app>
@ -22,7 +24,7 @@
<ion-toolbar>
<ion-segment class="event-tester" value="Free">
<ion-segment-button value="Paid">
Paid
PaidPaidPaid
</ion-segment-button>
<ion-segment-button value="Free">
Free
@ -62,23 +64,12 @@
</ion-toolbar>
<ion-toolbar>
<ion-segment color="danger">
<ion-segment-button value="sunny">
Sunny
<ion-segment>
<ion-segment-button value="all" checked>
All
</ion-segment-button>
<ion-segment-button value="rainy" checked>
Rainy
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<ion-toolbar color="primary">
<ion-segment color="light">
<ion-segment-button value="sunny">
Sunny
</ion-segment-button>
<ion-segment-button value="rainy" checked>
Rainy
<ion-segment-button value="missed">
Missed
</ion-segment-button>
</ion-segment>
</ion-toolbar>
@ -87,26 +78,38 @@
<ion-content>
<div class="ion-padding">
<ion-segment>
<ion-segment-button><ion-label>Seg 1</ion-label></ion-segment-button>
<ion-segment-button><ion-label>Seg 2</ion-label></ion-segment-button>
<ion-segment-button><ion-label>Seg 3</ion-label></ion-segment-button>
<ion-segment-button>
<ion-label>Seg 1</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>Seg 2</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>Seg 3</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment disabled>
<ion-segment-button><ion-label>Seg 2 1</ion-label></ion-segment-button>
<ion-segment-button checked><ion-label>Seg 2 2</ion-label></ion-segment-button>
<ion-segment-button><ion-label>Seg 2 3</ion-label></ion-segment-button>
<ion-segment class="segment-no-animate">
<ion-segment-button>
<ion-label>Animate</ion-label>
</ion-segment-button>
<ion-segment-button checked>
<ion-label>Is</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>False</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment color="dark" value="Reading List">
<ion-segment-button value="Bookmarks">
<ion-icon name="book"></ion-icon>
<ion-icon name="md-book"></ion-icon>
</ion-segment-button>
<ion-segment-button value="Reading List">
<ion-icon name="glasses"></ion-icon>
<ion-icon name="search"></ion-icon>
</ion-segment-button>
<ion-segment-button value="Shared Links">
<ion-icon name="at"></ion-icon>
<ion-icon name="md-time"></ion-icon>
</ion-segment-button>
</ion-segment>
@ -117,13 +120,13 @@
<ion-segment-button value="440">
<ion-label>440ml</ion-label>
</ion-segment-button>
<ion-segment-button value="500">
<ion-segment-button disabled value="500">
<ion-label>500ml</ion-label>
</ion-segment-button>
<ion-segment-button value="custom">
<ion-icon name="create"></ion-icon>
</ion-segment-button>
</ion-segment>
</ion-segment>
<ion-segment name="dynamicPropDisable" disabled color="danger">
<ion-segment-button value="Bookmarks">
@ -149,7 +152,7 @@
</ion-segment-button>
</ion-segment>
<ion-segment name="dynamicAttrElem" value="disabled">
<ion-segment name="dynamicAttrElem">
<ion-segment-button value="active">
<ion-label>Active</ion-label>
</ion-segment-button>
@ -162,7 +165,7 @@
</ion-segment>
<!-- Dynamic Buttons -->
<ion-segment id="dynamicButtons" color="dark"></ion-segment>
<ion-segment id="dynamicButtons"></ion-segment>
</div>
<div class="ion-padding-horizontal">
@ -204,7 +207,6 @@
async function listenForEvent() {
const ionSegmentElement = document.querySelector('ion-segment.event-tester');
await ionSegmentElement.componentOnReady();
ionSegmentElement.addEventListener('ionChange', (event) => {
console.log('event.target: ', event.target.value);
});
@ -218,13 +220,15 @@
}, 4000);
function updateSegmentButtons(length) {
dynamicButtons.innerHTML = '';
const buttonsLength = dynamicButtons.children.length;
const begin = buttonsLength === 0 ? 0 : buttonsLength;
for (var i = 0; i < length; i++) {
dynamicButtons.innerHTML += `
<ion-segment-button value="segment-${i}">
<ion-label>Btn ${i}</ion-label>
</ion-segment-button>`;
for (var i = begin; i < length; i++) {
const button = document.createElement('ion-segment-button');
button.value = `segment-${i}`;
button.innerHTML = `<ion-label>Btn ${i}</ion-label>`;
dynamicButtons.appendChild(button);
}
}
@ -236,6 +240,10 @@
margin-bottom: 10px;
}
.segment-no-animate ion-segment-button {
--indicator-transition: none;
--indicator-transform: none;
}
</style>
</ion-app>
</body>

View File

@ -0,0 +1,23 @@
import { newE2EPage } from '@stencil/core/testing';
test('segment: basic', async () => {
const page = await newE2EPage({
url: '/src/components/segment/test/basic?ionic:_testing=true'
});
await page.waitFor(250);
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});
test('segment:rtl: basic', async () => {
const page = await newE2EPage({
url: '/src/components/segment/test/basic?ionic:_testing=true&rtl=true'
});
await page.waitFor(250);
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});

View File

@ -0,0 +1,178 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Segment - Colors</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Segment - Colors</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-segment value="free">
<ion-segment-button value="paid">
Paid
</ion-segment-button>
<ion-segment-button value="free">
Free
</ion-segment-button>
<ion-segment-button value="top">
Top
</ion-segment-button>
</ion-segment>
<ion-segment color="primary" value="reading-list">
<ion-segment-button value="bookmarks">
Bookmarks
</ion-segment-button>
<ion-segment-button value="reading-list">
Reading List
</ion-segment-button>
<ion-segment-button value="shared-links">
Shared Links
</ion-segment-button>
</ion-segment>
<ion-segment color="secondary" value="active">
<ion-segment-button value="active">
Active
</ion-segment-button>
<ion-segment-button value="disabled" disabled="true">
Disabled
</ion-segment-button>
<ion-segment-button value="inactive" disabled="false">
Inactive
</ion-segment-button>
</ion-segment>
<ion-segment color="tertiary">
<ion-segment-button value="all" checked>
All
</ion-segment-button>
<ion-segment-button value="missed">
Missed
</ion-segment-button>
</ion-segment>
<ion-segment color="success">
<ion-segment-button checked value="330">
<ion-label>330ml</ion-label>
</ion-segment-button>
<ion-segment-button value="440">
<ion-label>440ml</ion-label>
</ion-segment-button>
<ion-segment-button value="500">
<ion-label>500ml</ion-label>
</ion-segment-button>
<ion-segment-button value="custom">
<ion-icon name="create"></ion-icon>
</ion-segment-button>
</ion-segment>
<ion-segment color="warning" value="reading-list">
<ion-segment-button value="bookmarks">
<ion-icon name="book"></ion-icon>
</ion-segment-button>
<ion-segment-button value="reading-list">
<ion-icon name="glasses"></ion-icon>
</ion-segment-button>
<ion-segment-button value="shared-links">
<ion-icon name="at"></ion-icon>
</ion-segment-button>
</ion-segment>
<ion-segment color="danger" value="bookmarks">
<ion-segment-button value="bookmarks">
<ion-label>Bookmarks</ion-label>
</ion-segment-button>
<ion-segment-button value="reading-list">
<ion-label>Reading List</ion-label>
</ion-segment-button>
<ion-segment-button value="shared-links">
<ion-label>Shared Links</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment color="light">
<ion-segment-button value="sunny">
Sunny
</ion-segment-button>
<ion-segment-button value="rainy" checked>
Rainy
</ion-segment-button>
</ion-segment>
<ion-segment color="medium">
<ion-segment-button checked>
<ion-label>Seg 1</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>Seg 2</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>Seg 3</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment color="dark">
<ion-segment-button>
<ion-label>Seg 2 1</ion-label>
</ion-segment-button>
<ion-segment-button checked>
<ion-label>Seg 2 2</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>Seg 2 3</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment disabled color="danger">
<ion-segment-button>
<ion-label>Seg 2 1</ion-label>
</ion-segment-button>
<ion-segment-button checked>
<ion-label>Seg 2 2</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>Seg 2 3</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment disabled color="medium">
<ion-segment-button>
<ion-label>Seg 2 1</ion-label>
</ion-segment-button>
<ion-segment-button checked>
<ion-label>Seg 2 2</ion-label>
</ion-segment-button>
<ion-segment-button>
<ion-label>Seg 2 3</ion-label>
</ion-segment-button>
</ion-segment>
</ion-content>
<style>
ion-content ion-segment {
margin-bottom: 10px;
}
</style>
</ion-app>
</body>
</html>

View File

@ -28,17 +28,31 @@
</ion-segment>
</ion-toolbar>
<ion-toolbar>
<ion-segment value="Free" class="custom-checked">
<ion-segment-button value="Paid">
<ion-label>Paid</ion-label>
</ion-segment-button>
<ion-segment-button value="Free">
<ion-label>Free</ion-label>
</ion-segment-button>
<ion-segment-button value="Top">
<ion-label>Top</ion-label>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<ion-toolbar>
<ion-segment class="custom-icon" value="instagram">
<ion-segment-button class="segment-facebook" value="facebook">
<ion-segment-button class="segment-button-facebook" value="facebook">
<ion-label>Facebook</ion-label>
<ion-icon name="logo-facebook"></ion-icon>
</ion-segment-button>
<ion-segment-button class="segment-instagram" value="instagram">
<ion-segment-button class="segment-button-instagram" value="instagram">
<ion-label>Instagram</ion-label>
<ion-icon name="logo-instagram"></ion-icon>
</ion-segment-button>
<ion-segment-button class="segment-slack" value="slack">
<ion-segment-button class="segment-button-slack" value="slack">
<ion-label>Slack</ion-label>
<ion-icon name="logo-slack"></ion-icon>
</ion-segment-button>
@ -61,11 +75,39 @@
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<ion-toolbar>
<ion-segment class="custom-states-color" value="disabled">
<ion-segment-button value="inactive">
<ion-label>Inactive</ion-label>
</ion-segment-button>
<ion-segment-button value="inactive2">
<ion-label>Inactive</ion-label>
</ion-segment-button>
<ion-segment-button value="disabled" disabled>
<ion-label>Disabled</ion-label>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<ion-toolbar>
<ion-segment class="custom-states-background" value="checked">
<ion-segment-button value="checked">
<ion-label>Checked</ion-label>
</ion-segment-button>
<ion-segment-button value="inactive">
<ion-label>Inactive</ion-label>
</ion-segment-button>
<ion-segment-button value="disabled" disabled>
<ion-label>Disabled</ion-label>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-content class="ion-padding-top">
<ion-segment class="custom" value="active">
<ion-segment class="custom-active" value="active">
<ion-segment-button value="active">
<ion-label>Active</ion-label>
</ion-segment-button>
@ -77,16 +119,16 @@
</ion-segment-button>
</ion-segment>
<ion-segment class="custom-icon" value="instagram">
<ion-segment-button class="segment-facebook" value="facebook">
<ion-segment class="custom-icon" value="slack">
<ion-segment-button class="segment-button-facebook" value="facebook">
<ion-label>Facebook</ion-label>
<ion-icon name="logo-facebook"></ion-icon>
</ion-segment-button>
<ion-segment-button class="segment-instagram" value="instagram">
<ion-segment-button class="segment-button-instagram" value="instagram">
<ion-label>Instagram</ion-label>
<ion-icon name="logo-instagram"></ion-icon>
</ion-segment-button>
<ion-segment-button class="segment-slack" value="slack">
<ion-segment-button class="segment-button-slack" value="slack">
<ion-label>Slack</ion-label>
<ion-icon name="logo-slack"></ion-icon>
</ion-segment-button>
@ -107,34 +149,30 @@
</ion-segment-button>
</ion-segment>
<h2>Activated</h2>
<ion-segment>
<ion-segment-button class="activated" value="Paid">
<ion-label>Paid</ion-label>
<ion-segment class="custom-states-color" value="checked">
<ion-segment-button value="checked">
<ion-label>Checked</ion-label>
</ion-segment-button>
<ion-segment-button class="activated" value="Free">
<ion-label>Free</ion-label>
<ion-segment-button value="inactive">
<ion-label>Inactive</ion-label>
</ion-segment-button>
<ion-segment-button class="activated" value="Top">
<ion-label>Top</ion-label>
<ion-segment-button value="disabled" disabled>
<ion-label>Disabled</ion-label>
</ion-segment-button>
</ion-segment>
<ion-segment class="custom-icon">
<ion-segment-button class="activated segment-facebook" value="facebook">
<ion-label>Facebook</ion-label>
<ion-icon name="logo-facebook"></ion-icon>
<ion-segment class="custom-states-background" value="checked">
<ion-segment-button value="checked">
<ion-label>Checked</ion-label>
</ion-segment-button>
<ion-segment-button class="activated segment-instagram" value="instagram">
<ion-label>Instagram</ion-label>
<ion-icon name="logo-instagram"></ion-icon>
<ion-segment-button value="inactive">
<ion-label>Inactive</ion-label>
</ion-segment-button>
<ion-segment-button class="activated segment-slack" value="slack">
<ion-label>Slack</ion-label>
<ion-icon name="logo-slack"></ion-icon>
<ion-segment-button value="disabled" disabled>
<ion-label>Disabled</ion-label>
</ion-segment-button>
</ion-segment>
</ion-content>
</ion-app>
@ -153,107 +191,153 @@
margin-bottom: 0;
}
pre {
border: 1px solid #e6e9ee;
background: white;
margin: 10px;
padding: 4px;
line-height: 24px;
/*
* Custom Checked Segment (Paid, Free, Top)
*
* This tests that the colors are able to be overridden on
* a segment inside of a toolbar
*
* Indicator color / ripple color can be set on ion-segment
*
* Backgrounds / colors for the button must be set on the
* ion-segment-button
*/
.custom-checked {
--ripple-color: purple;
--indicator-color: purple;
}
code {
display: block;
padding: 0.5em;
background: #ffffff;
word-wrap: normal;
white-space: pre;
color: #314361;
.ios .custom-checked ion-segment-button {
--color-checked: white;
}
.md .custom-checked ion-segment-button {
--background-hover: rgba(17, 228, 10, 0.5);
--color-checked: purple;
--color-hover: blue;
}
/*
* Custom Themed Segment (Themed to Primary)
*/
.themed {
--ion-toolbar-background: #3880ff;
--ion-toolbar-color: #fff;
--ion-toolbar-color-activated: #fff;
--ion-toolbar-color-unchecked: rgba(255, 255, 255, .6);
--ion-toolbar-color-checked: #fff;
/* Segment */
--ion-toolbar-segment-indicator-color: #ffffff;
}
.custom {
/* Material Design Segment */
.md .themed {
--ion-toolbar-segment-color: rgba(255, 255, 255, .6);
--ion-toolbar-segment-color-checked: #ffffff;
--ion-toolbar-segment-background-hover: rgba(255, 255, 255, 0.04);
}
/* iOS Segment */
.ios .themed {
--ion-toolbar-segment-background: rgba(255, 255, 255, 0.065);
--ion-toolbar-segment-color: #ffffff;
--ion-toolbar-segment-color-checked: #3880ff;
}
/*
* Custom Active Segment (Active, Inactive, Disabled)
*/
.custom-active {
--background: papayawhip;
--background-checked: navy;
--border-color: navy;
--border-color-checked: navy;
--border-color-disabled: navy;
--color: navy;
--color-activated: purple;
--color-checked: papayawhip;
--color: purple;
--color-disabled: rgba(0, 0, 0, 0.3);
}
/* Custom Icon Segment MD */
.md .custom-icon {
--indicator-color: lightgray;
.ios .custom-active {
--color-checked: papayawhip;
--indicator-color: navy;
}
.md .segment-facebook {
--background-hover: rgba(59, 89, 153, .04);
--color-activated: #3b5999;
--color-checked: #3b5999;
}
.md .segment-instagram {
--background-hover: rgba(228, 64, 95, .04);
--color-activated: #e4405f;
--color-checked: #e4405f;
}
.md .segment-slack {
--background-hover: rgba(58, 175, 133, .04);
--color-activated: #3aaf85;
--color-checked: #3aaf85;
}
/* Custom Icon Segment iOS */
.ios .custom-icon ion-segment-button {
--border-width: 0;
}
.ios .segment-facebook {
--color: #3b5999;
--color-checked: #ffffff;
--background-hover: rgba(59, 89, 153, .1);
--background-activated: rgba(59, 89, 153, .16);
--background-checked: #3b5999;
}
.ios .segment-instagram {
--color: #e4405f;
--color-checked: #ffffff;
--background-hover: rgba(228, 64, 95, .1);
--background-activated: rgba(228, 64, 95, .16);
--background-checked: #e4405f;
}
.ios .segment-slack {
--color: #3aaf85;
--color-checked: #ffffff;
--background-hover: rgba(58, 175, 133, .1);
--background-activated: rgba(58, 175, 133, .16);
--background-checked: #3aaf85;
.md .custom-active {
--color-checked: navy;
--indicator-color: navy;
}
/*
* Custom Icon Segment (Facebook, Instagram, Slack)
*/
.custom-icon ion-icon {
font-size: 44px;
}
/*
* MD Custom Icon Segment (Facebook, Instagram, Slack)
*/
.md .segment-button-facebook {
--background-hover: rgb(58, 61, 70, .04);
--color-checked: #3a3d46;
--indicator-color: #3a3d46;
}
.md .segment-button-instagram {
--background-hover: rgb(228, 64, 95, .04);
--color-checked: #e4405f;
--indicator-color: #e4405f;
}
.md .segment-button-slack {
--background-hover: rgb(58, 175, 133, .04);
--color-checked: #3aaf85;
--indicator-color: #3aaf85;
}
/*
* iOS Custom Icon Segment (Facebook, Instagram, Slack)
*/
.ios .segment-button-facebook {
--color: #3a3d46;
--color-checked: #ffffff;
--indicator-color: #3a3d46;
}
.ios .segment-button-instagram {
--color: #e4405f;
--color-checked: #ffffff;
--indicator-color: #e4405f;
}
.ios .segment-button-slack {
--color: #3aaf85;
--color-checked: #ffffff;
--indicator-color: #3aaf85;
}
/* This CSS should not apply */
.custom-color {
--background: purple;
--color: blue;
}
.custom-states-color {
--color: red;
--color-disabled: blue;
--color-checked: indigo;
--color-hover: orange;
}
.custom-states-background ion-segment-button {
--indicator-color: transparent;
--indicator-box-shadow: none;
--color: white;
--background: red;
--background-disabled: blue;
--background-checked: indigo;
--background-hover: orange;
}
.custom-states-background ion-segment-button:hover {
opacity: 1;
}
</style>
</html>

View File

@ -11,7 +11,7 @@
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script></head>
<body onLoad="setLayout()">
<body>
<ion-app>
<ion-header>
<ion-toolbar color="tertiary">
@ -38,7 +38,7 @@
<ion-content>
<!-- Label only -->
<ion-segment>
<ion-segment id="multi-color">
<ion-segment-button checked>
<ion-label>Item One</ion-label>
</ion-segment-button>
@ -96,7 +96,7 @@
</ion-segment>
<!-- Icon start -->
<ion-segment scrollable>
<ion-segment>
<ion-segment-button checked layout="icon-start">
<ion-label>Item One</ion-label>
<ion-icon name="call"></ion-icon>
@ -112,7 +112,7 @@
</ion-segment>
<!-- Icon end -->
<ion-segment scrollable>
<ion-segment>
<ion-segment-button checked layout="icon-end">
<ion-icon name="call"></ion-icon>
<ion-label>Item One</ion-label>
@ -144,7 +144,7 @@
</ion-segment>
<!-- Color -->
<ion-segment scrollable color="secondary">
<ion-segment color="secondary">
<ion-segment-button checked layout="icon-end">
<ion-icon name="call"></ion-icon>
<ion-label>Item One</ion-label>
@ -188,14 +188,30 @@
<style>
ion-content {
--background: #e5e5e5;
--padding-top: 16px;
}
ion-content ion-segment {
background: white;
margin-bottom: 12px;
}
.md ion-content {
--background: #e5e5e5;
}
.md ion-content ion-segment {
background: white;
}
#multi-color ion-segment-button:first-of-type {
--indicator-color: rgba(255, 0, 0, 0.5);
}
#multi-color ion-segment-button:nth-of-type(2) {
--indicator-color: rgba(0, 255, 0, 0.5);
}
#multi-color ion-segment-button:nth-of-type(3) {
--indicator-color: rgba(0, 0, 255, 0.5);
}
</style>
<script>
@ -209,6 +225,11 @@
segmentButtons[i].layout = (mode === 'ios') ? 'icon-hide' : 'icon-top';
}
}
document.addEventListener('DOMContentLoaded', () => {
requestAnimationFrame(() => {
setLayout();
});
});
</script>
</ion-app>

View File

@ -4,14 +4,16 @@
<head>
<meta charset="UTF-8">
<title>Segment - Standalone</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link href="../../../../../css/core.css" rel="stylesheet">
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script></head>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body>
<body onLoad="onLoad()">
<ion-toolbar>
<ion-segment value="Free">
<ion-segment-button value="Paid">
@ -77,15 +79,15 @@
</ion-segment>
<ion-segment class="custom-icon" value="instagram">
<ion-segment-button class="segment-facebook" value="facebook">
<ion-segment-button class="segment-button-facebook" value="facebook">
<ion-label>Facebook</ion-label>
<ion-icon name="logo-facebook"></ion-icon>
</ion-segment-button>
<ion-segment-button class="segment-instagram" value="instagram">
<ion-segment-button class="segment-button-instagram" value="instagram">
<ion-label>Instagram</ion-label>
<ion-icon name="logo-instagram"></ion-icon>
</ion-segment-button>
<ion-segment-button class="segment-slack" value="slack">
<ion-segment-button class="segment-button-slack" value="slack">
<ion-label>Slack</ion-label>
<ion-icon name="logo-slack"></ion-icon>
</ion-segment-button>
@ -145,6 +147,29 @@
results.innerHTML = value.charAt(0).toUpperCase() + value.slice(1);
segment.value = value;
}
async function onLoad() {
const customIconSegments = document.querySelectorAll('.custom-icon');
for (var i = 0; i < customIconSegments.length; i++) {
const customIconSegment = customIconSegments[i];
await customIconSegment.componentOnReady();
addIconClass(customIconSegment, customIconSegment.value);
customIconSegment.addEventListener('ionChange', function (ev) {
addIconClass(customIconSegment, ev.detail.value);
});
}
}
function addIconClass(el, value) {
console.log('adding class to', el, value);
if (value) {
el.classList.remove('segment-facebook-checked', 'segment-instagram-checked', 'segment-slack-checked');
el.classList.add(`segment-${value}-checked`);
}
}
</script>
<style>
@ -188,23 +213,64 @@
--color: navy;
}
.custom-icon {
--indicator-color: lightgray;
/*
* Custom Icon Segment (Facebook, Instagram, Slack)
*/
.custom-icon ion-icon {
font-size: 44px;
}
.segment-facebook {
--background-hover: rgba(59, 89, 153, .04);
--color-checked: #3b5999;
/*
* MD Custom Icon Segment (Facebook, Instagram, Slack)
*/
.md .segment-facebook-checked .segment-button-facebook {
--color-checked: #3a3d46;
--indicator-color: #3a3d46;
}
.segment-instagram {
--background-hover: rgba(228, 64, 95, .04);
.md .segment-instagram-checked .segment-button-instagram {
--color-checked: #e4405f;
--indicator-color: #e4405f;
}
.segment-slack {
--background-hover: rgba(58, 175, 133, .04);
.md .segment-slack-checked .segment-button-slack {
--color-checked: #3aaf85;
--indicator-color: #3aaf85;
}
/*
* iOS Custom Icon Segment (Facebook, Instagram, Slack)
*/
.ios .custom-icon {
--indicator-color: transparent;
--indicator-transition: none;
}
.ios .segment-facebook-checked .segment-button-facebook {
--background-checked: #3a3d46;
--color-checked: #ffffff;
}
.ios .segment-instagram-checked .segment-button-instagram {
--background-checked: #e4405f;
--color-checked: #ffffff;
}
.ios .segment-slack-checked .segment-button-slack {
--background-checked: #3aaf85;
--color-checked: #ffffff;
}
.ios .segment-button-facebook {
--color: #3a3d46;
}
.ios .segment-button-instagram {
--color: #e4405f;
}
.ios .segment-button-slack {
--color: #3aaf85;
}
.custom-indicator {
@ -215,6 +281,7 @@
.large-icon ion-icon {
font-size: 44px;
}
</style>
</html>

View File

@ -0,0 +1,23 @@
import { newE2EPage } from '@stencil/core/testing';
test('segment: toolbar', async () => {
const page = await newE2EPage({
url: '/src/components/segment/test/toolbar?ionic:_testing=true'
});
await page.waitFor(250);
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});
test('segment:rtl: toolbar', async () => {
const page = await newE2EPage({
url: '/src/components/segment/test/toolbar?ionic:_testing=true&rtl=true'
});
await page.waitFor(250);
const compare = await page.compareScreenshot();
expect(compare).toMatchScreenshot();
});

View File

@ -16,7 +16,7 @@
<ion-header>
<ion-toolbar>
<ion-title>Segment - Colors</ion-title>
<ion-title>Segment - Toolbar</ion-title>
</ion-toolbar>
<ion-toolbar>
@ -114,6 +114,17 @@
</ion-segment>
</ion-toolbar>
<ion-toolbar color="primary">
<ion-segment color="light">
<ion-segment-button value="sunny">
Sunny
</ion-segment-button>
<ion-segment-button value="rainy" checked>
Rainy
</ion-segment-button>
</ion-segment>
</ion-toolbar>
<!-- Label only -->
<ion-toolbar color="primary">
<ion-segment>
@ -264,13 +275,17 @@
}
.ios .themed {
--ion-toolbar-color-unchecked: #fff;
--ion-toolbar-color-checked: #3880ff;
--ion-toolbar-segment-background: rgba(255, 255, 255, 0.11);
--ion-toolbar-segment-color: #fff;
--ion-toolbar-segment-color-checked: #3880ff;
}
.md .themed {
--ion-toolbar-color-unchecked: rgba(255, 255, 255, 0.6);
--ion-toolbar-color-checked: #fff;
--ion-toolbar-segment-color: rgba(255, 255, 255, 0.6);
--ion-toolbar-segment-color-checked: #fff;
--ion-toolbar-segment-indicator-color: #fff;
}
</style>