diff --git a/components/carousel/index.js b/components/carousel/index.js
new file mode 100644
index 000000000..c35fd31e5
--- /dev/null
+++ b/components/carousel/index.js
@@ -0,0 +1,177 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import Icon from '../icon'
+import classNames from 'classnames'
+import './style/index'
+
+// const url = 'http://i1.mifile.cn/f/i/hiui/docs/'
+class Carousel extends Component {
+ constructor (props) {
+ super(props)
+ this.rootRef = React.createRef()
+ const defaultActive = props.defaultActive
+ this.state = {
+ rootWidth: 0,
+ showArrow: false,
+ active: (defaultActive >= props.children.length || defaultActive < 0) ? 0 : defaultActive
+ }
+ this.timer = null
+ }
+
+ componentDidMount () {
+ this.setState({
+ rootWidth: this.rootRef.current.clientWidth
+ }, () => {
+ if (this.props.duration) {
+ this.autoPage()
+ }
+ })
+ }
+
+ goTo (page) {
+ if (page > this.props.children.length || page < 0) {
+ return
+ }
+ this.setState({
+ active: page
+ })
+ }
+ componentWillUnmount () {
+ this.timer && window.clearInterval(this.timer)
+ }
+
+ autoPage () {
+ this.timer = window.setInterval(() => {
+ this.preNextEvent(1)
+ }, this.props.duration)
+ }
+
+ pageEvent (active) {
+ this.setState({
+ active
+ })
+ }
+
+ preNextEvent (val) {
+ let active = this.state.active + val
+ if (active >= this.props.children.length) {
+ active = 0
+ }
+ this.setState({
+ active
+ })
+ }
+
+ renderDot (type, key, index, active) {
+ if (type === 'sign') {
+ return
+ } else {
+ const cls = classNames(
+ 'hi-carousel__dot',
+ active === index && 'hi-carousel__dot--active'
+ )
+ return (
+
+ )
+ }
+ }
+
+ mouseEvent (type) {
+ let showArrow = true
+ if (type === 'over') {
+ this.timer && window.clearInterval(this.timer)
+ } else {
+ showArrow = false
+ this.props.duration && this.autoPage()
+ }
+ this.setState({showArrow})
+ }
+ render () {
+ const { rootWidth, active, showArrow } = this.state
+ const { showDots, showArrows } = this.props
+ const children = React.Children.toArray(this.props.children)
+ const arrowCls = classNames(
+ 'hi-carousel__arrows',
+ showArrow && 'hi-carousel__arrows--show'
+ )
+ return
+
+ {
+ children.map((child, index) => {
+ return React.cloneElement(child, {
+ key: index,
+ style: {
+ position: 'relative',
+ opacity: active === index ? 1 : 0,
+ transition: 'opacity 300ms ease 0s',
+ left: -(rootWidth * index),
+ width: rootWidth,
+ display: 'inline-block',
+ fontSize: 24,
+ ...child.props.style
+ }
+ })
+ })
+ }
+
+ {
+ showArrows &&
+ }
+ {
+ showDots &&
+ {
+ children.map((_, index) => {
+ const cls = classNames('hi-carousel__dot', active === index && 'hi-carousel__dot--active')
+ return
+ })
+ }
+
+ }
+
+ }
+}
+
+Carousel.propTypes = {
+ duration: PropTypes.number,
+ onClick: PropTypes.func,
+ beforeChange: PropTypes.func,
+ afterChange: PropTypes.func,
+ showDots: PropTypes.bool,
+ showArrows: PropTypes.bool,
+ defaultActive: PropTypes.number
+}
+Carousel.defaultProps = {
+ duration: 0,
+ onClick: () => {},
+ beforeChange: () => {},
+ afterChange: () => {},
+ showDots: true,
+ showArrows: true,
+ defaultActive: 0
+}
+
+export default Carousel
diff --git a/components/carousel/style/index.js b/components/carousel/style/index.js
new file mode 100644
index 000000000..63810a681
--- /dev/null
+++ b/components/carousel/style/index.js
@@ -0,0 +1 @@
+import './index.scss'
diff --git a/components/carousel/style/index.scss b/components/carousel/style/index.scss
new file mode 100644
index 000000000..cf049545b
--- /dev/null
+++ b/components/carousel/style/index.scss
@@ -0,0 +1,74 @@
+.hi-carousel {
+ width: 100%;
+ color: rgba(153, 153, 153, 1);
+ overflow: hidden;
+ position: relative;
+
+ &__container {
+ height: 100%;
+ transition: all 500ms;
+ }
+
+ &__dots {
+ position: absolute;
+ bottom: 24px;
+ margin: 0;
+ padding: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ &__dot {
+ width: 24px;
+ height: 4px;
+ background: rgba(255, 255, 255, 0.4);
+ border-radius: 2px;
+ display: inline-block;
+ margin-left: 4px;
+ cursor: pointer;
+ transition: all 1s;
+
+ &--active:not(.hi-carousel__dot--sign) {
+ background: rgba(255, 255, 255, 1);
+ width: 48px;
+ }
+
+ &--sign {
+ width: 24px;
+ }
+ }
+
+ &__arrows {
+ position: absolute;
+ width: 100%;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ top: 50%;
+ transform: translateY(-28px);
+ display: flex;
+ justify-content: space-between;
+ visibility: hidden;
+
+ &--show {
+ visibility: visible;
+ }
+ }
+
+ &__arrow {
+ width: 56px;
+ height: 56px;
+ background: rgba(0, 0, 0, 0.25);
+ border-radius: 50%;
+ text-align: center;
+ line-height: 56px;
+ color: #fff;
+ font-size: 32px;
+ margin-left: 24px;
+ cursor: pointer;
+
+ &:last-child {
+ margin-right: 24px;
+ }
+ }
+}
diff --git a/components/index.js b/components/index.js
index 823896e3c..51ee73cd2 100755
--- a/components/index.js
+++ b/components/index.js
@@ -42,4 +42,5 @@ export { default as Rate } from './rate'
export { default as Message } from './message'
export { default as Tag } from './tag'
export { default as Breadcrumb } from './breadcrumb'
+export { default as Carousel } from './carousel'
export { ThemeContext, LocaleContext } from './context'
diff --git a/docs/demo/breadcrumb/section-base.jsx b/docs/demo/breadcrumb/section-base.jsx
index 4a7f39e5f..a8dc191ef 100644
--- a/docs/demo/breadcrumb/section-base.jsx
+++ b/docs/demo/breadcrumb/section-base.jsx
@@ -3,7 +3,7 @@ import DocViewer from '../../../libs/doc-viewer'
import Breadcrumb from '../../../components/breadcrumb'
const prefix = 'alert-base'
const code = `import React from 'react'
-import Alert from '@hi-ui/hiui/es/alert'\n
+import Breadcrumb from '@hi-ui/hiui/es/breadcrumb'\n
class Demo extends React.Component {
render () {
const data = [{
diff --git a/docs/demo/carousel/section-base.jsx b/docs/demo/carousel/section-base.jsx
new file mode 100644
index 000000000..f0470c742
--- /dev/null
+++ b/docs/demo/carousel/section-base.jsx
@@ -0,0 +1,31 @@
+import React from 'react'
+import DocViewer from '../../../libs/doc-viewer'
+import Carousel from '../../../components/carousel'
+const prefix = 'carousel-base'
+const code = `import React from 'react'
+import Carousel from '@hi-ui/hiui/es/carousel'\n
+class Demo extends React.Component {
+ constructor (props) {
+ super(props)
+ }
+
+ render () {
+ const data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
+ return (
+
+
+ {
+ data.map((item) => {
+ return {item}
+ })
+ }
+
+
+ )
+ }
+}`
+
+const DemoBase = () =>
+export default DemoBase
diff --git a/docs/demo/carousel/section-icon.jsx b/docs/demo/carousel/section-icon.jsx
new file mode 100644
index 000000000..5ab0544a3
--- /dev/null
+++ b/docs/demo/carousel/section-icon.jsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import DocViewer from '../../../libs/doc-viewer'
+import Carousel from '../../../components/carousel'
+const prefix = 'carousel-base'
+const code = `import React from 'react'
+import Carousel from '@hi-ui/hiui/es/carousel'\n
+class Demo extends React.Component {
+ render () {
+ const data = [1, 2, 3, 4, 5, 6, 7, 8]
+ return (
+
+
+ {
+ data.map((item, index) => {
+ return
+ })
+ }
+
+
+ )
+ }
+}`
+
+const DemoBase = () =>
+export default DemoBase
diff --git a/docs/zh-CN/components/carousel.mdx b/docs/zh-CN/components/carousel.mdx
new file mode 100644
index 000000000..f5dc47f3d
--- /dev/null
+++ b/docs/zh-CN/components/carousel.mdx
@@ -0,0 +1,22 @@
+# Carousel 走马灯
+
+## 基础用法
+
+import DemoBase from '../../demo/carousel/section-base.jsx'
+
+
+
+## 图片展示
+
+import DemoImage from '../../demo/carousel/section-icon.jsx'
+
+
+
+## Props
+
+| 参数 | 说明 | 类型 | 可选值 | 默认值 |
+| -------------- | ------------------------------------------------- | --------------------------- | ------------- | ------------------------------------------------------- |
+| duration | 自动切换间隔,默认不自动切换 | number | - | 0 |
+| showDots | 是否显示分页指示器 | boolean | - | false |
+| showArrows | 是否显示箭头指示器 | boolean | - | false |
+| defaultActive | 默认激活索引,从0开始 | number | - | 0 |
diff --git a/site/locales/zh-CN.js b/site/locales/zh-CN.js
index 2ba8da091..b2e923332 100755
--- a/site/locales/zh-CN.js
+++ b/site/locales/zh-CN.js
@@ -51,7 +51,8 @@ module.exports = {
transfer: 'Transfer 穿梭框',
switch: 'Switch 开关',
rate: 'Rate 评分',
- breadcrumb: 'Breadcrumb 面包屑'
+ breadcrumb: 'Breadcrumb 面包屑',
+ carousel: 'Carousel 走马灯'
},
designs: {
summarize: '概述',
diff --git a/site/pages/components/index.js b/site/pages/components/index.js
index 1581ea15a..cbcaf03a3 100755
--- a/site/pages/components/index.js
+++ b/site/pages/components/index.js
@@ -51,7 +51,8 @@ export default {
popover: components['popover'],
progress: components['progress'],
card: components['card'],
- timeline: components['timeline']
+ timeline: components['timeline'],
+ carousel: components['carousel']
},
'group-tips': {
modal: components['modal'],