@@ -4,40 +4,35 @@ behave as links) in the same uniform manner.
4
4
5
5
[ Examples] ( #examples )
6
6
7
- ** Why?** &mdash ; Some buttons in our applications, although they look like
8
- regular buttons, should behave as external (to different apps/webpages) or
9
- internal (to different routes inside the app) links. Often, there is a need to
10
- switch between this link-like and the true button behavior as the development
11
- goes. The ` <Button> ` button component separates button styling from its logic,
12
- helping to switch these behaviors without caring about styling, and update the
13
- styling without caring about functionality.
14
-
15
- Under the hood, a ` <Button> ` is rendered in one of the three ways:
16
- 1 . When the ` <Button> ` is disabled it is rendered as ` <div> ` element with
17
- button content, which allows to style disabled buttons the same way, whether
18
- they are true or buttons or button-like links;
19
- 2 . Otherwise, if the ` <Button> ` has ` to ` property set it is rendered as
20
- [ ` <Link> ` ] ( link-and-navlink.md ) (in this case it accepts all other props a
21
- ` <Link> ` can accept). It helps to properly handle transitions both to external
22
- URLs, and to other routes within the app (these are handled via the React
23
- Router's mechanics, without reloading the app);
24
- 3 . Otherwise the ` <Button> ` is rendered as a regular HTML ` <button> ` (we could
25
- just use the ` <Link> ` in this case as well, but rendering and handling the
26
- ` <button> ` is a bit more efficient.
7
+ ** Why?** &mdash ; Sometimes we want a button to behave as an external or internal
8
+ link, i.e. either to redirect a visitor to another resource, outside of the app,
9
+ or to a different route, without reloading the app. Often there is also a need
10
+ to switch between this and the regular button behavior, without changin the
11
+ component look and layout. The ` <Button> ` component separates button styling
12
+ from its logic, helping to conveniently handle them independently.
13
+
14
+ Under the hood, a ` <Button> ` instance is rendered as:
15
+ 1 . A ` <div> ` block, when the button is disabled. It helps to ensure exactly the
16
+ same style of disabled buttons and button-like links;
17
+ 2 . A [ ` <Link> ` ] ( link-and-navlink.md ) component, when ` to ` property is set. This
18
+ takes care about internal and external links.
19
+ 3 . A ` <button> ` element, otherwise. In principle, our ` <Link> ` component can
20
+ play the button role as well, thus this third case could be avoided, but
21
+ rendering true buttons with ` <button> ` elements is somewhat more efficient.
27
22
28
23
### Button Properties
29
- - ** ` active ` ** &mdash ; * Boolean* &mdash ; Optional. When * true* the button is
24
+ - ** ` active ` ** &mdash ; * Boolean* &mdash ; Optional. When * true* , the button is
30
25
rendered in active state, even if it is not active otherwise;
31
- - ** ` disabled ` ** &mdash ; * Boolean* &mdash ; Optional. When * true* the button is
26
+ - ** ` disabled ` ** &mdash ; * Boolean* &mdash ; Optional. When * true* , the button is
32
27
disabled;
33
28
- ** ` enforceA ` ** &mdash ; * Boolean* &mdash ; Optional. When the button is rendered
34
- as ` <Link> ` this prop enforces it to be rendered as a simple ` <a> ` element (thus
35
- being treated as an external link);
29
+ as ` <Link> ` , this prop enforces it to be rendered as a simple ` <a> ` element
30
+ ( external link);
36
31
- ** ` onClick ` ** &mdash ; * Function* &mdash ; Optional. * onClick* event handler;
37
32
- ** ` onMouseDown ` ** &mdash ; * Function* &mdash ; Optional. * onMouseDown* event
38
33
handler;
39
34
- ** ` opneNewTab ` ** &mdash ; * Boolean* &mdash ; Optional. When the button is
40
- rendered as ` <Link> ` this property tells to open the link in a new tab;
35
+ rendered as ` <Link> ` , this property tells to open the link in a new tab;
41
36
- ** ` replace ` ** &mdash ; * Boolean* &mdash ; Optional. When the button is rendered
42
37
as ` <Link> ` , and the URL is internal, this property tells that the new route
43
38
should replace the last record in the browser's history, rather than be pushed
@@ -47,9 +42,7 @@ as a new entry into the history stack;
47
42
the button. It is supposed to control button size, and although any values can
48
43
be used, it is recommended to stick with ` xs ` , ` sm ` , ` md ` , ` lg ` , and ` xl ` size
49
44
labels, with ` md ` size being the default, when no ` size ` property is passed in;
50
- - ** ` theme ` ** &mdash ; * Object* &mdash ; Button theme (we use
51
- [ react-css-super-themr] ( https://www.npmjs.com/package/react-css-super-themr )
52
- to manage default / context / ad-hoc theming of components). This object is
45
+ - ** ` theme ` ** &mdash ; * Object* &mdash ; Button theme. This object is
53
46
supposed to have the following fields:
54
47
- ** ` button ` ** &mdash ; * String* &mdash ; The class to apply to the root element
55
48
of the button in all cases;
@@ -64,16 +57,137 @@ supposed to have the following fields:
64
57
- Other fields matching acceptable values of the ` size ` prop. Each of them
65
58
will hold the class to additionally apply to the root element of the button,
66
59
when the ` <size> ` value matches;
67
- - ** ` to ` ** &mdash ; * Object* or * String* &mdash ; When specified the button will
60
+ - ** ` to ` ** &mdash ; * Object* or * String* &mdash ; When specified, the button will
68
61
be rendered as ` <Link> ` (if non-disabled), and it will point to the specified
69
62
URL/location.
70
63
71
64
### <a name =" examples " >Examples</a >
72
- Simple button:
73
- ``` js
65
+ First of all, you want to define button theme, here is a good example to start from:
66
+ ``` scss
67
+ // theme.scss
68
+
69
+ /* Base button style (medium size). */
70
+ .button {
71
+ align-items : center ;
72
+ background : while;
73
+ border : solid 1px black ;
74
+ color : black ;
75
+ display : inline-flex ;
76
+ font : normal 15px arial ;
77
+ justify-content : center ;
78
+ min-height : 40px ;
79
+ margin : 5px ;
80
+ padding : 5px 23px ;
81
+ vertical-align : middle ;
82
+ }
83
+
84
+ /* Extra styling for the disabled buttons. */
85
+ .disabled {
86
+ cursor : not-allowed ;
87
+ opacity : 0.3 ;
88
+ }
89
+
90
+ /* To ensure that visited button-like links look the same as the non-visited
91
+ * ones (as typical buttons should not look different if they used to be clicked
92
+ * before). */
93
+ .link :visited {
94
+ color : black ;
95
+ font : normal 15px arial ;
96
+ }
97
+
98
+ /* .link and .regular classes are applied only to active buttons and button-like
99
+ * links. Here we provide visual feedback for button "active", "focus", and
100
+ * "hover" states. */
101
+ .link ,
102
+ .regular {
103
+ & :focus {
104
+ box-shadow : 0 0 2px 1px #cfe6ff ;
105
+ border-color : #59a7ff ;
106
+ outline : none ;
107
+ }
108
+
109
+ & :hover {
110
+ background-image : linear-gradient (to top , #f5f5f5 , white 49% , white );
111
+ border-color : $tc-gray-40 ;
112
+ }
113
+
114
+ /* We need both ":active" selector and ".active" class here, if we want to
115
+ * properly support the "active" option of the <Button>. */
116
+ & .active ,
117
+ & :active {
118
+ background-image : linear-gradient (to bottom , #f5f5f5 , white 49% , white );
119
+ box-shadow : inset 0 1px 2px 0 rgba (0 , 0 , 0 , 0.2 );
120
+ border-color : $tc-gray-40 ;
121
+ }
122
+ }
123
+
124
+ /* And a few extra classes to support "xs", "sm", and "lg" button sizes. */
125
+ .xs {
126
+ font : normal 11px arial ;
127
+ min-height : 20px ;
128
+ padding : 1px 13px ;
129
+ }
130
+
131
+ .sm {
132
+ font : normal 13px arial ;
133
+ min-height : 30px ;
134
+ padding : 4px 18px ;
135
+ }
136
+
137
+ .lg {
138
+ font : normal 17px arial ;
139
+ min-height : 50px ;
140
+ padding : 5px 28px ;
141
+ }
142
+ ```
143
+
144
+ You can apply this theme directly to your ` <Button> ` , but it is more
145
+ convenient to use
146
+ [ react-css-super-themr] ( https://www.npmjs.com/package/react-css-super-themr )
147
+ for management of the button default / context / and ad-hoc theming. To use it,
148
+ you should wrap the ` <Button> ` component with ` themr(..) ` decorator:
149
+ ``` jsx
150
+ // ThemedButton.js
74
151
import { Button } from ' topcoder-react-utils' ;
152
+ import { themr } from ' react-css-super-themr' ;
153
+ import theme from ' ./theme.scss' ;
154
+
155
+ export default const ThemedButton = themr (' ThemedButton' , theme)(Button);
156
+ ```
157
+
158
+ Now you can use the button in your code in multiple ways:
159
+ ``` js
160
+ import React from ' react' ;
161
+ import { ThemeProvider } from ' react-css-super-themr' ;
162
+ import Button from ' ./ThemedButton' ;
163
+
164
+ // Some themes we want to use for the ad-hoc and context theming.
165
+ import adHocTheme from ' ./adHocStyle.scss' ;
166
+ import contextTheme from ' ./contextTheme' ;
75
167
76
168
export default function Example () {
77
- return < Button onClick= {() => console .log (' Clicked!' )}> Click Me! < / Button> ;
169
+ return (
170
+ < div>
171
+ < Button
172
+ // Button with the default theme.
173
+ onClick= {() => console .log (' Clicked!' )}
174
+ > Click Me! < / Button>
175
+
176
+ < Button
177
+ // Button-like link with ad-hoc theming.
178
+ theme= {adHocTheme}
179
+ to= " https://www.topcoder.com"
180
+ > Click Me! < / Button>
181
+
182
+ < ThemeProvider
183
+ theme= {{ ThemedButton: contextTheme }}
184
+ >
185
+ < Button
186
+ // Button with context theming.
187
+ onClick= {() => console .log (' Clicked!' )}
188
+ > Click Me! < / Button>
189
+ < / ThemeProvider>
190
+ < / div>
191
+ );
78
192
}
79
193
```
0 commit comments