From c518024d9ca33b6d59818c263b2a755313036618 Mon Sep 17 00:00:00 2001 From: André Oliveira <37463445+SpecialAro@users.noreply.github.com> Date: Sun, 12 Jun 2022 03:20:22 +0530 Subject: Feature: Add color picker component for accent color setting (#228) Co-authored-by: Vijay A --- package-lock.json | 94 ++++++++++++++++++ package.json | 1 + .../settings/settings/EditSettingsForm.js | 40 +++++--- src/components/ui/ColorPickerInput.tsx | 107 +++++++++++++++++++++ src/i18n/locales/en-US.json | 3 +- src/styles/settings.scss | 20 ++++ 6 files changed, 252 insertions(+), 13 deletions(-) create mode 100644 src/components/ui/ColorPickerInput.tsx diff --git a/package-lock.json b/package-lock.json index 3f7c9a06c..8e550ef08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,6 +62,7 @@ "prop-types": "^15.8.1", "react": "^17.0.2", "react-addons-css-transition-group": "^15.6.2", + "react-color": "2.19.3", "react-confetti": "^6.0.1", "react-dom": "^17.0.2", "react-dropzone": "^11.7.1", @@ -3414,6 +3415,14 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -20075,6 +20084,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -20652,6 +20666,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -24102,6 +24121,23 @@ "react": "^15.4.2" } }, + "node_modules/react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "dependencies": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-confetti": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", @@ -24372,6 +24408,14 @@ "csstype": "^3.0.2" } }, + "node_modules/reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "dependencies": { + "lodash": "^4.0.1" + } + }, "node_modules/reactive-localstorage": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/reactive-localstorage/-/reactive-localstorage-0.0.2.tgz", @@ -27747,6 +27791,14 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "node_modules/tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==", + "engines": { + "node": "*" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -33442,6 +33494,11 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==" + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -46577,6 +46634,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -47063,6 +47125,11 @@ } } }, + "material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -49793,6 +49860,20 @@ "react-transition-group": "^1.2.0" } }, + "react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "requires": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + } + }, "react-confetti": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", @@ -50003,6 +50084,14 @@ } } }, + "reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "requires": { + "lodash": "^4.0.1" + } + }, "reactive-localstorage": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/reactive-localstorage/-/reactive-localstorage-0.0.2.tgz", @@ -52757,6 +52846,11 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "tinycolor2": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz", + "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/package.json b/package.json index 6c982cabf..b00128a80 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,7 @@ "prop-types": "^15.8.1", "react": "^17.0.2", "react-addons-css-transition-group": "^15.6.2", + "react-color": "2.19.3", "react-confetti": "^6.0.1", "react-dom": "^17.0.2", "react-dropzone": "^11.7.1", diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 1d61a7510..3f36f5e44 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js @@ -12,6 +12,7 @@ import Button from '../../ui/button'; import Toggle from '../../ui/Toggle'; import Select from '../../ui/Select'; import Input from '../../ui/Input'; +import ColorPickerInput from '../../ui/ColorPickerInput'; import Infobox from '../../ui/Infobox'; import { H1, H2, H3, H5 } from '../../ui/headline'; @@ -115,15 +116,19 @@ const messages = defineMessages({ id: 'settings.app.sectionServiceIconsSettings', defaultMessage: 'Service Icons Settings', }, - universalDarkModeInfo: { - id: 'settings.app.universalDarkModeInfo', - defaultMessage: - 'Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.', + sectionAccentColorSettings: { + id: 'settings.app.sectionAccentColorSettings', + defaultMessage: 'Accent Color Settings', }, accentColorInfo: { id: 'settings.app.accentColorInfo', defaultMessage: - 'Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})', + 'Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor} or clear the input field)', + }, + universalDarkModeInfo: { + id: 'settings.app.universalDarkModeInfo', + defaultMessage: + 'Universal Dark Mode tries to dynamically generate dark mode styles for services that are otherwise not currently supported.', }, headlinePrivacy: { id: 'settings.app.headlinePrivacy', @@ -595,18 +600,29 @@ class EditSettingsForm extends Component { )}
- - this.submit(e)} - field={form.$('accentColor')} - /> +

