aboutsummaryrefslogtreecommitdiff
path: root/src/settings/components
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2020-09-21 16:08:44 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2020-09-21 22:07:55 +0900
commitc28ae6b82860693b8e6b012a939fb8a3dd320e23 (patch)
tree2f690587d6c3b83453f52b070151a4c5996028e8 /src/settings/components
parent063ceb215f858a8e2a5bde85d8f9ca24240894c6 (diff)
Introduce styled-components on settings ui
Diffstat (limited to 'src/settings/components')
-rw-r--r--src/settings/components/site.scss8
-rw-r--r--src/settings/components/ui/AddButton.scss13
-rw-r--r--src/settings/components/ui/AddButton.tsx31
-rw-r--r--src/settings/components/ui/DeleteButton.scss13
-rw-r--r--src/settings/components/ui/DeleteButton.tsx30
-rw-r--r--src/settings/components/ui/Input.scss29
-rw-r--r--src/settings/components/ui/Radio.tsx59
-rw-r--r--src/settings/components/ui/Text.tsx70
-rw-r--r--src/settings/components/ui/TextArea.tsx76
9 files changed, 145 insertions, 184 deletions
diff --git a/src/settings/components/site.scss b/src/settings/components/site.scss
index c0c4f9e..e8415e8 100644
--- a/src/settings/components/site.scss
+++ b/src/settings/components/site.scss
@@ -1,12 +1,6 @@
.vimvixen-settings-form {
padding: 2px;
-
- textarea[name=json] {
- font-family: monospace;
- width: 100%;
- min-height: 64ex;
- resize: vertical;
- }
+ font-family: system-ui;
fieldset {
margin: 0;
diff --git a/src/settings/components/ui/AddButton.scss b/src/settings/components/ui/AddButton.scss
deleted file mode 100644
index beb5688..0000000
--- a/src/settings/components/ui/AddButton.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-.ui-add-button {
- border: none;
- padding: 4;
- display: inline;
- background: none;
- font-weight: bold;
- color: green;
- cursor: pointer;
-
- &:hover {
- color: darkgreen;
- }
-}
diff --git a/src/settings/components/ui/AddButton.tsx b/src/settings/components/ui/AddButton.tsx
index c15a732..8cf4300 100644
--- a/src/settings/components/ui/AddButton.tsx
+++ b/src/settings/components/ui/AddButton.tsx
@@ -1,19 +1,24 @@
-import "./AddButton.scss";
import React from "react";
+import styled from "styled-components";
-type Props = React.AllHTMLAttributes<HTMLInputElement>;
+const Button = styled.input`
+ border: none;
+ padding: 4;
+ display: inline;
+ background: none;
+ font-weight: bold;
+ color: green;
+ cursor: pointer;
-class AddButton extends React.Component<Props> {
- render() {
- return (
- <input
- className="ui-add-button"
- type="button"
- value="&#x271a;"
- {...this.props}
- />
- );
+ &:hover {
+ color: darkgreen;
}
-}
+`;
+
+type Props = React.InputHTMLAttributes<HTMLInputElement>;
+
+const AddButton: React.FC<Props> = (props) => (
+ <Button type="button" value="&#x271a;" {...props} />
+);
export default AddButton;
diff --git a/src/settings/components/ui/DeleteButton.scss b/src/settings/components/ui/DeleteButton.scss
deleted file mode 100644
index 5932a72..0000000
--- a/src/settings/components/ui/DeleteButton.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-
-.ui-delete-button {
- border: none;
- padding: 4;
- display: inline;
- background: none;
- color: red;
- cursor: pointer;
-
- &:hover {
- color: darkred;
- }
-}
diff --git a/src/settings/components/ui/DeleteButton.tsx b/src/settings/components/ui/DeleteButton.tsx
index df8976e..ce0183b 100644
--- a/src/settings/components/ui/DeleteButton.tsx
+++ b/src/settings/components/ui/DeleteButton.tsx
@@ -1,19 +1,23 @@
-import "./DeleteButton.scss";
import React from "react";
+import styled from "styled-components";
-type Props = React.AllHTMLAttributes<HTMLInputElement>;
+const Button = styled.input`
+ border: none;
+ padding: 4;
+ display: inline;
+ background: none;
+ color: red;
+ cursor: pointer;
-class DeleteButton extends React.Component<Props> {
- render() {
- return (
- <input
- className="ui-delete-button"
- type="button"
- value="&#x2716;"
- {...this.props}
- />
- );
+ &:hover {
+ color: darkred;
}
-}
+`;
+
+type Props = React.InputHTMLAttributes<HTMLInputElement>;
+
+const DeleteButton: React.FC<Props> = (props) => (
+ <Button type="button" value="&#x2716;" {...props} />
+);
export default DeleteButton;
diff --git a/src/settings/components/ui/Input.scss b/src/settings/components/ui/Input.scss
deleted file mode 100644
index ad4daf8..0000000
--- a/src/settings/components/ui/Input.scss
+++ /dev/null
@@ -1,29 +0,0 @@
-.settings-ui-input {
- page-break-inside: avoid;
-
- * {
- page-break-inside: avoid;
- }
-
- label {
- font-weight: bold;
- min-width: 14rem;
- display: inline-block;
- }
-
- input[type='text'] {
- padding: 4px;
- width: 8rem;
- }
-
- input.input-crror,
- textarea.input-error {
- box-shadow: 0 0 2px red;
- }
-
- &-error {
- font-weight: bold;
- color: red;
- min-height: 1.5em;
- }
-}
diff --git a/src/settings/components/ui/Radio.tsx b/src/settings/components/ui/Radio.tsx
index 20d4ad6..c0d4dd9 100644
--- a/src/settings/components/ui/Radio.tsx
+++ b/src/settings/components/ui/Radio.tsx
@@ -1,44 +1,33 @@
import React from "react";
-import "./Input.scss";
+import styled from "styled-components";
-interface Props extends React.AllHTMLAttributes<HTMLElement> {
- name: string;
- error?: string;
+const Container = styled.div`
+ font-family: system-ui;
+`;
+
+interface Props extends React.InputHTMLAttributes<HTMLInputElement> {
label: string;
- value: string;
onValueChange?: (name: string, value: string) => void;
- onBlur?: (e: React.FocusEvent<Element>) => void;
}
-class Input extends React.Component<Props> {
- renderRadio(props: Props) {
- const inputClassName = props.error ? "input-error" : "";
- const pp = { ...props };
- delete pp.onValueChange;
- return (
- <div className="settings-ui-input">
- <label>
- <input
- type="radio"
- className={inputClassName}
- onChange={this.bindOnChange.bind(this)}
- {...pp}
- />
- {props.label}
- </label>
- </div>
- );
- }
+const Radio: React.FC<Props> = (props) => {
+ const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ if (props.onValueChange) {
+ props.onValueChange(e.target.name, e.target.value);
+ }
+ };
- render() {
- return this.renderRadio(this.props);
- }
+ const pp = { ...props };
+ delete pp.onValueChange;
- bindOnChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
- if (this.props.onValueChange) {
- this.props.onValueChange(e.target.name, e.target.value);
- }
- }
-}
+ return (
+ <Container>
+ <label htmlFor={props.id}>
+ <input type="radio" onChange={onChange} {...pp} />
+ {props.label}
+ </label>
+ </Container>
+ );
+};
-export default Input;
+export default Radio;
diff --git a/src/settings/components/ui/Text.tsx b/src/settings/components/ui/Text.tsx
index 7ecef88..700b08a 100644
--- a/src/settings/components/ui/Text.tsx
+++ b/src/settings/components/ui/Text.tsx
@@ -1,42 +1,54 @@
import React from "react";
-import "./Input.scss";
+import styled from "styled-components";
-interface Props extends React.AllHTMLAttributes<HTMLElement> {
+const Container = styled.div`
+ page-break-inside: avoid;
+`;
+
+const Input = styled.input<{ hasError: boolean }>`
+ padding: 4px;
+ width: 8rem;
+ box-shadow: ${({ hasError }) => (hasError ? "0 0 2px red" : "none")};
+`;
+
+const Label = styled.label`
+ font-weight: bold;
+ min-width: 14rem;
+ display: inline-block;
+`;
+
+interface Props extends React.HTMLAttributes<HTMLElement> {
name: string;
error?: string;
label: string;
value: string;
onValueChange?: (name: string, value: string) => void;
- onBlur?: (e: React.FocusEvent<Element>) => void;
}
-class Input extends React.Component<Props> {
- renderText(props: Props) {
- const inputClassName = props.error ? "input-error" : "";
- const pp = { ...props };
- delete pp.onValueChange;
- return (
- <div className="settings-ui-input">
- <label htmlFor={props.id}>{props.label}</label>
- <input
+const Text: React.FC<Props> = (props) => {
+ const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ if (props.onValueChange) {
+ props.onValueChange(e.target.name, e.target.value);
+ }
+ };
+
+ const pp = { ...props };
+ delete pp.onValueChange;
+
+ return (
+ <Container>
+ <Label>
+ {props.label}
+ <br />
+ <Input
type="text"
- className={inputClassName}
- onChange={this.bindOnChange.bind(this)}
+ hasError={props.error !== undefined}
+ onChange={onChange}
{...pp}
/>
- </div>
- );
- }
-
- render() {
- return this.renderText(this.props);
- }
-
- bindOnChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
- if (this.props.onValueChange) {
- this.props.onValueChange(e.target.name, e.target.value);
- }
- }
-}
+ </Label>
+ </Container>
+ );
+};
-export default Input;
+export default Text;
diff --git a/src/settings/components/ui/TextArea.tsx b/src/settings/components/ui/TextArea.tsx
index f2b832f..58b7bd3 100644
--- a/src/settings/components/ui/TextArea.tsx
+++ b/src/settings/components/ui/TextArea.tsx
@@ -1,42 +1,54 @@
import React from "react";
-import "./Input.scss";
+import styled from "styled-components";
-interface Props extends React.AllHTMLAttributes<HTMLElement> {
- name: string;
+const Container = styled.div`
+ page-break-inside: avoid;
+`;
+
+const Label = styled.label`
+ font-weight: bold;
+ min-width: 14rem;
+ display: inline-block;
+`;
+
+const ErrorableTextArea = styled.textarea<{ hasError: boolean }>`
+ box-shadow: ${({ hasError }) => (hasError ? "0 0 2px red" : "none")};
+ font-family: monospace;
+ font-family: monospace;
+ width: 100%;
+ min-height: 64ex;
+ resize: vertical;
+`;
+
+const ErrorMessage = styled.p`
+ font-weight: bold;
+ color: red;
+ min-height: 1.5em;
+`;
+
+interface Props extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
error?: string;
label: string;
- value: string;
onValueChange?: (name: string, value: string) => void;
- onBlur?: (e: React.FocusEvent<Element>) => void;
}
-class TextArea extends React.Component<Props> {
- renderTextArea(props: Props) {
- const inputClassName = props.error ? "input-error" : "";
- const pp = { ...props };
- delete pp.onValueChange;
- return (
- <div className="settings-ui-input">
- <label htmlFor={props.id}>{props.label}</label>
- <textarea
- className={inputClassName}
- onChange={this.bindOnChange.bind(this)}
- {...pp}
- />
- <p className="settings-ui-input-error">{this.props.error}</p>
- </div>
- );
- }
-
- render() {
- return this.renderTextArea(this.props);
- }
-
- bindOnChange(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
- if (this.props.onValueChange) {
- this.props.onValueChange(e.target.name, e.target.value);
+const TextArea: React.FC<Props> = (props) => {
+ const onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
+ if (props.onValueChange) {
+ props.onValueChange(e.target.name, e.target.value);
}
- }
-}
+ };
+
+ const hasError = typeof props.error !== "undefined" && props.error !== "";
+ const pp = { ...props };
+ delete pp.onValueChange;
+ return (
+ <Container>
+ <Label htmlFor={props.id}>{props.label}</Label>
+ <ErrorableTextArea hasError={hasError} onChange={onChange} {...pp} />
+ {hasError ? <ErrorMessage>{props.error}</ErrorMessage> : null}
+ </Container>
+ );
+};
export default TextArea;