From 3233d9b8024dd59600edddef6d017e0089f59a9d Mon Sep 17 00:00:00 2001 From: undergroundwires Date: Sun, 13 Mar 2022 12:45:17 +0100 Subject: [PATCH] Improve click/touch without unintended interaction Disable selecting clickables as text. Selecting buttons leads to unintended selection. This is seen when touching on clickables using mobile devices. Prevent blue highlight when touching on clickables. This is seen on mobile webkit browsers. It looks ugly and the visual clue provided is not needed beacuse all clickables on mobile already have visual clues. --- docs/presentation.md | 4 ++++ src/presentation/assets/styles/_mixins.scss | 13 +++++++++++++ .../components/Code/CodeButtons/Code.vue | 2 +- .../components/Code/CodeButtons/IconButton.vue | 3 ++- .../components/Scripts/Menu/MenuOptionListItem.vue | 2 +- .../components/Scripts/Slider/Handle.vue | 2 +- .../components/Scripts/View/Cards/CardListItem.vue | 4 ++-- .../SelectableTree/Node/DocumentationUrls.vue | 2 +- .../SelectableTree/Node/RevertToggle.vue | 3 +-- .../components/Scripts/View/TheScriptsView.vue | 2 +- src/presentation/components/Shared/Dialog.vue | 2 +- .../components/TheFooter/DownloadUrlListItem.vue | 6 ++++-- 12 files changed, 32 insertions(+), 13 deletions(-) diff --git a/docs/presentation.md b/docs/presentation.md index 7f0b5f15..1a3b99c3 100644 --- a/docs/presentation.md +++ b/docs/presentation.md @@ -26,6 +26,10 @@ It's designed event-driven from bottom to top. It listens user events (from top) - [**`/postcss.config.js`**](./../postcss.config.js): PostCSS configurations used by Vue CLI internally. - [**`/babel.config.js`**](./../babel.config.js): Babel configurations for polyfills used by `@vue/cli-plugin-babel`. +## Visual design best-practices + +Add visual clues for clickable items. It should be as clear as possible that they're interactable at first look without hovering. They should also have different visual state when hovering/touching on them that indicates that they are being clicked, which helps with accessibility. + ## Application data Components (should) use [ApplicationFactory](./../src/application/ApplicationFactory.ts) singleton to reach the application domain to avoid [parsing and compiling](./application.md#parsing-and-compiling) the application again. diff --git a/src/presentation/assets/styles/_mixins.scss b/src/presentation/assets/styles/_mixins.scss index aedc9c7c..ffb0e8b4 100644 --- a/src/presentation/assets/styles/_mixins.scss +++ b/src/presentation/assets/styles/_mixins.scss @@ -14,3 +14,16 @@ } } } + +@mixin clickable($cursor: 'pointer') { + cursor: #{$cursor}; + user-select: none; + /* + It removes (blue) background during touch as seen in mobile webkit browsers (Chrome, Safari, Edge). + The default behavior is that any element (or containing element) that has cursor:pointer + explicitly set and is clicked will flash blue momentarily. + Removing it could have accessibility issue since that hides an interactive cue. But as we still provide + response to user actions through :active by `hover-or-touch` mixin. + */ + -webkit-tap-highlight-color: transparent; +} diff --git a/src/presentation/components/Code/CodeButtons/Code.vue b/src/presentation/components/Code/CodeButtons/Code.vue index 8d97476d..a1926c00 100644 --- a/src/presentation/components/Code/CodeButtons/Code.vue +++ b/src/presentation/components/Code/CodeButtons/Code.vue @@ -42,7 +42,7 @@ export default class Code extends Vue { } .copy-button { margin-left: 1rem; - cursor: pointer; + @include clickable; @include hover-or-touch { color: $color-primary; } diff --git a/src/presentation/components/Code/CodeButtons/IconButton.vue b/src/presentation/components/Code/CodeButtons/IconButton.vue index 5be2b8c9..284223be 100644 --- a/src/presentation/components/Code/CodeButtons/IconButton.vue +++ b/src/presentation/components/Code/CodeButtons/IconButton.vue @@ -42,7 +42,8 @@ export default class IconButton extends Vue { box-shadow: 0 3px 9px $color-primary-darkest; border-radius: 4px; - cursor: pointer; + @include clickable; + width: 10%; min-width: 90px; @include hover-or-touch { diff --git a/src/presentation/components/Scripts/Menu/MenuOptionListItem.vue b/src/presentation/components/Scripts/Menu/MenuOptionListItem.vue index 214b6896..ba81deb8 100644 --- a/src/presentation/components/Scripts/Menu/MenuOptionListItem.vue +++ b/src/presentation/components/Scripts/Menu/MenuOptionListItem.vue @@ -29,7 +29,7 @@ export default class MenuOptionListItem extends Vue { @use "@/presentation/assets/styles/main" as *; .enabled { - cursor: pointer; + @include clickable; @include hover-or-touch { font-weight:bold; text-decoration:underline; diff --git a/src/presentation/components/Scripts/Slider/Handle.vue b/src/presentation/components/Scripts/Slider/Handle.vue index d060d418..ac1ecb53 100644 --- a/src/presentation/components/Scripts/Slider/Handle.vue +++ b/src/presentation/components/Scripts/Slider/Handle.vue @@ -52,7 +52,7 @@ $color : $color-primary-dark; $color-hover : $color-primary; .handle { - user-select: none; + @include clickable($cursor: 'ew-resize'); display: flex; flex-direction: column; align-items: center; diff --git a/src/presentation/components/Scripts/View/Cards/CardListItem.vue b/src/presentation/components/Scripts/View/Cards/CardListItem.vue index 078b7e66..44b29f60 100644 --- a/src/presentation/components/Scripts/View/Cards/CardListItem.vue +++ b/src/presentation/components/Scripts/View/Cards/CardListItem.vue @@ -130,7 +130,7 @@ $card-horizontal-gap : $card-gap; padding-bottom: 0; padding-left: $card-inner-padding; position: relative; - cursor: pointer; + @include clickable; background-color: $color-primary; color: $color-on-primary; font-size: 1.5em; @@ -187,7 +187,7 @@ $card-horizontal-gap : $card-gap; font-size: 1.5em; align-self: flex-start; margin-right: 0.25em; - cursor: pointer; + @include clickable; color: $color-primary-light; @include hover-or-touch { color: $color-primary; diff --git a/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/DocumentationUrls.vue b/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/DocumentationUrls.vue index 8ea8f1d6..8f1623dd 100644 --- a/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/DocumentationUrls.vue +++ b/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/DocumentationUrls.vue @@ -33,8 +33,8 @@ export default class DocumentationUrls extends Vue { .documentationUrl { display: flex; color: $color-primary; - cursor: pointer; vertical-align: middle; + @include clickable; @include hover-or-touch { color: $color-primary-darker; } diff --git a/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/RevertToggle.vue b/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/RevertToggle.vue index 4287a0ae..56d8196b 100644 --- a/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/RevertToggle.vue +++ b/src/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/RevertToggle.vue @@ -65,7 +65,6 @@ $size-height : 30px; // https://www.designlabthemes.com/css-toggle-switch/ .checkbox-switch { - cursor: pointer; display: inline-block; overflow: hidden; position: relative; @@ -87,7 +86,7 @@ $size-height : 30px; margin: 0; opacity: 0; z-index: 2; - cursor: pointer; + @include clickable; } .checkbox-animate { diff --git a/src/presentation/components/Scripts/View/TheScriptsView.vue b/src/presentation/components/Scripts/View/TheScriptsView.vue index e5a0ce34..37263d48 100644 --- a/src/presentation/components/Scripts/View/TheScriptsView.vue +++ b/src/presentation/components/Scripts/View/TheScriptsView.vue @@ -137,7 +137,7 @@ $margin-inner: 4px; margin-top: 1em; color: $color-primary; &__close-button { - cursor: pointer; + @include clickable; font-size: 1.25em; margin-left: 0.25rem; @include hover-or-touch { diff --git a/src/presentation/components/Shared/Dialog.vue b/src/presentation/components/Shared/Dialog.vue index f8f01ab7..a5a7cfa5 100644 --- a/src/presentation/components/Shared/Dialog.vue +++ b/src/presentation/components/Shared/Dialog.vue @@ -52,7 +52,7 @@ export default class Dialog extends Vue { font-size: 1.5em; margin-right: 0.25em; align-self: flex-start; - cursor: pointer; + @include clickable; @include hover-or-touch { color: $color-primary; } diff --git a/src/presentation/components/TheFooter/DownloadUrlListItem.vue b/src/presentation/components/TheFooter/DownloadUrlListItem.vue index 6f1d9f3f..72135f50 100644 --- a/src/presentation/components/TheFooter/DownloadUrlListItem.vue +++ b/src/presentation/components/TheFooter/DownloadUrlListItem.vue @@ -69,12 +69,14 @@ function getOperatingSystemName(os: OperatingSystem): string {