aboutsummaryrefslogtreecommitdiffstats
path: root/app/assets/stylesheets/utilities
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/stylesheets/utilities')
-rw-r--r--app/assets/stylesheets/utilities/_accessibility.scss52
-rw-r--r--app/assets/stylesheets/utilities/_loading.scss58
-rw-r--r--app/assets/stylesheets/utilities/_reduce-motion.scss27
-rw-r--r--app/assets/stylesheets/utilities/_tooltip.scss278
4 files changed, 415 insertions, 0 deletions
diff --git a/app/assets/stylesheets/utilities/_accessibility.scss b/app/assets/stylesheets/utilities/_accessibility.scss
new file mode 100644
index 0000000..e97ed7e
--- /dev/null
+++ b/app/assets/stylesheets/utilities/_accessibility.scss
@@ -0,0 +1,52 @@
+/**
+ * Accessibility & User interaction
+ */
+
+// Based on :
+// - normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
+// - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
+// ––––––––––––––––––––
+
+// Accessibility
+
+// Change the cursor on control elements in all browsers (opinionated)
+[aria-controls] {
+ cursor: pointer;
+}
+
+// Change the cursor on disabled, not-editable, or otherwise inoperable elements in all browsers (opinionated)
+[aria-disabled="true"],
+[disabled] {
+ cursor: not-allowed;
+}
+
+// Change the display on visually hidden accessible elements in all browsers (opinionated)
+[aria-hidden="false"][hidden] {
+ display: initial;
+}
+
+[aria-hidden="false"][hidden]:not(:focus) {
+ clip: rect(0, 0, 0, 0);
+ position: absolute;
+}
+
+// User interaction
+// Remove the tapping delay in IE 10
+a,
+area,
+button,
+input,
+label,
+select,
+summary,
+textarea,
+[tabindex] {
+ -ms-touch-action: manipulation;
+}
+
+// Pico
+// ––––––––––––––––––––
+
+[dir="rtl"] {
+ direction: rtl;
+}
diff --git a/app/assets/stylesheets/utilities/_loading.scss b/app/assets/stylesheets/utilities/_loading.scss
new file mode 100644
index 0000000..c6f3afe
--- /dev/null
+++ b/app/assets/stylesheets/utilities/_loading.scss
@@ -0,0 +1,58 @@
+/**
+ * Loading ([aria-busy=true])
+ */
+
+
+// Cursor
+[aria-busy="true"] {
+ cursor: progress;
+}
+
+// Everyting except form elements
+[aria-busy="true"]:not(input, select, textarea, html) {
+
+ &::before {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ border: 0.1875em solid currentColor;
+ border-radius: 1em;
+ border-right-color: transparent;
+ content: "";
+ vertical-align: text-bottom;
+ vertical-align: -.125em; // Visual alignment
+ animation: spinner 0.75s linear infinite;
+ opacity: var(--loading-spinner-opacity);
+ }
+
+ &:not(:empty) {
+ &::before {
+ margin-right: calc(var(--spacing) * 0.5);
+ margin-left: 0;
+ margin-inline-start: 0;
+ margin-inline-end: calc(var(--spacing) * 0.5);
+ }
+ }
+
+ &:empty {
+ text-align: center;
+ }
+}
+
+// Buttons and links
+button,
+input[type="submit"],
+input[type="button"],
+input[type="reset"],
+a {
+ &[aria-busy="true"] {
+ pointer-events: none;
+ }
+}
+
+// Animation: rotate
+@keyframes spinner {
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/app/assets/stylesheets/utilities/_reduce-motion.scss b/app/assets/stylesheets/utilities/_reduce-motion.scss
new file mode 100644
index 0000000..ecfd6fd
--- /dev/null
+++ b/app/assets/stylesheets/utilities/_reduce-motion.scss
@@ -0,0 +1,27 @@
+@if $enable-transitions and $enable-important {
+ /**
+ * Reduce Motion Features
+ */
+
+ // Based on :
+ // - sanitize.css v13.0.0 | CC0 1.0 Universal | github.com/csstools/sanitize.css
+ // ––––––––––––––––––––
+
+ // 1. Remove animations when motion is reduced (opinionated)
+ // 2. Remove fixed background attachments when motion is reduced (opinionated)
+ // 3. Remove timed scrolling behaviors when motion is reduced (opinionated)
+ // 4. Remove transitions when motion is reduced (opinionated)
+ @media (prefers-reduced-motion: reduce) {
+ *:not([aria-busy="true"]),
+ :not([aria-busy="true"])::before,
+ :not([aria-busy="true"])::after {
+ background-attachment: initial !important; // 2
+ animation-duration: 1ms !important; // 1
+ animation-delay: -1ms !important; // 1
+ animation-iteration-count: 1 !important; // 1
+ scroll-behavior: auto !important; // 3
+ transition-delay: 0s !important; // 4
+ transition-duration: 0s !important; // 4
+ }
+ }
+}
diff --git a/app/assets/stylesheets/utilities/_tooltip.scss b/app/assets/stylesheets/utilities/_tooltip.scss
new file mode 100644
index 0000000..d0355a3
--- /dev/null
+++ b/app/assets/stylesheets/utilities/_tooltip.scss
@@ -0,0 +1,278 @@
+/**
+ * Tooltip ([data-tooltip])
+ */
+
+[data-tooltip] {
+ position: relative;
+
+ &:not(a, button, input) {
+ border-bottom: 1px dotted;
+ text-decoration: none;
+ cursor: help;
+ }
+
+ &[data-placement="top"]::before,
+ &[data-placement="top"]::after,
+ &::before,
+ &::after {
+ display: block;
+ z-index: 99;
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ padding: .25rem .5rem;
+ overflow: hidden;
+ transform: translate(-50%, -.25rem);
+ border-radius: var(--border-radius);
+ background: var(--tooltip-background-color);
+ content: attr(data-tooltip);
+ color: var(--tooltip-color);
+ font-style: normal;
+ font-weight: var(--font-weight);
+ font-size: .875rem;
+ text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ // Caret
+ &[data-placement="top"]::after,
+ &::after {
+ padding: 0;
+ transform: translate(-50%, 0rem);
+ border-top: .3rem solid;
+ border-right: .3rem solid transparent;
+ border-left: .3rem solid transparent;
+ border-radius: 0;
+ background-color: transparent;
+ content: "";
+ color: var(--tooltip-background-color);
+ }
+
+ &[data-placement="bottom"] {
+ &::before,
+ &::after {
+ top: 100%;
+ bottom: auto;
+ transform: translate(-50%, .25rem);
+ }
+
+ &:after{
+ transform: translate(-50%, -.3rem);
+ border: .3rem solid transparent;
+ border-bottom: .3rem solid;
+ }
+ }
+
+ &[data-placement="left"] {
+ &::before,
+ &::after {
+ top: 50%;
+ right: 100%;
+ bottom: auto;
+ left: auto;
+ transform: translate(-.25rem, -50%);
+ }
+
+ &:after{
+ transform: translate(.3rem, -50%);
+ border: .3rem solid transparent;
+ border-left: .3rem solid;
+ }
+ }
+
+ &[data-placement="right"] {
+ &::before,
+ &::after {
+ top: 50%;
+ right: auto;
+ bottom: auto;
+ left: 100%;
+ transform: translate(.25rem, -50%);
+ }
+
+ &:after{
+ transform: translate(-.3rem, -50%);
+ border: .3rem solid transparent;
+ border-right: .3rem solid;
+ }
+ }
+
+ // Display
+ &:focus,
+ &:hover {
+ &::before,
+ &::after {
+ opacity: 1;
+ }
+ }
+
+
+ @if $enable-transitions {
+
+ // Animations, excluding touch devices
+ @media (hover: hover) and (pointer: fine) {
+ &[data-placement="bottom"]:focus,
+ &[data-placement="bottom"]:hover
+ &:focus,
+ &:hover {
+ &::before,
+ &::after {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-top;
+ }
+
+ &::after {
+ animation-name: tooltip-caret-slide-top;
+ }
+ }
+
+ &[data-placement="bottom"] {
+ &:focus,
+ &:hover {
+ &::before,
+ &::after {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-bottom;
+ }
+
+ &::after {
+ animation-name: tooltip-caret-slide-bottom;
+ }
+ }
+ }
+
+ &[data-placement="left"] {
+ &:focus,
+ &:hover {
+ &::before,
+ &::after {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-left;
+ }
+
+ &::after {
+ animation-name: tooltip-caret-slide-left;
+ }
+ }
+ }
+
+ &[data-placement="right"] {
+ &:focus,
+ &:hover {
+ &::before,
+ &::after {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-right;
+ }
+
+ &::after {
+ animation-name: tooltip-caret-slide-right;
+ }
+ }
+ }
+ }
+
+ @keyframes tooltip-slide-top {
+ from {
+ transform: translate(-50%, .75rem);
+ opacity: 0;
+ }
+ to {
+ transform: translate(-50%, -.25rem);
+ opacity: 1;
+ }
+ }
+
+ @keyframes tooltip-caret-slide-top {
+ from {
+ opacity: 0;
+ }
+ 50% {
+ transform: translate(-50%, -.25rem);
+ opacity: 0;
+ }
+ to {
+ transform: translate(-50%, 0rem);
+ opacity: 1;
+ }
+ }
+
+ @keyframes tooltip-slide-bottom {
+ from {
+ transform: translate(-50%, -.75rem);
+ opacity: 0;
+ }
+ to {
+ transform: translate(-50%, .25rem);
+ opacity: 1;
+ }
+ }
+
+ @keyframes tooltip-caret-slide-bottom {
+ from {
+ opacity: 0;
+ }
+ 50% {
+ transform: translate(-50%, -.5rem);
+ opacity: 0;
+ }
+ to {
+ transform: translate(-50%, -.3rem);
+ opacity: 1;
+ }
+ }
+
+ @keyframes tooltip-slide-left {
+ from {
+ transform: translate(.75rem, -50%);
+ opacity: 0;
+ }
+ to {
+ transform: translate(-.25rem, -50%);
+ opacity: 1;
+ }
+ }
+
+ @keyframes tooltip-caret-slide-left {
+ from {
+ opacity: 0;
+ }
+ 50% {
+ transform: translate(.05rem, -50%);
+ opacity: 0;
+ }
+ to {
+ transform: translate(.3rem, -50%);
+ opacity: 1;
+ }
+ }
+
+ @keyframes tooltip-slide-right {
+ from {
+ transform: translate(-.75rem, -50%);
+ opacity: 0;
+ }
+ to {
+ transform: translate(.25rem, -50%);
+ opacity: 1;
+ }
+ }
+
+ @keyframes tooltip-caret-slide-right {
+ from {
+ opacity: 0;
+ }
+ 50% {
+ transform: translate(-.05rem, -50%);
+ opacity: 0;
+ }
+ to {
+ transform: translate(-.3rem, -50%);
+ opacity: 1;
+ }
+ }
+ }
+}