UNPKG

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