+ {intl.formatMessage(messages.sectionAccentColorSettings)} +

+
+ this.submit(e)} + field={form.$('accentColor')} + className='color-picker-input' + /> + <> +

{intl.formatMessage(messages.accentColorInfo, { defaultAccentColor: DEFAULT_APP_SETTINGS.accentColor, })}

-

diff --git a/src/components/ui/ColorPickerInput.tsx b/src/components/ui/ColorPickerInput.tsx new file mode 100644 index 000000000..7cbdb295b --- /dev/null +++ b/src/components/ui/ColorPickerInput.tsx @@ -0,0 +1,107 @@ +import { ChangeEvent, Component } from 'react'; +import { observer } from 'mobx-react'; +import { Field } from 'mobx-react-form'; +import classnames from 'classnames'; +import { SliderPicker } from 'react-color'; +import { DEFAULT_APP_SETTINGS } from '../../config'; + +interface IProps { + field: Field; + className?: string; + focus?: boolean; +}; + +interface IState { + background: string; +} + +class ColorPickerInput extends Component { + static defaultProps = { + className: null, + focus: false, + }; + + state = { + background: DEFAULT_APP_SETTINGS.accentColor, + }; + + inputElement: HTMLInputElement | null | undefined; + + componentDidMount() { + if (this.props.focus) { + this.focus(); + } + } + + onChange(e: ChangeEvent) { + const { field } = this.props; + + field.onChange(e); + } + + focus() { + this.inputElement?.focus(); + } + + handleChangeComplete = (color: { hex: string; }) => { + const { field } = this.props; + this.setState({ background: color.hex }); + field.value = color.hex + }; + + render() { + const { + field, + className, + } = this.props; + + let { type } = field; + type = 'text'; + + return ( +
+ { + this.inputElement = element; + }} + disabled={field.disabled} + /> +
+ this.onChange(e)} + onBlur={field.onBlur} + onFocus={field.onFocus} + ref={element => { + this.inputElement = element; + }} + disabled={field.disabled} + /> +
+
+ ); + } +} + +export default observer(ColorPickerInput); diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index f787b90e4..3c5eef258 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -182,7 +182,7 @@ "settings.account.tryReloadUserInfoRequest": "Try again", "settings.account.userInfoRequestFailed": "Could not load user information", "settings.account.yourLicense": "Your Ferdium License:", - "settings.app.accentColorInfo": "Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor})", + "settings.app.accentColorInfo": "Write your accent color in a CSS-compatible format. (Default: {defaultAccentColor} or clear the input field)", "settings.app.buttonClearAllCache": "Clear cache", "settings.app.buttonInstallUpdate": "Restart & install update", "settings.app.buttonOpenFerdiumProfileFolder": "Open Profile folder", @@ -267,6 +267,7 @@ "settings.app.restartRequired": "Changes require restart", "settings.app.scheduledDNDInfo": "Scheduled Do-not-Disturb allows you to define a period of time in which you do not want to get Notifications from Ferdium.", "settings.app.scheduledDNDTimeInfo": "Times in 24-Hour-Format. End time can be before start time (e.g. start 17:00, end 09:00) to enable Do-not-Disturb overnight.", + "settings.app.sectionAccentColorSettings": "Accent Color Settings", "settings.app.sectionGeneralUi": "General UI", "settings.app.sectionHibernation": "Hibernation", "settings.app.sectionMain": "Main", diff --git a/src/styles/settings.scss b/src/styles/settings.scss index 2bb9074ba..e2cf46478 100644 --- a/src/styles/settings.scss +++ b/src/styles/settings.scss @@ -176,6 +176,26 @@ overflow: hidden; background: #fff; } + + .settings__section_header { + text-align: center; + } + + .settings__settings-group__apply-color { + display: flex; + } + + .settings__settings-group__apply-color__button { + height: 60px; + } + + .franz-form__input-wrapper__color-picker { + width: 20% !important; + margin-top: 2%; + } + .color-picker-input { + align-items: center; + } .settings__header { align-items: center; -- cgit v1.2.3-54-g00ecf