diff --git a/src/components/float-layout/index.jsx b/src/components/float-layout/index.jsx
new file mode 100644
index 0000000..ce424a9
--- /dev/null
+++ b/src/components/float-layout/index.jsx
@@ -0,0 +1,174 @@
+import classNames from 'classnames'
+import { handleTouchScroll } from '../../utils/common'
+
+export default {
+ name: 'FloatLayout',
+ props: {
+ title: {
+ type: String,
+ default: '',
+ },
+ isOpened: {
+ type: Boolean,
+ default: false,
+ },
+ scrollY: {
+ type: Boolean,
+ default: true,
+ },
+ scrollX: {
+ type: Boolean,
+ default: false,
+ },
+ scrollWithAnimation: {
+ type: Boolean,
+ default: false,
+ },
+ onClose: {
+ type: Function,
+ default: () => () => {},
+ },
+ onScroll: {
+ type: Function,
+ default: () => () => {},
+ },
+ onScrollToLower: {
+ type: Function,
+ default: () => () => {},
+ },
+ onScrollToUpper: {
+ type: Function,
+ default: () => () => {},
+ },
+ scrollTop: {
+ type: Number,
+ default: 0,
+ },
+ scrollLeft: {
+ type: Number,
+ default: 0,
+ },
+ upperThreshold: {
+ type: Number,
+ default: 0,
+ },
+ lowerThreshold: {
+ type: Number,
+ default: 0,
+ },
+ className: {
+ type: [String, Array],
+ default: '',
+ },
+ },
+ data() {
+ const { isOpened } = this
+ return {
+ state: {
+ _isOpened: isOpened,
+ },
+ }
+ },
+ watch: {
+ isOpened(val, oldVal) {
+ if (val !== oldVal) {
+ handleTouchScroll(val)
+ }
+ if (val !== this.state._isOpened) {
+ this.setState({
+ _isOpened: val,
+ })
+ }
+ },
+ },
+ methods: {
+ setState(newState, fn) {
+ const ks = Object.keys(newState)
+ if (Array.isArray(ks)) {
+ ks.forEach((k) => {
+ if (k in this.state) {
+ this.state[k] = newState[k]
+ }
+ })
+ }
+ this.$nextTick(() => {
+ typeof fn === 'function' && fn.call(this)
+ })
+ },
+ handleClose() {
+ if (typeof this.onClose === 'function') {
+ this.onClose()
+ }
+ },
+ close() {
+ this.setState(
+ {
+ _isOpened: false,
+ },
+ this.handleClose
+ )
+ },
+ /**
+ *
+ * @param {event} e
+ */
+ handleTouchMove(e) {
+ e.stopPropagation()
+ },
+ },
+ render() {
+ const { _isOpened } = this.state
+ const {
+ title,
+
+ scrollY,
+ scrollX,
+ scrollTop,
+ scrollLeft,
+ upperThreshold,
+ lowerThreshold,
+ scrollWithAnimation,
+ } = this
+
+ const rootClass = classNames(
+ 'at-float-layout',
+ {
+ 'at-float-layout--active': _isOpened,
+ },
+ this.className
+ )
+
+ return (
+
+
+
+ {title ? (
+
+ ) : null}
+
+
+ {this.$slots.default}
+
+
+
+
+ )
+ },
+}
diff --git a/src/components/index.ts b/src/components/index.ts
index c096adc..40d9a51 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -2,5 +2,6 @@ import Grid from './grid/index'
import List from './list/index'
import ListItem from './list/item/index'
import Card from './card/index'
+import FloatLayout from './float-layout/index'
-export { Grid, List, ListItem, Card }
+export { Grid, List, ListItem, Card, FloatLayout }
diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue
index 41579cc..0fd156b 100644
--- a/src/pages/index/index.vue
+++ b/src/pages/index/index.vue
@@ -2,6 +2,12 @@
+
+ 这是内容区 随你怎么写这是内容区 随你怎么写这是内容区 随你怎么写这是内容区
+ 随你怎么写这是内容区 随你怎么写这是内容区 随你怎么写
+