first commit
This commit is contained in:
37
uni_modules/tdesign-uniapp/components/fab/README.en-US.md
Normal file
37
uni_modules/tdesign-uniapp/components/fab/README.en-US.md
Normal file
@@ -0,0 +1,37 @@
|
||||
:: BASE_DOC ::
|
||||
|
||||
## API
|
||||
|
||||
### Fab Props
|
||||
|
||||
name | type | default | description | required
|
||||
-- | -- | -- | -- | --
|
||||
custom-style | Object | - | CSS(Cascading Style Sheets) | N
|
||||
button-props | Object | - | Typescript:`ButtonProps`,[Button API Documents](./button?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/fab/type.ts) | N
|
||||
draggable | String / Boolean | false | Typescript:`boolean \| FabDirectionEnum ` `type FabDirectionEnum = 'all' \| 'vertical' \| 'horizontal'`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/fab/type.ts) | N
|
||||
icon | String | - | \- | N
|
||||
style | String | right: 16px; bottom: 32px; | \- | N
|
||||
text | String | - | \- | N
|
||||
using-custom-navbar | Boolean | false | \- | N
|
||||
y-bounds | Array | - | Typescript:`Array<string \| number>` | N
|
||||
|
||||
### Fab Events
|
||||
|
||||
name | params | description
|
||||
-- | -- | --
|
||||
click | `(context: {e: Event})` | \-
|
||||
drag-end | `(context: { e: TouchEvent })` | \-
|
||||
drag-start | `(context: { e: TouchEvent })` | \-
|
||||
|
||||
### Fab Slots
|
||||
|
||||
name | Description
|
||||
-- | --
|
||||
\- | \-
|
||||
|
||||
### CSS Variables
|
||||
|
||||
The component provides the following CSS variables, which can be used to customize styles.
|
||||
Name | Default Value | Description
|
||||
-- | -- | --
|
||||
--td-fab-shadow | @shadow-2 | -
|
||||
81
uni_modules/tdesign-uniapp/components/fab/README.md
Normal file
81
uni_modules/tdesign-uniapp/components/fab/README.md
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Fab 悬浮按钮
|
||||
description: 当功能使用图标即可表意清楚时,可使用纯图标悬浮按钮,例如:添加、发布。
|
||||
spline: form
|
||||
isComponent: true
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 引入
|
||||
|
||||
可在 `main.ts` 或在需要使用的页面或组件中引入。
|
||||
|
||||
```js
|
||||
import TFab from '@tdesign/uniapp/fab/fab.vue';
|
||||
```
|
||||
|
||||
### 基础使用
|
||||
|
||||
{{ base }}
|
||||
|
||||
### 进阶使用
|
||||
|
||||
{{ advance }}
|
||||
|
||||
### 可移动悬浮按钮
|
||||
|
||||
{{ draggable }}
|
||||
|
||||
### 带自动收缩功能
|
||||
|
||||
{{ collapsible }}
|
||||
|
||||
## FAQ
|
||||
|
||||
### 为什么通过 style/customStyle 设置 top/left 调整初试定位后,会使页面内容无法点击以及拖拽异常?
|
||||
|
||||
由于 `position: fixed;` 会使得元素脱离文档流,它将悬浮于页面上方。同时,元素没有设置宽高,当同时使用 `top`、`right`、`bottom` 和 `left` 属性时,浏览器会根据给定的 `top`、`right`、`bottom` 和 `left` 创建一个矩形框来容纳元素及其内容,所以会出现元素覆盖页面内容及拖拽异常等问题。
|
||||
|
||||
Fab 组件默认定位 `right: 16px; bottom: 32px;`,且拖拽功能也是通过调整 `right` 与 `bottom` 属性值实现,因此在使用 `Fab` 组件时,仅支持通过 `style/customStyle` 属性设置 `right/bottom` 来调整初试位置, 避免使用 `top/left`。
|
||||
|
||||
### 开启 Skyline 渲染引擎后,组件所在页面崩溃?
|
||||
|
||||
因为 Skyline 还不支持多层阴影,要等微信官方处理。当下可参考 [#2865](https://github.com/Tencent/tdesign-miniprogram/issues/2865) 进行规避处理
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### Fab Props
|
||||
|
||||
名称 | 类型 | 默认值 | 描述 | 必传
|
||||
-- | -- | -- | -- | --
|
||||
custom-style | Object | - | 自定义样式 | N
|
||||
button-props | Object | - | 透传至 Button 组件。TS 类型:`ButtonProps`,[Button API Documents](./button?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/fab/type.ts) | N
|
||||
draggable | String / Boolean | false | 是否可拖拽。`true` / `'all'`可拖动<br>`'vertical'`可垂直拖动<br>`'horizontal'`可水平拖动<br>`false`禁止拖动。TS 类型:`boolean \| FabDirectionEnum ` `type FabDirectionEnum = 'all' \| 'vertical' \| 'horizontal'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/fab/type.ts) | N
|
||||
icon | String | - | 图标 | N
|
||||
style | String | right: 16px; bottom: 32px; | 悬浮按钮的样式,常用于调整位置(即将废弃,建议使用 `style`) | N
|
||||
text | String | - | 文本内容 | N
|
||||
using-custom-navbar | Boolean | false | 是否使用了自定义导航栏 | N
|
||||
y-bounds | Array | - | 设置垂直方向边界限制,示例:[48, 48] 或 ['96px', 80]。TS 类型:`Array<string \| number>` | N
|
||||
|
||||
### Fab Events
|
||||
|
||||
名称 | 参数 | 描述
|
||||
-- | -- | --
|
||||
click | `(context: {e: Event})` | 悬浮按钮点击事件
|
||||
drag-end | `(context: { e: TouchEvent })` | 结束拖拽时触发
|
||||
drag-start | `(context: { e: TouchEvent })` | 开始拖拽时触发
|
||||
|
||||
### Fab Slots
|
||||
|
||||
名称 | 描述
|
||||
-- | --
|
||||
\- | 默认插槽,按钮内容
|
||||
|
||||
### CSS Variables
|
||||
|
||||
组件提供了下列 CSS 变量,可用于自定义样式。
|
||||
名称 | 默认值 | 描述
|
||||
-- | -- | --
|
||||
--td-fab-shadow | @shadow-2 | -
|
||||
9
uni_modules/tdesign-uniapp/components/fab/fab.css
Normal file
9
uni_modules/tdesign-uniapp/components/fab/fab.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.t-fab {
|
||||
position: fixed;
|
||||
}
|
||||
.t-fab__button {
|
||||
box-shadow: var(--td-fab-shadow, var(--td-shadow-2, 0 3px 14px 2px rgba(0, 0, 0, 0.05), 0 8px 10px 1px rgba(0, 0, 0, 0.06), 0 5px 5px -3px rgba(0, 0, 0, 0.1)));
|
||||
}
|
||||
.t-fab__draggable {
|
||||
position: fixed;
|
||||
}
|
||||
238
uni_modules/tdesign-uniapp/components/fab/fab.vue
Normal file
238
uni_modules/tdesign-uniapp/components/fab/fab.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<t-draggable
|
||||
v-if="draggable"
|
||||
ref="draggable"
|
||||
:custom-style="tools._style(['right: 16px; bottom: 32px;', customStyle, moveStyle])"
|
||||
:direction="draggable === true ? 'all' : draggable"
|
||||
:t-class="tClass"
|
||||
@start="onStart"
|
||||
@move="onMove"
|
||||
@end="onEnd"
|
||||
>
|
||||
<slot v-if="!buttonData.content && !buttonData.icon" />
|
||||
<block
|
||||
v-else
|
||||
name="button"
|
||||
>
|
||||
<t-button
|
||||
:t-id="buttonData.tId"
|
||||
:custom-style="buttonData.style || ''"
|
||||
:block="buttonData.block"
|
||||
:class="getActionClass(classPrefix, buttonData.buttonLayout) || ''"
|
||||
:t-class="buttonData.tClass"
|
||||
:disabled="buttonData.disabled"
|
||||
:data-type="'action'"
|
||||
:data-extra="buttonData.index"
|
||||
:custom-dataset="buttonData.customDataset"
|
||||
:content="buttonData.content"
|
||||
:icon="buttonData.icon"
|
||||
:loading="buttonData.loading"
|
||||
:loading-props="buttonData.loadingProps"
|
||||
:theme="buttonData.theme"
|
||||
:ghost="buttonData.ghost"
|
||||
:shape="buttonData.shape"
|
||||
:size="buttonData.size"
|
||||
:variant="buttonData.variant"
|
||||
:open-type="buttonData.openType"
|
||||
:hover-class="buttonData.hoverClass"
|
||||
:hover-stop-propagation="buttonData.hoverStopPropagation"
|
||||
:hover-start-time="buttonData.hoverStartTime"
|
||||
:hover-stay-time="buttonData.hoverStayTime"
|
||||
:lang="buttonData.lang"
|
||||
:session-from="buttonData.sessionFrom"
|
||||
:send-message-title="buttonData.sendMessageTitle"
|
||||
:send-message-path="buttonData.sendMessagePath"
|
||||
:send-message-img="buttonData.sendMessageImg"
|
||||
:app-parameter="buttonData.appParameter"
|
||||
:show-message-card="buttonData.showMessageCard"
|
||||
:aria-label="buttonData.ariaLabel"
|
||||
@click="onTplButtonTap"
|
||||
@getuserinfo="onTplButtonTap"
|
||||
@contact="onTplButtonTap"
|
||||
@getphonenumber="onTplButtonTap"
|
||||
@error="onTplButtonTap"
|
||||
@opensetting="onTplButtonTap"
|
||||
@launchapp="onTplButtonTap"
|
||||
@agreeprivacyauthorization="onTplButtonTap"
|
||||
>
|
||||
<slot v-if="true || false" />
|
||||
</t-button>
|
||||
</block>
|
||||
</t-draggable>
|
||||
|
||||
<view
|
||||
v-else
|
||||
:class="[classPrefix, tClass]"
|
||||
:style="tools._style(['right: 16px; bottom: 32px;', customStyle])"
|
||||
>
|
||||
<slot v-if="!buttonData || !buttonData.content && !buttonData.icon" />
|
||||
<t-button
|
||||
v-else
|
||||
:t-id="buttonData.tId"
|
||||
:custom-style="buttonData.style || ''"
|
||||
:block="buttonData.block"
|
||||
:class="getActionClass(classPrefix, buttonData.buttonLayout) || ''"
|
||||
:t-class="buttonData.tClass"
|
||||
:disabled="buttonData.disabled"
|
||||
:data-type="'action'"
|
||||
:data-extra="buttonData.index"
|
||||
:custom-dataset="buttonData.customDataset"
|
||||
:content="buttonData.content"
|
||||
:icon="buttonData.icon"
|
||||
:loading="buttonData.loading"
|
||||
:loading-props="buttonData.loadingProps"
|
||||
:theme="buttonData.theme"
|
||||
:ghost="buttonData.ghost"
|
||||
:shape="buttonData.shape"
|
||||
:size="buttonData.size"
|
||||
:variant="buttonData.variant"
|
||||
:open-type="buttonData.openType"
|
||||
:hover-class="buttonData.hoverClass"
|
||||
:hover-stop-propagation="buttonData.hoverStopPropagation"
|
||||
:hover-start-time="buttonData.hoverStartTime"
|
||||
:hover-stay-time="buttonData.hoverStayTime"
|
||||
:lang="buttonData.lang"
|
||||
:session-from="buttonData.sessionFrom"
|
||||
:send-message-title="buttonData.sendMessageTitle"
|
||||
:send-message-path="buttonData.sendMessagePath"
|
||||
:send-message-img="buttonData.sendMessageImg"
|
||||
:app-parameter="buttonData.appParameter"
|
||||
:show-message-card="buttonData.showMessageCard"
|
||||
:aria-label="buttonData.ariaLabel"
|
||||
@click="onTplButtonTap"
|
||||
@getuserinfo="onTplButtonTap"
|
||||
@contact="onTplButtonTap"
|
||||
@getphonenumber="onTplButtonTap"
|
||||
@error="onTplButtonTap"
|
||||
@opensetting="onTplButtonTap"
|
||||
@launchapp="onTplButtonTap"
|
||||
@agreeprivacyauthorization="onTplButtonTap"
|
||||
>
|
||||
<slot />
|
||||
</t-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TButton from '../button/button';
|
||||
import TDraggable from '../draggable/draggable.vue';
|
||||
import { uniComponent } from '../common/src/index';
|
||||
import { prefix } from '../common/config';
|
||||
import props from './props';
|
||||
import useCustomNavbar from '../mixins/using-custom-navbar';
|
||||
import { unitConvert, getWindowInfo } from '../common/utils';
|
||||
import tools from '../common/utils.wxs';
|
||||
|
||||
const name = `${prefix}-fab`;
|
||||
|
||||
const baseButtonProps = {
|
||||
size: 'large',
|
||||
shape: 'circle',
|
||||
theme: 'primary',
|
||||
tClass: `${prefix}-fab__button`,
|
||||
};
|
||||
|
||||
export default uniComponent({
|
||||
name,
|
||||
options: {
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
externalClasses: [`${prefix}-class`, `${prefix}-class-button`],
|
||||
mixins: [useCustomNavbar],
|
||||
components: {
|
||||
TButton,
|
||||
TDraggable,
|
||||
},
|
||||
props: {
|
||||
...props,
|
||||
},
|
||||
emits: [
|
||||
'move',
|
||||
'start',
|
||||
'end',
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
prefix,
|
||||
classPrefix: name,
|
||||
moveStyle: null,
|
||||
tools,
|
||||
systemInfo: getWindowInfo(),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
buttonData() {
|
||||
return {
|
||||
...baseButtonProps,
|
||||
shape: this.text ? 'round' : 'circle',
|
||||
...this.buttonProps,
|
||||
icon: this.icon,
|
||||
content: this.text,
|
||||
ariaLabel: this.ariaLabel,
|
||||
};
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
icon: 'computedSize',
|
||||
ariaLabel: 'computedSize',
|
||||
yBounds: 'computedSize',
|
||||
buttonProps: 'computedSize',
|
||||
text: {
|
||||
handler(val) {
|
||||
this.content = val;
|
||||
this.computedSize();
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onTplButtonTap(e) {
|
||||
this.$emit('click', { e });
|
||||
},
|
||||
onStart(t) {
|
||||
this.$emit('drag-start', t);
|
||||
},
|
||||
onMove(e) {
|
||||
const {
|
||||
yBounds = [],
|
||||
distanceTop,
|
||||
systemInfo,
|
||||
} = this;
|
||||
|
||||
const { x, y, rect } = e;
|
||||
const maxX = systemInfo.windowWidth - rect.width; // 父容器宽度 - 拖动元素宽度
|
||||
const maxY = systemInfo.windowHeight - Math.max(distanceTop, unitConvert(yBounds[0])) - rect.height; // 父容器高度 - 拖动元素高度
|
||||
const right = Math.max(0, Math.min(x, maxX));
|
||||
const bottom = Math.max(0, unitConvert(yBounds[1]), Math.min(y, maxY));
|
||||
|
||||
|
||||
this.moveStyle = `right: ${right}px; bottom: ${bottom}px;`;
|
||||
},
|
||||
onEnd(t) {
|
||||
this.$emit('drag-end', t);
|
||||
},
|
||||
computedSize() {
|
||||
if (!this.draggable) return;
|
||||
|
||||
setTimeout(() => {
|
||||
const insChild = this.$refs.draggableTemplate?.$refs?.draggable;
|
||||
|
||||
|
||||
// button 更新时,重新获取其尺寸
|
||||
if (this?.yBounds?.[1]) {
|
||||
this.moveStyle = `bottom: ${unitConvert(this.yBounds[1])}px`;
|
||||
insChild?.computedRect();
|
||||
} else {
|
||||
insChild?.computedRect();
|
||||
}
|
||||
});
|
||||
},
|
||||
getActionClass(a, b) {
|
||||
return `${a}-${b}`;
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
@import './fab.css';
|
||||
</style>
|
||||
54
uni_modules/tdesign-uniapp/components/fab/props.ts
Normal file
54
uni_modules/tdesign-uniapp/components/fab/props.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
|
||||
* */
|
||||
|
||||
import type { TdFabProps } from './type';
|
||||
export default {
|
||||
/** 透传至 Button 组件 */
|
||||
buttonProps: {
|
||||
type: Object,
|
||||
},
|
||||
/** 是否可拖拽。`true` / `'all'`可拖动<br>`'vertical'`可垂直拖动<br>`'horizontal'`可水平拖动<br>`false`禁止拖动 */
|
||||
draggable: {
|
||||
type: [String, Boolean],
|
||||
default: false as TdFabProps['draggable'],
|
||||
},
|
||||
/** 图标 */
|
||||
icon: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/** 悬浮按钮的样式,常用于调整位置(即将废弃,建议使用 `style`) */
|
||||
style: {
|
||||
type: String,
|
||||
default: 'right: 16px; bottom: 32px;',
|
||||
},
|
||||
/** 文本内容 */
|
||||
text: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/** 是否使用了自定义导航栏 */
|
||||
usingCustomNavbar: Boolean,
|
||||
/** 设置垂直方向边界限制,示例:[48, 48] 或 ['96px', 80] */
|
||||
yBounds: {
|
||||
type: Array,
|
||||
},
|
||||
/** 悬浮按钮点击事件 */
|
||||
onClick: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
/** 结束拖拽时触发 */
|
||||
onDragEnd: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
/** 开始拖拽时触发 */
|
||||
onDragStart: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
};
|
||||
57
uni_modules/tdesign-uniapp/components/fab/type.ts
Normal file
57
uni_modules/tdesign-uniapp/components/fab/type.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
|
||||
* */
|
||||
|
||||
import type { TdButtonProps as ButtonProps } from '../button/type';
|
||||
|
||||
export interface TdFabProps {
|
||||
/**
|
||||
* 透传至 Button 组件
|
||||
*/
|
||||
buttonProps?: ButtonProps;
|
||||
/**
|
||||
* 是否可拖拽。`true` / `'all'`可拖动<br>`'vertical'`可垂直拖动<br>`'horizontal'`可水平拖动<br>`false`禁止拖动
|
||||
* @default false
|
||||
*/
|
||||
draggable?: boolean | FabDirectionEnum;
|
||||
/**
|
||||
* 图标
|
||||
* @default ''
|
||||
*/
|
||||
icon?: string;
|
||||
/**
|
||||
* 悬浮按钮的样式,常用于调整位置(即将废弃,建议使用 `style`)
|
||||
* @default right: 16px; bottom: 32px;
|
||||
*/
|
||||
style?: string;
|
||||
/**
|
||||
* 文本内容
|
||||
* @default ''
|
||||
*/
|
||||
text?: string;
|
||||
/**
|
||||
* 是否使用了自定义导航栏
|
||||
* @default false
|
||||
*/
|
||||
usingCustomNavbar?: boolean;
|
||||
/**
|
||||
* 设置垂直方向边界限制,示例:[48, 48] 或 ['96px', 80]
|
||||
*/
|
||||
yBounds?: Array<string | number>;
|
||||
/**
|
||||
* 悬浮按钮点击事件
|
||||
*/
|
||||
onClick?: (context: { e: Event }) => void;
|
||||
/**
|
||||
* 结束拖拽时触发
|
||||
*/
|
||||
onDragEnd?: (context: { e: TouchEvent }) => void;
|
||||
/**
|
||||
* 开始拖拽时触发
|
||||
*/
|
||||
onDragStart?: (context: { e: TouchEvent }) => void;
|
||||
}
|
||||
|
||||
export type FabDirectionEnum = 'all' | 'vertical' | 'horizontal';
|
||||
Reference in New Issue
Block a user