Skip to content

Commit c1c380e

Browse files
author
Dustyn Blackmore
committed
Component Class Name Refactor
Was still not happy with the duplicated code, and inconsistency of class names accross elements. Additionally; whilst lost of class names are available, I believe this is a better option than attempting to manage a method to enable them in the component. You can just ignore them if you don't need them. Refactored the classNames generation to maintain consistency. Reworked tests to expect these changes. These are, by no means; final. But they are a huge improvement. Added examples for classnames, which demonstrates these overrides (with an array, which results in lots of classes by design).
1 parent 096ef17 commit c1c380e

14 files changed

Lines changed: 375 additions & 233 deletions

File tree

examples/classnames/app.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
.ReactInput__Overlay {
2+
-webkit-perspective: 600;
3+
perspective: 600;
4+
opacity: 0;
5+
}
6+
7+
.ReactInput__Overlay--after-open {
8+
opacity: 1;
9+
transition: opacity 150ms ease-out;
10+
}
11+
12+
.ReactInput__Content {
13+
-webkit-transform: scale(0.5) rotateX(-30deg);
14+
transform: scale(0.5) rotateX(-30deg);
15+
}
16+
17+
.ReactInput__Content--after-open {
18+
-webkit-transform: scale(1) rotateX(0deg);
19+
transform: scale(1) rotateX(0deg);
20+
transition: all 150ms ease-in;
21+
}
22+
23+
.ReactInput__Overlay--before-close {
24+
opacity: 0;
25+
}
26+
27+
.ReactInput__Content--before-close {
28+
-webkit-transform: scale(0.5) rotateX(30deg);
29+
transform: scale(0.5) rotateX(30deg);
30+
transition: all 150ms ease-in;
31+
}

examples/classnames/app.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React, { Component } from 'react';
2+
import ReactDOM from 'react-dom';
3+
import Input from 'react-component_input';
4+
import Button from './button';
5+
import Radio from './radio';
6+
import TextExample from './text';
7+
import Textarea from './textarea';
8+
9+
const appElement = document.getElementById('example');
10+
11+
const examples = [
12+
Button,
13+
Radio,
14+
TextExample,
15+
Textarea
16+
];
17+
18+
class App extends Component {
19+
render() {
20+
return (
21+
<div>
22+
{examples.map((example, key) => {
23+
const ExampleApp = example.app;
24+
return (
25+
<div key={key + 1} className="example">
26+
<h3>{`#${key + 1}. ${example.label}`}</h3>
27+
<ExampleApp />
28+
</div>
29+
);
30+
})}
31+
</div>
32+
);
33+
}
34+
}
35+
36+
ReactDOM.render(<App />, appElement);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React, { Component } from 'react';
2+
import Input from 'react-component_input';
3+
4+
class Button extends Component {
5+
render() {
6+
return (
7+
<div>
8+
<Input
9+
identifier="buttonInput"
10+
labelContent="Button Input"
11+
type="button"
12+
value="button"
13+
containerClassNames={["button-custom-container", "my-button-custom-container"]}
14+
inputClassNames={["button-custom-input", "my-button-custom-input"]}
15+
labelClassNames={["button-custom-label", "my-button-custom-label"]}
16+
validationClassNames={["button-custom-validation", "my-button-custom-validation"]}
17+
/>
18+
</div>
19+
);
20+
}
21+
}
22+
23+
export default {
24+
label: "Input - Button",
25+
app: Button
26+
};

examples/classnames/index.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!doctype html public "embarassment">
2+
<html>
3+
<head>
4+
<title>Classnames Example</title>
5+
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
6+
<link rel="stylesheet" href="/base.css"/>
7+
<link rel="stylesheet" href="app.css"/>
8+
</head>
9+
<body>
10+
<header class="branding padbox">
11+
<h1>react-component_input</h1>
12+
<h2>An input component to serve the common good</h2>
13+
</header>
14+
<div id="example" class="padbox"></div>
15+
<a target="_top" href="https://github.com/dmblack/react-component_input.js">react-component_input</a>
16+
<script src="../__build__/shared.js"></script>
17+
<script src="../__build__/classnames.js"></script>
18+
</body>
19+
</html>

