diff --git a/README.md b/README.md
index 06eb91e6..18093210 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ const App = () => {
### Action Components
-- [ ] ActionSheet
+- [x] ActionSheet
- [ ] Dialog
- [ ] DropdownMenu
- [ ] Loading
diff --git a/src/components/ActionSheet/ActionSheet.tsx b/src/components/ActionSheet/ActionSheet.tsx
new file mode 100644
index 00000000..ac3faf69
--- /dev/null
+++ b/src/components/ActionSheet/ActionSheet.tsx
@@ -0,0 +1,135 @@
+/*
+ * @Author: zhaohui
+ * @Date: 2021-05-29 12:11:37
+ * @LastEditTime: 2021-05-30 15:45:07
+ * @LastEditors: zhaohui
+ * @Description:
+ * @FilePath: /vant-react/src/components/ActionSheet/ActionSheet.tsx
+ */
+import React from 'react';
+import { ActionSheetProps, ActionItem, BaseClass } from './types';
+import classnames from '../../utils/classNames';
+import { renderLoadingIcon } from '../Button/helper';
+import Icon from '../Icons';
+import './index.scss';
+
+const ActionSheet = ({
+ actions,
+ cancelText,
+ description,
+ cancelClick,
+ closeIcon,
+ closeable,
+ title
+}: ActionSheetProps) => {
+ const containerStyle = {
+ className: classnames(`${BaseClass}__container`, []),
+ style: {}
+ };
+ const actionCon = {
+ className: classnames(`${BaseClass}__action__con`, []),
+ style: {}
+ };
+ const actionDescription = {
+ className: classnames(`${BaseClass}__description`, []),
+ style: {}
+ };
+ const actionItem = {
+ className: classnames(`${BaseClass}__action__item`, []),
+ style: {}
+ };
+ const actionItemSubName = {
+ className: classnames(`${BaseClass}__action__item__subName`, []),
+ style: {}
+ };
+ const _closeIcon = {
+ className: classnames(`${BaseClass}__close`, []),
+ style: {}
+ };
+ const _titleStyle = {
+ className: classnames(`${BaseClass}__title`, []),
+ style: {}
+ };
+ return (
+
+ {closeable && (
+
cancelClick && cancelClick()
+ })}
+ >
+ {typeof closeIcon === 'string' ? (
+
+ ) : (
+
+ )}
+
+ )}
+
+
+ {title && typeof title === 'string' ? (
+
{title}
+ ) : (
+ title
+ )}
+ {description && typeof description === 'string' ? (
+
{description}
+ ) : (
+ description
+ )}
+ {actions &&
+ actions.map((item: ActionItem) => (
+
+ ))}
+ {cancelText &&
}
+ {cancelText && typeof cancelText === 'string' ? (
+
+ ) : (
+ cancelText
+ )}
+
+
+ );
+};
+export default ActionSheet;
diff --git a/src/components/ActionSheet/index.scss b/src/components/ActionSheet/index.scss
new file mode 100644
index 00000000..3dbf5f19
--- /dev/null
+++ b/src/components/ActionSheet/index.scss
@@ -0,0 +1,80 @@
+@import '../../styles/colors.scss';
+
+$baseClass: 'vant-action-sheet';
+
+* {
+ box-sizing: border-box;
+}
+.#{$baseClass}__gap {
+ height: 8px;
+ background: $grey-background;
+}
+.#{$baseClass}__close {
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ color: $placeholder;
+ font-size: 22px;
+ cursor: pointer;
+}
+.#{$baseClass}__title {
+ flex-shrink: 0;
+ font-weight: 500;
+ font-size: 16px;
+ line-height: 48px;
+ text-align: center;
+}
+.#{$baseClass}__container {
+ position: relative;
+ width: 100vw;
+ .#{$baseClass}__action__con {
+ display: flex;
+ flex-direction: column;
+ justify-items: start;
+ text-align: center;
+ .#{$baseClass}__cancel {
+ background: #000;
+ }
+ .#{$baseClass}__description {
+ padding: 20px;
+ color: $grey;
+ font-size: 14px;
+ border-bottom: 1px solid $grey-background;
+ }
+ .#{$baseClass}__action__item {
+ line-height: 22px;
+ display: block;
+ width: 100%;
+ padding: 14px 16px;
+ font-size: 16px;
+ background-color: #fff;
+ border: none;
+ cursor: pointer;
+ &:active {
+ background-color: $grey-background;
+ }
+
+ .#{$baseClass}__action__item__name {
+ font-size: 16px;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ &__danger {
+ color: $danger;
+ }
+ .loading {
+ svg {
+ circle {
+ stroke: #c8c9cc !important;
+ }
+ }
+ }
+ }
+ .#{$baseClass}__action__item__subName {
+ font-size: 12px;
+ color: $grey;
+ }
+ }
+ }
+}
diff --git a/src/components/ActionSheet/index.stories.tsx b/src/components/ActionSheet/index.stories.tsx
new file mode 100644
index 00000000..2e0237f8
--- /dev/null
+++ b/src/components/ActionSheet/index.stories.tsx
@@ -0,0 +1,250 @@
+/*
+ * @Author: zhaohui
+ * @Date: 2021-05-13 18:18:19
+ * @LastEditTime: 2021-05-30 15:51:25
+ * @LastEditors: zhaohui
+ * @Description:
+ * @FilePath: /vant-react/src/components/ActionSheet/index.stories.tsx
+ */
+import React, { useState } from 'react';
+import ActionSheet from '.';
+import { ActionItem } from './types';
+import Cell from '../Cell';
+import '../../styles/stories.scss';
+import Toast from '../Toast';
+
+export default {
+ title: 'ActionSheet',
+ component: ActionSheet
+};
+
+export const ActionSheetDefault = () => {
+ const [visible, setVisible] = useState(false);
+ const actions: ActionItem[] = [
+ {
+ name: 'Option1',
+ value: 1,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisible(false);
+ }
+ },
+ {
+ name: 'Option2',
+ value: 2,
+ subname: 'This is a description',
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisible(false);
+ }
+ }
+ ];
+ return (
+
+
{
+ setVisible(true);
+ }
+ }}
+ />
+ setVisible(false)}
+ actions={actions}
+ />
+ |
+ );
+};
+export const ActionSheetWithStatus = () => {
+ const [visible, setVisible] = useState(false);
+ const actions: ActionItem[] = [
+ {
+ name: 'Disabled',
+ value: 1,
+ disabled: true,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisible(false);
+ }
+ },
+ {
+ name: 'Loading...',
+ value: 2,
+ loading: true,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisible(false);
+ }
+ },
+ {
+ name: 'Danger...',
+ value: 3,
+ danger: true,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisible(false);
+ }
+ }
+ ];
+ return (
+
+
{
+ setVisible(true);
+ }
+ }}
+ />
+ setVisible(false)}
+ actions={actions}
+ />
+ |
+ );
+};
+export const ActionSheetWithDiffrentButton = () => {
+ const [visibleTitle, setVisibleTitle] = useState(false);
+ const [visibleDescription, setVisibleDescription] = useState(false);
+ const [visibleCancel, setVisibleCancel] = useState(false);
+ const [visibleCancelIcon, setVisibleCancelIcon] = useState(false);
+ const actionsTitle: ActionItem[] = [
+ {
+ name: 'Option',
+ value: 1,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisibleTitle(false);
+ }
+ }
+ ];
+ const actionsCancel: ActionItem[] = [
+ {
+ name: 'Option',
+ value: 1,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisibleTitle(false);
+ }
+ }
+ ];
+ const actionsCancelIcon: ActionItem[] = [
+ {
+ name: 'Option',
+ value: 1,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisibleTitle(false);
+ }
+ }
+ ];
+ const actionTitle: ActionItem[] = [
+ {
+ name: 'Option',
+ value: 1,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisibleTitle(false);
+ }
+ }
+ ];
+ const actionsDescription: ActionItem[] = [
+ {
+ name: 'Option',
+ value: 1,
+ callback: (item: ActionItem) => {
+ Toast.info({ message: item.name });
+ setVisibleTitle(false);
+ }
+ }
+ ];
+ return (
+
+
{
+ setVisibleTitle(true);
+ }
+ }}
+ />
+ {
+ setVisibleDescription(true);
+ }
+ }}
+ />
+ {
+ setVisibleCancel(true);
+ }
+ }}
+ />
+ {
+ setVisibleCancelIcon(true);
+ }
+ }}
+ />
+ setVisibleTitle(false)}
+ actions={actionTitle}
+ title='This is title'
+ />
+ setVisibleDescription(false)}
+ actions={actionsDescription}
+ description='This is description'
+ />
+ setVisibleCancel(false)}
+ actions={actionsCancel}
+ />
+ setVisibleCancelIcon(false)}
+ closeable
+ actions={actionsCancelIcon}
+ />
+ setVisibleCancelIcon(false)}
+ closeable
+ actions={actionsTitle}
+ />
+ | | | |
+ );
+};
diff --git a/src/components/ActionSheet/index.tsx b/src/components/ActionSheet/index.tsx
new file mode 100644
index 00000000..85d27562
--- /dev/null
+++ b/src/components/ActionSheet/index.tsx
@@ -0,0 +1,35 @@
+/*
+ * @Author: zhaohui
+ * @Date: 2021-05-29 11:24:50
+ * @LastEditTime: 2021-05-30 15:44:24
+ * @LastEditors: zhaohui
+ * @Description:
+ * @FilePath: /vant-react/src/components/ActionSheet/index.tsx
+ */
+import React, { useState, useEffect } from 'react';
+import Popup from '../Popup';
+import { ActionSheetProps } from './types';
+import ActionSheet from './ActionSheet';
+
+const ActionSheetContainer = (props: ActionSheetProps) => {
+ const [_visible, setVisible] = useState(false);
+ const _maskClick = () => {
+ if (props.maskClick) {
+ props.maskClick();
+ }
+ };
+ useEffect(() => {
+ setVisible(props.visible);
+ });
+ return (
+
+
_maskClick()}
+ content={}
+ />
+
+ );
+};
+export default ActionSheetContainer;
diff --git a/src/components/ActionSheet/types.ts b/src/components/ActionSheet/types.ts
new file mode 100644
index 00000000..24d98de8
--- /dev/null
+++ b/src/components/ActionSheet/types.ts
@@ -0,0 +1,36 @@
+/*
+ * @Author: zhaohui
+ * @Date: 2021-05-29 11:34:24
+ * @LastEditTime: 2021-05-30 14:47:58
+ * @LastEditors: zhaohui
+ * @Description:
+ * @FilePath: /vant-react/src/components/ActionSheet/types.ts
+ */
+import { LoadingTypes } from '../Button/types';
+
+export interface ActionSheetProps {
+ visible: boolean;
+ actions?: ActionItem[];
+ title?: string | React.ReactNode;
+ cancelText?: string | React.ReactNode;
+ description?: string | React.ReactNode;
+ closeIcon?: string | React.ReactNode;
+ safeAreaInsetBottom?: boolean;
+ closeable?: boolean;
+ maskClick?: Function; // click mask
+ cancelClick?: Function;
+}
+
+export interface ActionItem {
+ name: string | React.ReactNode;
+ value: any;
+ subname?: string | React.ReactNode;
+ color?: string;
+ className?: string;
+ loading?: boolean;
+ loadingType?: LoadingTypes;
+ disabled?: boolean;
+ callback?: Function;
+ danger?: boolean;
+}
+export const BaseClass = 'vant-action-sheet';
diff --git a/src/index.tsx b/src/index.tsx
index 0c4568ca..703c19ca 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -13,6 +13,7 @@ import Checkbox from './components/Checkbox';
import Radio from './components/Radio';
import Stepper from './components/Stepper';
import Toast from './components/Toast';
+import ActionSheet from './components/ActionSheet';
export { default as Button } from './components/Button';
export { default as Icon } from './components/Icons';
@@ -29,6 +30,7 @@ export { default as Checkbox } from './components/Checkbox';
export { default as Radio } from './components/Radio';
export { default as Stepper } from './components/Stepper';
export { default as Toast } from './components/Toast';
+export { default as ActionSheet } from './components/ActionSheet';
const Vant = {
Button,
@@ -45,7 +47,8 @@ const Vant = {
Checkbox,
Radio,
Stepper,
- Toast
+ Toast,
+ ActionSheet
};
export default Vant;