From 969eda02a66050cf4518ddfa657e86d1d6d8b6c3 Mon Sep 17 00:00:00 2001 From: Markus Hatvan Date: Tue, 10 Aug 2021 19:04:54 +0200 Subject: feat: follow OS reduced motion setting (#1757) - add missing meta charset to index.html - dont restrict scaling for user in index.html - load animations.css conditionally based on motion preference - load transitions conditionally in js and css based on motion preference Co-authored-by: Vijay Raghavan Aravamudhan --- src/components/auth/SetupAssistant.js | 110 ++++++----- src/components/layout/AppLayout.js | 86 +++++---- .../services/content/ConnectionLostBanner.js | 36 ++-- src/components/services/tabs/TabItem.js | 193 +++++++++++-------- src/components/ui/AppLoader/styles.js | 8 +- src/features/webControls/components/WebControls.js | 65 +++---- .../workspaces/components/WorkspaceDrawerItem.js | 47 +++-- .../components/WorkspaceSwitchingIndicator.js | 23 ++- src/i18n/locales/defaultMessages.json | 46 ++--- .../src/components/auth/SetupAssistant.json | 10 +- .../messages/src/components/layout/AppLayout.json | 2 +- .../services/content/ConnectionLostBanner.json | 12 +- .../src/components/services/tabs/TabItem.json | 2 +- .../webControls/components/WebControls.json | 20 +- src/index.html | 122 +++++++----- src/internal-server/public/css/main.css | 11 +- src/styles/button.scss | 91 ++++++--- src/styles/content-tabs.scss | 29 ++- src/styles/fonts.scss | 6 + src/styles/image-upload.scss | 32 +++- src/styles/layout.scss | 70 +++++-- src/styles/main.scss | 1 - src/styles/radio.scss | 19 +- src/styles/recipes.scss | 36 ++-- src/styles/settings.scss | 213 +++++++++++++++------ src/styles/slider.scss | 29 +-- src/styles/tabs.scss | 58 ++++-- src/styles/toggle.scss | 4 +- src/styles/type.scss | 46 +++-- src/styles/welcome.scss | 36 ++-- src/webview/screenshare.js | 16 +- 31 files changed, 924 insertions(+), 555 deletions(-) (limited to 'src') diff --git a/src/components/auth/SetupAssistant.js b/src/components/auth/SetupAssistant.js index bd9069eb7..06ab09892 100644 --- a/src/components/auth/SetupAssistant.js +++ b/src/components/auth/SetupAssistant.js @@ -18,15 +18,16 @@ const SLACK_ID = 'slack'; const messages = defineMessages({ headline: { id: 'setupAssistant.headline', - defaultMessage: '!!!Let\'s get started', + defaultMessage: "!!!Let's get started", }, subHeadline: { id: 'setupAssistant.subheadline', - defaultMessage: '!!!Choose from our most used services and get back on top of your messaging now.', + defaultMessage: + '!!!Choose from our most used services and get back on top of your messaging now.', }, submitButtonLabel: { id: 'setupAssistant.submit.label', - defaultMessage: '!!!Let\'s go', + defaultMessage: "!!!Let's go", }, inviteSuccessInfo: { id: 'invite.successInfo', @@ -34,14 +35,19 @@ const messages = defineMessages({ }, }); -const styles = (theme) => ({ +let transition = 'none'; + +if (window.matchMedia('(prefers-reduced-motion: no-preference)')) { + transition = 'all 0.25s'; +} + +const styles = theme => ({ root: { width: '500px !important', textAlign: 'center', padding: 20, - '& h1': { - }, + '& h1': {}, }, servicesGrid: { display: 'flex', @@ -60,7 +66,7 @@ const styles = (theme) => ({ borderRadius: theme.borderRadius, marginBottom: 10, opacity: 0.5, - transition: 'all 0.25s', + transition, border: [3, 'solid', 'transparent'], '& h2': { @@ -70,10 +76,8 @@ const styles = (theme) => ({ '&:hover': { border: [3, 'solid', theme.brandPrimary], - '& $serviceIcon': { - }, + '& $serviceIcon': {}, }, - }, selected: { border: [3, 'solid', theme.brandPrimary], @@ -82,7 +86,7 @@ const styles = (theme) => ({ }, serviceIcon: { width: 50, - transition: 'all 0.25s', + transition, }, slackModalContent: { @@ -125,7 +129,8 @@ const styles = (theme) => ({ }, }); -@injectSheet(styles) @observer +@injectSheet(styles) +@observer class SetupAssistant extends Component { static propTypes = { classes: PropTypes.object.isRequired, @@ -144,13 +149,17 @@ class SetupAssistant extends Component { }; state = { - services: [{ - id: 'whatsapp', - }, { - id: 'messenger', - }, { - id: 'gmail', - }], + services: [ + { + id: 'whatsapp', + }, + { + id: 'messenger', + }, + { + id: 'gmail', + }, + ], isSlackModalOpen: false, slackWorkspace: '', }; @@ -158,10 +167,12 @@ class SetupAssistant extends Component { slackWorkspaceHandler() { const { slackWorkspace = '', services } = this.state; - const sanitizedWorkspace = slackWorkspace.trim().replace(/^https?:\/\//, ''); + const sanitizedWorkspace = slackWorkspace + .trim() + .replace(/^https?:\/\//, ''); if (sanitizedWorkspace) { - const index = services.findIndex((s) => s.id === SLACK_ID); + const index = services.findIndex(s => s.id === SLACK_ID); if (index === -1) { const newServices = services; @@ -179,9 +190,17 @@ class SetupAssistant extends Component { render() { const { intl } = this.context; const { - classes, isInviteSuccessful, onSubmit, services, isSettingUpServices, + classes, + isInviteSuccessful, + onSubmit, + services, + isSettingUpServices, } = this.props; - const { isSlackModalOpen, slackWorkspace, services: addedServices } = this.state; + const { + isSlackModalOpen, + slackWorkspace, + services: addedServices, + } = this.state; return (
@@ -197,29 +216,22 @@ class SetupAssistant extends Component { )} - -

- {intl.formatMessage(messages.headline)} -

-

- {intl.formatMessage(messages.subHeadline)} -

+ +

{intl.formatMessage(messages.headline)}

+

{intl.formatMessage(messages.subHeadline)}

