diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2020-09-21 16:08:44 +0900 |
---|---|---|
committer | Shin'ya Ueoka <ueokande@i-beam.org> | 2020-09-21 22:07:55 +0900 |
commit | c28ae6b82860693b8e6b012a939fb8a3dd320e23 (patch) | |
tree | 2f690587d6c3b83453f52b070151a4c5996028e8 /src/settings | |
parent | 063ceb215f858a8e2a5bde85d8f9ca24240894c6 (diff) |
Introduce styled-components on settings ui
Diffstat (limited to 'src/settings')
-rw-r--r-- | src/settings/components/site.scss | 8 | ||||
-rw-r--r-- | src/settings/components/ui/AddButton.scss | 13 | ||||
-rw-r--r-- | src/settings/components/ui/AddButton.tsx | 31 | ||||
-rw-r--r-- | src/settings/components/ui/DeleteButton.scss | 13 | ||||
-rw-r--r-- | src/settings/components/ui/DeleteButton.tsx | 30 | ||||
-rw-r--r-- | src/settings/components/ui/Input.scss | 29 | ||||
-rw-r--r-- | src/settings/components/ui/Radio.tsx | 59 | ||||
-rw-r--r-- | src/settings/components/ui/Text.tsx | 70 | ||||
-rw-r--r-- | src/settings/components/ui/TextArea.tsx | 76 |
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="✚" - {...this.props} - /> - ); + &:hover { + color: darkgreen; } -} +`; + +type Props = React.InputHTMLAttributes<HTMLInputElement>; + +const AddButton: React.FC<Props> = (props) => ( + <Button type="button" value="✚" {...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="✖" - {...this.props} - /> - ); + &:hover { + color: darkred; } -} +`; + +type Props = React.InputHTMLAttributes<HTMLInputElement>; + +const DeleteButton: React.FC<Props> = (props) => ( + <Button type="button" value="✖" {...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; |