examples/classnames/radio/index.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React, { Component } from 'react';
2+
import Input from 'react-component_input';
3+
4+
class Radio extends Component {
5+
render() {
6+
return (
7+
<div>
8+
<Input
9+
identifier="radioInput"
10+
labelContent="Radio Input"
11+
type="radio"
12+
containerClassNames={["radio-custom-container", "my-radio-custom-container"]}
13+
inputClassNames={["radio-custom-input", "my-radio-custom-input"]}
14+
labelClassNames={["radio-custom-label", "my-radio-custom-label"]}
15+
validationClassNames={["radio-custom-validation", "my-radio-custom-validation"]}
16+
/>
17+
</div>
18+
);
19+
}
20+
}
21+
22+
export default {
23+
label: "Input - Radio",
24+
app: Radio
25+
};

examples/classnames/text/index.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React, { Component } from 'react';
2+
import Input from 'react-component_input';
3+
4+
class TextExample extends Component {
5+
render() {
6+
return (
7+
<div>
8+
<Input
9+
identifier="textInput"
10+
labelContent="Text Input"
11+
type="text"
12+
containerClassNames={["text-custom-container", "my-text-custom-container"]}
13+
inputClassNames={["text-custom-input", "my-text-custom-input"]}
14+
labelClassNames={["text-custom-label", "my-text-custom-label"]}
15+
validationClassNames={["text-custom-validation", "my-text-custom-validation"]}
16+
/>
17+
</div>
18+
);
19+
}
20+
}
21+
22+
export default {
23+
label: "Input - Text",
24+
app: TextExample
25+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React, { Component } from 'react';
2+
import Input from 'react-component_input';
3+
4+
class Textarea extends Component {
5+
6+
render() {
7+
return (
8+
<div>
9+
<Input
10+
type="textarea"
11+
identifier="textarea"
12+
labelContent="Text Area"
13+
containerClassNames={["textarea-custom-container", "my-textarea-custom-container"]}
14+
inputClassNames={["textarea-custom-input", "my-textarea-custom-input"]}
15+
labelClassNames={["textarea-custom-label", "my-textarea-custom-label"]}
16+
validationClassNames={["textarea-custom-validation", "my-textarea-custom-validation"]}
17+
/>
18+
</div>
19+
);
20+
}
21+
}
22+
23+
export default {
24+
label: "Input - Textarea",
25+
app: Textarea
26+
};

examples/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ <h2>An input component to serve the common good</h2>
1212
</header>
1313
<div id="example" class="padbox">
1414
<a href="/basic/">basic</a>
15+
<a href="/classnames/">classnames</a>
1516
<a href="/bootstrapped/">bootstrapped</a>
1617
<a href="/validation/">validation</a>
1718
<a href="/validationcss/">validation (With recommended min css)</a>

specs/Input.test.js

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ it("container has appropriate classes", () => {
4848
<Input type="text" identifier="testInput" labelContent="Test Input" />
4949
);
5050
let container = wrapper.find(
51-
"[className='input input-container input-text container-untouched container-nofocus']"
51+
"[className='input input-container input-text input-untouched input-nofocus input-novalidation']"
5252
);
5353

5454
expect(container.length).toEqual(1);
@@ -64,7 +64,7 @@ it("container has appropriate classes when over-ridden with single string", () =
6464
/>
6565
);
6666
let container = wrapper.find(
67-
"[className='reniatnoc container-untouched container-nofocus']"
67+
"[className='reniatnoc reniatnoc-container reniatnoc-text reniatnoc-untouched reniatnoc-nofocus reniatnoc-novalidation']"
6868
);
6969

7070
expect(container.length).toEqual(1);
@@ -80,7 +80,7 @@ it("container has appropriate classes when over-ridden with array of strings", (
8080
/>
8181
);
8282
let container = wrapper.find(
83-
"[className='reniatnoc reniatno container-untouched container-nofocus']"
83+
"[className='reniatnoc reniatnoc-container reniatnoc-text reniatnoc-untouched reniatnoc-nofocus reniatnoc-novalidation reniatno reniatno-container reniatno-text reniatno-untouched reniatno-nofocus reniatno-novalidation']"
8484
);
8585

8686
expect(container.length).toEqual(1);
@@ -100,7 +100,7 @@ it("label should have appropraite classes", () => {
100100
<Input type="text" identifier="testInput" labelContent="Test Input" />
101101
);
102102
let label = wrapper.find(
103-
"[className='label label-container label-text label-untouched label-nofocus']"
103+
"[className='label label-container label-text label-untouched label-nofocus label-novalidation']"
104104
);
105105

106106
expect(label.length).toEqual(1);
@@ -116,7 +116,7 @@ it("label should have appropraite classes when over-ridden with an array of stri
116116
/>
117117
);
118118
let label = wrapper.find(
119-
"[className='lebal leba label-untouched label-nofocus']"
119+
"[className='lebal lebal-container lebal-text lebal-untouched lebal-nofocus lebal-novalidation leba leba-container leba-text leba-untouched leba-nofocus leba-novalidation']"
120120
);
121121

122122
expect(label.length).toEqual(1);
@@ -136,7 +136,7 @@ it("input should have appropriate classes", () => {
136136
<Input type="text" identifier="testInput" labelContent="Test Input" />
137137
);
138138
let input = wrapper.find(
139-
"[className='text text-container input-untouched input-nofocus']"
139+
"[className='input input-container input-text input-untouched input-nofocus input-novalidation']"
140140
);
141141

142142
expect(input.length).toEqual(1);
@@ -152,7 +152,7 @@ it("input should have appropriate classes when over-ridden with an array of stri
152152
/>
153153
);
154154
let input = wrapper.find(
155-
"[className='tupni tupn input-untouched input-nofocus']"
155+
"[className='tupni tupni-container tupni-text tupni-untouched tupni-nofocus tupni-novalidation tupn tupn-container tupn-text tupn-untouched tupn-nofocus tupn-novalidation']"
156156
);
157157

158158
expect(input.length).toEqual(1);
@@ -182,7 +182,7 @@ it("p (validation) should have appropriate classes", () => {
182182
/>
183183
);
184184
let input = wrapper.find(
185-
"[className='validation validation-container validation-text validation-untouched validation-nofocus validation-invalid']"
185+
"[className='validation validation-container validation-text validation-untouched validation-nofocus validation-validation validation-invalid']"
186186
);
187187

188188
expect(input.length).toEqual(1);
@@ -199,7 +199,7 @@ it("p (validation) should have appropriate classes when over-ridden by an array
199199
/>
200200
);
201201
let input = wrapper.find(
202-
"[className='noitadilav noitadila validation-untouched validation-nofocus validation-invalid']"
202+
"[className='noitadilav noitadilav-container noitadilav-text noitadilav-untouched noitadilav-nofocus noitadilav-validation noitadilav-invalid noitadila noitadila-container noitadila-text noitadila-untouched noitadila-nofocus noitadila-validation noitadila-invalid']"
203203
);
204204

205205
expect(input.length).toEqual(1);
@@ -282,89 +282,89 @@ it("accepts, and renders, placeholder property text - control (ensures no false
282282
expect(placeholder.length).toEqual(0);
283283
});
284284

285-
it("component contains a container-nofocus class default", () => {
285+
it("component contains a text-nofocus class default", () => {
286286
const wrapper = shallow(
287287
<Input type="text" identifier="testInput" labelContent="Test Input" />
288288
);
289289

290-
let hasNoFocus = wrapper.find(".container-nofocus");
290+
let hasNoFocus = wrapper.find(".text-nofocus");
291291

292292
expect(hasNoFocus.length).toEqual(1);
293293
});
294294

295-
it("component contains a container-focus class upon receiving focus", () => {
295+
it("component contains a text-focus class upon receiving focus", () => {
296296
const wrapper = shallow(
297297
<Input type="text" identifier="testInput" labelContent="Test Input" />
298298
);
299299

300-
let hasNoFocus = wrapper.find(".container-nofocus");
300+
let hasNoFocus = wrapper.find(".text-nofocus");
301301

302302
expect(hasNoFocus.length).toEqual(1);
303303

304304
wrapper.find("input").simulate("focus");
305305

306-
let nowHasFocus = wrapper.find(".container-focus");
306+
let nowHasFocus = wrapper.find(".text-focus");
307307

308308
expect(nowHasFocus.length).toEqual(1);
309309
});
310310

311-
it("component contains a container-nofocus class upon receiving focus, then again losing focus", () => {
311+
it("component contains a text-nofocus class upon receiving focus, then again losing focus", () => {
312312
const wrapper = shallow(
313313
<Input type="text" identifier="testInput" labelContent="Test Input" />
314314
);
315315

316-
let hasNoFocus = wrapper.find(".container-nofocus");
316+
let hasNoFocus = wrapper.find(".text-nofocus");
317317
expect(hasNoFocus.length).toEqual(1);
318318

319319
wrapper.find("input").simulate("focus");
320-
let nowHasFocus = wrapper.find(".container-focus");
320+
let nowHasFocus = wrapper.find(".text-focus");
321321
expect(nowHasFocus.length).toEqual(1);
322322

323323
wrapper.find("input").simulate("blur");
324-
let noLongerHasFocus = wrapper.find(".container-nofocus");
324+
let noLongerHasFocus = wrapper.find(".text-nofocus");
325325
expect(noLongerHasFocus.length).toEqual(1);
326326
});
327327

328-
it("component contains a container-untouched class default", () => {
328+
it("component contains a text-untouched class default", () => {
329329
const wrapper = shallow(
330330
<Input type="text" identifier="testInput" labelContent="Test Input" />
331331
);
332332

333-
let hasNoTouched = wrapper.find(".container-untouched");
333+
let hasNoTouched = wrapper.find(".text-untouched");
334334

335335
expect(hasNoTouched.length).toEqual(1);
336336
});
337337

338-
it("component contains a container-focus class upon change (touched)", () => {
338+
it("component contains a text-focus class upon change (touched)", () => {
339339
const wrapper = shallow(
340340
<Input type="text" identifier="testInput" labelContent="Test Input" />
341341
);
342342

343-
let hasNoTouched = wrapper.find(".container-untouched");
343+
let hasNoTouched = wrapper.find(".text-untouched");
344344

345345
expect(hasNoTouched.length).toEqual(1);
346346

347347
wrapper.find("input").simulate("change", { target: { value: "a" } });
348348

349-
let nowHasTouched = wrapper.find(".container-touched");
349+
let nowHasTouched = wrapper.find(".text-touched");
350350

351351
expect(nowHasTouched.length).toEqual(1);
352352
});
353353

354-
it("component contains a container-untouched class upon change (Touched), and is retained on blur", () => {
354+
it("component contains a text-untouched class upon change (Touched), and is retained on blur", () => {
355355
const wrapper = shallow(
356356
<Input type="text" identifier="testInput" labelContent="Test Input" />
357357
);
358358

359-
let hasNoTouched = wrapper.find(".container-untouched");
359+
let hasNoTouched = wrapper.find(".text-untouched");
360360
expect(hasNoTouched.length).toEqual(1);
361361

362362
wrapper.find("input").simulate("change", { target: { value: "a" } });
363-
let nowHasTouched = wrapper.find(".container-touched");
363+
let nowHasTouched = wrapper.find(".text-touched");
364364
expect(nowHasTouched.length).toEqual(1);
365365

366366
wrapper.find("input").simulate("blur");
367-
let stillRetainsTouched = wrapper.find(".container-touched");
367+
let stillRetainsTouched = wrapper.find(".text-touched");
368368
expect(stillRetainsTouched.length).toEqual(1);
369369
});
370370

0 commit comments

Comments
 (0)