- {Object.keys(services).map((id) => { + {Object.keys(services).map(id => { const service = services[id]; return (
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js index ccf3333f8..023e152c7 100644 --- a/src/components/services/tabs/TabItem.js +++ b/src/components/services/tabs/TabItem.js @@ -1,6 +1,4 @@ -import { - Menu, dialog, app, getCurrentWindow, -} from '@electron/remote'; +import { Menu, dialog, app, getCurrentWindow } from '@electron/remote'; import React, { Component } from 'react'; import { defineMessages, intlShape } from 'react-intl'; import PropTypes from 'prop-types'; @@ -14,7 +12,9 @@ import { observable, autorun } from 'mobx'; import ServiceModel from '../../../models/Service'; import { ctrlKey, cmdKey } from '../../../environment'; -const IS_SERVICE_DEBUGGING_ENABLED = (localStorage.getItem('debug') || '').includes('Ferdi:Service'); +const IS_SERVICE_DEBUGGING_ENABLED = ( + localStorage.getItem('debug') || '' +).includes('Ferdi:Service'); const messages = defineMessages({ reload: { @@ -63,10 +63,21 @@ const messages = defineMessages({ }, confirmDeleteService: { id: 'tabs.item.confirmDeleteService', - defaultMessage: '!!!Do you really want to delete the {serviceName} service?', + defaultMessage: + '!!!Do you really want to delete the {serviceName} service?', }, }); +let pollIndicatorTransition = 'none'; +let polledTransition = 'none'; +let pollAnsweredTransition = 'none'; + +if (window.matchMedia('(prefers-reduced-motion: no-preference)')) { + pollIndicatorTransition = 'background 0.5s'; + polledTransition = 'background 0.1s'; + pollAnsweredTransition = 'background 0.1s'; +} + const styles = { pollIndicator: { position: 'absolute', @@ -75,7 +86,7 @@ const styles = { height: 10, borderRadius: 5, background: 'gray', - transition: 'background 0.5s', + transition: pollIndicatorTransition, }, pollIndicatorPoll: { left: 2, @@ -85,18 +96,20 @@ const styles = { }, polled: { background: 'yellow !important', - transition: 'background 0.1s', + transition: polledTransition, }, pollAnswered: { background: 'green !important', - transition: 'background 0.1s', + transition: pollAnsweredTransition, }, stale: { background: 'red !important', }, }; -@injectSheet(styles) @observer class TabItem extends Component { +@injectSheet(styles) +@observer +class TabItem extends Component { static propTypes = { classes: PropTypes.object.isRequired, service: PropTypes.instanceOf(ServiceModel).isRequired, @@ -131,13 +144,17 @@ const styles = { if (Date.now() - service.lastPoll < ms('0.2s')) { this.isPolled = true; - setTimeout(() => { this.isPolled = false; }, ms('1s')); + setTimeout(() => { + this.isPolled = false; + }, ms('1s')); } if (Date.now() - service.lastPollAnswer < ms('0.2s')) { this.isPollAnswered = true; - setTimeout(() => { this.isPollAnswered = false; }, ms('1s')); + setTimeout(() => { + this.isPollAnswered = false; + }, ms('1s')); } }); } @@ -163,62 +180,85 @@ const styles = { } = this.props; const { intl } = this.context; - const menuTemplate = [{ - label: service.name || service.recipe.name, - enabled: false, - }, { - type: 'separator', - }, { - label: intl.formatMessage(messages.reload), - click: reload, - accelerator: `${cmdKey}+R`, - }, { - label: intl.formatMessage(messages.edit), - click: () => openSettings({ - path: `services/edit/${service.id}`, - }), - }, { - type: 'separator', - }, { - label: service.isNotificationEnabled - ? intl.formatMessage(messages.disableNotifications) - : intl.formatMessage(messages.enableNotifications), - click: () => toggleNotifications(), - }, { - label: service.isMuted - ? intl.formatMessage(messages.enableAudio) - : intl.formatMessage(messages.disableAudio), - click: () => toggleAudio(), - }, { - label: intl.formatMessage(service.isEnabled ? messages.disableService : messages.enableService), - click: () => (service.isEnabled ? disableService() : enableService()), - }, { - label: intl.formatMessage(service.isHibernating ? messages.wakeUpService : messages.hibernateService), - click: () => (service.isHibernating ? wakeUpService() : hibernateService()), - enabled: service.canHibernate, - }, { - type: 'separator', - }, { - label: intl.formatMessage(messages.deleteService), - click: () => { - const selection = dialog.showMessageBoxSync(app.mainWindow, { - type: 'question', - message: intl.formatMessage(messages.deleteService), - detail: intl.formatMessage(messages.confirmDeleteService, { serviceName: service.name || service.recipe.name }), - buttons: [ - 'Yes', - 'No', - ], - }); - if (selection === 0) { - deleteService(); - } + const menuTemplate = [ + { + label: service.name || service.recipe.name, + enabled: false, + }, + { + type: 'separator', + }, + { + label: intl.formatMessage(messages.reload), + click: reload, + accelerator: `${cmdKey}+R`, + }, + { + label: intl.formatMessage(messages.edit), + click: () => + openSettings({ + path: `services/edit/${service.id}`, + }), + }, + { + type: 'separator', }, - }]; + { + label: service.isNotificationEnabled + ? intl.formatMessage(messages.disableNotifications) + : intl.formatMessage(messages.enableNotifications), + click: () => toggleNotifications(), + }, + { + label: service.isMuted + ? intl.formatMessage(messages.enableAudio) + : intl.formatMessage(messages.disableAudio), + click: () => toggleAudio(), + }, + { + label: intl.formatMessage( + service.isEnabled ? messages.disableService : messages.enableService, + ), + click: () => (service.isEnabled ? disableService() : enableService()), + }, + { + label: intl.formatMessage( + service.isHibernating + ? messages.wakeUpService + : messages.hibernateService, + ), + click: () => + (service.isHibernating ? wakeUpService() : hibernateService()), + enabled: service.canHibernate, + }, + { + type: 'separator', + }, + { + label: intl.formatMessage(messages.deleteService), + click: () => { + const selection = dialog.showMessageBoxSync(app.mainWindow, { + type: 'question', + message: intl.formatMessage(messages.deleteService), + detail: intl.formatMessage(messages.confirmDeleteService, { + serviceName: service.name || service.recipe.name, + }), + buttons: ['Yes', 'No'], + }); + if (selection === 0) { + deleteService(); + } + }, + }, + ]; const menu = Menu.buildFromTemplate(menuTemplate); let notificationBadge = null; - if ((showMessageBadgeWhenMutedSetting || service.isNotificationEnabled) && showMessageBadgesEvenWhenMuted && service.isBadgeEnabled) { + if ( + (showMessageBadgeWhenMutedSetting || service.isNotificationEnabled) && + showMessageBadgesEvenWhenMuted && + service.isBadgeEnabled + ) { notificationBadge = ( {service.unreadDirectMessageCount > 0 && ( @@ -226,17 +266,13 @@ const styles = { {service.unreadDirectMessageCount} )} - {service.unreadIndirectMessageCount > 0 - && service.unreadDirectMessageCount === 0 - && service.isIndirectMessageBadgeEnabled && ( - - • - + {service.unreadIndirectMessageCount > 0 && + service.unreadDirectMessageCount === 0 && + service.isIndirectMessageBadgeEnabled && ( + )} {service.isHibernating && ( - - • - + )} ); @@ -245,7 +281,8 @@ const styles = { return (
  • menu.popup(getCurrentWindow())} - data-tip={`${service.name} ${shortcutIndex <= 9 ? `(${ctrlKey}+${shortcutIndex})` : ''}`} + data-tip={`${service.name} ${ + shortcutIndex <= 9 ? `(${ctrlKey}+${shortcutIndex})` : '' + }`} > - + {notificationBadge} {IS_SERVICE_DEBUGGING_ENABLED && ( <> diff --git a/src/components/ui/AppLoader/styles.js b/src/components/ui/AppLoader/styles.js index 755a56b40..011f6282d 100644 --- a/src/components/ui/AppLoader/styles.js +++ b/src/components/ui/AppLoader/styles.js @@ -1,3 +1,9 @@ +let sloganTransition = 'none'; + +if (window.matchMedia('(prefers-reduced-motion: no-preference)')) { + sloganTransition = 'opacity 1s ease'; +} + export default { component: { color: '#FFF', @@ -5,7 +11,7 @@ export default { slogan: { display: 'block', opacity: 0, - transition: 'opacity 1s ease', + transition: sloganTransition, position: 'absolute', textAlign: 'center', width: '100%', diff --git a/src/features/webControls/components/WebControls.js b/src/features/webControls/components/WebControls.js index 1cdd14e55..417ebb0b0 100644 --- a/src/features/webControls/components/WebControls.js +++ b/src/features/webControls/components/WebControls.js @@ -6,7 +6,11 @@ import { Icon } from '@meetfranz/ui'; import { defineMessages, intlShape } from 'react-intl'; import { - mdiReload, mdiArrowRight, mdiArrowLeft, mdiHomeOutline, mdiEarth, + mdiReload, + mdiArrowRight, + mdiArrowLeft, + mdiHomeOutline, + mdiEarth, } from '@mdi/js'; const messages = defineMessages({ @@ -32,7 +36,13 @@ const messages = defineMessages({ }, }); -const styles = (theme) => ({ +let buttonTransition = 'none'; + +if (window.matchMedia('(prefers-reduced-motion: no-preference)')) { + buttonTransition = 'opacity 0.25s'; +} + +const styles = theme => ({ root: { background: theme.colorBackground, position: 'relative', @@ -51,7 +61,7 @@ const styles = (theme) => ({ button: { width: 30, height: 50, - transition: 'opacity 0.25s', + transition: buttonTransition, '&:hover': { opacity: 0.8, @@ -83,7 +93,8 @@ const styles = (theme) => ({ }, }); -@injectSheet(styles) @observer +@injectSheet(styles) +@observer class WebControls extends Component { static propTypes = { classes: PropTypes.object.isRequired, @@ -96,7 +107,7 @@ class WebControls extends Component { openInBrowser: PropTypes.func.isRequired, url: PropTypes.string.isRequired, navigate: PropTypes.func.isRequired, - } + }; static contextTypes = { intl: intlShape, @@ -119,7 +130,7 @@ class WebControls extends Component { state = { inputUrl: '', editUrl: false, - } + }; render() { const { @@ -135,10 +146,7 @@ class WebControls extends Component { navigate, } = this.props; - const { - inputUrl, - editUrl, - } = this.state; + const { inputUrl, editUrl } = this.state; const { intl } = this.context; @@ -151,10 +159,7 @@ class WebControls extends Component { data-tip={intl.formatMessage(messages.goHome)} data-place="bottom" > - + this.setState({ - inputUrl: event.target.value, - })} - onFocus={(event) => { + onChange={event => + this.setState({ + inputUrl: event.target.value, + }) + } + onFocus={event => { console.log('on focus event'); event.target.select(); this.setState({ editUrl: true, }); }} - onKeyDown={(event) => { + onKeyDown={event => { if (event.key === 'Enter') { this.setState({ editUrl: false, @@ -231,10 +229,7 @@ class WebControls extends Component { data-tip={intl.formatMessage(messages.openInBrowser)} data-place="bottom" > - +
  • ); diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.js b/src/features/workspaces/components/WorkspaceDrawerItem.js index 0294f69fc..c3f9fcb19 100644 --- a/src/features/workspaces/components/WorkspaceDrawerItem.js +++ b/src/features/workspaces/components/WorkspaceDrawerItem.js @@ -18,12 +18,18 @@ const messages = defineMessages({ }, }); -const styles = (theme) => ({ +let itemTransition = 'none'; + +if (window.matchMedia('(prefers-reduced-motion: no-preference)')) { + itemTransition = 'background-color 300ms ease-out'; +} + +const styles = theme => ({ item: { height: '67px', padding: `15px ${theme.workspaces.drawer.padding}px`, borderBottom: `1px solid ${theme.workspaces.drawer.listItem.border}`, - transition: 'background-color 300ms ease-out', + transition: itemTransition, '&:first-child': { borderTop: `1px solid ${theme.workspaces.drawer.listItem.border}`, }, @@ -59,7 +65,8 @@ const styles = (theme) => ({ }, }); -@injectSheet(styles) @observer +@injectSheet(styles) +@observer class WorkspaceDrawerItem extends Component { static propTypes = { classes: PropTypes.object.isRequired, @@ -91,15 +98,19 @@ class WorkspaceDrawerItem extends Component { } = this.props; const { intl } = this.context; - const contextMenuTemplate = [{ - label: name, - enabled: false, - }, { - type: 'separator', - }, { - label: intl.formatMessage(messages.contextMenuEdit), - click: onContextMenuEditClick, - }]; + const contextMenuTemplate = [ + { + label: name, + enabled: false, + }, + { + type: 'separator', + }, + { + label: intl.formatMessage(messages.contextMenuEdit), + click: onContextMenuEditClick, + }, + ]; const contextMenu = Menu.buildFromTemplate(contextMenuTemplate); @@ -110,10 +121,12 @@ class WorkspaceDrawerItem extends Component { isActive ? classes.isActiveItem : null, ])} onClick={onClick} - onContextMenu={() => ( + onContextMenu={() => onContextMenuEditClick && contextMenu.popup(getCurrentWindow()) - )} - data-tip={`${shortcutIndex <= 9 ? `(${ctrlKey}+${altKey}+${shortcutIndex})` : ''}`} + } + data-tip={`${ + shortcutIndex <= 9 ? `(${ctrlKey}+${altKey}+${shortcutIndex})` : '' + }`} > - {services.length ? services.join(', ') : intl.formatMessage(messages.noServicesAddedYet)} + {services.length + ? services.join(', ') + : intl.formatMessage(messages.noServicesAddedYet)} ); diff --git a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js index b46959e91..613075c4a 100644 --- a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js +++ b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js @@ -15,12 +15,18 @@ const messages = defineMessages({ }, }); -const styles = (theme) => ({ +let wrapperTransition = 'none'; + +if (window.matchMedia('(prefers-reduced-motion: no-preference)')) { + wrapperTransition = 'width 0.5s ease'; +} + +const styles = theme => ({ wrapper: { display: 'flex', alignItems: 'flex-start', position: 'absolute', - transition: 'width 0.5s ease', + transition: wrapperTransition, width: `calc(100% - ${theme.workspaces.drawer.width}px)`, marginTop: '20px', }, @@ -47,7 +53,8 @@ const styles = (theme) => ({ }, }); -@injectSheet(styles) @observer +@injectSheet(styles) +@observer class WorkspaceSwitchingIndicator extends Component { static propTypes = { classes: PropTypes.object.isRequired, @@ -63,13 +70,11 @@ class WorkspaceSwitchingIndicator extends Component { const { intl } = this.context; const { isSwitchingWorkspace, nextWorkspace } = workspaceStore; if (!isSwitchingWorkspace) return null; - const nextWorkspaceName = nextWorkspace ? nextWorkspace.name : 'All services'; + const nextWorkspaceName = nextWorkspace + ? nextWorkspace.name + : 'All services'; return ( -
    +
    - - Ferdi - - - - - -
    -
    DEV MODE
    -
    -
    - + + +
    +
    DEV MODE
    +
    +
    + - + }; + }; + })(); + } + + diff --git a/src/internal-server/public/css/main.css b/src/internal-server/public/css/main.css index a1c5653d7..b20b67922 100644 --- a/src/internal-server/public/css/main.css +++ b/src/internal-server/public/css/main.css @@ -4,7 +4,8 @@ input { padding: 0.5rem; } -button, .button { +button, +.button { display: flex; overflow: hidden; padding: 12px 12px; @@ -14,7 +15,9 @@ button, .button { -moz-user-select: none; -ms-user-select: none; user-select: none; - transition: all 150ms linear; + @media (prefers-reduced-motion: no-preference) { + transition: all 150ms linear; + } text-align: center; white-space: nowrap; text-decoration: none !important; @@ -33,7 +36,7 @@ button, .button { align-items: center; flex: 0 0 160px; box-shadow: 2px 5px 10px #e4e4e4; - color: #FFFFFF; + color: #ffffff; background: #161616; } @@ -66,4 +69,4 @@ button, .button { td { word-break: break-all; -} \ No newline at end of file +} diff --git a/src/styles/button.scss b/src/styles/button.scss index d18b683d5..86b3501f0 100644 --- a/src/styles/button.scss +++ b/src/styles/button.scss @@ -4,29 +4,45 @@ background: $theme-brand-primary; color: $dark-theme-text-color; - &:hover { background: darken($theme-brand-primary, 5%); } - &:active { background: lighten($theme-brand-primary, 5%); } + &:hover { + background: darken($theme-brand-primary, 5%); + } + &:active { + background: lighten($theme-brand-primary, 5%); + } &.franz-form__button--secondary { background: $dark-theme-gray-dark; color: $dark-theme-text-color; - &:hover { background: lighten($dark-theme-gray-dark, 10%); } - &:active { background: lighten($dark-theme-gray-dark, 20%); } + &:hover { + background: lighten($dark-theme-gray-dark, 10%); + } + &:active { + background: lighten($dark-theme-gray-dark, 20%); + } } &.franz-form__button--danger { background: $theme-brand-danger; - &:hover { background: darken($theme-brand-danger, 5%); } - &:active { background: lighten($theme-brand-danger, 5%); } + &:hover { + background: darken($theme-brand-danger, 5%); + } + &:active { + background: lighten($theme-brand-danger, 5%); + } } &.franz-form__button--warning { background: $theme-brand-warning; - &:hover { background: darken($theme-brand-warning, 5%); } - &:active { background: lighten($theme-brand-warning, 5%); } + &:hover { + background: darken($theme-brand-warning, 5%); + } + &:active { + background: lighten($theme-brand-warning, 5%); + } } &.franz-form__button--inverted { @@ -39,27 +55,35 @@ } } - &:disabled { opacity: .5; } + &:disabled { + opacity: 0.5; + } } .franz-form__button { background: $theme-brand-primary; border-radius: 3px; display: block; - color: #FFF; + color: #fff; padding: 10px 20px; position: relative; - transition: background .5s; + @media (prefers-reduced-motion: no-preference) { + transition: background 0.5s; + } text-align: center; - &:hover { background: darken($theme-brand-primary, 5%) } + &:hover { + background: darken($theme-brand-primary, 5%); + } &:active { background: lighten($theme-brand-primary, 5%); transition: none; } - &:disabled { opacity: .2; } + &:disabled { + opacity: 0.2; + } &.franz-form__button--large { width: 100%; @@ -70,22 +94,34 @@ background: $theme-gray-lighter; color: $theme-gray; - &:hover { background: darken($theme-gray-lighter, 5%); } - &:active { background: lighten($theme-gray-lighter, 5%); } + &:hover { + background: darken($theme-gray-lighter, 5%); + } + &:active { + background: lighten($theme-gray-lighter, 5%); + } } &.franz-form__button--danger { background: $theme-brand-danger; - &:hover { background: darken($theme-brand-danger, 5%); } - &:active { background: lighten($theme-brand-danger, 5%); } + &:hover { + background: darken($theme-brand-danger, 5%); + } + &:active { + background: lighten($theme-brand-danger, 5%); + } } &.franz-form__button--warning { background: $theme-brand-warning; - &:hover { background: darken($theme-brand-warning, 5%); } - &:active { background: lighten($theme-brand-warning, 5%); } + &:hover { + background: darken($theme-brand-warning, 5%); + } + &:active { + background: lighten($theme-brand-warning, 5%); + } } &.franz-form__button--inverted { @@ -93,11 +129,12 @@ border: 2px solid $theme-brand-primary; color: $theme-brand-primary; padding: 10px 20px; - transition: background .5s, color .5s; - + @media (prefers-reduced-motion: no-preference) { + transition: background 0.5s, color 0.5s; + } &:hover { background: darken($theme-brand-primary, 5%); - color: #FFF; + color: #fff; } } @@ -122,20 +159,20 @@ z-index: 9998; list-style: none; background: $theme-brand-primary; - + position: absolute; bottom: 20px; right: 20px; cursor: pointer; - + display: flex; justify-content: center; align-items: center; - + a { font-size: 30px; - color: #FFFFFF; - cursor: pointer; + color: #ffffff; + cursor: pointer; } } diff --git a/src/styles/content-tabs.scss b/src/styles/content-tabs.scss index 03befedcb..41bd2c251 100644 --- a/src/styles/content-tabs.scss +++ b/src/styles/content-tabs.scss @@ -9,7 +9,7 @@ .content-tabs__tabs { .content-tabs__item { background: $dark-theme-gray; - color: #FFF; + color: #fff; border: 0; } } @@ -24,19 +24,26 @@ overflow: hidden; .content-tabs__item { - background: linear-gradient($theme-gray-lightest 80%, darken($theme-gray-lightest, 3%)); + background: linear-gradient( + $theme-gray-lightest 80%, + darken($theme-gray-lightest, 3%) + ); border-right: 1px solid $theme-gray-lighter; color: $theme-gray-dark; flex: 1; padding: 10px; - transition: background $theme-transition-time; + @media (prefers-reduced-motion: no-preference) { + transition: background $theme-transition-time; + } - &:last-of-type { border-right: 0; } + &:last-of-type { + border-right: 0; + } &.is-active { background: $theme-brand-primary; box-shadow: none; - color: #FFF; + color: #fff; } } } @@ -51,10 +58,16 @@ display: none; top: 0; - &.is-active { display: block; } + &.is-active { + display: block; + } } - .franz-form__input-wrapper { background: #FFF; } - .franz-form__field:last-of-type { margin-bottom: 0; } + .franz-form__input-wrapper { + background: #fff; + } + .franz-form__field:last-of-type { + margin-bottom: 0; + } } } diff --git a/src/styles/fonts.scss b/src/styles/fonts.scss index 432332b49..1b2c99945 100644 --- a/src/styles/fonts.scss +++ b/src/styles/fonts.scss @@ -5,6 +5,7 @@ src: url('../assets/fonts/OpenSans-Light.ttf'); font-weight: 300; font-style: normal; + display: swap; } @font-face { @@ -12,6 +13,7 @@ src: url('../assets/fonts/OpenSans-Regular.ttf'); font-weight: normal; font-style: normal; + display: swap; } @font-face { @@ -19,6 +21,7 @@ src: url('../assets/fonts/OpenSans-Bold.ttf'); font-weight: bold; font-style: normal; + display: swap; } @font-face { @@ -26,6 +29,7 @@ src: url('../assets/fonts/OpenSans-BoldItalic.ttf'); font-weight: bold; font-style: italic; + display: swap; } @font-face { @@ -33,6 +37,7 @@ src: url('../assets/fonts/OpenSans-ExtraBold.ttf'); font-weight: 800; font-style: normal; + display: swap; } @font-face { @@ -40,4 +45,5 @@ src: url('../assets/fonts/OpenSans-ExtraBoldItalic.ttf'); font-weight: 800; font-style: italic; + display: swap; } diff --git a/src/styles/image-upload.scss b/src/styles/image-upload.scss index 31300c227..b5f6d5cd4 100644 --- a/src/styles/image-upload.scss +++ b/src/styles/image-upload.scss @@ -5,17 +5,23 @@ color: $dark-theme-gray-lighter; &__action { - &-background { background: rgba($dark-theme-black, .7); } + &-background { + background: rgba($dark-theme-black, 0.7); + } button { color: $dark-theme-gray-lightest; - .mdi { color: $dark-theme-gray-lightest; } + .mdi { + color: $dark-theme-gray-lightest; + } } } } - .image-upload-wrapper .mdi { color: $dark-theme-gray-light; } + .image-upload-wrapper .mdi { + color: $dark-theme-gray-light; + } } .image-upload { @@ -49,11 +55,13 @@ justify-content: center; opacity: 0; position: relative; - transition: opacity .5s; + @media (prefers-reduced-motion: no-preference) { + transition: opacity 0.5s; + } z-index: 10; &-background { - background: rgba($theme-gray, .7); + background: rgba($theme-gray, 0.7); bottom: 0; left: 0; position: absolute; @@ -63,11 +71,13 @@ } button { - color: #FFF; + color: #fff; position: relative; z-index: 100; - .mdi { color: #FFF; } + .mdi { + color: #fff; + } } } @@ -83,7 +93,9 @@ &__dropzone, button { - .mdi { margin-bottom: 5px; } + .mdi { + margin-bottom: 5px; + } p { font-size: 10px; @@ -91,7 +103,9 @@ } } - &:hover .image-upload__action { opacity: 1; } + &:hover .image-upload__action { + opacity: 1; + } } .image-upload-wrapper .mdi { diff --git a/src/styles/layout.scss b/src/styles/layout.scss index acbd65ad1..49e041022 100644 --- a/src/styles/layout.scss +++ b/src/styles/layout.scss @@ -1,6 +1,8 @@ @import './config.scss'; -html { overflow: hidden; } +html { + overflow: hidden; +} @keyframes pulse-danger { 0% { @@ -21,7 +23,7 @@ html { overflow: hidden; } &::after { box-shadow: inset 0 0 5px 0 $dark-theme-black, - inset 0 0 2px 0 rgba(0, 0, 0, 0.4); + inset 0 0 2px 0 rgba(0, 0, 0, 0.4); } .sidebar__add-service { @@ -48,12 +50,12 @@ html { overflow: hidden; } filter: grayscale(1); } - .update-available { + .update-available { align-items: center; background: $theme-brand-danger; border-radius: 20px; bottom: 5px; - color: #FFF; + color: #fff; display: flex; justify-content: center; padding: 0px 5px; @@ -71,7 +73,9 @@ html { overflow: hidden; } } } - .app-loader .app-loader__title { color: $dark-theme-gray-lightest; } + .app-loader .app-loader__title { + color: $dark-theme-gray-lightest; + } } body.win32:not(.isFullScreen) .app .app__content { @@ -96,7 +100,9 @@ body.win32:not(.isFullScreen) .app .app__content { } } -.electron-app-title-bar { z-index: 99999999; } +.electron-app-title-bar { + z-index: 99999999; +} .window-draggable { height: 22px; @@ -109,7 +115,9 @@ body.win32:not(.isFullScreen) .app .app__content { -webkit-app-region: drag; } -.darwin .sidebar { padding-top: 23px; } +.darwin .sidebar { + padding-top: 23px; +} .sidebar { position: relative; @@ -133,8 +141,8 @@ body.win32:not(.isFullScreen) .app .app__content { z-index: 1000; pointer-events: none; clip-path: inset(10px 0 10px 10px); - box-shadow: inset 0 0 10px 0 rgba(0, 0, 0, .12), - inset 0 0 2px 0 rgba(0, 0, 0, 0.24); + box-shadow: inset 0 0 10px 0 rgba(0, 0, 0, 0.12), + inset 0 0 2px 0 rgba(0, 0, 0, 0.24); } .sidebar__add-service { @@ -154,16 +162,25 @@ body.win32:not(.isFullScreen) .app .app__content { width: $theme-sidebar-width; &:hover, - &:active { color: lighten($theme-gray-light, 10%); } - &.is-muted, &.is-active { color: $theme-brand-primary; } - &--new-service { padding-bottom: 6px; } + &:active { + color: lighten($theme-gray-light, 10%); + } + &.is-muted, + &.is-active { + color: $theme-brand-primary; + } + &--new-service { + padding-bottom: 6px; + } } & > div { display: flex; overflow-y: scroll; - &::-webkit-scrollbar { display: none; } + &::-webkit-scrollbar { + display: none; + } } } @@ -171,8 +188,12 @@ body.win32:not(.isFullScreen) .app .app__content { display: flex; flex-direction: row; - & > * { margin-right: 20px; } - & :last-child { margin-right: 0; } + & > * { + margin-right: 20px; + } + & :last-child { + margin-right: 0; + } } .app-loader { @@ -181,19 +202,23 @@ body.win32:not(.isFullScreen) .app .app__content { justify-content: center; .app-loader__title { - color: #FFF; + color: #fff; font-size: 40px; } - & > span { height: auto; } + & > span { + height: auto; + } } -.dev-warning { display: none; } +.dev-warning { + display: none; +} .isDevMode .dev-warning { border-radius: 3px; background: $theme-brand-warning; - color: #FFF; + color: #fff; display: block; font-size: 8px; height: auto; @@ -201,12 +226,15 @@ body.win32:not(.isFullScreen) .app .app__content { position: fixed; left: 9px; bottom: 0px; - transition: opacity .5s ease; + @media (prefers-reduced-motion: no-preference) { + transition: opacity 0.5s ease; + } width: auto; z-index: 999999999; pointer-events: none; } -a, button { +a, +button { cursor: pointer; } diff --git a/src/styles/main.scss b/src/styles/main.scss index 4cc996785..b0815e086 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -22,7 +22,6 @@ $mdi-font-path: '../node_modules/@mdi/font/fonts'; @import './tooltip.scss'; @import './info-bar.scss'; @import './status-bar-target-url.scss'; -@import './animations.scss'; @import './infobox.scss'; @import './badge.scss'; @import './content-tabs.scss'; diff --git a/src/styles/radio.scss b/src/styles/radio.scss index b1e148ca0..e8297408d 100644 --- a/src/styles/radio.scss +++ b/src/styles/radio.scss @@ -11,9 +11,10 @@ } } - .franz-form { - .franz-form__radio-wrapper { display: flex; } + .franz-form__radio-wrapper { + display: flex; + } .franz-form__radio { border: 2px solid $theme-gray-lighter; @@ -24,18 +25,24 @@ margin-right: 20px; padding: 11px; text-align: center; - transition: background $theme-transition-time; + @media (prefers-reduced-motion: no-preference) { + transition: background $theme-transition-time; + } - &:last-of-type { margin-right: 0; } + &:last-of-type { + margin-right: 0; + } &.is-selected { - background: #FFF; + background: #fff; border-width: 2px; border-style: solid; border-color: $theme-brand-primary; color: $theme-brand-primary; } - input { display: none; } + input { + display: none; + } } } diff --git a/src/styles/recipes.scss b/src/styles/recipes.scss index 5bdc60a57..37c2febf6 100644 --- a/src/styles/recipes.scss +++ b/src/styles/recipes.scss @@ -4,7 +4,9 @@ background-color: $dark-theme-gray-dark; color: $dark-theme-text-color; - &:hover { background-color: $dark-theme-gray; } + &:hover { + background-color: $dark-theme-gray; + } } .recipes { @@ -17,7 +19,7 @@ &.recipes__list--disabled { filter: grayscale(100%); - opacity: .3; + opacity: 0.3; pointer-events: none; } } @@ -26,16 +28,20 @@ height: auto; margin-bottom: 35px; - .badge { margin-right: 10px; } + .badge { + margin-right: 10px; + } &.recipes__navigation--disabled { filter: grayscale(100%); - opacity: .3; + opacity: 0.3; pointer-events: none; } } - &__service-request { float: right; } + &__service-request { + float: right; + } } .recipe-teaser { @@ -45,24 +51,32 @@ margin: 0 20px 20px 0; overflow: hidden; position: relative; - transition: background $theme-transition-time; + @media (prefers-reduced-motion: no-preference) { + transition: background $theme-transition-time; + } width: calc(25% - 20px); - &:hover { background-color: $theme-gray-lighter; } + &:hover { + background-color: $theme-gray-lighter; + } .recipe-teaser__icon { margin-bottom: 10px; width: 50px; } - .recipe-teaser__label { display: block; } + .recipe-teaser__label { + display: block; + } - h2 { z-index: 10; } + h2 { + z-index: 10; + } &__dev-badge { background: $theme-brand-warning; - box-shadow: 0 0 4px rgba(black, .2); - color: #FFF; + box-shadow: 0 0 4px rgba(black, 0.2); + color: #fff; font-size: 10px; position: absolute; right: -13px; diff --git a/src/styles/settings.scss b/src/styles/settings.scss index 5d4e81a4f..501f97b98 100644 --- a/src/styles/settings.scss +++ b/src/styles/settings.scss @@ -1,63 +1,85 @@ @import './config.scss'; %headline { - color: #FFF; + color: #fff; font-size: 20px; font-weight: 400; letter-spacing: -1px; - a { color: #FFF } + a { + color: #fff; + } } %headline__dark { - color: #FFF; + color: #fff; font-size: 20px; font-weight: 400; letter-spacing: -1px; - a { color: #FFF } + a { + color: #fff; + } } .theme__dark { - .settings-wrapper { background: rgba($dark-theme-black, .8); } + .settings-wrapper { + background: rgba($dark-theme-black, 0.8); + } .settings { .settings__header { - .mdi { color: #FFF } + .mdi { + color: #fff; + } } .settings__main { background: $dark-theme-gray-darkest; } - .settings__body::-webkit-scrollbar-thumb { background: $dark-theme-gray; } + .settings__body::-webkit-scrollbar-thumb { + background: $dark-theme-gray; + } .settings__close { - color: #FFF; + color: #fff; } - &__settings-group h3 { color: $dark-theme-gray-lightest; } + &__settings-group h3 { + color: $dark-theme-gray-lightest; + } .settings__message { border-top: 1px solid $theme-gray-lighter; color: $dark-theme-gray-lightest; - .mdi { color: $dark-theme-gray-lightest; } + .mdi { + color: $dark-theme-gray-lightest; + } } - .settings__help { color: $dark-theme-gray-lightest; } + .settings__help { + color: $dark-theme-gray-lightest; + } .settings__controls { background: $dark-theme-gray-darker; - .franz-form__button.franz-form__button--secondary { background: $theme-gray-light; } + .franz-form__button.franz-form__button--secondary { + background: $theme-gray-light; + } } .account { - .account__box { background: $dark-theme-gray-darker; } + .account__box { + background: $dark-theme-gray-darker; + } } - .legal { color: $theme-gray-light; } + .legal { + color: $theme-gray-light; + } } .settings-navigation { @@ -69,7 +91,7 @@ border-bottom: 1px solid darken($dark-theme-gray-darker, 3%); &:last-child { - border: 0, + border: 0; } .badge { @@ -87,7 +109,7 @@ } &.is-disabled { - filter: grayscale(100%) opacity(.2); + filter: grayscale(100%) opacity(0.2); } &.is-active { @@ -101,13 +123,15 @@ } } - .settings-navigation__action-badge { background: $theme-brand-danger; } + .settings-navigation__action-badge { + background: $theme-brand-danger; + } } } .settings-wrapper { align-items: center; - background: rgba(black, .5); + background: rgba(black, 0.5); display: flex; height: 100%; left: 0; @@ -129,7 +153,7 @@ .settings { border-radius: $theme-border-radius; - box-shadow: 0 20px 50px rgba($dark-theme-black, .5); + box-shadow: 0 20px 50px rgba($dark-theme-black, 0.5); display: flex; height: 100%; max-height: 720px; @@ -147,7 +171,7 @@ height: auto; border-radius: 0 $theme-border-radius $theme-border-radius 0; overflow: hidden; - background: #FFF; + background: #fff; } .settings__header { @@ -157,7 +181,7 @@ height: 50px; padding: 0 40px; width: calc(100% - 60px); - color: #FFF; + color: #fff; h1 { @extend %headline; @@ -177,11 +201,13 @@ transform: skew(15deg) rotate(2deg); } - .mdi { color: $theme-gray-light; } + .mdi { + color: $theme-gray-light; + } } .settings_titles { - display:inline-block; + display: inline-block; } .settings__body { @@ -190,9 +216,13 @@ overflow-y: scroll; padding: 25px 15px 15px 25px; - .badge { margin-right: 10px; } + .badge { + margin-right: 10px; + } - &::-webkit-scrollbar { width: 8px; } + &::-webkit-scrollbar { + width: 8px; + } /* Track */ &::-webkit-scrollbar-track { @@ -208,9 +238,16 @@ -webkit-border-radius: 10px; } - &::-webkit-scrollbar-thumb:window-inactive { background: none; } - .service-flex-grid { display: flex; } - .service-name,.user-agent { flex: 1px; } + &::-webkit-scrollbar-thumb:window-inactive { + background: none; + } + .service-flex-grid { + display: flex; + } + .service-name, + .user-agent { + flex: 1px; + } .service-icon { float: right; @@ -232,20 +269,28 @@ .settings__close { background: $theme-brand-primary; // border-left: 1px solid darken($theme-brand-primary, 8%); - color: #FFF; + color: #fff; font-size: 20px; height: 50px; padding: 0 20px; position: absolute; right: 0; - transition: background $theme-transition-time; + @media (prefers-reduced-motion: no-preference) { + transition: background $theme-transition-time; + } cursor: pointer; - &::before { cursor: pointer; } - &:hover { background: darken($theme-brand-primary, 5%); } + &::before { + cursor: pointer; + } + &:hover { + background: darken($theme-brand-primary, 5%); + } } - .search-input { margin-bottom: 30px; } + .search-input { + margin-bottom: 30px; + } &__options { flex: 1; @@ -258,10 +303,12 @@ h3 { color: $theme-gray-light; font-weight: bold; - letter-spacing: -.1px; + letter-spacing: -0.1px; margin: 25px 0 15px; - &:first-of-type { margin-top: 0; } + &:first-of-type { + margin-top: 0; + } .badge { font-weight: normal; @@ -302,14 +349,20 @@ padding: 10px 20px; .franz-form__button { - &[type='submit'] { margin-left: auto; } - &.franz-form__button--secondary { background: $theme-gray-light; } + &[type='submit'] { + margin-left: auto; + } + &.franz-form__button--secondary { + background: $theme-gray-light; + } } } - .settings__delete-button { right: 0; } + .settings__delete-button { + right: 0; + } .settings__open-recipe-file-button { - cursor:pointer; + cursor: pointer; margin-right: 10px; } .settings__open-recipe-file-container { @@ -330,7 +383,9 @@ margin-bottom: 1em; } - a.button { margin-top: 40px; } + a.button { + margin-top: 40px; + } } .account { @@ -343,8 +398,12 @@ margin-bottom: 40px; padding: 20px; - &.account__box--flex { display: flex; } - &.account__box--last { margin-bottom: 0; } + &.account__box--flex { + display: flex; + } + &.account__box--last { + margin-bottom: 0; + } .auth__button { margin-top: 10px; @@ -360,16 +419,24 @@ .account__info { flex: 1; - h2 { margin-bottom: 5px; } - .badge { margin-top: 5px; } - .username { margin-right: 10 } + h2 { + margin-bottom: 5px; + } + .badge { + margin-top: 5px; + } + .username { + margin-right: 10; + } } .account__subscription { align-items: center; display: flex; - .badge { margin-left: 10px; } + .badge { + margin-left: 10px; + } } .manage-user-links { @@ -378,10 +445,18 @@ justify-content: space-between; } - .account__subscription-button { margin-left: auto; } - .franz-form__button { white-space: nowrap; } - div { height: auto; } - [data-type="franz-button"] div { height: 20px } + .account__subscription-button { + margin-left: auto; + } + .franz-form__button { + white-space: nowrap; + } + div { + height: auto; + } + [data-type='franz-button'] div { + height: 20px; + } .invoices { width: 100%; @@ -399,7 +474,9 @@ .invoices__action { text-align: right; - button { color: $theme-brand-primary; } + button { + color: $theme-brand-primary; + } } } } @@ -409,7 +486,9 @@ font-size: 40px; margin-bottom: 20px; - img { width: 40px; } + img { + width: 40px; + } } .content-tabs { @@ -432,8 +511,8 @@ width: 240px; height: 100%; align-self: center; - border-top-left-radius: $theme-border-radius;; - border-bottom-left-radius: $theme-border-radius;; + border-top-left-radius: $theme-border-radius; + border-bottom-left-radius: $theme-border-radius; overflow: hidden; .settings-navigation__link { @@ -445,12 +524,15 @@ height: 51px; padding: 0 20px; text-decoration: none; - transition: background $theme-transition-time, color $theme-transition-time; + @media (prefers-reduced-motion: no-preference) { + transition: background $theme-transition-time, + color $theme-transition-time; + } border-bottom: 1px solid darken($theme-gray-lightest, 3%); .badge { background: $theme-gray-light; - color: #FFF; + color: #fff; } &:hover { @@ -458,26 +540,31 @@ .badge { background: $theme-gray-light; - color: #FFF; + color: #fff; } } &.is-active { background: $theme-brand-primary; - color: #FFF; + color: #fff; .badge { - background: #FFF; + background: #fff; color: $theme-brand-primary; } } } - .settings-navigation__expander { flex: 1; } + .settings-navigation__expander { + flex: 1; + } .badge { display: initial; - transition: background $theme-transition-time, color $theme-transition-time; + @media (prefers-reduced-motion: no-preference) { + transition: background $theme-transition-time, + color $theme-transition-time; + } } .settings-navigation__action-badge { @@ -491,5 +578,7 @@ } .settings__support-badges { - a { margin-right: 10px } + a { + margin-right: 10px; + } } diff --git a/src/styles/slider.scss b/src/styles/slider.scss index 8bb771586..85b31660f 100644 --- a/src/styles/slider.scss +++ b/src/styles/slider.scss @@ -3,43 +3,44 @@ .theme__dark .franz-form .franz-form__slider-wrapper .slider { border: 1px solid $dark-theme-gray; background: $dark-theme-gray; - } - .franz-form { - .franz-form__slider-wrapper { + .franz-form__slider-wrapper { display: flex; flex-direction: row; - .franz-form__label { margin-left: 20px; } + .franz-form__label { + margin-left: 20px; + } .slider-container { - width: 100%; /* Width of the outside container */ + width: 100%; /* Width of the outside container */ } - + /* The slider itself */ .slider { -webkit-appearance: none; width: 100%; height: 14px; - border-radius: $theme-border-radius; + border-radius: $theme-border-radius; background: $theme-gray-lighter; outline: none; - opacity: 1.0; - -webkit-transition: .2s; - transition: opacity .2s; + opacity: 1; + @media (prefers-reduced-motion: no-preference) { + transition: opacity 0.2s; + } } - + .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 14px; height: 14px; - border-radius: 50%; + border-radius: 50%; background: $theme-brand-primary; - box-shadow: 0 1px 4px rgba(0, 0, 0, .3); + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); cursor: pointer; } - } + } } diff --git a/src/styles/tabs.scss b/src/styles/tabs.scss index 31a239387..df10da77c 100644 --- a/src/styles/tabs.scss +++ b/src/styles/tabs.scss @@ -4,11 +4,17 @@ &.is-active { background: $dark-theme-gray; - .tab-item__icon { margin-left: -4px; } + .tab-item__icon { + margin-left: -4px; + } } - &.is-disabled .tab-item__icon { filter: grayscale(100%) opacity(.2); } - .tab-item__icon { width: 34px; } + &.is-disabled .tab-item__icon { + filter: grayscale(100%) opacity(0.2); + } + .tab-item__icon { + width: 34px; + } } .tabs { @@ -29,22 +35,34 @@ justify-content: center; min-height: 50px; position: relative; - transition: background $theme-transition-time; + @media (prefers-reduced-motion: no-preference) { + transition: background $theme-transition-time; + } width: $theme-sidebar-width; &.is-active { - background: change-color($theme-brand-primary, - $lightness: min(lightness($theme-brand-primary) * 1.35, 100)); + background: change-color( + $theme-brand-primary, + $lightness: min(lightness($theme-brand-primary) * 1.35, 100) + ); border-left-width: 4px; border-left-style: solid; color: $theme-brand-primary; - .tab-item__icon { margin-left: -4px; } + .tab-item__icon { + margin-left: -4px; + } } - &.is-disabled .tab-item__icon { filter: grayscale(100%) opacity(0.2); } - &.has-custom-icon .tab-item__icon { border-radius: $theme-border-radius; } - &:active .tab-item__icon { opacity: .7; } + &.is-disabled .tab-item__icon { + filter: grayscale(100%) opacity(0.2); + } + &.has-custom-icon .tab-item__icon { + border-radius: $theme-border-radius; + } + &:active .tab-item__icon { + opacity: 0.7; + } .tab-item__icon { height: auto; @@ -56,7 +74,7 @@ background: $theme-brand-danger; border-radius: 20px; bottom: 8px; - color: #FFF; + color: #fff; display: flex; font-size: 11px; justify-content: center; @@ -66,13 +84,13 @@ position: absolute; right: 8px; - &.is-indirect { + &.is-indirect { padding-top: 0; background: #0088cc; - } - &.hibernating { - padding-top: 0; - background: $theme-gray; + } + &.hibernating { + padding-top: 0; + background: $theme-gray; font-size: 0px; min-height: 10px; min-width: 10px; @@ -96,11 +114,13 @@ right: 8px; width: 17px; - &.is-indirect { + &.is-indirect { padding-top: 0; background: #0088cc; - } + } } - &.is-reordering { z-index: 99999; } + &.is-reordering { + z-index: 99999; + } } diff --git a/src/styles/toggle.scss b/src/styles/toggle.scss index 5cd9e4526..ed4c0d11b 100644 --- a/src/styles/toggle.scss +++ b/src/styles/toggle.scss @@ -39,7 +39,9 @@ $toggle-button-size: 22px; left: 1px; top: 1px; position: absolute; - transition: all 0.5s; + @media (prefers-reduced-motion: no-preference) { + transition: all 0.5s; + } width: $toggle-size - 2; } diff --git a/src/styles/type.scss b/src/styles/type.scss index 37ec0bcca..234c4d5c4 100644 --- a/src/styles/type.scss +++ b/src/styles/type.scss @@ -2,9 +2,15 @@ @import './mixins.scss'; .theme__dark { - a { color: $dark-theme-gray-smoke; } - .label { color: $dark-theme-gray-lightest; } - .footnote { color: $dark-theme-gray-lightest; } + a { + color: $dark-theme-gray-smoke; + } + .label { + color: $dark-theme-gray-lightest; + } + .footnote { + color: $dark-theme-gray-lightest; + } } h1 { @@ -21,36 +27,45 @@ h2 { margin-bottom: 25px; margin-top: 5px; - &:first-of-type { margin-top: 0; } + &:first-of-type { + margin-top: 0; + } } p { margin-bottom: 10px; line-height: 1.7rem; - &:last-of-type { margin-bottom: 0; } + &:last-of-type { + margin-bottom: 0; + } } -strong { font-weight: bold; } +strong { + font-weight: bold; +} -a, button { +a, +button { color: $theme-text-color; text-decoration: none; &.button { background: $theme-brand-primary; - color: #FFF; + color: #fff; border-radius: 3px; display: inline-block; padding: 10px 20px; position: relative; text-align: center; - transition: background .5s, color .5s; + @media (prefers-reduced-motion: no-preference) { + transition: background 0.5s, color 0.5s; + } cursor: pointer; &:hover { background: darken($theme-brand-primary, 10%); - color: #FFF; + color: #fff; } } @@ -60,14 +75,19 @@ a, button { } } -.error-message, .error-message:last-of-type { +.error-message, +.error-message:last-of-type { color: $theme-brand-danger; margin: 10px 0; } -.center { text-align: center; } +.center { + text-align: center; +} -.label { @include formLabel(); } +.label { + @include formLabel(); +} .footnote { color: $theme-gray-light; diff --git a/src/styles/welcome.scss b/src/styles/welcome.scss index c1f85391e..7202fe148 100644 --- a/src/styles/welcome.scss +++ b/src/styles/welcome.scss @@ -1,24 +1,26 @@ .auth .welcome { height: auto; - + &__content { align-items: center; - color: #FFF; + color: #fff; display: flex; justify-content: center; height: auto; } - &__logo { width: 100px; } + &__logo { + width: 100px; + } &__text { - border-left: 1px solid #FFF; + border-left: 1px solid #fff; margin-left: 40px; padding-left: 40px; h1 { font-size: 60px; - letter-spacing: -.4rem; + letter-spacing: -0.4rem; margin-bottom: 5px; } @@ -42,33 +44,35 @@ text-align: center; height: auto; - .button:first-of-type { margin-right: 25px; } + .button:first-of-type { + margin-right: 25px; + } } .button { - border-color: #FFF; - color: #FFF; + border-color: #fff; + color: #fff; cursor: pointer; &:hover { - background: #FFF; + background: #fff; color: $theme-brand-primary; } &__inverted { - background: #FFF; + background: #fff; color: $theme-brand-primary; } &__inverted:hover { background: none; - color: #FFF; + color: #fff; } } &__featured-services { align-items: center; - background: #FFF; + background: #fff; border-radius: 6px; display: flex; flex-wrap: wrap; @@ -82,9 +86,13 @@ &__featured-service { margin: 0 10px 15px; height: 35px; - transition: .5s filter, .5s opacity; + @media (prefers-reduced-motion: no-preference) { + transition: 0.5s filter, 0.5s opacity; + } width: 35px; - img { width: 35px; } + img { + width: 35px; + } } } diff --git a/src/webview/screenshare.js b/src/webview/screenshare.js index ab548a625..e7e43c04e 100644 --- a/src/webview/screenshare.js +++ b/src/webview/screenshare.js @@ -3,17 +3,23 @@ import { desktopCapturer } from 'electron'; const CANCEL_ID = 'desktop-capturer-selection__cancel'; export async function getDisplayMediaSelector() { - const sources = await desktopCapturer.getSources({ types: ['screen', 'window'] }); + const sources = await desktopCapturer.getSources({ + types: ['screen', 'window'], + }); return `
      - ${sources.map(({ id, name, thumbnail }) => ` + ${sources + .map( + ({ id, name, thumbnail }) => `
    • - `).join('')} + `, + ) + .join('')}