Skip to content

Commit d74de13

Browse files
jw-fosskchjxxgh
authored andcommitted
Drawer: Add drawer component (ElemeFE#16577)
1 parent 72aa72f commit d74de13

File tree

16 files changed

+1944
-2
lines changed

16 files changed

+1944
-2
lines changed

components.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,6 @@
7373
"link": "./packages/link/index.js",
7474
"divider": "./packages/divider/index.js",
7575
"image": "./packages/image/index.js",
76-
"calendar": "./packages/calendar/index.js"
76+
"calendar": "./packages/calendar/index.js",
77+
"drawer": "./packages/drawer/index.js"
7778
}

examples/demo-styles/drawer.scss

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
.demo-drawer {
2+
&__content {
3+
display: flex;
4+
flex-direction: column;
5+
height: 100%;
6+
form {
7+
flex: 1;
8+
}
9+
}
10+
11+
&__footer {
12+
display: flex;
13+
button {
14+
flex: 1;
15+
}
16+
}
17+
}
18+
19+
.el-drawer__body {
20+
padding: 20px;
21+
}

examples/demo-styles/index.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@
4141
@import "./upload.scss";
4242
@import "./divider.scss";
4343
@import "./image.scss";
44+
@import "./drawer.scss";
45+

examples/docs/en-US/drawer.md

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
## Drawer
2+
3+
Sometimes, `Dialog` does not always satisfy our requirements, let's say you have a massive form, or you need space to display something like `terms & conditions`, `Drawer` has almost identical API with `Dialog`, but it introduces different user experience.
4+
5+
### Basic Usage
6+
7+
Callout a temporary drawer, from multiple direction
8+
9+
:::demo You must set `visible` for `Drawer` like `Dialog` does to control the visibility of `Drawer` itself, it's `boolean` type. `Drawer` has to parts: `title` & `body`, the `title` is a named slot, you can also set the title through attribute named `title`, default to an empty string, the `body` part is the main area of `Drawer`, which contains user defined content. When opening, `Drawer` expand itself from the **right corner to left** which size is **30%** of the browser window by default. You can change that default behavior by setting `direction` and `size` attribute. This show case also demonstrated how to use the `before-close` API, check the Attribute section for more detail
10+
11+
```html
12+
<el-radio-group v-model="direction">
13+
<el-radio label="ltr">left to right</el-radio>
14+
<el-radio label="rtl">right to left</el-radio>
15+
<el-radio label="ttb">top to bottom</el-radio>
16+
<el-radio label="btt">bottom to top</el-radio>
17+
</el-radio-group>
18+
19+
<el-button @click="drawer = true" type="primary" style="margin-left: 16px;">
20+
open
21+
</el-button>
22+
23+
<el-drawer
24+
title="I am the title"
25+
:visible.sync="drawer"
26+
:direction="direction"
27+
:before-close="handleClose">
28+
<span>Hi, there!</span>
29+
</el-drawer>
30+
31+
<script>
32+
export default {
33+
data() {
34+
return {
35+
drawer: false,
36+
direction: 'rtl',
37+
};
38+
},
39+
methods: {
40+
handleClose(done) {
41+
this.$confirm('Are you sure you want to close this?')
42+
.then(_ => {
43+
done();
44+
})
45+
.catch(_ => {});
46+
}
47+
}
48+
};
49+
</script>
50+
```
51+
:::
52+
53+
### Customization Content
54+
55+
Like `Dialog`, `Drawer` can do many diverse interaction as you wanted.
56+
57+
:::demo
58+
59+
```html
60+
<el-button type="text" @click="table = true">Open Drawer with nested table</el-button>
61+
<el-button type="text" @click="dialog = true">Open Drawer with nested form</el-button>
62+
<el-drawer
63+
title="I have a nested table inside!"
64+
:visible.sync="table"
65+
direction="rtl"
66+
size="50%">
67+
<el-table :data="gridData">
68+
<el-table-column property="date" label="Date" width="150"></el-table-column>
69+
<el-table-column property="name" label="Name" width="200"></el-table-column>
70+
<el-table-column property="address" label="Address"></el-table-column>
71+
</el-table>
72+
</el-drawer>
73+
74+
<el-drawer
75+
title="I have a nested form inside!"
76+
:before-close="handleClose"
77+
:visible.sync="dialog"
78+
direction="ltr"
79+
custom-class="demo-drawer"
80+
ref="drawer"
81+
>
82+
<div class="demo-drawer__content">
83+
<el-form :model="form">
84+
<el-form-item label="Name" :label-width="formLabelWidth">
85+
<el-input v-model="form.name" autocomplete="off"></el-input>
86+
</el-form-item>
87+
<el-form-item label="Area" :label-width="formLabelWidth">
88+
<el-select v-model="form.region" placeholder="Please select activity area">
89+
<el-option label="Area1" value="shanghai"></el-option>
90+
<el-option label="Area2" value="beijing"></el-option>
91+
</el-select>
92+
</el-form-item>
93+
</el-form>
94+
<div class="demo-drawer__footer">
95+
<el-button @click="dialog = false">Cancel</el-button>
96+
<el-button type="primary" @click="$refs.drawer.closeDrawer()" :loading="loading">{{ loading ? 'Submitting ...' : 'Submit' }}</el-button>
97+
</div>
98+
</div>
99+
</el-drawer>
100+
101+
<script>
102+
export default {
103+
data() {
104+
return {
105+
table: false,
106+
dialog: false,
107+
loading: false,
108+
gridData: [{
109+
date: '2016-05-02',
110+
name: 'Peter Parker',
111+
address: 'Queens, New York City'
112+
}, {
113+
date: '2016-05-04',
114+
name: 'Peter Parker',
115+
address: 'Queens, New York City'
116+
}, {
117+
date: '2016-05-01',
118+
name: 'Peter Parker',
119+
address: 'Queens, New York City'
120+
}, {
121+
date: '2016-05-03',
122+
name: 'Peter Parker',
123+
address: 'Queens, New York City'
124+
}],
125+
form: {
126+
name: '',
127+
region: '',
128+
date1: '',
129+
date2: '',
130+
delivery: false,
131+
type: [],
132+
resource: '',
133+
desc: ''
134+
},
135+
formLabelWidth: '80px'
136+
};
137+
},
138+
methods: {
139+
handleClose(done) {
140+
this.$confirm('Do you want to submit?')
141+
.then(_ => {
142+
this.loading = true;
143+
setTimeout(() => {
144+
this.loading = false;
145+
done();
146+
}, 2000);
147+
})
148+
.catch(_ => {});
149+
}
150+
}
151+
}
152+
</script>
153+
```
154+
:::
155+
156+
### Nested Drawer
157+
158+
You can also have multiple layer of `Drawer` just like `Dialog`.
159+
:::demo If you need multiple Drawer in different layer, you must set the `append-to-body` attribute to **true**
160+
161+
```html
162+
163+
<el-button @click="drawer = true" type="primary" style="margin-left: 16px;">
164+
open
165+
</el-button>
166+
167+
<el-drawer
168+
title="I'm outer Drawer"
169+
:visible.sync="drawer"
170+
size="50%">
171+
<div>
172+
<el-button @click="innerDrawer = true">Click me!</el-button>
173+
<el-drawer
174+
title="I'm inner Drawer"
175+
:append-to-body="true"
176+
:before-close="handleClose"
177+
:visible.sync="innerDrawer">
178+
<p>_(:зゝ∠)_</p>
179+
</el-drawer>
180+
</div>
181+
</el-drawer>
182+
183+
<script>
184+
export default {
185+
data() {
186+
return {
187+
drawer: false,
188+
innerDrawer: false,
189+
};
190+
},
191+
methods: {
192+
handleClose(done) {
193+
this.$confirm('You still have unsaved data, proceed?')
194+
.then(_ => {
195+
done();
196+
})
197+
.catch(_ => {});
198+
}
199+
}
200+
};
201+
</script>
202+
203+
```
204+
:::
205+
206+
:::tip
207+
208+
The content inside Drawer should be lazy rendered, which means that the content inside Drawer will not impact the initial render performance, therefore any DOM operation should be performed through `ref` or after `open` event emitted.
209+
210+
:::
211+
212+
:::tip
213+
214+
Drawer provides an API called `destroyOnClose`, which is a flag variable that indicates should destroy the children content inside Drawer after Drawer was closed. You can use this API when you need your `mounted` life cycle to be called every time the Drawer opens.
215+
216+
:::
217+
218+
:::tip
219+
220+
If the variable bound to `visible` is managed in Vuex store, the `.sync` can not work properly. In this case, please remove the `.sync` modifier, listen to `open` and `close` events of Dialog, and commit Vuex mutations to update the value of that variable in the event handlers.
221+
222+
:::
223+
224+
### Drawer Attributes
225+
226+
| Parameter| Description | Type | Acceptable Values | Defaults |
227+
|---------- |-------------- |---------- |-------------------------------- |-------- |
228+
| append-to-body | Controls should Drawer be inserted to DocumentBody Element, nested Drawer must assign this param to **true**| boolean || false |
229+
| before-close | If set, closing procedure will be halted | function(done), done is function type that accepts a boolean as parameter, calling done with true or without parameter will abort the close procedure |||
230+
| close-on-press-escape | Indicates whether Drawer can be closed by pressing ESC | boolean || true |
231+
| custom-class | Extra class names for Drawer | string |||
232+
| destroy-on-close | Indicates whether children should be destroyed after Drawer closed | boolean | - | false |
233+
| modal | Should show shadowing layer | boolean || true |
234+
| modal-append-to-body | Indicates should shadowing layer be insert into DocumentBody element | boolean || true |
235+
| direction | Drawer's opening direction | Direction | rtl / ltr / ttb / tbb | rtl |
236+
| show-close | Should show close button at the top right of Drawer | boolean || true |
237+
| size | Drawer's size, if Drawer is horizontal mode, it effects the width property, otherwise it effects the height property, when size is `number` type, it describes the size by unit of pixels; when size is `string` type, it should be used with `x%` notation, other wise it will be interpreted to pixel unit | number / string | - | '30%' |
238+
| title | Drawer's title, can also be set by named slot, detailed descriptions can be found in the slot form | string |||
239+
| visible | Should Drawer be displayed, also support the `.sync` notation | boolean || false |
240+
| wrapperClosable | Indicates whether user can close Drawer by clicking the shadowing layer. | boolean | - | true |
241+
242+
### Drawer Slot
243+
244+
| Name | Description |
245+
|------|--------|
246+
|| Drawer's Content |
247+
| title | Drawer Title Section |
248+
249+
### Drawer Methods
250+
251+
| Name | Description |
252+
| ---- | --- |
253+
| closeDrawer | In order to close Drawer, this method will call `before-close`. |
254+
255+
### Drawer Events
256+
257+
| Event Name | Description | Parameter |
258+
|---------- |-------- |---------- |
259+
| open | Triggered before Drawer opening animation begins ||
260+
| opened | Triggered after Drawer opening animation ended ||
261+
| close | Triggered before Drawer closing animation begins ||
262+
| closed | Triggered after Drawer closing animation ended ||

0 commit comments

Comments
 (0)