mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 04:14:21 +08:00
feat(segment): add segment component
This commit is contained in:
125
packages/core/src/components/segment-button/segment-button.tsx
Normal file
125
packages/core/src/components/segment-button/segment-button.tsx
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import { Component, h, Ionic, Prop, State } from '@stencil/core';
|
||||||
|
|
||||||
|
import { CssClassObject } from '../../util/interfaces';
|
||||||
|
import { createThemedClasses } from '../../util/theme';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name SegmentButton
|
||||||
|
* @description
|
||||||
|
* The child buttons of the `ion-segment` component. Each `ion-segment-button` must have a value.
|
||||||
|
*
|
||||||
|
* @usage
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <ion-content>
|
||||||
|
* <!-- Segment buttons with icons -->
|
||||||
|
* <ion-segment [(ngModel)]="icons" color="secondary">
|
||||||
|
* <ion-segment-button value="camera">
|
||||||
|
* <ion-icon name="camera"></ion-icon>
|
||||||
|
* </ion-segment-button>
|
||||||
|
* <ion-segment-button value="bookmark">
|
||||||
|
* <ion-icon name="bookmark"></ion-icon>
|
||||||
|
* </ion-segment-button>
|
||||||
|
* </ion-segment>
|
||||||
|
*
|
||||||
|
* <!-- Segment buttons with text -->
|
||||||
|
* <ion-segment [(ngModel)]="relationship" color="primary">
|
||||||
|
* <ion-segment-button value="friends" (ionSelect)="selectedFriends()">
|
||||||
|
* Friends
|
||||||
|
* </ion-segment-button>
|
||||||
|
* <ion-segment-button value="enemies" (ionSelect)="selectedEnemies()">
|
||||||
|
* Enemies
|
||||||
|
* </ion-segment-button>
|
||||||
|
* </ion-segment>
|
||||||
|
* </ion-content>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @demo /docs/demos/src/segment/
|
||||||
|
* @see {@link /docs/components#segment Segment Component Docs}
|
||||||
|
* @see {@link /docs/api/components/segment/Segment/ Segment API Docs}
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
tag: 'ion-segment-button'
|
||||||
|
})
|
||||||
|
export class SegmentButton {
|
||||||
|
styleTmr: any;
|
||||||
|
|
||||||
|
mode: string;
|
||||||
|
color: string;
|
||||||
|
|
||||||
|
@State() activated: boolean = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @input {boolean} If true, the button is selected. Default false.
|
||||||
|
*/
|
||||||
|
@Prop({ state: true }) checked: boolean = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @input {boolean} If true, the user cannot interact with this element. Default false.
|
||||||
|
*/
|
||||||
|
@Prop({ state: true }) disabled: boolean = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @input {string} the value of the segment button. Required.
|
||||||
|
*/
|
||||||
|
@Prop({ state: true }) value: string;
|
||||||
|
|
||||||
|
segmentButtonClick(ev: UIEvent) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
console.log('in segment button click');
|
||||||
|
this.emitClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit the click event to the parent segment
|
||||||
|
*/
|
||||||
|
private emitClick() {
|
||||||
|
clearTimeout(this.styleTmr);
|
||||||
|
|
||||||
|
this.styleTmr = setTimeout(() => {
|
||||||
|
Ionic.emit(this, 'ionClick', {
|
||||||
|
detail: {
|
||||||
|
'segmentButton': this,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
* Get the element classes to add to the child element
|
||||||
|
*/
|
||||||
|
getElementClassList() {
|
||||||
|
let classList = [].concat(
|
||||||
|
this.disabled ? 'segment-button-disabled' : [],
|
||||||
|
this.activated ? 'segment-activated' : [],
|
||||||
|
);
|
||||||
|
|
||||||
|
return classList;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const segmentButtonCss = createThemedClasses(this.mode, this.color, 'segment-button');
|
||||||
|
|
||||||
|
var segmentButtonClasses: CssClassObject = []
|
||||||
|
.concat(
|
||||||
|
this.getElementClassList()
|
||||||
|
)
|
||||||
|
.reduce((prevValue, cssClass) => {
|
||||||
|
prevValue[cssClass] = true;
|
||||||
|
return prevValue;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
segmentButtonClasses = Object.assign(segmentButtonClasses, segmentButtonCss);
|
||||||
|
|
||||||
|
return [
|
||||||
|
<button onClick={this.segmentButtonClick.bind(this)} class={segmentButtonClasses} aria-pressed={this.activated}>
|
||||||
|
<slot></slot>
|
||||||
|
</button>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
231
packages/core/src/components/segment/segment.ios.scss
Normal file
231
packages/core/src/components/segment/segment.ios.scss
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
@import "../../themes/ionic.globals.ios";
|
||||||
|
@import "./segment";
|
||||||
|
|
||||||
|
// iOS Segment
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
/// @prop - Background of the segment button
|
||||||
|
$segment-button-ios-background-color: transparent !default;
|
||||||
|
|
||||||
|
/// @prop - Background of the activated segment button
|
||||||
|
$segment-button-ios-background-color-activated: $toolbar-ios-active-color !default;
|
||||||
|
|
||||||
|
/// @prop - Text color of the segment button
|
||||||
|
$segment-button-ios-text-color: color-contrast($colors-ios, $segment-button-ios-background-color-activated) !default;
|
||||||
|
|
||||||
|
/// @prop - Transition of the activated segment button
|
||||||
|
$segment-button-ios-transition-activated: 100ms all linear !default;
|
||||||
|
|
||||||
|
/// @prop - Transition of the segment button on hover
|
||||||
|
$segment-button-ios-transition-hover: 100ms all linear !default;
|
||||||
|
|
||||||
|
/// @prop - Transition of the segment button when pressed
|
||||||
|
$segment-button-ios-transition-active: 100ms all linear !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-active: .16 !default;
|
||||||
|
|
||||||
|
/// @prop - Opacity of the activated segment button
|
||||||
|
$segment-button-ios-opacity-activated: 1 !default;
|
||||||
|
|
||||||
|
/// @prop - Opacity of the disabled segment button
|
||||||
|
$segment-button-ios-opacity-disabled: .3 !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: 3.2rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of the segment button
|
||||||
|
$segment-button-ios-line-height: 2.8rem !default;
|
||||||
|
|
||||||
|
/// @prop - Font size of the segment button
|
||||||
|
$segment-button-ios-font-size: 1.3rem !default;
|
||||||
|
|
||||||
|
/// @prop - Border radius of the segment button
|
||||||
|
$segment-button-ios-border-radius: 4px !default;
|
||||||
|
|
||||||
|
/// @prop - Size of an icon in the segment button
|
||||||
|
$segment-button-ios-icon-size: 2.6rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of an icon in the segment button
|
||||||
|
$segment-button-ios-icon-line-height: 2.8rem !default;
|
||||||
|
|
||||||
|
/// @prop - Max width of the segment button in a toolbar
|
||||||
|
$segment-button-ios-toolbar-button-max-width: 100px !default;
|
||||||
|
|
||||||
|
/// @prop - Height of the segment button in a toolbar
|
||||||
|
$segment-button-ios-toolbar-button-height: 2.6rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of the segment button in a toolbar
|
||||||
|
$segment-button-ios-toolbar-line-height: 2.2rem !default;
|
||||||
|
|
||||||
|
/// @prop - Font size of the segment button in a toolbar
|
||||||
|
$segment-button-ios-toolbar-font-size: 1.2rem !default;
|
||||||
|
|
||||||
|
/// @prop - Size of an icon in the segment button in a toolbar
|
||||||
|
$segment-button-ios-toolbar-icon-size: 2.2rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of an icon in the segment button in a toolbar
|
||||||
|
$segment-button-ios-toolbar-icon-line-height: 2.4rem !default;
|
||||||
|
|
||||||
|
.segment-ios ion-segment-button {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
width: 0;
|
||||||
|
|
||||||
|
&:first-of-type .segment-button {
|
||||||
|
@include border-radius($segment-button-ios-border-radius, 0, 0, $segment-button-ios-border-radius);
|
||||||
|
@include margin-horizontal(null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-of-type) .segment-button {
|
||||||
|
border-left-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-of-type .segment-button {
|
||||||
|
@include border-radius(0, $segment-button-ios-border-radius, $segment-button-ios-border-radius, 0);
|
||||||
|
@include margin-horizontal(0, null);
|
||||||
|
|
||||||
|
border-left-width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-ios .segment-button {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
height: $segment-button-ios-height;
|
||||||
|
|
||||||
|
border-width: $segment-button-ios-border-width;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: $segment-button-ios-background-color-activated;
|
||||||
|
|
||||||
|
font-size: $segment-button-ios-font-size;
|
||||||
|
line-height: $segment-button-ios-line-height;
|
||||||
|
|
||||||
|
color: $segment-button-ios-background-color-activated;
|
||||||
|
background-color: $segment-button-ios-background-color;
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
font-size: $segment-button-ios-icon-size;
|
||||||
|
line-height: $segment-button-ios-icon-line-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.segment-activated {
|
||||||
|
color: $segment-button-ios-text-color;
|
||||||
|
background-color: $segment-button-ios-background-color-activated;
|
||||||
|
opacity: $segment-button-ios-opacity-activated;
|
||||||
|
transition: $segment-button-ios-transition-activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:not(.segment-activated) {
|
||||||
|
background-color: rgba($segment-button-ios-background-color-activated, $segment-button-ios-opacity-hover);
|
||||||
|
transition: $segment-button-ios-transition-hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active:not(.segment-activated) {
|
||||||
|
background-color: rgba($segment-button-ios-background-color-activated, $segment-button-ios-opacity-active);
|
||||||
|
transition: $segment-button-ios-transition-active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .segment-ios ion-segment-button {
|
||||||
|
&:first-of-type .segment-button {
|
||||||
|
border-left-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-of-type .segment-button {
|
||||||
|
border-left-width: $segment-button-ios-border-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.segment-ios.segment-disabled {
|
||||||
|
opacity: .4;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-ios .segment-button-disabled {
|
||||||
|
color: rgba($segment-button-ios-background-color-activated, $segment-button-ios-opacity-disabled);
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// iOS Segment in Toolbar
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
.toolbar-ios .segment-ios {
|
||||||
|
@include position(0, 0, 0, 0);
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-ios ion-segment-button {
|
||||||
|
max-width: $segment-button-ios-toolbar-button-max-width;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-ios .segment-button {
|
||||||
|
height: $segment-button-ios-toolbar-button-height;
|
||||||
|
|
||||||
|
font-size: $segment-button-ios-toolbar-font-size;
|
||||||
|
line-height: $segment-button-ios-toolbar-line-height;
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
font-size: $segment-button-ios-toolbar-icon-size;
|
||||||
|
line-height: $segment-button-ios-toolbar-icon-line-height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// iOS Segment Button Mixin
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@mixin ios-segment-button($color-name, $color-base, $color-contrast) {
|
||||||
|
|
||||||
|
.segment-ios-#{$color-name} {
|
||||||
|
|
||||||
|
.segment-button {
|
||||||
|
border-color: $color-base;
|
||||||
|
color: $color-base;
|
||||||
|
|
||||||
|
&:hover:not(.segment-activated) {
|
||||||
|
background-color: rgba($color-base, $segment-button-ios-opacity-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active:not(.segment-activated) {
|
||||||
|
background-color: rgba($color-base, $segment-button-ios-opacity-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.segment-activated {
|
||||||
|
color: $color-contrast;
|
||||||
|
background-color: $color-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-button-disabled {
|
||||||
|
color: rgba($color-base, $segment-button-ios-opacity-disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// iOS Segment Color Generation
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@each $color-name, $color-base, $color-contrast in get-colors($colors-ios) {
|
||||||
|
|
||||||
|
@include ios-segment-button($color-name, $color-base, $color-contrast);
|
||||||
|
|
||||||
|
.toolbar-ios-#{$color-name} .segment-ios .segment-button.segment-activated {
|
||||||
|
color: $color-base;
|
||||||
|
}
|
||||||
|
}
|
145
packages/core/src/components/segment/segment.md.scss
Normal file
145
packages/core/src/components/segment/segment.md.scss
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
@import "../../themes/ionic.globals.md";
|
||||||
|
@import "./segment";
|
||||||
|
|
||||||
|
// Material Design Segment
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
/// @prop - Text color of the activated segment button
|
||||||
|
$segment-button-md-text-color-activated: $toolbar-md-active-color !default;
|
||||||
|
|
||||||
|
/// @prop - Border color of the activated segment button
|
||||||
|
$segment-button-md-border-color-activated: $toolbar-md-active-color !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: rgba(#000, .10) !default;
|
||||||
|
|
||||||
|
/// @prop - Opacity of the segment button
|
||||||
|
$segment-button-md-opacity: .7 !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;
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
$segment-button-md-padding: null !default;
|
||||||
|
|
||||||
|
/// @prop - Padding top of the segment button
|
||||||
|
$segment-button-md-padding-top: 0 !default;
|
||||||
|
|
||||||
|
/// @prop - Padding end of the segment button
|
||||||
|
$segment-button-md-padding-end: 6px !default;
|
||||||
|
|
||||||
|
/// @prop - Padding bottom of the segment button
|
||||||
|
$segment-button-md-padding-bottom: $segment-button-md-padding-top !default;
|
||||||
|
|
||||||
|
/// @prop - Padding start of the segment button
|
||||||
|
$segment-button-md-padding-start: $segment-button-md-padding-end !default;
|
||||||
|
|
||||||
|
/// @prop - Height of the segment button
|
||||||
|
$segment-button-md-height: 4.2rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of the segment button
|
||||||
|
$segment-button-md-line-height: 4rem !default;
|
||||||
|
|
||||||
|
/// @prop - Font size of the segment button
|
||||||
|
$segment-button-md-font-size: 1.2rem !default;
|
||||||
|
|
||||||
|
/// @prop - Size of an icon in the segment button
|
||||||
|
$segment-button-md-icon-size: 2.6rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of an icon in the segment button
|
||||||
|
$segment-button-md-icon-line-height: $segment-button-md-line-height !default;
|
||||||
|
|
||||||
|
|
||||||
|
.segment-md ion-segment-button {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-md .segment-button {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
width: 0;
|
||||||
|
height: $segment-button-md-height;
|
||||||
|
|
||||||
|
border-bottom-width: $segment-button-md-border-bottom-width;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-color: $segment-button-md-border-bottom-color;
|
||||||
|
|
||||||
|
font-size: $segment-button-md-font-size;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: $segment-button-md-line-height;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
color: $segment-button-md-text-color-activated;
|
||||||
|
background-color: transparent;
|
||||||
|
opacity: $segment-button-md-opacity;
|
||||||
|
transition: 100ms all linear;
|
||||||
|
|
||||||
|
@include deprecated-variable(padding, $segment-button-md-padding) {
|
||||||
|
@include padding($segment-button-md-padding-top, $segment-button-md-padding-end, $segment-button-md-padding-bottom, $segment-button-md-padding-start);
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
font-size: $segment-button-md-icon-size;
|
||||||
|
line-height: $segment-button-md-icon-line-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.activated,
|
||||||
|
&.segment-activated {
|
||||||
|
border-color: $segment-button-md-border-color-activated;
|
||||||
|
opacity: $segment-button-md-opacity-activated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-md.segment-disabled,
|
||||||
|
.segment-md .segment-button-disabled {
|
||||||
|
opacity: $segment-button-md-opacity-disabled;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
|
||||||
|
.segment-md {
|
||||||
|
@include margin(0, auto);
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-md .segment-button.activated,
|
||||||
|
.segment-md .segment-button.segment-activated {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Material Design Segment Button Mixin
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@mixin md-segment-button($color-name, $color-base, $color-contrast) {
|
||||||
|
|
||||||
|
.segment-md-#{$color-name} .segment-button {
|
||||||
|
color: $color-base;
|
||||||
|
|
||||||
|
&.activated,
|
||||||
|
&.segment-activated {
|
||||||
|
border-color: $color-base;
|
||||||
|
color: $color-base;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Material Design Segment Color Generation
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@each $color-name, $color-base, $color-contrast in get-colors($colors-md) {
|
||||||
|
@include md-segment-button($color-name, $color-base, $color-contrast);
|
||||||
|
}
|
28
packages/core/src/components/segment/segment.scss
Normal file
28
packages/core/src/components/segment/segment.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
@import "../../themes/ionic.globals";
|
||||||
|
|
||||||
|
// Segment
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
ion-segment {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
flex: 1;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-button {
|
||||||
|
@include margin-horizontal(0);
|
||||||
|
@include text-align(center);
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
130
packages/core/src/components/segment/segment.tsx
Normal file
130
packages/core/src/components/segment/segment.tsx
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { Component, h, Listen, Prop, PropDidChange } from '@stencil/core';
|
||||||
|
import { SegmentButtonEvent, VNodeData } from '../../util/interfaces';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Segment
|
||||||
|
* @description
|
||||||
|
* A Segment is a group of buttons, sometimes known as Segmented Controls, that allow the user to interact with a compact group of a number of controls.
|
||||||
|
* Segments provide functionality similar to tabs, selecting one will unselect all others. You should use a tab bar instead of a segmented control when you want to let the user move back and forth between distinct pages in your app.
|
||||||
|
* You could use Angular's `ngModel` or `FormBuilder` API. For an overview on how `FormBuilder` works, checkout [Angular Forms](http://learnangular2.com/forms/), or [Angular FormBuilder](https://angular.io/docs/ts/latest/api/forms/index/FormBuilder-class.html)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ```html
|
||||||
|
* <!-- Segment in a header -->
|
||||||
|
* <ion-header>
|
||||||
|
* <ion-toolbar>
|
||||||
|
* <ion-segment [(ngModel)]="icons" color="secondary">
|
||||||
|
* <ion-segment-button value="camera">
|
||||||
|
* <ion-icon name="camera"></ion-icon>
|
||||||
|
* </ion-segment-button>
|
||||||
|
* <ion-segment-button value="bookmark">
|
||||||
|
* <ion-icon name="bookmark"></ion-icon>
|
||||||
|
* </ion-segment-button>
|
||||||
|
* </ion-segment>
|
||||||
|
* </ion-toolbar>
|
||||||
|
* </ion-header>
|
||||||
|
*
|
||||||
|
* <ion-content>
|
||||||
|
* <!-- Segment in content -->
|
||||||
|
* <ion-segment [(ngModel)]="relationship" color="primary" (ionChange)="segmentChanged($event)">
|
||||||
|
* <ion-segment-button value="friends">
|
||||||
|
* Friends
|
||||||
|
* </ion-segment-button>
|
||||||
|
* <ion-segment-button value="enemies">
|
||||||
|
* Enemies
|
||||||
|
* </ion-segment-button>
|
||||||
|
* </ion-segment>
|
||||||
|
*
|
||||||
|
* <!-- Segment in a form -->
|
||||||
|
* <form [formGroup]="myForm">
|
||||||
|
* <ion-segment formControlName="mapStyle" color="danger">
|
||||||
|
* <ion-segment-button value="standard">
|
||||||
|
* Standard
|
||||||
|
* </ion-segment-button>
|
||||||
|
* <ion-segment-button value="hybrid">
|
||||||
|
* Hybrid
|
||||||
|
* </ion-segment-button>
|
||||||
|
* <ion-segment-button value="sat">
|
||||||
|
* Satellite
|
||||||
|
* </ion-segment-button>
|
||||||
|
* </ion-segment>
|
||||||
|
* </form>
|
||||||
|
* </ion-content>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @demo /docs/demos/src/segment/
|
||||||
|
* @see {@link /docs/components#segment Segment Component Docs}
|
||||||
|
* @see [Angular Forms](http://learnangular2.com/forms/)
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
tag: 'ion-segment',
|
||||||
|
styleUrls: {
|
||||||
|
ios: 'segment.ios.scss',
|
||||||
|
md: 'segment.md.scss',
|
||||||
|
wp: 'segment.wp.scss'
|
||||||
|
},
|
||||||
|
host: {
|
||||||
|
theme: 'segment'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export class Segment {
|
||||||
|
buttons: any;
|
||||||
|
$el: any;
|
||||||
|
|
||||||
|
@Prop({ state: true }) disabled: boolean = false;
|
||||||
|
|
||||||
|
@Prop({ state: true }) value: string;
|
||||||
|
|
||||||
|
@PropDidChange('value')
|
||||||
|
changed(val: string) {
|
||||||
|
this.selectButton(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ionViewDidLoad() {
|
||||||
|
this.buttons = this.$el.querySelectorAll('ion-segment-button');
|
||||||
|
|
||||||
|
for (var i = 0; i < this.buttons.length; i++) {
|
||||||
|
const button = this.buttons[i].$instance;
|
||||||
|
|
||||||
|
button.activated = (button.value === this.value);
|
||||||
|
|
||||||
|
// If there is no value set on the segment and a button
|
||||||
|
// is checked we should activate it
|
||||||
|
if (!this.value && button.checked) {
|
||||||
|
button.activated = button.checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listen('ionClick')
|
||||||
|
segmentClick(ev: SegmentButtonEvent) {
|
||||||
|
let selectedButton = ev.detail.segmentButton;
|
||||||
|
|
||||||
|
this.value = selectedButton.value;
|
||||||
|
this.selectButton(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectButton(val: string) {
|
||||||
|
for (var i = 0; i < this.buttons.length; i++) {
|
||||||
|
const button = this.buttons[i].$instance;
|
||||||
|
button.activated = (button.value === val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returning true tells the renderer to queue an update
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hostData(): VNodeData {
|
||||||
|
return {
|
||||||
|
class: {
|
||||||
|
'segment-disabled': this.disabled
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <slot></slot>;
|
||||||
|
}
|
||||||
|
}
|
133
packages/core/src/components/segment/segment.wp.scss
Normal file
133
packages/core/src/components/segment/segment.wp.scss
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
@import "../../themes/ionic.globals.wp";
|
||||||
|
@import "./segment";
|
||||||
|
|
||||||
|
// Windows Segment
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
/// @prop - Background of the segment button
|
||||||
|
$segment-button-wp-background-color: transparent !default;
|
||||||
|
|
||||||
|
/// @prop - Text color of the activated segment button
|
||||||
|
$segment-button-wp-text-color-activated: $toolbar-wp-text-color !default;
|
||||||
|
|
||||||
|
// deprecated
|
||||||
|
$segment-button-wp-padding: null !default;
|
||||||
|
|
||||||
|
/// @prop - Padding top of the segment button
|
||||||
|
$segment-button-wp-padding-top: 0 !default;
|
||||||
|
|
||||||
|
/// @prop - Padding end of the segment button
|
||||||
|
$segment-button-wp-padding-end: 6px !default;
|
||||||
|
|
||||||
|
/// @prop - Padding bottom of the segment button
|
||||||
|
$segment-button-wp-padding-bottom: $segment-button-wp-padding-top !default;
|
||||||
|
|
||||||
|
/// @prop - Padding start of the segment button
|
||||||
|
$segment-button-wp-padding-start: $segment-button-wp-padding-end !default;
|
||||||
|
|
||||||
|
/// @prop - Height of the segment button
|
||||||
|
$segment-button-wp-height: 4rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of the segment button
|
||||||
|
$segment-button-wp-line-height: 4rem !default;
|
||||||
|
|
||||||
|
/// @prop - Font size of the segment button
|
||||||
|
$segment-button-wp-font-size: 1.3rem !default;
|
||||||
|
|
||||||
|
/// @prop - Text transform of the segment button
|
||||||
|
$segment-button-wp-text-transform: uppercase !default;
|
||||||
|
|
||||||
|
/// @prop - Font weight of the segment button
|
||||||
|
$segment-button-wp-font-weight: bold !default;
|
||||||
|
|
||||||
|
/// @prop - Opacity of the segment button
|
||||||
|
$segment-button-wp-opacity: .5 !default;
|
||||||
|
|
||||||
|
/// @prop - Opacity of the activated segment button
|
||||||
|
$segment-button-wp-opacity-activated: 1 !default;
|
||||||
|
|
||||||
|
/// @prop - Opacity of the disabled segment button
|
||||||
|
$segment-button-wp-opacity-disabled: .3 !default;
|
||||||
|
|
||||||
|
/// @prop - Size of an icon in the segment button
|
||||||
|
$segment-button-wp-icon-size: 2.6rem !default;
|
||||||
|
|
||||||
|
/// @prop - Line height of an icon in the segment button
|
||||||
|
$segment-button-wp-icon-line-height: $segment-button-wp-line-height !default;
|
||||||
|
|
||||||
|
/// @prop - Position of the buttons in the segment
|
||||||
|
$segment-button-wp-buttons-justify-content: flex-start !default;
|
||||||
|
|
||||||
|
|
||||||
|
.segment-wp {
|
||||||
|
justify-content: $segment-button-wp-buttons-justify-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-wp .segment-button {
|
||||||
|
height: $segment-button-wp-height;
|
||||||
|
|
||||||
|
font-size: $segment-button-wp-font-size;
|
||||||
|
font-weight: $segment-button-wp-font-weight;
|
||||||
|
line-height: $segment-button-wp-line-height;
|
||||||
|
|
||||||
|
text-transform: $segment-button-wp-text-transform;
|
||||||
|
|
||||||
|
color: $segment-button-wp-text-color-activated;
|
||||||
|
background-color: $segment-button-wp-background-color;
|
||||||
|
opacity: $segment-button-wp-opacity;
|
||||||
|
|
||||||
|
@include deprecated-variable(padding, $segment-button-wp-padding) {
|
||||||
|
@include padding($segment-button-wp-padding-top, $segment-button-wp-padding-end, $segment-button-wp-padding-bottom, $segment-button-wp-padding-start);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.segment-activated {
|
||||||
|
opacity: $segment-button-wp-opacity-activated;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
font-size: $segment-button-wp-icon-size;
|
||||||
|
line-height: $segment-button-wp-icon-line-height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.segment-wp.segment-disabled,
|
||||||
|
.segment-wp .segment-button-disabled {
|
||||||
|
opacity: $segment-button-wp-opacity-disabled;
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
|
||||||
|
.segment-wp {
|
||||||
|
@include margin(0, auto);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Windows Segment Button Mixin
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@mixin wp-segment-button($color-name, $color-base) {
|
||||||
|
|
||||||
|
.segment-wp-#{$color-name} .segment-button {
|
||||||
|
color: $color-base;
|
||||||
|
|
||||||
|
&.activated,
|
||||||
|
&.segment-activated {
|
||||||
|
border-color: $color-base;
|
||||||
|
color: $color-base;
|
||||||
|
opacity: $segment-button-wp-opacity-activated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Windows Segment Color Generation
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@each $color-name, $color-base, $color-contrast in get-colors($colors-wp) {
|
||||||
|
@include wp-segment-button($color-name, $color-base);
|
||||||
|
}
|
@ -211,6 +211,13 @@ export interface GestureCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface SegmentButtonEvent {
|
||||||
|
detail: {
|
||||||
|
segmentButton: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface ScrollDetail extends GestureDetail {
|
export interface ScrollDetail extends GestureDetail {
|
||||||
scrollTop?: number;
|
scrollTop?: number;
|
||||||
scrollLeft?: number;
|
scrollLeft?: number;
|
||||||
|
@ -11,6 +11,7 @@ exports.config = {
|
|||||||
{ components: ['ion-loading', 'ion-loading-controller'] },
|
{ components: ['ion-loading', 'ion-loading-controller'] },
|
||||||
{ components: ['ion-menu'], priority: 'low' },
|
{ components: ['ion-menu'], priority: 'low' },
|
||||||
{ components: ['ion-modal', 'ion-modal-controller'] },
|
{ components: ['ion-modal', 'ion-modal-controller'] },
|
||||||
|
{ components: ['ion-segment', 'ion-segment-button'] },
|
||||||
{ components: ['ion-slides', 'ion-slide'] },
|
{ components: ['ion-slides', 'ion-slide'] },
|
||||||
{ components: ['ion-spinner'] },
|
{ components: ['ion-spinner'] },
|
||||||
{ components: ['ion-toggle'] }
|
{ components: ['ion-toggle'] }
|
||||||
|
Reference in New Issue
Block a user