mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 14:01:20 +08:00
refactor(fab): rename files and styles for the fab components (#13585)
* refactor(fab): rename files to match tag names * refactor(fab): fix class names and separate styles * chore(config): bundle fab button separately
This commit is contained in:
2868
packages/core/src/components.d.ts
vendored
2868
packages/core/src/components.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@ -1,26 +1,26 @@
|
||||
@import "./fab";
|
||||
@import "./fab.ios.vars";
|
||||
@import "./fab-button";
|
||||
@import "./fab-button.ios.vars";
|
||||
|
||||
// iOS FAB Button
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-ios {
|
||||
.fab-button-ios {
|
||||
color: $fab-ios-text-color;
|
||||
background-color: $fab-ios-background-color;
|
||||
}
|
||||
|
||||
.fab-ios.activated {
|
||||
.fab-button-ios.activated {
|
||||
background-color: $fab-ios-background-color-activated;
|
||||
}
|
||||
|
||||
.fab-ios .icon {
|
||||
.fab-button-ios .icon {
|
||||
fill: $fab-ios-icon-fill-color;
|
||||
}
|
||||
|
||||
// FAB buttons in a list
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-ios-in-list {
|
||||
.fab-button-ios-in-list {
|
||||
color: $fab-ios-list-button-text-color;
|
||||
background-color: $fab-ios-list-button-background-color;
|
||||
|
||||
@ -28,11 +28,11 @@
|
||||
opacity $fab-ios-list-button-transition-duration $fab-ios-list-button-transition-timing-function $fab-ios-list-button-transition-delay;
|
||||
}
|
||||
|
||||
.fab-ios-in-list.activated {
|
||||
.fab-button-ios-in-list.activated {
|
||||
background-color: $fab-ios-list-button-background-color-activated;
|
||||
}
|
||||
|
||||
.fab-ios-in-list .icon {
|
||||
.fab-button-ios-in-list .icon {
|
||||
fill: $fab-ios-list-button-icon-fill-color;
|
||||
}
|
||||
|
||||
@ -60,16 +60,16 @@
|
||||
$bg-color-activated: color-shade($bg-color);
|
||||
$fg-color: $color-contrast;
|
||||
|
||||
.fab-ios-#{$color-name} {
|
||||
.fab-button-ios-#{$color-name} {
|
||||
color: $fg-color;
|
||||
background-color: $bg-color;
|
||||
}
|
||||
|
||||
.fab-ios-#{$color-name} .icon {
|
||||
.fab-button-ios-#{$color-name} .icon {
|
||||
fill: $fg-color;
|
||||
}
|
||||
|
||||
.fab-ios-#{$color-name}.activated {
|
||||
.fab-button-ios-#{$color-name}.activated {
|
||||
background-color: $bg-color-activated;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
@import "./fab";
|
||||
@import "./fab.md.vars";
|
||||
@import "./fab-button";
|
||||
@import "./fab-button.md.vars";
|
||||
|
||||
// Material Design FAB Button
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-md {
|
||||
.fab-button-md {
|
||||
color: $fab-md-text-color;
|
||||
background-color: $fab-md-background-color;
|
||||
|
||||
@ -15,12 +15,12 @@
|
||||
color $fab-button-md-transition-duration $fab-button-md-transition-timing-function;
|
||||
}
|
||||
|
||||
.fab-md.activated {
|
||||
.fab-button-md.activated {
|
||||
background-color: $fab-md-background-color-activated;
|
||||
box-shadow: $fab-md-box-shadow-activated;
|
||||
}
|
||||
|
||||
.fab-md .icon {
|
||||
.fab-button-md .icon {
|
||||
fill: $fab-md-icon-fill-color;
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
// FAB buttons in a list
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-md-in-list {
|
||||
.fab-button-md-in-list {
|
||||
color: $fab-md-list-button-text-color;
|
||||
background-color: $fab-md-list-button-background-color;
|
||||
|
||||
@ -39,11 +39,11 @@
|
||||
color $fab-button-md-transition-duration $fab-button-md-transition-timing-function;
|
||||
}
|
||||
|
||||
.fab-md-in-list.activated {
|
||||
.fab-button-md-in-list.activated {
|
||||
background-color: $fab-md-list-button-background-color-activated;
|
||||
}
|
||||
|
||||
.fab-md-in-list .icon {
|
||||
.fab-button-md-in-list .icon {
|
||||
fill: $fab-md-list-button-icon-fill-color;
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
// Material Design FAB Ripple
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-md .button-effect {
|
||||
.fab-button-md .button-effect {
|
||||
background-color: color-contrast($colors-md, $fab-md-background-color);
|
||||
}
|
||||
|
||||
@ -65,20 +65,20 @@
|
||||
$bg-color-activated: color-shade($bg-color);
|
||||
$fg-color: $color-contrast;
|
||||
|
||||
.fab-md-#{$color-name} {
|
||||
.fab-button-md-#{$color-name} {
|
||||
color: $fg-color;
|
||||
background-color: $bg-color;
|
||||
}
|
||||
|
||||
.fab-md-#{$color-name} .icon {
|
||||
.fab-button-md-#{$color-name} .icon {
|
||||
fill: $fg-color;
|
||||
}
|
||||
|
||||
.fab-md-#{$color-name}.activated {
|
||||
.fab-button-md-#{$color-name}.activated {
|
||||
background-color: $bg-color-activated;
|
||||
}
|
||||
|
||||
.fab-md-#{$color-name} .button-effect {
|
||||
.fab-button-md-#{$color-name} .button-effect {
|
||||
background-color: $fg-color;
|
||||
}
|
||||
}
|
95
packages/core/src/components/fab-button/fab-button.scss
Executable file
95
packages/core/src/components/fab-button/fab-button.scss
Executable file
@ -0,0 +1,95 @@
|
||||
@import "./fab-button.vars";
|
||||
|
||||
// Floating Action Buttons
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-button {
|
||||
@include text-align(center);
|
||||
@include appearance(none);
|
||||
@include border-radius(50%);
|
||||
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
|
||||
width: $fab-size;
|
||||
height: $fab-size;
|
||||
|
||||
font-size: 14px;
|
||||
line-height: $fab-size;
|
||||
text-overflow: ellipsis;
|
||||
text-transform: none;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: background-color, opacity 100ms linear;
|
||||
|
||||
background-clip: padding-box;
|
||||
font-kerning: none;
|
||||
user-select: none;
|
||||
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
.fab-button ion-icon {
|
||||
flex: 1;
|
||||
|
||||
font-size: 2.4rem;
|
||||
line-height: 1.8rem;
|
||||
}
|
||||
|
||||
// FAB Mini
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-fab-button[mini] .fab-button {
|
||||
@include margin(($fab-size - $fab-mini-size) / 2);
|
||||
|
||||
width: $fab-mini-size;
|
||||
height: $fab-mini-size;
|
||||
|
||||
line-height: $fab-mini-size;
|
||||
}
|
||||
|
||||
// FAB Close Icon
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-button-close-icon {
|
||||
@include position(0, 0, null, 0);
|
||||
|
||||
position: absolute;
|
||||
|
||||
height: 100%;
|
||||
|
||||
opacity: 0;
|
||||
transform: scale(.4) rotateZ(-45deg);
|
||||
transition: all ease-in-out 300ms;
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.fab-button-close-icon .icon-inner {
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
// FAB Animation
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-button .button-inner {
|
||||
transition: all ease-in-out 300ms;
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.fab-button-close-active .fab-button-close-icon {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotateZ(0deg);
|
||||
}
|
||||
|
||||
.fab-button-close-active .button-inner {
|
||||
opacity: 0;
|
||||
transform: scale(.4) rotateZ(45deg);
|
||||
}
|
149
packages/core/src/components/fab-button/fab-button.tsx
Executable file
149
packages/core/src/components/fab-button/fab-button.tsx
Executable file
@ -0,0 +1,149 @@
|
||||
import { Component, CssClassMap, Element, Prop, State } from '@stencil/core';
|
||||
import { createThemedClasses, getElementClassObject } from '../../utils/theme';
|
||||
|
||||
|
||||
@Component({
|
||||
tag: 'ion-fab-button',
|
||||
styleUrls: {
|
||||
ios: 'fab-button.ios.scss',
|
||||
md: 'fab-button.md.scss'
|
||||
}
|
||||
})
|
||||
export class FabButton {
|
||||
@Element() private el: HTMLElement;
|
||||
|
||||
/**
|
||||
* @input {string} The color to use from your Sass `$colors` map.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"danger"`, `"light"`, and `"dark"`.
|
||||
* For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
*/
|
||||
@Prop() color: string;
|
||||
|
||||
/**
|
||||
* @input {string} The mode determines which platform styles to use.
|
||||
* Possible values are: `"ios"` or `"md"`.
|
||||
* For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||
*/
|
||||
@Prop() mode: 'ios' | 'md';
|
||||
|
||||
/**
|
||||
* @input {string} Contains a URL or a URL fragment that the hyperlink points to.
|
||||
* If this property is set, an anchor tag will be rendered.
|
||||
*/
|
||||
@Prop() href: string;
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, adds transparency to the fab.
|
||||
* Only affects `ios` mode. Defaults to `false`.
|
||||
*/
|
||||
@Prop() translucent: boolean = false;
|
||||
|
||||
@Prop() activated: boolean = false;
|
||||
@Prop() toggleActive: Function = () => {};
|
||||
|
||||
@Prop() show: boolean = false;
|
||||
|
||||
@State() private inContainer: boolean = false;
|
||||
@State() private inList: boolean = false;
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, sets the button into a disabled state.
|
||||
*/
|
||||
@Prop() disabled: boolean = false;
|
||||
|
||||
componentDidLoad() {
|
||||
const parentNode = this.el.parentNode.nodeName;
|
||||
|
||||
this.inList = (parentNode === 'ION-FAB-LIST');
|
||||
this.inContainer = (parentNode === 'ION-FAB');
|
||||
}
|
||||
|
||||
|
||||
clickedFab() {
|
||||
if (this.inContainer) {
|
||||
this.toggleActive();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* Get the classes for fab buttons in lists
|
||||
*/
|
||||
getFabListClassList() {
|
||||
if (!this.inList) {
|
||||
return [];
|
||||
}
|
||||
let listClasses = [
|
||||
`fab-button-in-list`,
|
||||
`fab-button-${this.mode}-in-list`
|
||||
];
|
||||
|
||||
if (this.translucent) {
|
||||
listClasses.push(`fab-button-translucent-${this.mode}-in-list`);
|
||||
}
|
||||
|
||||
return listClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* Get the close active class for fab buttons
|
||||
*/
|
||||
getFabActiveClassList() {
|
||||
if (!this.activated) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
`fab-button-close-active`
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* Get the show class for fab buttons
|
||||
*/
|
||||
getFabShowClassList() {
|
||||
if (!this.show) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
`fab-button-show`
|
||||
];
|
||||
}
|
||||
|
||||
render() {
|
||||
const themedClasses = createThemedClasses(this.mode, this.color, 'fab-button');
|
||||
const translucentClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'fab-button-translucent') : {};
|
||||
const hostClasses = getElementClassObject(this.el.classList);
|
||||
|
||||
const elementClasses: CssClassMap = []
|
||||
.concat(
|
||||
this.getFabListClassList(),
|
||||
this.getFabActiveClassList(),
|
||||
this.getFabShowClassList()
|
||||
)
|
||||
.reduce((prevValue, cssClass) => {
|
||||
prevValue[cssClass] = true;
|
||||
return prevValue;
|
||||
}, {});
|
||||
|
||||
const TagType = this.href ? 'a' : 'button';
|
||||
|
||||
const fabClasses = {
|
||||
...themedClasses,
|
||||
...translucentClasses,
|
||||
...hostClasses,
|
||||
...elementClasses
|
||||
};
|
||||
|
||||
return (
|
||||
<TagType class={fabClasses} onClick={this.clickedFab.bind(this)} disabled={this.disabled}>
|
||||
<ion-icon name='close' class='fab-button-close-icon'></ion-icon>
|
||||
<span class='button-inner'>
|
||||
<slot></slot>
|
||||
</span>
|
||||
<div class='button-effect'></div>
|
||||
</TagType>
|
||||
);
|
||||
}
|
||||
}
|
13
packages/core/src/components/fab-button/fab-button.vars.scss
Executable file
13
packages/core/src/components/fab-button/fab-button.vars.scss
Executable file
@ -0,0 +1,13 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
|
||||
// Floating Action Buttons
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - Width and height of the FAB button
|
||||
$fab-size: 56px !default;
|
||||
|
||||
/// @prop - Width and height of the mini FAB button
|
||||
$fab-mini-size: 40px !default;
|
||||
|
||||
/// @prop - Background color of the button in a list
|
||||
$fab-list-button-background-color: #f4f4f4 !default;
|
126
packages/core/src/components/fab-button/readme.md
Normal file
126
packages/core/src/components/fab-button/readme.md
Normal file
@ -0,0 +1,126 @@
|
||||
# ion-fab-button
|
||||
|
||||
Floating Action Buttons (FABs) represent the primary action in an application. By default, they have a circular shape. When pressed, the button may open more related actions. As the name suggests, FABs generally float over the content in a fixed position. This is not achieved exclusively by using an `<ion-fab-button>FAB</ion-fab-button>`. They need to be wrapped with an `<ion-fab>` component in order to be fixed over the content:
|
||||
|
||||
```html
|
||||
<ion-content>
|
||||
<!-- Fixed Floating Action Button that does not scroll with the content -->
|
||||
<ion-fab>
|
||||
<ion-fab-button>Button</ion-fab-button>
|
||||
</ion-fab>
|
||||
|
||||
<!-- Default Floating Action Button that scrolls with the content.-->
|
||||
<ion-fab-button>Button</ion-fab-button>
|
||||
</ion-content>
|
||||
```
|
||||
|
||||
If the FAB button is not wrapped with `<ion-fab>`, it will scroll with the content. FAB buttons have a default size, a mini size and can accept different colors:
|
||||
|
||||
```html
|
||||
<ion-content>
|
||||
<ion-fab-button>Default</ion-fab-button>
|
||||
|
||||
<!-- Mini -->
|
||||
<ion-fab-button mini>Mini</ion-fab-button>
|
||||
|
||||
<!-- Colors -->
|
||||
<ion-fab-button color="primary">Primary</ion-fab-button>
|
||||
<ion-fab-button color="secondary">Secondary</ion-fab-button>
|
||||
<ion-fab-button color="danger">Danger</ion-fab-button>
|
||||
<ion-fab-button color="light">Light</ion-fab-button>
|
||||
<ion-fab-button color="dark">Dark</ion-fab-button>
|
||||
</ion-content>
|
||||
```
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
#### activated
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### color
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### disabled
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### href
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### show
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### toggleActive
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### translucent
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
## Attributes
|
||||
|
||||
#### activated
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### color
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### disabled
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### href
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### show
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### toggleActive
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### translucent
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built by [StencilJS](https://stenciljs.com/)*
|
@ -1,39 +0,0 @@
|
||||
import { Component, Element, Method, State } from '@stencil/core';
|
||||
|
||||
|
||||
@Component({
|
||||
tag: 'ion-fab',
|
||||
})
|
||||
export class FabContainer {
|
||||
@Element() private el: HTMLElement;
|
||||
|
||||
@State() activated = false;
|
||||
|
||||
/**
|
||||
* Close an active FAB list container
|
||||
*/
|
||||
@Method()
|
||||
close() {
|
||||
this.activated = false;
|
||||
}
|
||||
|
||||
toggleActive = () => {
|
||||
this.activated = !this.activated;
|
||||
}
|
||||
|
||||
render() {
|
||||
const fab: any = this.el.querySelector('ion-fab-button');
|
||||
fab.toggleActive = this.toggleActive;
|
||||
fab.activated = this.activated;
|
||||
|
||||
const lists = this.el.querySelectorAll('ion-fab-list');
|
||||
for (let i = 0, length = lists.length; i < length; i += 1) {
|
||||
lists[i].activated = this.activated;
|
||||
}
|
||||
|
||||
return (
|
||||
<slot></slot>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
# ion-fab
|
||||
|
||||
`<ion-fab>` is not a FAB button by itself but a container that assist the fab button (`<button ion-fab>`) allowing it
|
||||
to be placed in fixed position that does not scroll with the content. It is also used to implement "material design speed dial",
|
||||
ie. a FAB buttons displays a small lists of related actions when clicked.
|
||||
|
||||
|
||||
```
|
||||
[top] - Places the container on the top of the content
|
||||
[bottom] - Places the container on the bottom of the content
|
||||
[left] - Places the container on the left
|
||||
[right] - Places the container on the right
|
||||
[middle] - Places the container on the middle vertically
|
||||
[center] - Places the container on the center horizontally
|
||||
[edge] - Used to place the container between the content and the header/footer
|
||||
```
|
||||
|
||||
|
||||
```html
|
||||
<!-- this fab is placed at top right -->
|
||||
<ion-content>
|
||||
<ion-fab top right>
|
||||
<button ion-fab>Button</button>
|
||||
</ion-fab>
|
||||
|
||||
<!-- this fab is placed at the center of the content viewport -->
|
||||
<ion-fab center middle>
|
||||
<button ion-fab>Button</button>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
```
|
||||
|
||||
Ionic's FAB also supports "material design's fab speed dial". It is a normal fab button
|
||||
that shows a list of related actions when clicked.
|
||||
|
||||
The same `ion-fab` container can contain several `ion-fab-list` with different side values:
|
||||
`top`, `bottom`, `left` and `right`. For example, if you want to have a list of button that are
|
||||
on the top of the main button, you should use `side="top"` and so on. By default, if side is ommited, `side="bottom"`.
|
||||
|
||||
|
||||
```html
|
||||
<ion-content>
|
||||
<!-- this fab is placed at bottom right -->
|
||||
<ion-fab bottom right >
|
||||
<button ion-fab>Share</button>
|
||||
<ion-fab-list side="top">
|
||||
<button ion-fab>Facebook</button>
|
||||
<button ion-fab>Twitter</button>
|
||||
<button ion-fab>Youtube</button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="left">
|
||||
<button ion-fab>Vimeo</button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
```
|
||||
|
||||
A FAB speed dial can also be closed programatically.
|
||||
|
||||
```html
|
||||
<ion-content>
|
||||
<ion-fab bottom right #fab>
|
||||
<button ion-fab>Share</button>
|
||||
<ion-fab-list side="top">
|
||||
<button ion-fab (click)="share('facebook', fab)">Facebook</button>
|
||||
<button ion-fab (click)="share('twitter', fab)">Twitter</button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
```
|
||||
|
||||
```ts
|
||||
share(socialNet: string, fab: FabContainer) {
|
||||
fab.close();
|
||||
console.log("Sharing in", socialNet);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
#### close()
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built by [StencilJS](https://stenciljs.com/)*
|
65
packages/core/src/components/fab-list/fab-list.scss
Normal file
65
packages/core/src/components/fab-list/fab-list.scss
Normal file
@ -0,0 +1,65 @@
|
||||
@import './fab-list.vars';
|
||||
|
||||
// Floating Action Button List
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-fab-list {
|
||||
@include margin($fab-size + $fab-list-margin, 0);
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
display: none;
|
||||
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
min-width: $fab-size;
|
||||
min-height: $fab-size;
|
||||
}
|
||||
|
||||
.fab-list-active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.fab-button-in-list {
|
||||
@include margin(8px, 0);
|
||||
|
||||
width: $fab-mini-size;
|
||||
height: $fab-mini-size;
|
||||
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.fab-button-in-list.fab-button-show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
ion-fab-list[side=left] .fab-button-in-list,
|
||||
ion-fab-list[side=right] .fab-button-in-list {
|
||||
@include margin(0, 8px);
|
||||
}
|
||||
|
||||
ion-fab-list[side=top] {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
ion-fab-list[side=left] {
|
||||
@include margin(0, $fab-size + $fab-list-margin);
|
||||
@include position-horizontal(null, 0);
|
||||
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
ion-fab-list[side=right] {
|
||||
@include margin(0, $fab-size + $fab-list-margin);
|
||||
@include position(null, null, null, 0);
|
||||
|
||||
flex-direction: row;
|
||||
}
|
@ -3,6 +3,7 @@ import { Component, Element, Prop, PropDidChange } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-fab-list',
|
||||
styleUrl: 'fab-list.scss'
|
||||
})
|
||||
export class FabList {
|
||||
@Element() private el: HTMLIonFabElement;
|
||||
|
9
packages/core/src/components/fab-list/fab-list.vars.scss
Normal file
9
packages/core/src/components/fab-list/fab-list.vars.scss
Normal file
@ -0,0 +1,9 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
|
||||
@import "../fab-button/fab-button.vars";
|
||||
|
||||
// Floating Action Button List
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - Margin of the FAB List
|
||||
$fab-list-margin: 10px !default;
|
@ -1,19 +1,26 @@
|
||||
# ion-fab-list
|
||||
|
||||
`ion-fab-list` is a container for multiple FAB buttons. They are components of `ion-fab` and allow you to specificy the buttons position, left, right, top, bottom.
|
||||
The `ion-fab-list` element is a container for multiple FAB buttons. This collection of FAB buttons contains actions related to the main FAB button and is flung out on click. To specify the side of the main button to show the list on, use the following:
|
||||
|
||||
```
|
||||
[top] - Show the list of buttons above the main FAB button
|
||||
[bottom] - Show the list of buttons under the main FAB button
|
||||
[left] - Show the list of buttons to the left of the main FAB button
|
||||
[right] - Show the list of buttons to the right of the main FAB button
|
||||
```
|
||||
|
||||
```html
|
||||
<ion-fab bottom right>
|
||||
<button ion-fab>Share</button>
|
||||
<ion-fab-list side="top">
|
||||
<button ion-fab>Facebook</button>
|
||||
<button ion-fab>Twitter</button>
|
||||
<button ion-fab>Youtube</button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="left">
|
||||
<button ion-fab>Vimeo</button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
<ion-fab bottom right>
|
||||
<ion-fab-button>Share</ion-fab-button>
|
||||
<ion-fab-list side="top">
|
||||
<ion-fab-button>Facebook</ion-fab-button>
|
||||
<ion-fab-button>Twitter</ion-fab-button>
|
||||
<ion-fab-button>Youtube</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="left">
|
||||
<ion-fab-button>Vimeo</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
```
|
||||
|
||||
|
||||
|
163
packages/core/src/components/fab/fab.scss
Executable file → Normal file
163
packages/core/src/components/fab/fab.scss
Executable file → Normal file
@ -1,57 +1,6 @@
|
||||
@import "./fab.vars";
|
||||
|
||||
// Floating Action Buttons
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab {
|
||||
@include text-align(center);
|
||||
@include appearance(none);
|
||||
@include border-radius(50%);
|
||||
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
|
||||
width: $fab-size;
|
||||
height: $fab-size;
|
||||
|
||||
font-size: 14px;
|
||||
line-height: $fab-size;
|
||||
text-overflow: ellipsis;
|
||||
text-transform: none;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: background-color, opacity 100ms linear;
|
||||
|
||||
background-clip: padding-box;
|
||||
font-kerning: none;
|
||||
user-select: none;
|
||||
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
.fab ion-icon {
|
||||
flex: 1;
|
||||
|
||||
font-size: 2.4rem;
|
||||
line-height: 1.8rem;
|
||||
}
|
||||
|
||||
// FAB Mini
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-fab-button[mini] .fab {
|
||||
@include margin(($fab-size - $fab-mini-size) / 2);
|
||||
|
||||
width: $fab-mini-size;
|
||||
height: $fab-mini-size;
|
||||
|
||||
line-height: $fab-mini-size;
|
||||
}
|
||||
|
||||
|
||||
// FAB Container
|
||||
// Floating Action Button Container
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-fab {
|
||||
@ -120,113 +69,3 @@ ion-fab {
|
||||
bottom: -$fab-size / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FAB List (Speed Dial)
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-fab-list {
|
||||
@include margin($fab-size + $fab-list-margin, 0);
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
display: none;
|
||||
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
min-width: $fab-size;
|
||||
min-height: $fab-size;
|
||||
}
|
||||
|
||||
.fab-in-list {
|
||||
@include margin(8px, 0);
|
||||
|
||||
width: $fab-mini-size;
|
||||
height: $fab-mini-size;
|
||||
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.fab-in-list.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
ion-fab-list[side=left] .fab-in-list,
|
||||
ion-fab-list[side=right] .fab-in-list {
|
||||
@include margin(0, 8px);
|
||||
}
|
||||
|
||||
ion-fab-list[side=top] {
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
ion-fab-list[side=left] {
|
||||
@include margin(0, $fab-size + $fab-list-margin);
|
||||
@include position-horizontal(null, 0);
|
||||
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
ion-fab-list[side=right] {
|
||||
@include margin(0, $fab-size + $fab-list-margin);
|
||||
@include position(null, null, null, 0);
|
||||
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
|
||||
// FAB Close Icon
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-close-icon {
|
||||
@include position(0, 0, null, 0);
|
||||
|
||||
position: absolute;
|
||||
|
||||
height: 100%;
|
||||
|
||||
opacity: 0;
|
||||
transform: scale(.4) rotateZ(-45deg);
|
||||
transition: all ease-in-out 300ms;
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.fab-close-icon .icon-inner {
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
// FAB Animation
|
||||
// --------------------------------------------------
|
||||
|
||||
.fab-list-active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.fab .button-inner {
|
||||
transition: all ease-in-out 300ms;
|
||||
transition-property: transform, opacity;
|
||||
}
|
||||
|
||||
.fab-close-active .fab-close-icon {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotateZ(0deg);
|
||||
}
|
||||
|
||||
.fab-close-active .button-inner {
|
||||
opacity: 0;
|
||||
transform: scale(.4) rotateZ(45deg);
|
||||
}
|
||||
|
149
packages/core/src/components/fab/fab.tsx
Executable file → Normal file
149
packages/core/src/components/fab/fab.tsx
Executable file → Normal file
@ -1,149 +1,40 @@
|
||||
import { Component, CssClassMap, Element, Prop, State } from '@stencil/core';
|
||||
import { createThemedClasses, getElementClassObject } from '../../utils/theme';
|
||||
import { Component, Element, Method, State } from '@stencil/core';
|
||||
|
||||
|
||||
@Component({
|
||||
tag: 'ion-fab-button',
|
||||
styleUrls: {
|
||||
ios: 'fab.ios.scss',
|
||||
md: 'fab.md.scss'
|
||||
}
|
||||
tag: 'ion-fab',
|
||||
styleUrl: 'fab.scss'
|
||||
})
|
||||
export class FabButton {
|
||||
export class Fab {
|
||||
@Element() private el: HTMLElement;
|
||||
|
||||
/**
|
||||
* @input {string} The color to use from your Sass `$colors` map.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"danger"`, `"light"`, and `"dark"`.
|
||||
* For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
*/
|
||||
@Prop() color: string;
|
||||
@State() activated = false;
|
||||
|
||||
/**
|
||||
* @input {string} The mode determines which platform styles to use.
|
||||
* Possible values are: `"ios"` or `"md"`.
|
||||
* For more information, see [Platform Styles](/docs/theming/platform-specific-styles).
|
||||
* Close an active FAB list container
|
||||
*/
|
||||
@Prop() mode: 'ios' | 'md';
|
||||
|
||||
/**
|
||||
* @input {string} Contains a URL or a URL fragment that the hyperlink points to.
|
||||
* If this property is set, an anchor tag will be rendered.
|
||||
*/
|
||||
@Prop() href: string;
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, adds transparency to the fab.
|
||||
* Only affects `ios` mode. Defaults to `false`.
|
||||
*/
|
||||
@Prop() translucent: boolean = false;
|
||||
|
||||
@Prop() activated: boolean = false;
|
||||
@Prop() toggleActive: Function = () => {};
|
||||
|
||||
@Prop() show: boolean = false;
|
||||
|
||||
@State() private inContainer: boolean = false;
|
||||
@State() private inList: boolean = false;
|
||||
|
||||
/**
|
||||
* @input {boolean} If true, sets the button into a disabled state.
|
||||
*/
|
||||
@Prop() disabled: boolean = false;
|
||||
|
||||
componentDidLoad() {
|
||||
const parentNode = this.el.parentNode.nodeName;
|
||||
|
||||
this.inList = (parentNode === 'ION-FAB-LIST');
|
||||
this.inContainer = (parentNode === 'ION-FAB');
|
||||
@Method()
|
||||
close() {
|
||||
this.activated = false;
|
||||
}
|
||||
|
||||
|
||||
clickedFab() {
|
||||
if (this.inContainer) {
|
||||
this.toggleActive();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* Get the classes for fab buttons in lists
|
||||
*/
|
||||
getFabListClassList() {
|
||||
if (!this.inList) {
|
||||
return [];
|
||||
}
|
||||
let listClasses = [
|
||||
`fab-in-list`,
|
||||
`fab-${this.mode}-in-list`
|
||||
];
|
||||
|
||||
if (this.translucent) {
|
||||
listClasses.push(`fab-translucent-${this.mode}-in-list`);
|
||||
}
|
||||
|
||||
return listClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* Get the close active class for fab buttons
|
||||
*/
|
||||
getFabActiveClassList() {
|
||||
if (!this.activated) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
`fab-close-active`
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @hidden
|
||||
* Get the show class for fab buttons
|
||||
*/
|
||||
getFabShowClassList() {
|
||||
if (!this.show) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
`show`
|
||||
];
|
||||
toggleActive = () => {
|
||||
this.activated = !this.activated;
|
||||
}
|
||||
|
||||
render() {
|
||||
const themedClasses = createThemedClasses(this.mode, this.color, 'fab');
|
||||
const translucentClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'fab-translucent') : {};
|
||||
const hostClasses = getElementClassObject(this.el.classList);
|
||||
const fab: any = this.el.querySelector('ion-fab-button');
|
||||
fab.toggleActive = this.toggleActive;
|
||||
fab.activated = this.activated;
|
||||
|
||||
const elementClasses: CssClassMap = []
|
||||
.concat(
|
||||
this.getFabListClassList(),
|
||||
this.getFabActiveClassList(),
|
||||
this.getFabShowClassList()
|
||||
)
|
||||
.reduce((prevValue, cssClass) => {
|
||||
prevValue[cssClass] = true;
|
||||
return prevValue;
|
||||
}, {});
|
||||
|
||||
const TagType = this.href ? 'a' : 'button';
|
||||
|
||||
const fabClasses = {
|
||||
...themedClasses,
|
||||
...translucentClasses,
|
||||
...hostClasses,
|
||||
...elementClasses
|
||||
};
|
||||
const lists = this.el.querySelectorAll('ion-fab-list');
|
||||
for (let i = 0, length = lists.length; i < length; i += 1) {
|
||||
lists[i].activated = this.activated;
|
||||
}
|
||||
|
||||
return (
|
||||
<TagType class={fabClasses} onClick={this.clickedFab.bind(this)} disabled={this.disabled}>
|
||||
<ion-icon name='close' class='fab-close-icon'></ion-icon>
|
||||
<span class='button-inner'>
|
||||
<slot></slot>
|
||||
</span>
|
||||
<div class='button-effect'></div>
|
||||
</TagType>
|
||||
<slot></slot>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
16
packages/core/src/components/fab/fab.vars.scss
Executable file → Normal file
16
packages/core/src/components/fab/fab.vars.scss
Executable file → Normal file
@ -1,19 +1,9 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
|
||||
// Floating Action Buttons
|
||||
@import "../fab-button/fab-button.vars";
|
||||
|
||||
// Floating Action Button Container
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - Width and height of the FAB button
|
||||
$fab-size: 56px !default;
|
||||
|
||||
/// @prop - Width and height of the mini FAB button
|
||||
$fab-mini-size: 40px !default;
|
||||
|
||||
/// @prop - Margin of the FAB Container
|
||||
$fab-content-margin: 10px !default;
|
||||
|
||||
/// @prop - Margin of the FAB List
|
||||
$fab-list-margin: 10px !default;
|
||||
|
||||
/// @prop - Background color of the button in a list
|
||||
$fab-list-button-background-color: #f4f4f4 !default;
|
||||
|
@ -1,121 +1,62 @@
|
||||
# ion-fab
|
||||
|
||||
FABs (Floating Action Buttons) are standard material design components. They are shaped as a circle that represents a promoted action. When pressed, it may contain more related actions.
|
||||
FABs as its name suggests are floating over the content in a fixed position. This is not achieved exclusively with `<button ion-fab>Button</button>` but it has to wrapped with the `<ion-fab>` component, like this:
|
||||
The `<ion-fab>` element is a container element that places the FAB button (`<ion-fab-button>`) in a fixed position that does not scroll with the content. It is also used to display a list of FAB buttons. It accepts the following attributes to position the FAB button element with respect to the content:
|
||||
|
||||
```
|
||||
[top] - Places the container at the top of the content
|
||||
[bottom] - Places the container at the bottom of the content
|
||||
[left] - Places the container on the left
|
||||
[right] - Places the container on the right
|
||||
[middle] - Places the container in the middle vertically
|
||||
[center] - Places the container in the center horizontally
|
||||
[edge] - Used to place the container between the content and the header/footer
|
||||
```
|
||||
|
||||
|
||||
```html
|
||||
<!-- this fab is placed at the top right -->
|
||||
<ion-content>
|
||||
<!-- Real floating action button, fixed. It will not scroll with the content -->
|
||||
<ion-fab>
|
||||
<button ion-fab>Button</button>
|
||||
</ion-fab>
|
||||
<ion-fab top right>
|
||||
<ion-fab-button>Button</ion-fab-button>
|
||||
</ion-fab>
|
||||
|
||||
<!-- Button shaped as a circle that just like a normal button scrolls with the content -->
|
||||
<button ion-fab>Button</button>
|
||||
<!-- this fab is placed at the center of the content -->
|
||||
<ion-fab center middle>
|
||||
<ion-fab-button>Button</ion-fab-button>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
```
|
||||
|
||||
In case the button is not wrapped with `<ion-fab>`, the fab button will behave like a normal button, scrolling with the content.
|
||||
Ionic's FAB also supports FAB lists. This is a list of related buttons that show when the main FAB button is clicked.
|
||||
|
||||
The same `ion-fab` container can contain several `ion-fab-list` elements with different side values:
|
||||
`top`, `bottom`, `left` and `right`. If side is ommited, the default is `bottom`.
|
||||
|
||||
|
||||
```html
|
||||
|
||||
<!-- Colors -->
|
||||
<ion-fab>
|
||||
<button ion-fab color="primary">Button</button>
|
||||
</ion-fab>
|
||||
|
||||
<!-- Mini -->
|
||||
<ion-fab>
|
||||
<button ion-fab mini>Small</button>
|
||||
</ion-fab>
|
||||
<ion-content>
|
||||
<!-- this fab is placed at bottom right -->
|
||||
<ion-fab bottom right>
|
||||
<ion-fab-button>Share</ion-fab-button>
|
||||
<ion-fab-list side="top">
|
||||
<ion-fab-button>Facebook</ion-fab-button>
|
||||
<ion-fab-button>Twitter</ion-fab-button>
|
||||
<ion-fab-button>Youtube</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
<ion-fab-list side="left">
|
||||
<ion-fab-button>Vimeo</ion-fab-button>
|
||||
</ion-fab-list>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
```
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
## Properties
|
||||
## Methods
|
||||
|
||||
#### activated
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### color
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### disabled
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### href
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### show
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### toggleActive
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### translucent
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
## Attributes
|
||||
|
||||
#### activated
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### color
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### disabled
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### href
|
||||
|
||||
string
|
||||
|
||||
|
||||
#### mode
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### show
|
||||
|
||||
boolean
|
||||
|
||||
|
||||
#### toggleActive
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### translucent
|
||||
|
||||
boolean
|
||||
#### close()
|
||||
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
<pre id="log" style="right:10px; bottom:50px; text-shadow: 0 0 2px rgba(0, 0, 0, 0.24);" slot="fixed">log</pre>
|
||||
<ion-button>Test</ion-button>
|
||||
<ion-fab-button>FAB</ion-fab-button>
|
||||
|
||||
<ion-fab top right edge id="fab1" slot="fixed">
|
||||
<ion-fab-button onclick="clickMainFAB('fab1')" mini class="e2eFabTopRight"><ion-icon name="add"></ion-icon></ion-fab-button>
|
||||
|
4
packages/core/src/index.d.ts
vendored
4
packages/core/src/index.d.ts
vendored
@ -26,9 +26,9 @@ export { ChipButton } from './components/chip-button/chip-button';
|
||||
export { Column } from './components/col/col';
|
||||
export { Content } from './components/content/content';
|
||||
export { Datetime } from './components/datetime/datetime';
|
||||
export { FabContainer } from './components/fab-container/fab-container';
|
||||
export { Fab } from './components/fab/fab';
|
||||
export { FabList } from './components/fab-list/fab-list';
|
||||
export { FabButton } from './components/fab/fab';
|
||||
export { FabButton } from './components/fab-button/fab-button';
|
||||
export { Footer } from './components/footer/footer';
|
||||
export { Gesture, GestureCallback, GestureDetail } from './components/gesture/gesture';
|
||||
export { PanRecognizer } from './components/gesture/recognizers';
|
||||
|
@ -14,7 +14,8 @@ exports.config = {
|
||||
{ components: ['ion-checkbox'] },
|
||||
{ components: ['ion-chip', 'ion-chip-button'] },
|
||||
{ components: ['ion-datetime', 'ion-picker', 'ion-picker-column', 'ion-picker-controller'] },
|
||||
{ components: ['ion-fab', 'ion-fab-button', 'ion-fab-list'] },
|
||||
{ components: ['ion-fab', 'ion-fab-list'] },
|
||||
{ components: ['ion-fab-button'] },
|
||||
{ components: ['ion-gesture'], priority: 'low' },
|
||||
{ components: ['ion-grid', 'ion-row', 'ion-col'] },
|
||||
{ components: ['ion-item', 'ion-item-divider', 'ion-label', 'ion-list', 'ion-list-header', 'ion-skeleton-text'] },
|
||||
|
Reference in New Issue
Block a user