1
- import _ from 'lodash'
2
1
import cx from 'classnames'
2
+ import _ from 'lodash'
3
3
import React , { Component , PropTypes } from 'react'
4
4
5
5
import {
@@ -16,37 +16,14 @@ import {
16
16
} from '../../lib'
17
17
import Icon from '../Icon/Icon'
18
18
import Label from '../Label/Label'
19
-
20
19
import ButtonContent from './ButtonContent'
21
20
import ButtonGroup from './ButtonGroup'
22
21
import ButtonOr from './ButtonOr'
23
22
24
23
const debug = makeDebugger ( 'button' )
25
24
26
- const _meta = {
27
- name : 'Button' ,
28
- type : META . TYPES . ELEMENT ,
29
- props : {
30
- animated : [ 'fade' , 'vertical' ] ,
31
- attached : [ 'left' , 'right' , 'top' , 'bottom' ] ,
32
- color : [
33
- ...SUI . COLORS ,
34
- 'facebook' ,
35
- 'twitter' ,
36
- 'google plus' ,
37
- 'vk' ,
38
- 'linkedin' ,
39
- 'instagram' ,
40
- 'youtube' ,
41
- ] ,
42
- floated : SUI . FLOATS ,
43
- labelPosition : [ 'right' , 'left' ] ,
44
- size : SUI . SIZES ,
45
- } ,
46
- }
47
-
48
25
/**
49
- * A Button indicates a possible user action
26
+ * A Button indicates a possible user action.
50
27
* @see Form
51
28
* @see Icon
52
29
* @see Label
@@ -56,19 +33,19 @@ class Button extends Component {
56
33
/** An element type to render as (string or function). */
57
34
as : customPropTypes . as ,
58
35
59
- /** A button can show it is currently the active user selection */
36
+ /** A button can show it is currently the active user selection. */
60
37
active : PropTypes . bool ,
61
38
62
- /** A button can animate to show hidden content */
39
+ /** A button can animate to show hidden content. */
63
40
animated : PropTypes . oneOfType ( [
64
41
PropTypes . bool ,
65
- PropTypes . oneOf ( _meta . props . animated ) ,
42
+ PropTypes . oneOf ( [ 'fade' , 'vertical' ] ) ,
66
43
] ) ,
67
44
68
- /** A button can be attached to the top or bottom of other content */
69
- attached : PropTypes . oneOf ( _meta . props . attached ) ,
45
+ /** A button can be attached to the top or bottom of other content. */
46
+ attached : PropTypes . oneOf ( [ 'left' , 'right' , 'top' , 'bottom' ] ) ,
70
47
71
- /** A basic button is less pronounced */
48
+ /** A basic button is less pronounced. */
72
49
basic : PropTypes . bool ,
73
50
74
51
/** Primary content. */
@@ -87,55 +64,58 @@ class Button extends Component {
87
64
) ,
88
65
] ) ,
89
66
90
- /** A button can be circular */
91
- circular : PropTypes . bool ,
92
-
93
67
/** Additional classes. */
94
68
className : PropTypes . string ,
95
69
96
- /** Shorthand for primary content . */
97
- content : customPropTypes . contentShorthand ,
70
+ /** A button can be circular . */
71
+ circular : PropTypes . bool ,
98
72
99
73
/** A button can have different colors */
100
- color : PropTypes . oneOf ( _meta . props . color ) ,
74
+ color : PropTypes . oneOf ( [
75
+ ...SUI . COLORS ,
76
+ 'facebook' , 'google plus' , 'instagram' , 'linkedin' , 'twitter' , 'vk' , 'youtube' ,
77
+ ] ) ,
101
78
102
- /** A button can reduce its padding to fit into tighter spaces */
79
+ /** A button can reduce its padding to fit into tighter spaces. */
103
80
compact : PropTypes . bool ,
104
81
105
- /** A button can show it is currently unable to be interacted with */
82
+ /** Shorthand for primary content. */
83
+ content : customPropTypes . contentShorthand ,
84
+
85
+ /** A button can show it is currently unable to be interacted with. */
106
86
disabled : PropTypes . bool ,
107
87
108
- /** A button can be aligned to the left or right of its container */
109
- floated : PropTypes . oneOf ( _meta . props . floated ) ,
88
+ /** A button can be aligned to the left or right of its container. */
89
+ floated : PropTypes . oneOf ( SUI . FLOATS ) ,
110
90
111
- /** A button can take the width of its container */
91
+ /** A button can take the width of its container. */
112
92
fluid : PropTypes . bool ,
113
93
114
- /** Add an Icon by name, props object, or pass an <Icon /> */
94
+ /** Add an Icon by name, props object, or pass an <Icon />. */
115
95
icon : customPropTypes . some ( [
116
96
PropTypes . bool ,
117
97
PropTypes . string ,
118
98
PropTypes . object ,
119
99
PropTypes . element ,
120
100
] ) ,
121
101
122
- /** A button can be formatted to appear on dark backgrounds */
102
+ /** A button can be formatted to appear on dark backgrounds. */
123
103
inverted : PropTypes . bool ,
124
104
125
- /** A labeled button can format a Label or Icon to appear on the left or right */
126
- labelPosition : PropTypes . oneOf ( _meta . props . labelPosition ) ,
127
-
128
- /** Add a Label by text, props object, or pass a <Label /> */
105
+ /** Add a Label by text, props object, or pass a <Label />. */
129
106
label : customPropTypes . some ( [
130
107
PropTypes . string ,
131
108
PropTypes . object ,
132
109
PropTypes . element ,
133
110
] ) ,
134
111
135
- /** A button can show a loading indicator */
112
+ /** A labeled button can format a Label or Icon to appear on the left or right. */
113
+ labelPosition : PropTypes . oneOf ( [ 'right' , 'left' ] ) ,
114
+
115
+ /** A button can show a loading indicator. */
136
116
loading : PropTypes . bool ,
137
117
138
- /** A button can hint towards a negative consequence */
118
+ /** A button can hint towards a negative consequence. */
139
119
negative : PropTypes . bool ,
140
120
141
121
/**
@@ -145,33 +125,37 @@ class Button extends Component {
145
125
*/
146
126
onClick : PropTypes . func ,
147
127
148
- /** A button can hint towards a positive consequence */
128
+ /** A button can hint towards a positive consequence. */
149
129
positive : PropTypes . bool ,
150
130
151
- /** A button can be formatted to show different levels of emphasis */
131
+ /** A button can be formatted to show different levels of emphasis. */
152
132
primary : PropTypes . bool ,
153
133
154
- /** A button can be formatted to show different levels of emphasis */
134
+ /** A button can be formatted to show different levels of emphasis. */
155
135
secondary : PropTypes . bool ,
156
136
157
- /** A button can have different sizes */
158
- size : PropTypes . oneOf ( _meta . props . size ) ,
137
+ /** A button can have different sizes. */
138
+ size : PropTypes . oneOf ( SUI . SIZES ) ,
159
139
160
140
/** A button can receive focus. */
161
141
tabIndex : PropTypes . oneOfType ( [
162
- PropTypes . string ,
163
142
PropTypes . number ,
143
+ PropTypes . string ,
164
144
] ) ,
165
145
166
- /** A button can be formatted to toggle on and off */
146
+ /** A button can be formatted to toggle on and off. */
167
147
toggle : PropTypes . bool ,
168
148
}
169
149
170
150
static defaultProps = {
171
151
as : 'button' ,
172
152
}
173
153
174
- static _meta = _meta
154
+ static _meta = {
155
+ name : 'Button' ,
156
+ type : META . TYPES . ELEMENT ,
157
+ }
158
+
175
159
static Content = ButtonContent
176
160
static Group = ButtonGroup
177
161
static Or = ButtonOr
@@ -187,6 +171,14 @@ class Button extends Component {
187
171
if ( onClick ) onClick ( e , this . props )
188
172
}
189
173
174
+ computeTabIndex = ElementType => {
175
+ const { disabled, tabIndex } = this . props
176
+
177
+ if ( ! _ . isNil ( tabIndex ) ) return tabIndex
178
+ if ( disabled ) return - 1
179
+ if ( ElementType === 'div' ) return 0
180
+ }
181
+
190
182
render ( ) {
191
183
const {
192
184
active,
@@ -212,7 +204,6 @@ class Button extends Component {
212
204
primary,
213
205
secondary,
214
206
size,
215
- tabIndex,
216
207
toggle,
217
208
} = this . props
218
209
@@ -224,13 +215,10 @@ class Button extends Component {
224
215
color ,
225
216
size ,
226
217
useKeyOnly ( active , 'active' ) ,
227
- useKeyOrValueAndKey ( animated , 'animated' ) ,
228
- useKeyOrValueAndKey ( attached , 'attached' ) ,
229
218
useKeyOnly ( basic , 'basic' ) ,
230
219
useKeyOnly ( circular , 'circular' ) ,
231
220
useKeyOnly ( compact , 'compact' ) ,
232
221
useKeyOnly ( disabled , 'disabled' ) ,
233
- useValueAndKey ( floated , 'floated' ) ,
234
222
useKeyOnly ( fluid , 'fluid' ) ,
235
223
useKeyOnly ( icon === true || icon && ( labelPosition || ! children && ! content ) , 'icon' ) ,
236
224
useKeyOnly ( inverted , 'inverted' ) ,
@@ -240,22 +228,21 @@ class Button extends Component {
240
228
useKeyOnly ( primary , 'primary' ) ,
241
229
useKeyOnly ( secondary , 'secondary' ) ,
242
230
useKeyOnly ( toggle , 'toggle' ) ,
231
+ useKeyOrValueAndKey ( animated , 'animated' ) ,
232
+ useKeyOrValueAndKey ( attached , 'attached' ) ,
233
+ useValueAndKey ( floated , 'floated' ) ,
243
234
)
244
235
const rest = getUnhandledProps ( Button , this . props )
245
236
const ElementType = getElementType ( Button , this . props , ( ) => {
246
237
if ( ! _ . isNil ( label ) || ! _ . isNil ( attached ) ) return 'div'
247
238
} )
248
-
249
- let computedTabIndex
250
- if ( ! _ . isNil ( tabIndex ) ) computedTabIndex = tabIndex
251
- else if ( disabled ) computedTabIndex = - 1
252
- else if ( ElementType === 'div' ) computedTabIndex = 0
239
+ const tabIndex = this . computeTabIndex ( ElementType )
253
240
254
241
if ( ! _ . isNil ( children ) ) {
255
242
const classes = cx ( 'ui' , baseClasses , labeledClasses , 'button' , className )
256
243
debug ( 'render children:' , { classes } )
257
244
return (
258
- < ElementType { ...rest } className = { classes } tabIndex = { computedTabIndex } onClick = { this . handleClick } >
245
+ < ElementType { ...rest } className = { classes } tabIndex = { tabIndex } onClick = { this . handleClick } >
259
246
{ children }
260
247
</ ElementType >
261
248
)
@@ -285,7 +272,7 @@ class Button extends Component {
285
272
const classes = cx ( 'ui' , labeledClasses , baseClasses , 'button' , className )
286
273
debug ( 'render icon && !label:' , { classes } )
287
274
return (
288
- < ElementType { ...rest } className = { classes } tabIndex = { computedTabIndex } onClick = { this . handleClick } >
275
+ < ElementType { ...rest } className = { classes } tabIndex = { tabIndex } onClick = { this . handleClick } >
289
276
{ Icon . create ( icon ) } { content }
290
277
</ ElementType >
291
278
)
@@ -295,7 +282,7 @@ class Button extends Component {
295
282
debug ( 'render default:' , { classes } )
296
283
297
284
return (
298
- < ElementType { ...rest } className = { classes } tabIndex = { computedTabIndex } onClick = { this . handleClick } >
285
+ < ElementType { ...rest } className = { classes } tabIndex = { tabIndex } onClick = { this . handleClick } >
299
286
{ content }
300
287
</ ElementType >
301
288
)
0 commit comments