mirror of
https://github.com/rio-labs/rio.git
synced 2026-02-08 23:00:39 -06:00
4146 lines
87 KiB
SCSS
4146 lines
87 KiB
SCSS
@use "sass:meta";
|
|
@use "switcheroos.scss";
|
|
|
|
/// For consistency, all components (and layout helper elements used for
|
|
/// alignment, scrolling, etc) share these styling attributes
|
|
@mixin shared-component-style {
|
|
position: relative;
|
|
}
|
|
|
|
/// For elements with a single child element. Stretches the child to fill the
|
|
/// parent if the parent is larger.
|
|
@mixin single-container {
|
|
display: flex;
|
|
|
|
& > * {
|
|
flex-grow: 1;
|
|
}
|
|
}
|
|
|
|
.rio-single-container {
|
|
@include single-container();
|
|
}
|
|
|
|
/// For elements with a single child element. Centers the child if the parent is
|
|
/// larger.
|
|
@mixin center-content {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
/// Kills the element's size request so it can't make its parent element grow.
|
|
/// Always takes the size of the nearest *positioned* parent element.
|
|
///
|
|
/// We have two implementations because they have different tradeoffs:
|
|
///
|
|
/// - `kill-size-request-with-zero-zero`: Doesn't work on "replaced elements"
|
|
/// like <svg> and <img>.
|
|
/// - `kill-size-request-with-absolute`: Can have unintended side effects (for
|
|
/// example, scroll anchoring excludes elements that are absolute)
|
|
@mixin kill-size-request-with-zero-zero {
|
|
// Prevent it from making the parent element grow
|
|
width: 0;
|
|
height: 0;
|
|
|
|
// Fill the entire parent
|
|
min-width: 100%;
|
|
min-height: 100%;
|
|
}
|
|
|
|
@mixin kill-size-request-with-absolute {
|
|
// Prevent it from making the parent element grow
|
|
position: absolute;
|
|
|
|
// Fill the entire parent
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
/// Kills the child's size request and adds scroll bars if necessary.
|
|
///
|
|
/// Requires 2 nested helper elements.
|
|
@mixin scroll-in-both-directions {
|
|
// The first element is responsible for scrolling
|
|
overflow: auto;
|
|
pointer-events: auto;
|
|
|
|
position: relative;
|
|
|
|
& > * {
|
|
// The 2nd element kills the content's size request
|
|
width: 0;
|
|
height: 0;
|
|
|
|
min-width: 100%;
|
|
min-height: 100%;
|
|
|
|
// For some reason horizontal scrolling forces the child's width to be
|
|
// the same as the parent's (minus the width of the scroll bar), which
|
|
// can lead to it being smaller than its content.
|
|
& > * {
|
|
min-width: max-content;
|
|
min-height: 100%;
|
|
|
|
@include single-container();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Light / Dark highlight.js themes
|
|
//
|
|
// Switch between these by setting the `data-theme` attribute on the `html`
|
|
html[data-theme="light"] {
|
|
@include meta.load-css("highlightjs-default-light.css");
|
|
}
|
|
|
|
html[data-theme="dark"] {
|
|
@include meta.load-css("highlightjs-default-dark.css");
|
|
}
|
|
|
|
// Not visible here:
|
|
//
|
|
// JavaScript sets global theming variables, of the form `--rio-global-...`.
|
|
|
|
// Z-indices for components which are expected to show up on top.
|
|
//
|
|
// - `popup` MUST be above `dev-tools` in order for pop-ups in the dev tools to
|
|
// work correctly.
|
|
// - `dev-tools` must be above `dev-tools-highlighter` so they don't get greyed
|
|
// out by it
|
|
$z-index-user-root: 1;
|
|
$z-index-overlay: 2;
|
|
$z-index-dev-tools-highlighter: 3;
|
|
$z-index-dev-tools: 4;
|
|
$z-index-popup: 5;
|
|
$z-index-error-popup: 6;
|
|
|
|
// "Infinite" corner radius, for creating pill shapes
|
|
$infinite-corner-radius: 99999px;
|
|
|
|
// Nonstandard transition timing function
|
|
$transition-timing-overshoot: cubic-bezier(0.5, 0.5, 0.2, 1.14);
|
|
|
|
// Monospace fonts
|
|
$monospace-fonts: var(--rio-global-monospace-font), monospace;
|
|
|
|
@keyframes barber-pole {
|
|
from {
|
|
background-position: 0 0;
|
|
}
|
|
|
|
to {
|
|
background-position: 3rem 0rem;
|
|
}
|
|
}
|
|
|
|
@mixin barber-pole($color) {
|
|
background-image: linear-gradient(
|
|
-45deg,
|
|
$color 15%,
|
|
transparent 15%,
|
|
transparent 50%,
|
|
$color 50%,
|
|
$color 65%,
|
|
transparent 65%
|
|
);
|
|
background-size: 3rem 3rem;
|
|
animation: barber-pole 1s linear infinite;
|
|
}
|
|
|
|
// NaturalSizeObservers
|
|
.rio-natural-height-observer {
|
|
position: relative;
|
|
overflow-y: hidden;
|
|
}
|
|
|
|
.rio-natural-height-observer-flexbox {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.rio-natural-size-observer-child-container {
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-natural-size-observer-spacer {
|
|
flex-grow: 1;
|
|
}
|
|
|
|
// General
|
|
a {
|
|
color: var(--rio-local-level-2-bg);
|
|
}
|
|
|
|
a:hover {
|
|
color: var(--rio-local-level-2-bg-active);
|
|
}
|
|
|
|
code {
|
|
font-family: $monospace-fonts;
|
|
}
|
|
|
|
html {
|
|
background: var(--rio-global-background-bg);
|
|
|
|
// Fill the whole screen, at least
|
|
min-width: 100%;
|
|
min-height: 100%;
|
|
|
|
@include single-container;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
|
|
font-family: var(--rio-global-font, sans-serif);
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
// Force input elements to use the font-family we specified. For some reason
|
|
// they don't inherit it per default.
|
|
input,
|
|
textarea,
|
|
select {
|
|
font-family: inherit;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
// Scrolling helper elements
|
|
.rio-scroll-helper {
|
|
@include shared-component-style();
|
|
}
|
|
|
|
// Alignment helper elements
|
|
.rio-align-outer {
|
|
pointer-events: none;
|
|
|
|
@include shared-component-style();
|
|
}
|
|
|
|
.rio-align-inner {
|
|
position: relative;
|
|
|
|
&.stretch-child-x > * {
|
|
width: 100%;
|
|
}
|
|
|
|
&.stretch-child-y > * {
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
// Margin helper element
|
|
.rio-margin {
|
|
pointer-events: none;
|
|
|
|
@include single-container();
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
// Container elements for child components
|
|
.rio-child-wrapper {
|
|
@include single-container();
|
|
}
|
|
|
|
// All components
|
|
.rio-component {
|
|
@include shared-component-style();
|
|
}
|
|
|
|
// User-defined components
|
|
.rio-high-level-component {
|
|
@include single-container();
|
|
}
|
|
|
|
// Fundamental Root Component
|
|
.rio-fundamental-root-component {
|
|
pointer-events: none;
|
|
|
|
display: grid;
|
|
|
|
grid-template-columns: minmax(min-content, 1fr) min-content;
|
|
|
|
// The user's root component
|
|
& > .rio-user-root-container-outer {
|
|
z-index: $z-index-user-root;
|
|
|
|
grid-row: 1;
|
|
grid-column: 1;
|
|
}
|
|
|
|
&[data-has-dev-tools="true"] > .rio-user-root-container-outer {
|
|
// If the dev tools sidebar is present, we don't want the scrollbar to
|
|
// be on their left side, so we must manually take care of scrolling
|
|
// instead of letting the <html> element do it.
|
|
@include scroll-in-both-directions();
|
|
}
|
|
|
|
&[data-has-dev-tools="false"] > .rio-user-root-container-outer {
|
|
// If the dev tools sidebar is not present, we want to let the <html>
|
|
// element handle scrolling. This is important because mobile browsers
|
|
// hide the URL bar when you scroll down.
|
|
@include single-container();
|
|
|
|
& > * {
|
|
@include single-container();
|
|
|
|
& > .rio-user-root-container-inner {
|
|
@include single-container();
|
|
}
|
|
}
|
|
}
|
|
|
|
// The contents of overlays
|
|
.rio-overlays-container {
|
|
z-index: $z-index-overlay;
|
|
|
|
overflow: hidden;
|
|
}
|
|
|
|
&[data-has-dev-tools="true"] > .rio-overlays-container {
|
|
grid-row: 1;
|
|
grid-column: 1;
|
|
|
|
// We don't want overlays to cover the dev tools sidebar, so if the dev
|
|
// tools exist, overlays should only be as large as this container. In
|
|
// order for that to work, this container must be a positioned element.
|
|
position: relative;
|
|
|
|
& > * {
|
|
@include kill-size-request-with-absolute();
|
|
}
|
|
}
|
|
|
|
&[data-has-dev-tools="false"] > .rio-overlays-container {
|
|
// If there are no dev tools present, then scrolling is handled by the
|
|
// <html> element instead our rio-user-root-container, so in this case
|
|
// overlays must be `position: fixed` and cover the whole screen.
|
|
position: fixed;
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
& > * {
|
|
position: fixed;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
// The dev tools sidebar
|
|
& > .rio-dev-tools-container {
|
|
z-index: $z-index-dev-tools;
|
|
|
|
grid-row: 1;
|
|
grid-column: 2;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
// The connection lost popup
|
|
& > .rio-connection-lost-popup-container {
|
|
z-index: $z-index-error-popup;
|
|
|
|
grid-row: 1;
|
|
grid-column: 1 / 3;
|
|
}
|
|
}
|
|
|
|
.rio-connection-lost-popup-container {
|
|
display: none;
|
|
background-color: transparent;
|
|
opacity: 0;
|
|
|
|
transition:
|
|
opacity 0.3s ease-in-out,
|
|
background-color 1s ease-in-out;
|
|
|
|
& > * {
|
|
transform: translateY(-5rem);
|
|
transition: transform 0.3s $transition-timing-overshoot;
|
|
}
|
|
}
|
|
|
|
.rio-connection-lost-popup-visible {
|
|
@include single-container(); // This also sets the display attribute
|
|
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
opacity: 1;
|
|
|
|
& > * {
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
// Dev Tools
|
|
.rio-dev-tools {
|
|
pointer-events: auto;
|
|
}
|
|
|
|
@media (width <= 50rem) or (height <= 30rem) {
|
|
.rio-dev-tools > * {
|
|
display: none !important;
|
|
}
|
|
|
|
.rio-dev-tools::after {
|
|
pointer-events: none;
|
|
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0.1rem;
|
|
bottom: 0;
|
|
|
|
content: "Screen too small for Dev Tools";
|
|
color: var(--rio-global-neutral-fg);
|
|
font-size: 0.8rem;
|
|
writing-mode: vertical-rl;
|
|
text-align: center;
|
|
|
|
opacity: 0.5;
|
|
}
|
|
}
|
|
|
|
// Row & Column
|
|
.rio-linear-container {
|
|
pointer-events: none;
|
|
|
|
@include single-container();
|
|
|
|
& > * > * {
|
|
display: flex;
|
|
align-items: stretch;
|
|
|
|
// Stretch to fill the parent
|
|
min-width: 100%;
|
|
min-height: 100%;
|
|
}
|
|
}
|
|
|
|
.rio-column > * > * {
|
|
flex-direction: column;
|
|
}
|
|
|
|
// Row & Column with proportions
|
|
.rio-row.has-proportions > * {
|
|
// Cut off the spacer element
|
|
overflow-x: hidden;
|
|
width: 100%;
|
|
}
|
|
|
|
.rio-column.has-proportions > * {
|
|
// Cut off the spacer element
|
|
overflow-y: hidden;
|
|
height: 100%;
|
|
}
|
|
|
|
// Grid
|
|
.rio-grid {
|
|
pointer-events: none;
|
|
display: inline-grid;
|
|
}
|
|
|
|
// Text
|
|
.rio-text {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
color: var(--rio-local-text-color);
|
|
}
|
|
|
|
.rio-text > * {
|
|
flex-grow: 1;
|
|
overflow: hidden;
|
|
|
|
// Remove default styling of headings
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
// Class-container
|
|
.rio-class-container {
|
|
pointer-events: none;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
// Key event listener
|
|
.rio-key-event-listener {
|
|
pointer-events: none;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
// Pointer event listener
|
|
.rio-pointer-event-listener {
|
|
pointer-events: auto;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
// Rectangle
|
|
.rio-rectangle {
|
|
pointer-events: auto;
|
|
border-style: solid;
|
|
|
|
@include single-container;
|
|
|
|
// The transition time is set via JS
|
|
transition-property: background, stroke-color, stroke-width, border-radius,
|
|
shadow-color, shadow-radius, shadow-offset;
|
|
transition-timing-function: ease;
|
|
|
|
// The following attributes are controlled via variables, to allow
|
|
// JavaScript to change them, even on pseudo-classes.
|
|
background: var(--rio-rectangle-background);
|
|
backdrop-filter: var(--rio-rectangle-backdrop-filter);
|
|
-webkit-backdrop-filter: var(--rio-rectangle-backdrop-filter);
|
|
border-color: var(--rio-rectangle-stroke_color);
|
|
border-width: var(--rio-rectangle-stroke_width);
|
|
border-radius: var(--rio-rectangle-corner_radius);
|
|
box-shadow: var(--rio-rectangle-shadow_offset_x)
|
|
var(--rio-rectangle-shadow_offset_y) var(--rio-rectangle-shadow_radius)
|
|
var(--rio-rectangle-shadow_color);
|
|
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.rio-rectangle:hover {
|
|
background: var(--rio-rectangle-hover-background);
|
|
backdrop-filter: var(--rio-rectangle-hover-backdrop-filter);
|
|
-webkit-backdrop-filter: var(--rio-rectangle-hover-backdrop-filter);
|
|
border-color: var(--rio-rectangle-hover-stroke_color);
|
|
border-width: var(--rio-rectangle-hover-stroke_width);
|
|
border-radius: var(--rio-rectangle-hover-corner_radius);
|
|
box-shadow: var(--rio-rectangle-hover-shadow_offset_x)
|
|
var(--rio-rectangle-hover-shadow_offset_y)
|
|
var(--rio-rectangle-hover-shadow_radius)
|
|
var(--rio-rectangle-hover-shadow_color);
|
|
}
|
|
|
|
// Input Box: This is a style common to multiple input components, such as
|
|
// `TextInput` and `Dropdown`.
|
|
$rio-input-box-height: 2rem;
|
|
$rio-input-box-reserved-height-for-label: 1rem;
|
|
$rio-input-box-text-distance-from-bottom: 0.38rem; // To be aligned with the <input>
|
|
$rio-input-box-horizontal-padding: 0.8rem;
|
|
$rio-input-box-large-label-font-size: 1rem;
|
|
$rio-input-box-small-label-font-size: 0.8rem;
|
|
$rio-input-box-small-label-spacing-top: 0.5rem;
|
|
|
|
.rio-input-box {
|
|
pointer-events: auto;
|
|
cursor: text;
|
|
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: stretch;
|
|
|
|
background-color: var(--rio-local-bg-variant);
|
|
|
|
transition: background-color 0.1s linear;
|
|
}
|
|
|
|
.rio-input-box-style-underlined {
|
|
border-radius: var(--rio-global-corner-radius-small)
|
|
var(--rio-global-corner-radius-small) 0 0;
|
|
}
|
|
|
|
.rio-input-box-style-rounded {
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
}
|
|
|
|
.rio-input-box-style-pill {
|
|
border-radius: $infinite-corner-radius;
|
|
}
|
|
|
|
*:not(.rio-input-box-style-underlined) > .rio-input-box-plain-bar,
|
|
*:not(.rio-input-box-style-underlined) > .rio-input-box-color-bar {
|
|
display: none;
|
|
}
|
|
|
|
.rio-input-box:hover:not(.rio-insensitive) {
|
|
background-color: var(--rio-local-bg-active);
|
|
}
|
|
|
|
.rio-input-box.rio-insensitive {
|
|
cursor: auto;
|
|
}
|
|
|
|
.rio-input-box:focus-within,
|
|
.rio-input-box.rio-input-box-focused {
|
|
outline: none;
|
|
background-color: var(--rio-local-bg-active);
|
|
}
|
|
|
|
.rio-input-box-padding {
|
|
width: $rio-input-box-horizontal-padding;
|
|
}
|
|
|
|
.rio-input-box-column {
|
|
min-height: $rio-input-box-height;
|
|
min-width: 1rem;
|
|
flex-grow: 1;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.rio-input-box.has-label > .rio-input-box-column {
|
|
min-height: calc(
|
|
$rio-input-box-height + $rio-input-box-reserved-height-for-label
|
|
);
|
|
}
|
|
|
|
.rio-input-box-column > input,
|
|
.rio-input-box-column > textarea {
|
|
min-width: 0;
|
|
|
|
padding: 0;
|
|
|
|
background-color: transparent;
|
|
color: var(--rio-local-text-color);
|
|
caret-color: var(--rio-local-level-2-bg);
|
|
border: none;
|
|
}
|
|
|
|
.rio-input-box-column > input {
|
|
// The input element has to cover the entire height so that clicking
|
|
// anywhere will position the cursor correctly. But there is no way to
|
|
// control the vertical alignment of the text in an input element, so as a
|
|
// workaround we have to make it overflow at the bottom.
|
|
//
|
|
// The math for calculating the height is actually quite simple: At its
|
|
// natural size, with no label or extra space, the text is perfectly
|
|
// centered. We want the text to be bottom-aligned, so if there is any extra
|
|
// space, it goes on top. That means we simply have to extend the height of
|
|
// the input element by the amount of extra space and it will be centered
|
|
// again.
|
|
//
|
|
// The extra space is equal to `100% - $rio-input-box-height`, so the height
|
|
// must be `100% + 100% - $rio-input-box-height`.
|
|
//
|
|
// Note: A vertical padding can make this math incorrect. Ensure that there
|
|
// is no padding or that `box-sizing` is set to `border-box`.
|
|
position: absolute;
|
|
width: 100%;
|
|
height: calc(200% - $rio-input-box-height);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.rio-input-box-column > textarea {
|
|
// Don't overlap with the label
|
|
//
|
|
// Padding would be better, since it's clickable, but oddly when the text is
|
|
// long, and scrolling down, the text will be visible under the label, in
|
|
// the element's padding.
|
|
margin-top: calc(
|
|
$rio-input-box-small-label-spacing-top +
|
|
$rio-input-box-small-label-font-size +
|
|
/* The bottom spacing is smaller than the top spacing, unfortunately
|
|
*/
|
|
0.3rem
|
|
);
|
|
|
|
// Don't overlap with the line at the bottom
|
|
margin-bottom: 0.1rem;
|
|
|
|
// Make the textarea exactly fill the allocated space, so wraps the text
|
|
// rather than weirdly overflowing
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
// Cut off the text instead of showing a scroll bar
|
|
overflow: hidden;
|
|
|
|
resize: none;
|
|
}
|
|
|
|
.rio-input-box-column > input:active,
|
|
.rio-input-box-column > textarea:active {
|
|
background-color: transparent;
|
|
}
|
|
|
|
.rio-input-box-column > input:focus-visible,
|
|
.rio-input-box-column > textarea:focus-visible {
|
|
outline: none;
|
|
}
|
|
|
|
.rio-input-box-label-width-reserver {
|
|
height: 0;
|
|
opacity: 0;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.rio-input-box.label-is-always-small .rio-input-box-label-width-reserver {
|
|
font-size: $rio-input-box-small-label-font-size;
|
|
}
|
|
|
|
.rio-input-box-label {
|
|
pointer-events: none;
|
|
|
|
position: absolute;
|
|
font-size: 1rem;
|
|
|
|
// Calculate the vertical position. When the InputBox is at its natural
|
|
// height, the result should be `$rio-input-box-text-distance-from-bottom`.
|
|
// When it's taller, we want to be approximately centered.
|
|
bottom: calc(50% - $rio-input-box-large-label-font-size / 2);
|
|
|
|
color: var(--rio-local-text-color);
|
|
opacity: 0.5;
|
|
|
|
transition: all 0.13s linear;
|
|
}
|
|
|
|
.rio-input-box:focus-within .rio-input-box-label,
|
|
.rio-input-box-focused .rio-input-box-label,
|
|
.rio-input-box.has-value .rio-input-box-label {
|
|
color: var(--rio-local-level-2-bg);
|
|
opacity: 1;
|
|
bottom: calc(
|
|
100% - $rio-input-box-small-label-spacing-top -
|
|
$rio-input-box-small-label-font-size
|
|
);
|
|
font-size: $rio-input-box-small-label-font-size;
|
|
}
|
|
|
|
.rio-input-box-hint-text {
|
|
// Align the text at the bottom
|
|
display: flex;
|
|
align-items: end;
|
|
padding-bottom: $rio-input-box-text-distance-from-bottom;
|
|
|
|
user-select: none;
|
|
|
|
color: var(--rio-local-text-color);
|
|
|
|
opacity: 0;
|
|
transition: all 0.13s linear;
|
|
}
|
|
|
|
.rio-input-box-prefix-text {
|
|
margin-right: 0.2rem;
|
|
}
|
|
|
|
.rio-input-box-suffix-text {
|
|
margin-left: 0.2rem;
|
|
}
|
|
|
|
.rio-input-box:focus-within > .rio-input-box-hint-text,
|
|
.rio-input-box-focused > .rio-input-box-hint-text,
|
|
.rio-input-box.has-value > .rio-input-box-hint-text {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.rio-input-box-suffix-element {
|
|
display: flex;
|
|
align-items: end;
|
|
|
|
& > * {
|
|
height: $rio-input-box-height;
|
|
}
|
|
}
|
|
|
|
.rio-input-box-plain-bar,
|
|
.rio-input-box-color-bar {
|
|
position: absolute;
|
|
bottom: 0;
|
|
height: 0.12rem;
|
|
}
|
|
|
|
.rio-input-box-plain-bar {
|
|
background-color: var(--rio-local-text-color);
|
|
|
|
left: 0;
|
|
right: 0;
|
|
opacity: 0.15;
|
|
}
|
|
|
|
.rio-input-box-color-bar {
|
|
background-color: var(--rio-local-level-2-bg);
|
|
|
|
left: 40%;
|
|
right: 40%;
|
|
opacity: 0;
|
|
|
|
transition: all 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-input-box:focus-within .rio-input-box-color-bar,
|
|
.rio-input-box-focused .rio-input-box-color-bar {
|
|
left: 0;
|
|
right: 0;
|
|
opacity: 1;
|
|
}
|
|
|
|
.rio-input-box.rio-insensitive {
|
|
--rio-local-text-color: var(--rio-global-disabled-fg);
|
|
background-color: var(--rio-global-disabled-bg);
|
|
|
|
.rio-input-box-label {
|
|
color: var(--rio-global-disabled-fg) !important;
|
|
}
|
|
}
|
|
|
|
.rio-input-box-accessibility-label {
|
|
position: absolute;
|
|
opacity: 0;
|
|
}
|
|
|
|
// Stack
|
|
.rio-stack {
|
|
pointer-events: none;
|
|
display: grid;
|
|
|
|
// Create a new stacking context, to ensure the children don't interfere
|
|
// with each other. `position` is already set by `rio-component`.
|
|
z-index: 0;
|
|
}
|
|
|
|
.rio-stack > * {
|
|
grid-row: 1;
|
|
grid-column: 1;
|
|
|
|
// Create a new stacking context, to ensure the children don't interfere
|
|
// with each other. `position` is already set by `rio-component`.
|
|
z-index: 0;
|
|
}
|
|
|
|
// Switch
|
|
.rio-switch {
|
|
pointer-events: none;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
// This reserves space for the outline so the switch doesn't change size
|
|
// when it's enabled or disabled
|
|
padding: 0.15rem;
|
|
|
|
// This div is centered in the allocated space
|
|
& > div {
|
|
pointer-events: auto;
|
|
position: relative;
|
|
|
|
width: 2.8rem;
|
|
height: 1.6rem;
|
|
|
|
background-color: var(--rio-global-disabled-bg);
|
|
border-radius: $infinite-corner-radius;
|
|
|
|
z-index: 1;
|
|
|
|
outline: 0.15rem solid var(--rio-global-disabled-bg-variant);
|
|
|
|
transition:
|
|
all 0.3s ease-in-out,
|
|
outline 0.15s linear;
|
|
}
|
|
|
|
svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
margin-top: 0.1rem;
|
|
|
|
transition: fill 0.1s ease-in-out;
|
|
}
|
|
|
|
& > div > input {
|
|
position: relative;
|
|
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
padding: 0;
|
|
margin: 0;
|
|
|
|
opacity: 0;
|
|
cursor: pointer;
|
|
z-index: 3;
|
|
}
|
|
|
|
& > div > .knob {
|
|
z-index: 2;
|
|
position: absolute;
|
|
|
|
top: 0.2rem;
|
|
left: 0.2rem;
|
|
width: 1.2rem;
|
|
height: 1.2rem;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
border-radius: $infinite-corner-radius;
|
|
background-color: var(--rio-global-disabled-bg-variant);
|
|
--icon-color: transparent;
|
|
|
|
transition: all 0.3s cubic-bezier(0.2, 0.9, 0.35, 1.15);
|
|
}
|
|
|
|
&:not(.rio-switcheroo-disabled) > div > input:active + .knob {
|
|
width: 1.8rem;
|
|
}
|
|
}
|
|
|
|
.rio-switch.is-on {
|
|
& > div {
|
|
background-color: var(--rio-local-level-2-bg);
|
|
outline: 0rem solid var(--rio-global-disabled-bg-variant);
|
|
}
|
|
|
|
& > div > .knob {
|
|
left: 1.4rem;
|
|
background-color: var(--rio-local-bg);
|
|
--icon-color: var(--rio-local-level-2-bg);
|
|
}
|
|
|
|
&:not(.rio-switcheroo-disabled) > div > input:active + .knob {
|
|
left: 0.8rem;
|
|
}
|
|
}
|
|
|
|
.rio-switch.rio-switcheroo-disabled {
|
|
opacity: 0.8;
|
|
|
|
& > div {
|
|
background-color: transparent !important;
|
|
outline: 0.15rem solid var(--rio-global-disabled-bg-variant) !important;
|
|
}
|
|
|
|
& > div > input {
|
|
cursor: default !important;
|
|
}
|
|
|
|
& > div > .knob {
|
|
background-color: var(--rio-global-disabled-bg-variant) !important;
|
|
}
|
|
}
|
|
|
|
// Dropdown
|
|
.rio-dropdown {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
&:not(.rio-insensitive) > .rio-input-box {
|
|
&,
|
|
input {
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
|
|
& > .rio-input-box {
|
|
flex-grow: 1;
|
|
}
|
|
|
|
// This is the element that contains the invisible copies of all options
|
|
// (which ensures that the dropdown is wide enough)
|
|
& > div:last-child {
|
|
height: 0;
|
|
overflow: hidden;
|
|
pointer-events: none;
|
|
font-weight: bold;
|
|
padding-right: 2rem; // Adds space for the arrow
|
|
}
|
|
}
|
|
|
|
.rio-dropdown-popup {
|
|
background-color: var(--rio-global-background-bg);
|
|
color: var(--rio-global-text-color);
|
|
border-radius: 0 0 var(--rio-global-corner-radius-small)
|
|
var(--rio-global-corner-radius-small);
|
|
box-shadow: 0 0 0.8rem var(--rio-global-shadow-color);
|
|
|
|
max-height: 0;
|
|
}
|
|
|
|
.rio-dropdown-popup {
|
|
transition:
|
|
max-height 0.2s ease-in-out,
|
|
box-shadow 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-dropdown-popup:not(.rio-popup-manager-open) {
|
|
max-height: 0 !important;
|
|
}
|
|
|
|
.rio-dropdown-popup-fullscreen {
|
|
position: absolute;
|
|
z-index: $z-index-popup;
|
|
|
|
left: 50%;
|
|
top: 50%;
|
|
min-width: 15rem;
|
|
transform: translate(-50%, -50%);
|
|
|
|
background-color: var(--rio-global-neutral-bg);
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
|
|
// FIXME: This should really shade the entire screen rather than just be a
|
|
// shadow. However, after spending hours on trying - and failing - to get
|
|
// this to work, I've decided a shadow will do.
|
|
box-shadow: 0 0 0 transparent;
|
|
}
|
|
|
|
.rio-dropdown-popup-fullscreen.rio-popup-manager-open {
|
|
box-shadow: 0 0 3rem var(--rio-global-shadow-color);
|
|
}
|
|
|
|
.rio-dropdown-arrow {
|
|
pointer-events: none;
|
|
|
|
// Position the SVG
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
svg {
|
|
width: 1.3rem;
|
|
height: 1.3rem;
|
|
}
|
|
}
|
|
|
|
.rio-dropdown-option-highlighted {
|
|
font-weight: bold;
|
|
color: var(--rio-local-level-2-bg);
|
|
}
|
|
|
|
.rio-dropdown-options {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
white-space: pre;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.rio-dropdown-options > div {
|
|
position: relative;
|
|
}
|
|
|
|
.rio-dropdown-options > svg {
|
|
position: relative;
|
|
|
|
width: 4rem;
|
|
height: 4rem;
|
|
|
|
margin: 1.5rem auto;
|
|
}
|
|
|
|
.rio-dropdown-option {
|
|
height: 2rem;
|
|
|
|
// Center the text vertically
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
// Align the options with the text in the dropdown
|
|
padding-left: $rio-input-box-horizontal-padding;
|
|
padding-right: $rio-input-box-horizontal-padding;
|
|
}
|
|
|
|
.rio-dropdown-popup-fullscreen .rio-dropdown-option {
|
|
height: 3rem;
|
|
justify-content: center;
|
|
}
|
|
|
|
// Spawn a brightly colored element when hovered
|
|
.rio-dropdown-option::after {
|
|
content: "";
|
|
pointer-events: none;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
background-color: var(--rio-global-primary-bg);
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.1s ease-in-out;
|
|
}
|
|
|
|
.rio-dropdown-option-highlighted::after {
|
|
opacity: 0.2;
|
|
}
|
|
|
|
// Progress Bar
|
|
.rio-progress-bar {
|
|
pointer-events: auto;
|
|
|
|
position: relative;
|
|
|
|
overflow: hidden; // For the animation
|
|
}
|
|
|
|
.rio-progress-bar-track {
|
|
// We can't set a min-height on the `rio-progress-bar` because JS will
|
|
// overwrite it, so we'll set it here instead
|
|
min-height: 0.2rem;
|
|
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
background: var(--rio-local-text-color);
|
|
opacity: 0.3;
|
|
}
|
|
|
|
.rio-progress-bar-fill {
|
|
position: absolute;
|
|
|
|
height: 100%;
|
|
|
|
background: var(--rio-local-bg);
|
|
}
|
|
|
|
@keyframes rio-progress-bar-animation-indeterminate {
|
|
0% {
|
|
left: -20%;
|
|
width: 6%;
|
|
}
|
|
|
|
50% {
|
|
width: 30%;
|
|
}
|
|
|
|
100% {
|
|
left: 120%;
|
|
width: 6%;
|
|
}
|
|
}
|
|
|
|
.rio-progress-bar-indeterminate .rio-progress-bar-fill {
|
|
transform: translateX(-50%);
|
|
animation: rio-progress-bar-animation-indeterminate 1.5s ease-in-out
|
|
infinite;
|
|
}
|
|
|
|
.rio-progress-bar:not(.rio-progress-bar-indeterminate) .rio-progress-bar-fill {
|
|
left: 0;
|
|
width: var(--rio-progress-bar-fraction);
|
|
|
|
transition: width 0.3s ease-in-out;
|
|
}
|
|
|
|
// Progress Circle
|
|
.rio-progress-circle {
|
|
// Pointer events are only enabled for the filled part of the circle
|
|
pointer-events: none;
|
|
|
|
stroke: var(--rio-local-bg);
|
|
|
|
// For some reason, `align-items: center` makes the spinner grow. So we
|
|
// can't use `@include center-content()` here.
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
// Since the svg inside is rotating, the corners of its bounding box will
|
|
// stick out. This can cause frequent re-layouting. To prevent this, we
|
|
// hide the overflow.
|
|
overflow: hidden;
|
|
}
|
|
|
|
.rio-progress-circle svg {
|
|
position: absolute;
|
|
max-width: 100%;
|
|
max-height: 100%;
|
|
}
|
|
|
|
.rio-progress-circle circle {
|
|
pointer-events: auto;
|
|
fill: none;
|
|
stroke-width: 3.5;
|
|
color: var(--rio-local-bg);
|
|
}
|
|
|
|
.spinning svg {
|
|
transform-origin: center;
|
|
animation: rotate 2s linear infinite;
|
|
}
|
|
|
|
.spinning .progress {
|
|
stroke-dasharray: 1, 200;
|
|
stroke-dashoffset: 0;
|
|
stroke-linecap: round;
|
|
animation: dash 1.5s ease-in-out infinite;
|
|
}
|
|
|
|
.rio-progress-circle:not(.spinning) .progress {
|
|
stroke-dashoffset: -94.25;
|
|
stroke-dasharray: var(--dasharray);
|
|
transition: stroke-dasharray 0.5s ease;
|
|
}
|
|
|
|
@keyframes rotate {
|
|
100% {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
@keyframes dash {
|
|
0% {
|
|
stroke-dasharray: 1, 200;
|
|
stroke-dashoffset: 0;
|
|
}
|
|
|
|
50% {
|
|
stroke-dasharray: 90, 200;
|
|
stroke-dashoffset: -35px;
|
|
}
|
|
|
|
100% {
|
|
stroke-dashoffset: -125px;
|
|
}
|
|
}
|
|
|
|
// Button
|
|
.rio-button {
|
|
pointer-events: auto;
|
|
|
|
// Preserve some colors outside of the switcheroo application, as some
|
|
// styles depend on them.
|
|
--outer-text-color: var(--rio-local-text-color);
|
|
--outer-bg-active-color: var(--rio-local-bg-active);
|
|
transition:
|
|
color 0.1s ease-in-out,
|
|
border-color 0.1s ease-in-out;
|
|
|
|
// Create a stacking context. This is needed so the `colored-text` and
|
|
// `plain-text` styles can reliably create an ::after element behind the
|
|
// text.
|
|
z-index: 0;
|
|
|
|
@include single-container;
|
|
position: relative; // For the ripple
|
|
|
|
& > * {
|
|
@include single-container;
|
|
}
|
|
}
|
|
|
|
.rio-buttonstyle-major {
|
|
background-color: var(--rio-local-bg);
|
|
|
|
box-shadow: 0 0 0 transparent;
|
|
transition:
|
|
background-color 0.1s ease-in-out,
|
|
box-shadow 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-buttonstyle-major:hover {
|
|
background-color: var(--rio-local-bg-active);
|
|
cursor: pointer;
|
|
|
|
box-shadow: 0 0.1rem 0.22rem rgba(0, 0, 0, 0.35);
|
|
}
|
|
|
|
.rio-buttonstyle-major.rio-insensitive {
|
|
cursor: default;
|
|
background-color: var(--rio-global-disabled-bg) !important;
|
|
color: var(--rio-global-disabled-fg) !important;
|
|
box-shadow: none;
|
|
}
|
|
|
|
.rio-buttonstyle-minor {
|
|
border: 0.1rem solid var(--rio-local-bg);
|
|
--rio-local-text-color: var(--rio-local-bg);
|
|
|
|
// Note the lack of transition here. While a transition would be nice, the
|
|
// text & icon wouldn't animate alongside the background, because they're
|
|
// independent high-level components. Having just the background transition
|
|
// but the foreground switch immediately is jarring.
|
|
}
|
|
|
|
.rio-buttonstyle-minor:hover {
|
|
background-color: var(--rio-local-bg);
|
|
--rio-local-text-color: var(--rio-local-fg);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.rio-buttonstyle-minor.rio-insensitive {
|
|
cursor: default;
|
|
border: 0.1rem solid var(--rio-global-disabled-bg) !important;
|
|
background-color: unset !important;
|
|
--rio-local-text-color: var(--rio-global-disabled-bg) !important;
|
|
}
|
|
|
|
.rio-buttonstyle-colored-text,
|
|
.rio-buttonstyle-plain-text {
|
|
&:hover {
|
|
cursor: pointer;
|
|
position: relative;
|
|
background-color: var(--outer-bg-active-color);
|
|
}
|
|
|
|
transition: background-color 0.1s ease-in-out;
|
|
}
|
|
|
|
.rio-buttonstyle-colored-text {
|
|
--rio-local-text-color: var(--rio-local-bg);
|
|
}
|
|
|
|
.rio-buttonstyle-plain-text {
|
|
--rio-local-text-color: var(--outer-text-color);
|
|
}
|
|
|
|
.rio-buttonstyle-plain-text.rio-insensitive {
|
|
cursor: default;
|
|
--rio-local-text-color: var(--rio-global-disabled-bg);
|
|
|
|
&::after {
|
|
background-color: unset;
|
|
}
|
|
}
|
|
|
|
// Button shapes
|
|
.rio-button > * {
|
|
// Note: This also affects the ripple
|
|
border-radius: var(--border-radius);
|
|
}
|
|
|
|
.rio-shape-pill {
|
|
// Assigning an SCSS variable to a CSS variable requires special syntax.
|
|
// Without it, the CSS variable would be literally set to
|
|
// '$infinite-corner-radius' instead of the numeric value
|
|
--border-radius: #{$infinite-corner-radius};
|
|
}
|
|
|
|
.rio-shape-rounded {
|
|
--border-radius: var(--rio-global-corner-radius-small);
|
|
}
|
|
|
|
.rio-shape-rectangle {
|
|
--border-radius: 0;
|
|
}
|
|
|
|
.rio-shape-circle {
|
|
--border-radius: 50%;
|
|
}
|
|
|
|
// Icon button
|
|
.rio-icon-button {
|
|
// Pointer events are only enabled for the circle
|
|
pointer-events: none;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.rio-button {
|
|
// Fill up the parent (helper) element
|
|
@include kill-size-request-with-absolute();
|
|
|
|
& > *:not(.rio-ripple-container) {
|
|
// Leave some padding around the icon so it doesn't stick out of the
|
|
// circle
|
|
padding: 15%;
|
|
box-sizing: border-box;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Revealer
|
|
.rio-revealer {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
justify-content: stretch;
|
|
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
|
|
transition: background-color 0.15s ease-out;
|
|
}
|
|
|
|
.rio-revealer-header {
|
|
cursor: pointer;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
|
|
color: var(--rio-local-text-color);
|
|
}
|
|
|
|
.rio-revealer-label {
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.rio-revealer-arrow {
|
|
transform: rotate(90deg);
|
|
|
|
transition: transform 0.25s ease-in-out;
|
|
}
|
|
|
|
.rio-revealer-open > * > .rio-revealer-arrow {
|
|
transform: rotate(0deg);
|
|
}
|
|
|
|
.rio-revealer-content-outer {
|
|
flex-grow: 1;
|
|
|
|
overflow: hidden;
|
|
|
|
transition: max-height 0.25s ease-in-out;
|
|
}
|
|
|
|
.rio-revealer-content-inner {
|
|
position: relative;
|
|
|
|
@include single-container();
|
|
|
|
opacity: 0;
|
|
transform: translateY(-50%);
|
|
|
|
transition:
|
|
opacity 0.45s ease-in-out,
|
|
transform 0.35s ease;
|
|
}
|
|
|
|
.rio-revealer-open > * > .rio-revealer-content-inner {
|
|
opacity: 1;
|
|
transform: translateY(0%);
|
|
}
|
|
|
|
// Plot
|
|
.rio-plot {
|
|
pointer-events: auto;
|
|
|
|
display: inline-block;
|
|
|
|
// Force the corner radius to be applied to the plot as well
|
|
overflow: hidden;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-plotly-plot {
|
|
position: relative;
|
|
|
|
& > div {
|
|
@include kill-size-request-with-zero-zero();
|
|
}
|
|
}
|
|
|
|
// Icon
|
|
.rio-icon {
|
|
pointer-events: auto;
|
|
|
|
svg {
|
|
@include kill-size-request-with-absolute();
|
|
}
|
|
}
|
|
|
|
// Slider
|
|
.rio-slider {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
--rio-slider-position-transition-time: 0.3s;
|
|
}
|
|
|
|
.rio-slider:not(.rio-switcheroo-disabled) {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.rio-slider-column {
|
|
flex-grow: 1; // Fill the entire width
|
|
|
|
min-width: 3rem;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.rio-slider-inner {
|
|
pointer-events: none;
|
|
|
|
position: relative;
|
|
|
|
height: 0.25rem;
|
|
|
|
margin-top: 0.4rem;
|
|
margin-bottom: 0.4rem;
|
|
|
|
margin-left: 0.6rem;
|
|
margin-right: 0.6rem;
|
|
}
|
|
|
|
.rio-slider-track {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
opacity: 0.3;
|
|
|
|
background: var(--rio-local-text-color);
|
|
border-radius: $infinite-corner-radius;
|
|
}
|
|
|
|
.rio-slider-fill {
|
|
position: absolute;
|
|
left: 0;
|
|
width: var(--rio-slider-fraction);
|
|
height: 100%;
|
|
|
|
background: var(--rio-local-level-2-bg);
|
|
border-radius: $infinite-corner-radius;
|
|
|
|
transition: width var(--rio-slider-position-transition-time) ease-in-out;
|
|
}
|
|
|
|
.rio-slider-glow {
|
|
position: absolute;
|
|
left: var(--rio-slider-fraction);
|
|
top: 50%;
|
|
width: 1.1rem;
|
|
height: 1.1rem;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
border-radius: 50%;
|
|
background-color: var(--rio-local-level-2-bg);
|
|
opacity: 0%;
|
|
|
|
transition:
|
|
left var(--rio-slider-position-transition-time) ease-in-out,
|
|
width 0.15s ease-in-out,
|
|
height 0.15s ease-in-out,
|
|
opacity 0.15s ease-in-out;
|
|
}
|
|
|
|
.rio-slider:hover:not(.rio-switcheroo-disabled) .rio-slider-glow {
|
|
width: 2.8rem;
|
|
height: 2.8rem;
|
|
|
|
opacity: 20%;
|
|
}
|
|
|
|
.rio-slider-knob {
|
|
position: absolute;
|
|
left: var(--rio-slider-fraction);
|
|
top: 50%;
|
|
width: 1.2rem;
|
|
height: 1.2rem;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
border-radius: 50%;
|
|
background-color: var(--rio-local-level-2-bg);
|
|
|
|
box-shadow: 0 0.1rem 0.2rem var(--rio-global-shadow-color);
|
|
|
|
transition:
|
|
left var(--rio-slider-position-transition-time) ease-in-out,
|
|
background-color 0.1s ease-in-out;
|
|
}
|
|
|
|
.rio-slider-values {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
|
|
margin-top: 0.1rem;
|
|
|
|
font-size: 0.8rem;
|
|
|
|
width: 100%;
|
|
}
|
|
|
|
// Slideshow
|
|
.rio-slideshow {
|
|
pointer-events: auto;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.slideshow-child-container {
|
|
position: relative;
|
|
display: grid;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.slideshow-child-container > div {
|
|
grid-column-start: 1;
|
|
grid-row-start: 1;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.slideshow-child-container > div > * {
|
|
grid-column-start: 1;
|
|
grid-row-start: 1;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.slideshow-progress {
|
|
position: absolute;
|
|
bottom: 0;
|
|
|
|
width: 100%;
|
|
height: 0.3rem;
|
|
background-color: var(--rio-local-level-2-bg);
|
|
}
|
|
|
|
// Overlay
|
|
.rio-overlay {
|
|
pointer-events: none;
|
|
}
|
|
|
|
.rio-overlay-content {
|
|
pointer-events: none;
|
|
|
|
@include single-container();
|
|
|
|
// The rest of the CSS is in fundamental-root-component
|
|
}
|
|
|
|
// Spacer
|
|
.rio-spacer {
|
|
pointer-events: none;
|
|
}
|
|
|
|
// MediaPlayer
|
|
.rio-media-player {
|
|
pointer-events: auto;
|
|
|
|
// It's not really a single-container, but this works for aligning the
|
|
// controls at the bottom ¯\_(ツ)_/¯
|
|
@include single-container();
|
|
align-items: end;
|
|
|
|
// Hide the blue outline that appears when it has keyboard focus
|
|
outline: none;
|
|
}
|
|
|
|
.rio-media-player video {
|
|
// Make it absolute so that it's behind the controls. (We don't want to make
|
|
// the controls absolute because then the media player could become too
|
|
// small for them.)
|
|
@include kill-size-request-with-absolute();
|
|
object-fit: contain;
|
|
}
|
|
|
|
.rio-media-player-alt-display {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
|
|
width: 50%;
|
|
height: 50%;
|
|
max-width: 20rem;
|
|
max-height: 20rem;
|
|
aspect-ratio: 1;
|
|
|
|
opacity: 0.5;
|
|
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
.rio-media-player-controls {
|
|
background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6));
|
|
padding-top: 2.5rem;
|
|
|
|
position: relative; // This puts it above the video
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0rem;
|
|
align-items: stretch;
|
|
|
|
transition: opacity 0.4s ease-in-out;
|
|
}
|
|
|
|
.rio-media-player-timeline {
|
|
cursor: pointer;
|
|
|
|
position: relative;
|
|
height: 2rem;
|
|
margin: 0 0.5rem;
|
|
}
|
|
|
|
.rio-media-player-timeline > div {
|
|
position: relative;
|
|
top: 50%;
|
|
height: 0.2rem;
|
|
transform: translateY(-50%);
|
|
|
|
transition: height 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-media-player-timeline:hover > div {
|
|
height: 0.4rem;
|
|
}
|
|
|
|
.rio-media-player-timeline-knob {
|
|
position: absolute;
|
|
width: 0rem;
|
|
height: 0rem;
|
|
left: 100%;
|
|
top: 50%;
|
|
background-color: var(--rio-global-primary-bg);
|
|
border-radius: 50%;
|
|
transform: translate(-50%, -50%);
|
|
|
|
transition:
|
|
width 0.2s ease-in-out,
|
|
height 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-media-player-timeline:hover .rio-media-player-timeline-knob {
|
|
width: 0.9rem;
|
|
height: 0.9rem;
|
|
}
|
|
|
|
.rio-media-player-timeline-background,
|
|
.rio-media-player-timeline-loaded,
|
|
.rio-media-player-timeline-hover,
|
|
.rio-media-player-timeline-played {
|
|
position: absolute;
|
|
width: 0%;
|
|
height: 100%;
|
|
background-color: white;
|
|
border-radius: $infinite-corner-radius;
|
|
}
|
|
|
|
.rio-media-player-timeline-background {
|
|
width: 100%;
|
|
opacity: 0.2;
|
|
}
|
|
|
|
.rio-media-player-timeline-loaded {
|
|
opacity: 0.3;
|
|
}
|
|
|
|
.rio-media-player-timeline-hover {
|
|
opacity: 0;
|
|
transition: opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-media-player-timeline-played {
|
|
background-color: var(--rio-global-primary-bg);
|
|
}
|
|
|
|
.rio-media-player-controls-row {
|
|
display: flex;
|
|
gap: 1.2rem;
|
|
align-items: center;
|
|
padding: 0.5rem;
|
|
padding-top: 0;
|
|
}
|
|
|
|
.rio-media-player-button {
|
|
cursor: pointer;
|
|
|
|
width: 2rem;
|
|
height: 2rem;
|
|
}
|
|
|
|
.rio-media-player-button > img {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.rio-media-player-volume {
|
|
cursor: pointer;
|
|
|
|
position: relative;
|
|
width: 5rem;
|
|
height: 1.5rem;
|
|
}
|
|
|
|
.rio-media-player-volume > div {
|
|
position: relative;
|
|
top: 50%;
|
|
height: 0.2rem;
|
|
transform: translateY(-50%);
|
|
}
|
|
|
|
.rio-media-player-volume-background,
|
|
.rio-media-player-volume-current {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: $infinite-corner-radius;
|
|
background-color: white;
|
|
}
|
|
|
|
.rio-media-player-volume-background {
|
|
opacity: 0.2;
|
|
}
|
|
|
|
.rio-media-player-volume-knob {
|
|
position: absolute;
|
|
width: 0.9rem;
|
|
height: 0.9rem;
|
|
left: 100%;
|
|
top: 50%;
|
|
background-color: white;
|
|
border-radius: 50%;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
.rio-media-player-volume > div {
|
|
position: relative;
|
|
top: 50%;
|
|
height: 0.2rem;
|
|
transform: translateY(-50%);
|
|
}
|
|
|
|
.rio-media-player-playtime-label {
|
|
color: white;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
// ScrollContainer
|
|
//
|
|
// Scrolling is super weird. You'd think scrolling would be easy to achieve, but
|
|
// no. I don't really understand what makes it so difficult, but here are some
|
|
// of the issues I struggled with:
|
|
//
|
|
// 1. The parent element refuses to become smaller than its content even when
|
|
// scrolling is enabled
|
|
// 2. You can force the parent element to become smaller, but depending on how
|
|
// you do it, you may end up shrinking its content as well.
|
|
// 3. If multiple elements can scroll, we want the innermost one to do it (and
|
|
// not the <html> element).
|
|
// 4. When scrolling is only enabled in one direction, the parent may need to
|
|
// grow larger in the other direction in order to fit the scroll bar.
|
|
// 5. The element must have a minimum size so that the scroll bars are usable.
|
|
//
|
|
// The solution I've found requires 3 nested elements. From the outside in:
|
|
//
|
|
// 1. An element with `position: relative`, so that its child can size itself
|
|
// with `100%`.
|
|
//
|
|
// 2. This is where the CSS `overflow` setting is applied. We also override the
|
|
// child's size request by explicitly setting the `width`/`height` to the
|
|
// minimum size where the scroll bars are still usable. Finally, we force the
|
|
// element to fill its parent by setting `min-width`/`min-height` to `100%`.
|
|
//
|
|
// 3. For some reason, when an element scrolls horizontally, it overrides the
|
|
// width of its child, which can lead to the child being smaller than its
|
|
// content. This element exists solely to fix that with a `min-width:
|
|
// max-content`.
|
|
|
|
.rio-scroll-container {
|
|
pointer-events: auto;
|
|
|
|
$min-scroll-size: 5rem; // Minimum size where the scroll bar is still usable
|
|
|
|
// Set the `overflow` appropriately
|
|
&[data-scroll-x="auto"] > * {
|
|
overflow-x: auto;
|
|
}
|
|
&[data-scroll-x="always"] > * {
|
|
overflow-x: scroll;
|
|
}
|
|
|
|
&[data-scroll-y="auto"] > * {
|
|
overflow-y: auto;
|
|
}
|
|
&[data-scroll-y="always"] > * {
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
// Kill the size request depending on the scroll direction
|
|
&[data-scroll-x="auto"] > *,
|
|
&[data-scroll-x="always"] > * {
|
|
width: $min-scroll-size;
|
|
min-width: 100%;
|
|
}
|
|
|
|
&[data-scroll-y="auto"] > *,
|
|
&[data-scroll-y="always"] > * {
|
|
height: $min-scroll-size;
|
|
min-height: 100%;
|
|
}
|
|
|
|
// For some reason, when scrolling is enabled in the horizontal direction,
|
|
// the child element's width gets set to the width of the scrolling element.
|
|
// This can cause it to become smaller than its content. We have to override
|
|
// this.
|
|
&[data-scroll-x="auto"] > * > *,
|
|
&[data-scroll-x="always"] > * > * {
|
|
width: max-content;
|
|
}
|
|
|
|
// Stretch to fill the parent (Note: This is the
|
|
// .rio-scroll-container-column)
|
|
& > * > * {
|
|
min-width: 100%;
|
|
min-height: 100%;
|
|
}
|
|
|
|
// 'auto'-scrolling in the y direction has a unique problem: Because the
|
|
// width of an element is decided before its height, the browser doesn't
|
|
// know whether a vertical scroll bar will be needed until it's too late. If
|
|
// it turns out that the parent didn't allocate enough width for the child
|
|
// *and* the vertical scroll bar, it will suddenly start scrolling in *both*
|
|
// directions. That's not what we want - we want to increase the parent's
|
|
// width instead.
|
|
&[data-scroll-x="never"][data-scroll-y="auto"] > * {
|
|
scrollbar-gutter: stable;
|
|
}
|
|
}
|
|
|
|
.rio-scroll-container-column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.rio-scroll-container-child-container {
|
|
flex-grow: 1;
|
|
overflow-anchor: none;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-scroll-container-anchor {
|
|
height: 1px;
|
|
}
|
|
|
|
// Markdown
|
|
.rio-markdown {
|
|
pointer-events: auto;
|
|
|
|
// Per default, the spacing between elements is super inconsistent. <p>
|
|
// elements have a margin on both sides, but most others (<ul>s, code
|
|
// blocks, ...) don't. So if you have two non-text elements next to each
|
|
// other, there's suddenly no spacing at all.
|
|
//
|
|
// To make things more predictable and easier to work with, we'll remove the
|
|
// margins from all direct children, but then add spacing between children.
|
|
// (This way the 1st child won't have a margin on top, and the last child
|
|
// won't have a margin on the bottom.)
|
|
//
|
|
// (Note: We have to do this not just for the markdown view itself, but any
|
|
// element that can contain multiple children. Like <li>. And... I think
|
|
// that's it?)
|
|
& > *,
|
|
li > * {
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
& > * + *,
|
|
li > * + * {
|
|
margin-top: 0.8rem;
|
|
}
|
|
|
|
li + li {
|
|
margin-top: 0.2rem;
|
|
}
|
|
|
|
// Because `overflow='ellipsize'` requires `overflow: hidden`, the bullet
|
|
// points in <ol> and <ul> elements get cut off. To fix this, we always hide
|
|
// the ::marker element (since it only supports very limited styling) and
|
|
// replace it with a ::before element that's positioned in the <li>'s
|
|
// padding.
|
|
li::marker {
|
|
font-size: 0;
|
|
}
|
|
|
|
ol,
|
|
ul {
|
|
padding-left: 0;
|
|
}
|
|
li {
|
|
padding-left: 2.2rem; // Barely enough for 3-digit <ol> counters
|
|
position: relative; // Required for ::after element positioning
|
|
box-sizing: border-box; // Required when wrapping is enabled
|
|
}
|
|
li::before {
|
|
position: absolute;
|
|
}
|
|
|
|
ol {
|
|
counter-reset: count;
|
|
}
|
|
ol > li::before {
|
|
counter-increment: count;
|
|
content: counter(count) ".";
|
|
|
|
top: 0;
|
|
right: calc(100% - 2rem);
|
|
}
|
|
|
|
ul > li::before {
|
|
content: "-";
|
|
font-weight: bold;
|
|
|
|
top: 0.1rem;
|
|
right: calc(100% - 1.7rem);
|
|
}
|
|
|
|
code {
|
|
font-family: $monospace-fonts;
|
|
background: var(--rio-local-bg-variant);
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
padding: 0.1rem 0.3rem;
|
|
}
|
|
|
|
h1 {
|
|
font-family: var(--rio-global-heading1-font-name);
|
|
color: var(--rio-local-heading1-color);
|
|
font-size: var(--rio-global-heading1-font-size);
|
|
font-style: var(--rio-global-heading1-italic);
|
|
font-weight: var(--rio-global-heading1-font-weight);
|
|
text-decoration: var(--rio-global-heading1-text-decoration);
|
|
text-transform: var(--rio-global-heading1-all-caps);
|
|
|
|
&:not(:first-child) {
|
|
margin-top: 2rem;
|
|
}
|
|
|
|
&:not(:last-child) {
|
|
margin-bottom: 1rem;
|
|
}
|
|
}
|
|
|
|
h2 {
|
|
font-family: var(--rio-global-heading2-font-name);
|
|
color: var(--rio-local-heading2-color);
|
|
font-size: var(--rio-global-heading2-font-size);
|
|
font-style: var(--rio-global-heading2-italic);
|
|
font-weight: var(--rio-global-heading2-font-weight);
|
|
text-decoration: var(--rio-global-heading2-text-decoration);
|
|
text-transform: var(--rio-global-heading2-all-caps);
|
|
|
|
margin-top: 0;
|
|
|
|
&:not(:first-child) {
|
|
margin-top: 1.5rem;
|
|
}
|
|
|
|
&:not(:last-child) {
|
|
margin-bottom: 0.8rem;
|
|
}
|
|
}
|
|
|
|
h3 {
|
|
font-family: var(--rio-global-heading3-font-name);
|
|
color: var(--rio-local-heading3-color);
|
|
font-size: var(--rio-global-heading3-font-size);
|
|
font-style: var(--rio-global-heading3-italic);
|
|
font-weight: var(--rio-global-heading3-font-weight);
|
|
text-decoration: var(--rio-global-heading3-text-decoration);
|
|
text-transform: var(--rio-global-heading3-all-caps);
|
|
|
|
margin-top: 0;
|
|
|
|
&:not(:first-child) {
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
&:not(:last-child) {
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
}
|
|
|
|
p {
|
|
font-family: var(--rio-global-font);
|
|
color: var(--rio-local-text-color);
|
|
font-size: var(--rio-global-text-font-size);
|
|
line-height: 1.35em; // Purposely uses em
|
|
font-style: var(--rio-global-text-italic);
|
|
font-weight: var(--rio-global-text-font-weight);
|
|
text-decoration: var(--rio-global-text-text-decoration);
|
|
text-transform: var(--rio-global-text-all-caps);
|
|
}
|
|
|
|
// Text wrapping
|
|
&[data-overflow="nowrap"] {
|
|
p,
|
|
li,
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
text-overflow: clip;
|
|
white-space: pre;
|
|
width: max-content;
|
|
}
|
|
}
|
|
|
|
&[data-overflow="wrap"] {
|
|
p,
|
|
li,
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
// Kill the size request, otherwise text will pretty much never wrap
|
|
width: min-content;
|
|
min-width: 100%;
|
|
}
|
|
}
|
|
|
|
&[data-overflow="ellipsize"] {
|
|
p,
|
|
li,
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
|
|
// Kill the size request, since ellipsizing is pointless if the text
|
|
// is entirely visible
|
|
width: 0;
|
|
min-width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Code Block (also used by markdown)
|
|
.rio-code-block {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
gap: 0.5rem;
|
|
padding: var(--rio-global-corner-radius-medium);
|
|
|
|
background: var(--rio-local-bg-variant);
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.rio-code-block-header {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
|
|
color: var(--rio-local-text-color);
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.rio-code-block-language {
|
|
font-weight: bold;
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.rio-code-block-copy-button {
|
|
width: 1.3rem;
|
|
height: 1.3rem;
|
|
|
|
cursor: pointer;
|
|
border: none;
|
|
background: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
opacity: 0.4;
|
|
|
|
transition: opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-code-block-copy-button:hover {
|
|
color: var(--rio-local-level-2-bg);
|
|
opacity: 1;
|
|
}
|
|
|
|
.rio-code-block > pre {
|
|
margin: 0;
|
|
font-size: var(--rio-global-text-font-size);
|
|
font-family: $monospace-fonts;
|
|
display: block;
|
|
}
|
|
|
|
.rio-experimental-scrolling-code-blocks .rio-code-block > pre {
|
|
overflow-x: auto;
|
|
width: 0;
|
|
min-width: 100%;
|
|
}
|
|
|
|
// Link
|
|
.rio-link {
|
|
pointer-events: auto;
|
|
cursor: pointer;
|
|
|
|
display: block;
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-text-link-icon {
|
|
width: 1rem;
|
|
height: 1rem;
|
|
margin-right: 0.3rem;
|
|
}
|
|
|
|
.rio-text-link {
|
|
color: var(--rio-local-level-2-bg);
|
|
|
|
// Center the text
|
|
@include center-content();
|
|
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.rio-link:not(.rio-text-link) {
|
|
// Remove the underline. For some reason it's necessary to set this on the
|
|
// link even though our text has its own `text-decoration` setting anyway
|
|
text-decoration: none;
|
|
}
|
|
|
|
// ScrollTarget
|
|
.rio-scroll-target {
|
|
pointer-events: none;
|
|
|
|
// Hide the link-copy-button unless the cursor is hovering above
|
|
& > .rio-scroll-target-url-copy-button {
|
|
pointer-events: auto;
|
|
cursor: pointer;
|
|
|
|
display: none;
|
|
}
|
|
|
|
&:hover > .rio-scroll-target-url-copy-button {
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
// Color Picker
|
|
.rio-color-picker {
|
|
pointer-events: none;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.rio-color-picker-color-square {
|
|
pointer-events: auto;
|
|
|
|
position: relative;
|
|
min-height: 6rem;
|
|
cursor: crosshair;
|
|
margin-bottom: 0.7rem;
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.rio-color-picker-slider-outer {
|
|
pointer-events: auto;
|
|
|
|
position: relative;
|
|
padding: 0.7rem 0;
|
|
}
|
|
|
|
.rio-color-slider-inner {
|
|
height: 0.9rem;
|
|
cursor: crosshair;
|
|
border-radius: $infinite-corner-radius;
|
|
}
|
|
|
|
.rio-color-picker-knob {
|
|
pointer-events: none;
|
|
cursor: crosshair;
|
|
|
|
width: 1.4rem;
|
|
height: 1.4rem;
|
|
border-radius: 50%;
|
|
border: 0.2rem solid var(--rio-local-text-color);
|
|
position: absolute;
|
|
transform: translate(-50%, -50%);
|
|
box-sizing: border-box;
|
|
background: var(--chosen-color-opaque);
|
|
}
|
|
|
|
.rio-color-picker-slider-outer > .rio-color-picker-knob {
|
|
top: 50%;
|
|
}
|
|
|
|
.color-slider-checkers {
|
|
border-radius: $infinite-corner-radius;
|
|
}
|
|
|
|
.rio-color-picker-hue-bar > .rio-color-slider-inner {
|
|
background: linear-gradient(
|
|
to right,
|
|
red,
|
|
yellow,
|
|
lime,
|
|
aqua,
|
|
blue,
|
|
magenta,
|
|
red
|
|
);
|
|
}
|
|
|
|
.rio-color-picker-opacity-bar > .rio-color-slider-inner:not(.rio-checkered) {
|
|
position: absolute;
|
|
top: 0.7rem;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0.7rem;
|
|
|
|
background: linear-gradient(
|
|
to right,
|
|
transparent,
|
|
var(--chosen-color-opaque)
|
|
);
|
|
}
|
|
|
|
.rio-color-picker-result-container {
|
|
margin-top: 0.5rem;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.8rem;
|
|
}
|
|
|
|
.rio-color-picker-selected-color-circle {
|
|
position: relative;
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
}
|
|
|
|
.rio-color-picker-selected-color-circle > * {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
|
|
box-sizing: border-box;
|
|
border: 0.2rem solid var(--rio-local-text-color);
|
|
}
|
|
|
|
.rio-color-picker-selected-color-circle > div:first-child {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
background: var(--chosen-color-transparent);
|
|
}
|
|
|
|
.rio-color-picker-selected-color-circle-color {
|
|
background: var(--chosen-color-transparent);
|
|
}
|
|
|
|
.rio-color-picker-selected-color-label {
|
|
pointer-events: auto;
|
|
opacity: 0.5;
|
|
|
|
/* Fixed width to avoid movement when the value changes */
|
|
width: 5rem;
|
|
|
|
/* Text style */
|
|
color: var(--rio-local-text-color);
|
|
font-size: 0.9rem;
|
|
text-align: center;
|
|
font-weight: bold;
|
|
|
|
/* Override the default styling */
|
|
background: transparent;
|
|
border: none;
|
|
padding: 0.3rem;
|
|
border-radius: 0.5rem;
|
|
|
|
transition:
|
|
opacity 0.1s ease-in-out,
|
|
color 0.1s ease-in-out,
|
|
background-color 0.1s ease-in-out;
|
|
}
|
|
|
|
.rio-color-picker-selected-color-label:focus {
|
|
outline: none;
|
|
|
|
opacity: 1;
|
|
color: var(--rio-local-level-2-bg);
|
|
background: var(--rio-local-bg-variant);
|
|
}
|
|
|
|
.rio-checkered {
|
|
--checker-color: #888;
|
|
--checker-size: 0.9rem;
|
|
|
|
background-image: linear-gradient(
|
|
45deg,
|
|
var(--checker-color) 25%,
|
|
transparent 25%
|
|
),
|
|
linear-gradient(45deg, transparent 75%, var(--checker-color) 75%),
|
|
linear-gradient(45deg, transparent 75%, var(--checker-color) 75%),
|
|
linear-gradient(45deg, var(--checker-color) 25%, transparent 25%);
|
|
|
|
background-size: var(--checker-size) var(--checker-size);
|
|
background-position:
|
|
0 0,
|
|
0 0,
|
|
calc(var(--checker-size) * -0.5) calc(var(--checker-size) * -0.5),
|
|
calc(var(--checker-size) * 0.5) calc(var(--checker-size) * 0.5);
|
|
}
|
|
|
|
// Drawer
|
|
.rio-drawer {
|
|
pointer-events: auto;
|
|
overflow: hidden;
|
|
|
|
display: flex;
|
|
align-items: stretch;
|
|
|
|
// Create a stacking context, so the anchor content cannot interfere with
|
|
// the drawer content. `position` is already set by `rio-component`.
|
|
z-index: 0;
|
|
}
|
|
|
|
.rio-drawer-shade {
|
|
pointer-events: none;
|
|
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
transition: background-color 0.3s ease-in-out;
|
|
}
|
|
|
|
.rio-drawer-anchor {
|
|
pointer-events: none;
|
|
flex-grow: 1;
|
|
|
|
// Create a stacking context, so the anchor content cannot interfere with
|
|
// the drawer content
|
|
z-index: 1;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-drawer-content-outer {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
|
|
position: absolute;
|
|
background-color: var(--rio-local-bg);
|
|
|
|
// Create a stacking context, so the anchor content cannot interfere with
|
|
// the drawer content
|
|
z-index: 2;
|
|
|
|
box-shadow: 0 0 1.3rem var(--rio-global-shadow-color);
|
|
|
|
transition: transform 0.3s ease-out;
|
|
}
|
|
|
|
.rio-drawer-content-inner {
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-drawer-knob {
|
|
align-self: center;
|
|
|
|
margin: 0.5rem;
|
|
|
|
border-radius: $infinite-corner-radius;
|
|
|
|
background: var(--rio-local-text-color);
|
|
opacity: 0.15;
|
|
}
|
|
|
|
.rio-drawer-left,
|
|
.rio-drawer-right {
|
|
.rio-drawer-content-inner {
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.rio-drawer-knob {
|
|
width: 0.4rem;
|
|
height: 4rem;
|
|
}
|
|
}
|
|
|
|
.rio-drawer-top,
|
|
.rio-drawer-bottom {
|
|
.rio-drawer-content-inner {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.rio-drawer-knob {
|
|
width: 4rem;
|
|
height: 0.4rem;
|
|
}
|
|
|
|
.rio-drawer-content-outer {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
|
|
.rio-drawer-left .rio-drawer-knob,
|
|
.rio-drawer-top .rio-drawer-knob {
|
|
order: 1;
|
|
}
|
|
|
|
.rio-drawer-right .rio-drawer-content-inner,
|
|
.rio-drawer-bottom .rio-drawer-content-inner {
|
|
order: 1;
|
|
}
|
|
|
|
.rio-drawer-left > .rio-drawer-content-outer {
|
|
top: 0;
|
|
left: 0;
|
|
bottom: 0;
|
|
width: fit-content;
|
|
|
|
border-radius: 0 var(--rio-global-corner-radius-large)
|
|
var(--rio-global-corner-radius-large) 0;
|
|
}
|
|
|
|
.rio-drawer-right > .rio-drawer-content-outer {
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
width: fit-content;
|
|
|
|
border-radius: var(--rio-global-corner-radius-large) 0 0
|
|
var(--rio-global-corner-radius-large);
|
|
}
|
|
|
|
.rio-drawer-top > .rio-drawer-content-outer {
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
height: fit-content;
|
|
|
|
border-radius: 0 0 var(--rio-global-corner-radius-large)
|
|
var(--rio-global-corner-radius-large);
|
|
}
|
|
|
|
.rio-drawer-bottom > .rio-drawer-content-outer {
|
|
left: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
height: fit-content;
|
|
|
|
border-radius: var(--rio-global-corner-radius-large)
|
|
var(--rio-global-corner-radius-large) 0 0;
|
|
}
|
|
|
|
.rio-drawer-no-transition {
|
|
transition: none !important;
|
|
}
|
|
|
|
.rio-drawer-no-transition > * {
|
|
transition: none !important;
|
|
}
|
|
|
|
// Popup
|
|
.rio-popup {
|
|
pointer-events: none;
|
|
|
|
z-index: $z-index-popup;
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-popup-anchor {
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-popup-content {
|
|
pointer-events: auto;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
// Image
|
|
.rio-image {
|
|
pointer-events: none;
|
|
|
|
@include center-content; // Required for the error icon
|
|
|
|
img {
|
|
pointer-events: auto;
|
|
@include kill-size-request-with-absolute();
|
|
}
|
|
|
|
// Error icon
|
|
svg {
|
|
pointer-events: auto;
|
|
max-width: 3rem;
|
|
}
|
|
}
|
|
|
|
// Card
|
|
.rio-card {
|
|
pointer-events: auto;
|
|
|
|
@include single-container();
|
|
|
|
background-color: var(--rio-local-bg);
|
|
box-shadow: 0 0 0 var(--rio-global-shadow-color);
|
|
|
|
transition:
|
|
box-shadow 0.15s ease-out,
|
|
background-color 0.1s ease-out;
|
|
}
|
|
|
|
.rio-card-elevate-on-hover:hover {
|
|
box-shadow: 0 0.15rem 0.4rem var(--rio-global-shadow-color);
|
|
}
|
|
|
|
.rio-card-colorize-on-hover:hover {
|
|
background-color: var(--rio-local-bg-active);
|
|
}
|
|
|
|
// SwitcherBar
|
|
.rio-switcher-bar {
|
|
// Pointer events are only enabled for the buttons
|
|
pointer-events: none;
|
|
|
|
// Stretch the options on the main axis and center it on the other axis
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.rio-switcher-bar > div {
|
|
flex-grow: 1;
|
|
|
|
position: relative;
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-switcher-bar-options {
|
|
flex-grow: 1;
|
|
|
|
display: flex;
|
|
align-items: stretch;
|
|
justify-content: space-between;
|
|
|
|
font-weight: bold;
|
|
}
|
|
|
|
.rio-switcher-bar-option {
|
|
pointer-events: auto;
|
|
cursor: pointer;
|
|
|
|
font-weight: bold;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
|
|
padding: 0.5rem;
|
|
box-sizing: border-box;
|
|
border-radius: var(--rio-global-corner-radius-large);
|
|
|
|
color: var(--rio-local-text-color);
|
|
|
|
transition:
|
|
background-color 0.1s ease-out,
|
|
color 0.1s ease-out;
|
|
}
|
|
|
|
.rio-switcher-bar-option > .rio-switcher-bar-icon {
|
|
width: 1.8rem;
|
|
height: 1.8rem;
|
|
margin-bottom: 0.5rem;
|
|
fill: currentColor;
|
|
|
|
& > svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.rio-switcher-bar-option:hover {
|
|
background-color: var(--rio-local-bg-active);
|
|
}
|
|
|
|
.rio-switcher-bar-option.selected {
|
|
// This matches the primary-bg used by the marker
|
|
color: var(--rio-global-primary-fg);
|
|
}
|
|
|
|
.rio-switcher-bar-option > svg {
|
|
width: 1.8rem;
|
|
height: 1.8rem;
|
|
margin-bottom: 0.5rem;
|
|
fill: currentColor;
|
|
}
|
|
|
|
.rio-switcher-bar-option > div {
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.rio-switcher-bar-marker {
|
|
position: absolute;
|
|
overflow: hidden;
|
|
|
|
pointer-events: none;
|
|
background: var(--rio-local-bg);
|
|
|
|
border-radius: var(--rio-global-corner-radius-large);
|
|
|
|
// Clicking too quickly sometimes ends up selecting the text, which is kinda
|
|
// ugly. Disable selection.
|
|
user-select: none;
|
|
}
|
|
|
|
.rio-switcher-bar-marker > .rio-switcher-bar-options {
|
|
position: absolute;
|
|
}
|
|
|
|
// Table
|
|
.rio-table {
|
|
pointer-events: auto;
|
|
|
|
display: grid;
|
|
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
|
|
// Headers
|
|
& > .rio-table-header {
|
|
position: relative;
|
|
|
|
font-weight: bold;
|
|
justify-content: center;
|
|
|
|
opacity: 1 !important;
|
|
|
|
background-color: var(--rio-local-bg-variant);
|
|
}
|
|
|
|
// Row Number
|
|
& > .rio-table-row-number {
|
|
opacity: 0.5;
|
|
justify-content: end;
|
|
}
|
|
|
|
// Regular cell
|
|
& > .rio-table-cell {
|
|
justify-content: end;
|
|
}
|
|
|
|
// Non-header cells
|
|
& > .rio-table-row-number,
|
|
& > .rio-table-cell {
|
|
border-bottom: 1px solid var(--rio-local-bg-variant);
|
|
}
|
|
|
|
// All cells
|
|
& > div {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
padding: 0.5rem;
|
|
transition: background-color 0.1s ease-out;
|
|
}
|
|
}
|
|
|
|
// Lists (ListView + various list items)
|
|
.rio-list-view {
|
|
pointer-events: none;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
align-content: stretch;
|
|
}
|
|
|
|
.rio-heading-list-item {
|
|
pointer-events: auto;
|
|
box-sizing: border-box;
|
|
margin-left: var(--rio-global-corner-radius-medium);
|
|
margin-top: 1rem;
|
|
margin-right: var(--rio-global-corner-radius-medium);
|
|
margin-bottom: 0.4rem;
|
|
}
|
|
|
|
.rio-separator-list-item {
|
|
pointer-events: none;
|
|
}
|
|
|
|
.rio-separator-list-item::after {
|
|
content: "";
|
|
display: block;
|
|
position: relative;
|
|
height: 1rem;
|
|
}
|
|
|
|
.rio-custom-list-item {
|
|
pointer-events: auto;
|
|
|
|
transition: background-color 0.1s ease-out;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-custom-list-item:hover {
|
|
background: var(--hover-color);
|
|
}
|
|
|
|
.rio-custom-list-item > * {
|
|
padding: 0.5rem 1rem;
|
|
}
|
|
|
|
.rio-listview-grouped {
|
|
position: relative;
|
|
pointer-events: auto;
|
|
|
|
background-color: var(--rio-local-bg-variant);
|
|
|
|
transition: background-color 0.1s ease-out;
|
|
}
|
|
|
|
.rio-listview-grouped + .rio-listview-grouped::after {
|
|
content: "";
|
|
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 1px;
|
|
|
|
background-color: var(--rio-local-text-color);
|
|
opacity: 0.2;
|
|
}
|
|
|
|
.rio-list-item-ripple:hover {
|
|
background: var(--rio-local-bg-active);
|
|
}
|
|
|
|
// Flow Container
|
|
.rio-flow-container {
|
|
pointer-events: none;
|
|
|
|
@include single-container();
|
|
|
|
& > div {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
|
|
width: min-content;
|
|
min-width: 100%;
|
|
}
|
|
}
|
|
|
|
// Traceback Popup
|
|
.rio-traceback {
|
|
pointer-events: auto;
|
|
|
|
position: relative;
|
|
|
|
margin-top: 1rem;
|
|
margin-bottom: 1rem;
|
|
|
|
padding: 2.2rem;
|
|
|
|
width: 50rem;
|
|
|
|
overflow: hidden;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
gap: 1.5rem;
|
|
|
|
border-radius: var(--rio-global-corner-radius-large);
|
|
|
|
box-shadow: 0 0.4rem 1rem var(--rio-global-shadow-color);
|
|
}
|
|
|
|
.rio-traceback-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.6rem;
|
|
}
|
|
|
|
.rio-traceback-header > svg {
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
fill: var(--rio-global-danger-bg);
|
|
}
|
|
|
|
.rio-traceback-header > div {
|
|
flex-grow: 1;
|
|
text-align: left;
|
|
|
|
font-size: 1.8rem;
|
|
color: var(--rio-global-danger-bg);
|
|
}
|
|
|
|
.rio-traceback-traceback {
|
|
font-family: $monospace-fonts;
|
|
font-size: 0.9rem;
|
|
white-space: pre-wrap;
|
|
overflow-wrap: break-word;
|
|
padding: 0.5rem 1rem;
|
|
background-color: var(--rio-local-bg-variant);
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
}
|
|
|
|
.rio-traceback-footer {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.rio-traceback-footer-links {
|
|
display: flex;
|
|
flex-direction: row;
|
|
gap: 0.5rem;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.rio-traceback-footer > a {
|
|
flex: 1;
|
|
}
|
|
|
|
.rio-traceback-bold {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.rio-traceback-dim {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.rio-traceback-red {
|
|
color: var(--rio-global-danger-bg);
|
|
}
|
|
|
|
.rio-traceback-yellow {
|
|
color: var(--rio-global-warning-bg);
|
|
}
|
|
|
|
// Dev Tools Connector
|
|
.rio-dev-tools-connector {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: end;
|
|
gap: 0.1rem;
|
|
z-index: 2;
|
|
|
|
text-decoration: none;
|
|
|
|
img {
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
object-fit: contain;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
div {
|
|
color: var(--rio-local-text-color);
|
|
transition: color 1s ease-in-out;
|
|
}
|
|
|
|
div:last-child {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
&:hover div {
|
|
color: var(--rio-global-secondary-fg);
|
|
transition: color 0.1s ease-in-out;
|
|
}
|
|
}
|
|
|
|
.rio-dev-tools-connector::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
left: 0;
|
|
z-index: -1;
|
|
|
|
background: linear-gradient(
|
|
to top,
|
|
var(--rio-global-secondary-bg),
|
|
transparent
|
|
);
|
|
|
|
opacity: 0;
|
|
transition: opacity 1s ease-out;
|
|
}
|
|
|
|
.rio-dev-tools-connector:hover::before {
|
|
opacity: 1;
|
|
transition: opacity 0.1s ease-out;
|
|
}
|
|
|
|
// Dev Tools Component Tree
|
|
.rio-dev-tools-component-tree {
|
|
pointer-events: auto;
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree > * {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.2rem;
|
|
}
|
|
|
|
@keyframes flash-text {
|
|
0% {
|
|
color: initial;
|
|
}
|
|
20% {
|
|
color: var(--rio-global-warning-bg);
|
|
}
|
|
100% {
|
|
color: initial;
|
|
}
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-flash {
|
|
animation: flash-text 3s linear;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header {
|
|
cursor: pointer;
|
|
z-index: 1;
|
|
|
|
position: relative;
|
|
padding: 0.3rem 0.6rem;
|
|
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
// Expander Arrow
|
|
.rio-dev-tools-component-tree-item
|
|
> .rio-dev-tools-component-tree-item-header
|
|
> div:first-child {
|
|
width: 1rem;
|
|
height: 1rem;
|
|
|
|
transition: transform 0.1s ease-in-out;
|
|
}
|
|
.rio-dev-tools-component-tree-item[data-expanded="true"]
|
|
> .rio-dev-tools-component-tree-item-header
|
|
> div:first-child {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header::after {
|
|
pointer-events: none;
|
|
content: "";
|
|
display: block;
|
|
|
|
z-index: -1;
|
|
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
background: var(--rio-global-secondary-bg);
|
|
border-radius: $infinite-corner-radius;
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.1s ease-in-out;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header > div > svg {
|
|
width: 1rem;
|
|
height: 1rem;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header-weakly-selected {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header-strongly-selected {
|
|
font-weight: bold;
|
|
color: var(--rio-global-secondary-fg);
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header:hover::after {
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header-weakly-selected::after {
|
|
opacity: 0.15;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header-strongly-selected::after {
|
|
opacity: 0.6;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-header-strongly-selected:hover::after {
|
|
opacity: 0.8;
|
|
}
|
|
|
|
.rio-dev-tools-component-tree-item-children {
|
|
margin-left: 0.7rem;
|
|
|
|
display: none;
|
|
flex-direction: column;
|
|
gap: 0.2rem;
|
|
}
|
|
.rio-dev-tools-component-tree-item[data-has-children="true"][data-expanded="true"]
|
|
> .rio-dev-tools-component-tree-item-children {
|
|
display: flex;
|
|
}
|
|
|
|
.rio-dev-tools-component-highlighter {
|
|
pointer-events: none;
|
|
position: fixed;
|
|
z-index: $z-index-dev-tools-highlighter;
|
|
|
|
transition:
|
|
left 0.3s ease-in-out,
|
|
top 0.3s ease-in-out,
|
|
width 0.3s ease-in-out,
|
|
height 0.3s ease-in-out;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0% {
|
|
left: -0.3rem;
|
|
top: -0.3rem;
|
|
right: -0.3rem;
|
|
bottom: -0.3rem;
|
|
border-width: 0.4rem;
|
|
}
|
|
50% {
|
|
left: -0.7rem;
|
|
top: -0.7rem;
|
|
right: -0.7rem;
|
|
bottom: -0.7rem;
|
|
border-width: 0.3rem;
|
|
}
|
|
100% {
|
|
left: -0.3rem;
|
|
top: -0.3rem;
|
|
right: -0.3rem;
|
|
bottom: -0.3rem;
|
|
border-width: 0.4rem;
|
|
}
|
|
}
|
|
|
|
.rio-dev-tools-component-highlighter::after {
|
|
content: "";
|
|
position: absolute;
|
|
display: block;
|
|
|
|
border-radius: 1rem;
|
|
box-shadow: 0 0 0 9999rem rgba(0, 0, 0, 0.6);
|
|
|
|
border-style: solid;
|
|
border-color: var(--rio-global-secondary-bg);
|
|
|
|
animation: pulse 1.4s infinite;
|
|
}
|
|
|
|
.rio-dev-tools-background {
|
|
position: relative;
|
|
|
|
z-index: 0;
|
|
|
|
background: var(--rio-local-bg);
|
|
}
|
|
|
|
.rio-dev-tools-background > * {
|
|
z-index: 2;
|
|
}
|
|
|
|
.rio-dev-tools-background::after {
|
|
content: "";
|
|
position: absolute;
|
|
display: block;
|
|
z-index: 1;
|
|
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
|
|
background-image: linear-gradient(
|
|
-45deg,
|
|
var(--rio-local-bg) 25%,
|
|
var(--rio-global-secondary-bg) 25%,
|
|
var(--rio-global-secondary-bg) 50%,
|
|
var(--rio-local-bg) 50%,
|
|
var(--rio-local-bg) 75%,
|
|
var(--rio-global-secondary-bg) 75%,
|
|
var(--rio-global-secondary-bg)
|
|
);
|
|
background-size: 3rem 3rem;
|
|
|
|
opacity: 0.02;
|
|
}
|
|
|
|
// Dev tools component picker
|
|
.rio-component-picker {
|
|
$size: 1.8rem;
|
|
width: $size;
|
|
height: $size;
|
|
|
|
box-sizing: border-box;
|
|
padding: 0.2rem;
|
|
|
|
border-radius: 999px;
|
|
|
|
cursor: pointer;
|
|
}
|
|
|
|
.rio-component-picker:hover {
|
|
background: var(--rio-local-bg-variant);
|
|
}
|
|
|
|
.rio-component-picker.active {
|
|
background: var(--rio-local-bg-active);
|
|
}
|
|
|
|
html.picking-component * {
|
|
cursor: crosshair !important;
|
|
}
|
|
|
|
// Switcher
|
|
.rio-switcher {
|
|
pointer-events: none;
|
|
|
|
// This is not a single-container because it can briefly have two children
|
|
// during an animation. It's more like a Stack.
|
|
display: grid;
|
|
|
|
overflow: hidden;
|
|
}
|
|
|
|
.rio-switcher > * {
|
|
grid-row: 1;
|
|
grid-column: 1;
|
|
|
|
@include single-container();
|
|
|
|
opacity: 0;
|
|
transition: opacity var(--rio-switcher-transition-time) ease-in-out;
|
|
}
|
|
|
|
.rio-switcher > *.rio-switcher-active-child {
|
|
opacity: 1;
|
|
}
|
|
|
|
.rio-switcher.resizing > *:not(.rio-switcher-resizer) {
|
|
// During the resize animation, make the children absolute so they can't
|
|
// influence the switcher's size
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.rio-switcher-resizer {
|
|
transition:
|
|
min-width var(--rio-switcher-transition-time) ease-in-out,
|
|
min-height var(--rio-switcher-transition-time) ease-in-out;
|
|
}
|
|
|
|
// Tooltip
|
|
.rio-tooltip {
|
|
pointer-events: auto;
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-tooltip-popup {
|
|
pointer-events: none;
|
|
|
|
width: min(max-content, 100vw);
|
|
padding: 0.5rem;
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
|
|
background: var(--rio-global-hud-bg);
|
|
box-shadow: 0 0.1rem 0.2rem var(--rio-global-shadow-color);
|
|
}
|
|
|
|
.rio-tooltip-popup * {
|
|
pointer-events: none !important;
|
|
}
|
|
|
|
// Build failed component
|
|
.rio-error-placeholder {
|
|
pointer-events: auto;
|
|
color: var(--rio-global-danger-fg);
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
|
|
background: var(--rio-global-danger-bg);
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
|
|
// `rio-error-placeholder-content` can't have a corner radius set, because that
|
|
// would make the barber pole peek through the corners. Instead enforce
|
|
// the corner radius from this element.
|
|
overflow: hidden;
|
|
|
|
@include barber-pole(var(--rio-global-danger-bg-variant));
|
|
}
|
|
|
|
.rio-error-placeholder-top,
|
|
.rio-error-placeholder-bottom {
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.rio-error-placeholder-top {
|
|
background: linear-gradient(
|
|
to top,
|
|
var(--rio-global-danger-bg),
|
|
var(--rio-global-danger-bg) 30%,
|
|
transparent
|
|
);
|
|
}
|
|
|
|
.rio-error-placeholder-bottom {
|
|
background: linear-gradient(
|
|
to bottom,
|
|
var(--rio-global-danger-bg),
|
|
var(--rio-global-danger-bg) 30%,
|
|
transparent
|
|
);
|
|
}
|
|
|
|
.rio-error-placeholder-content {
|
|
padding: 1rem;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
gap: 1rem;
|
|
|
|
background: var(--rio-global-danger-bg);
|
|
}
|
|
|
|
.rio-error-placeholder-header {
|
|
align-self: center;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.rio-error-placeholder-icon {
|
|
width: 2rem;
|
|
height: 2rem;
|
|
}
|
|
|
|
.rio-error-placeholder-summary {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.rio-error-placeholder-details {
|
|
align-self: center;
|
|
}
|
|
|
|
// Code Explorer
|
|
.rio-code-explorer {
|
|
pointer-events: none;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.rio-code-explorer-source-code {
|
|
pointer-events: auto;
|
|
|
|
display: block;
|
|
cursor: text;
|
|
white-space: pre;
|
|
font-size: 1rem;
|
|
font-family: $monospace-fonts;
|
|
|
|
position: relative;
|
|
width: min-content;
|
|
padding: 1rem;
|
|
|
|
background: var(--rio-local-bg-variant);
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
}
|
|
|
|
.rio-code-explorer-arrow {
|
|
width: 3rem;
|
|
height: 3rem;
|
|
}
|
|
|
|
.rio-code-explorer-build-result {
|
|
position: relative;
|
|
}
|
|
|
|
.rio-code-explorer-build-result > *:not(.rio-code-explorer-highlighter) {
|
|
position: relative !important;
|
|
}
|
|
|
|
.rio-code-explorer-highlighter {
|
|
pointer-events: none;
|
|
position: absolute;
|
|
|
|
opacity: 0;
|
|
|
|
transition:
|
|
opacity 0.3s ease-in-out,
|
|
left 0.3s ease-in-out,
|
|
top 0.3s ease-in-out,
|
|
width 0.3s ease-in-out,
|
|
height 0.3s ease-in-out;
|
|
}
|
|
|
|
.rio-code-explorer-highlighter::after {
|
|
content: "";
|
|
z-index: $z-index-dev-tools-highlighter;
|
|
position: absolute;
|
|
|
|
border-radius: 1rem;
|
|
border-style: solid;
|
|
border-width: 0.2rem !important;
|
|
border-color: var(--rio-global-secondary-bg);
|
|
|
|
box-shadow: 0 0 4rem 1rem var(--rio-global-secondary-bg);
|
|
|
|
opacity: 0.4;
|
|
|
|
animation: pulse 1.4s infinite;
|
|
}
|
|
|
|
// Separator
|
|
.rio-separator {
|
|
pointer-events: none;
|
|
|
|
background-color: var(--rio-local-bg);
|
|
|
|
// @single-container doesn't work with our ::after element, so we'll inline
|
|
// it
|
|
display: flex;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.rio-separator::after {
|
|
content: "";
|
|
|
|
flex-grow: 1;
|
|
|
|
// We can't set the min-size on the separator element itself because JS will
|
|
// overwrite it with the value from the backend, so we'll do it here
|
|
$min-size: 1px;
|
|
min-width: $min-size;
|
|
min-height: $min-size;
|
|
|
|
// This creates a lighter shade of the text color without being see-through
|
|
background-color: var(--separator-color);
|
|
opacity: var(--separator-opacity);
|
|
}
|
|
|
|
// Ripple Effect
|
|
.rio-ripple-container {
|
|
pointer-events: none;
|
|
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
overflow: hidden;
|
|
}
|
|
|
|
.rio-ripple-effect {
|
|
// background: radial-gradient(
|
|
// circle at center center,
|
|
// transparent 5%,
|
|
// var(--rio-ripple-color) 40%,
|
|
// transparent 70%
|
|
// );
|
|
position: absolute;
|
|
|
|
background: var(--rio-ripple-color);
|
|
|
|
border-radius: 50%;
|
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
transition:
|
|
top var(--rio-ripple-duration),
|
|
left var(--rio-ripple-duration),
|
|
width var(--rio-ripple-duration),
|
|
height var(--rio-ripple-duration),
|
|
opacity var(--rio-ripple-duration);
|
|
}
|
|
|
|
// Popup Manager (NOT the `Popup` component!)
|
|
.rio-popup-manager-content {
|
|
position: fixed;
|
|
z-index: $z-index-popup;
|
|
|
|
width: min-content;
|
|
height: min-content;
|
|
}
|
|
|
|
.rio-popup-animation-scale {
|
|
transform: scale(0);
|
|
opacity: 0;
|
|
|
|
transition:
|
|
transform 0.2s linear,
|
|
opacity 0.1s ease-in-out;
|
|
}
|
|
|
|
.rio-popup-animation-scale.rio-popup-manager-open {
|
|
transform: scale(1);
|
|
opacity: 1;
|
|
|
|
transition:
|
|
transform 0.2s $transition-timing-overshoot,
|
|
opacity 0.1s ease-in-out;
|
|
}
|
|
|
|
// Calendar
|
|
.rio-calendar {
|
|
pointer-events: auto;
|
|
@include center-content;
|
|
}
|
|
|
|
.rio-calendar-inner {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.rio-calendar-header {
|
|
display: flex;
|
|
flex-direction: row;
|
|
gap: 0.2rem;
|
|
flex: 0;
|
|
|
|
& > :nth-child(3) {
|
|
pointer-events: none;
|
|
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
flex-grow: 1;
|
|
}
|
|
}
|
|
|
|
.rio-calendar-button {
|
|
position: relative;
|
|
width: 1.6rem;
|
|
height: 1.6rem;
|
|
|
|
cursor: pointer;
|
|
|
|
color: var(--rio-local-text-color);
|
|
}
|
|
|
|
.rio-calendar-button:hover {
|
|
color: var(--rio-local-level-2-bg);
|
|
}
|
|
|
|
.rio-calendar-button:hover::after {
|
|
content: "";
|
|
position: absolute;
|
|
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
background: var(--rio-local-level-2-bg);
|
|
border-radius: $infinite-corner-radius;
|
|
opacity: 0.1;
|
|
}
|
|
|
|
.rio-calendar-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(7, 1.8rem);
|
|
grid-template-rows: repeat(7, 1.8rem);
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.rio-calendar-day-name {
|
|
font-weight: bold;
|
|
text-align: center;
|
|
}
|
|
|
|
.rio-calendar-day {
|
|
position: relative;
|
|
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
cursor: pointer;
|
|
}
|
|
|
|
.rio-calendar-day-other-month {
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.rio-calendar-day:hover::after {
|
|
content: "";
|
|
position: absolute;
|
|
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
background: var(--rio-local-text-color);
|
|
border-radius: $infinite-corner-radius;
|
|
opacity: 0.1;
|
|
}
|
|
|
|
.rio-calendar-selected-day {
|
|
font-weight: bold;
|
|
|
|
color: var(--rio-local-level-2-fg);
|
|
|
|
background: var(--rio-local-level-2-bg);
|
|
border-radius: $infinite-corner-radius;
|
|
}
|
|
|
|
// Layout Display
|
|
.rio-layout-display {
|
|
pointer-events: none;
|
|
@include center-content;
|
|
}
|
|
|
|
.rio-layout-display-parent {
|
|
pointer-events: auto;
|
|
|
|
position: relative;
|
|
z-index: 0;
|
|
|
|
background-color: var(--rio-global-neutral-bg-variant);
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
}
|
|
|
|
.rio-layout-display-margin {
|
|
position: absolute;
|
|
z-index: 1;
|
|
|
|
background-color: var(--rio-global-neutral-fg);
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
|
|
opacity: 0.15;
|
|
}
|
|
|
|
.rio-layout-display-child {
|
|
position: absolute;
|
|
z-index: 2;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
color: var(--rio-global-hud-fg);
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
|
|
background-color: var(--rio-global-hud-bg);
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
opacity: 0.5;
|
|
|
|
// Disable text selection, as that changes the cursor and is generally
|
|
// annoying in this context
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
-moz-user-select: none;
|
|
-ms-user-select: none;
|
|
|
|
transition:
|
|
background-color 0.1s ease-out,
|
|
box-shadow 0.15s ease-out;
|
|
}
|
|
|
|
.rio-layout-display-child:not(.rio-layout-display-target) {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.rio-layout-display-child:not(.rio-layout-display-target):hover {
|
|
background-color: var(--rio-global-hud-bg-active);
|
|
box-shadow: 0 0.15rem 0.3rem var(--rio-global-shadow-color);
|
|
}
|
|
|
|
.rio-layout-display-target {
|
|
color: var(--rio-global-secondary-fg) !important;
|
|
background-color: var(--rio-global-secondary-bg) !important;
|
|
opacity: 1 !important;
|
|
}
|
|
|
|
// Checkbox
|
|
.rio-checkbox {
|
|
pointer-events: none;
|
|
|
|
@include center-content();
|
|
}
|
|
|
|
.rio-checkbox > input {
|
|
pointer-events: auto;
|
|
cursor: pointer;
|
|
|
|
position: absolute;
|
|
width: 1.4rem;
|
|
height: 1.4rem;
|
|
|
|
margin: 0;
|
|
padding: 0;
|
|
border-width: 0;
|
|
|
|
opacity: 0;
|
|
}
|
|
|
|
.rio-checkbox.rio-insensitive > input {
|
|
pointer-events: none;
|
|
cursor: default;
|
|
}
|
|
|
|
.rio-checkbox-border {
|
|
border-width: 0.15rem;
|
|
border-style: solid;
|
|
border-color: var(--border-color);
|
|
border-radius: 0.2rem;
|
|
box-sizing: border-box;
|
|
|
|
background-color: transparent;
|
|
|
|
opacity: 0.5;
|
|
|
|
width: 1.4rem;
|
|
height: 1.4rem;
|
|
|
|
transition:
|
|
opacity 0.2s ease-in-out,
|
|
border-width 0.2s ease-in-out,
|
|
border-color 0.2s ease-in-out,
|
|
background-color 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-checkbox.is-on .rio-checkbox-border {
|
|
border-width: 0.7rem;
|
|
|
|
opacity: 1;
|
|
|
|
border-color: var(--rio-local-level-2-bg);
|
|
background-color: var(--rio-local-level-2-bg);
|
|
}
|
|
|
|
.rio-checkbox-check {
|
|
position: absolute;
|
|
|
|
width: 1.8rem;
|
|
height: 1.8rem;
|
|
|
|
transform: scale(0);
|
|
transition: transform 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-checkbox.is-on .rio-checkbox-check {
|
|
transform: scale(1);
|
|
}
|
|
|
|
// Html
|
|
.rio-html {
|
|
// Disable pointer events, the user can always turn them back on if desired
|
|
pointer-events: none;
|
|
|
|
@include single-container(); // FIXME: Should we do this?
|
|
}
|
|
|
|
// Dialogs
|
|
.rio-dialog-container {
|
|
pointer-events: none;
|
|
|
|
position: fixed;
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
z-index: $z-index-popup;
|
|
|
|
background-color: transparent;
|
|
opacity: 0;
|
|
|
|
// Theses durations are also referenced in code!
|
|
transition:
|
|
opacity 0.2s ease-in-out,
|
|
background-color 0.5s ease-in-out;
|
|
|
|
& > * {
|
|
transform: translateY(-2rem);
|
|
transition: transform 0.2s $transition-timing-overshoot;
|
|
}
|
|
|
|
@include single-container();
|
|
}
|
|
|
|
.rio-dialog-container-enter {
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
opacity: 1;
|
|
|
|
& > * {
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
// Website
|
|
.rio-website {
|
|
pointer-events: auto;
|
|
}
|
|
|
|
// Upload Area
|
|
.rio-file-picker-area {
|
|
pointer-events: auto;
|
|
|
|
position: relative;
|
|
cursor: pointer;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
justify-content: start;
|
|
|
|
// To round the progress indicator
|
|
overflow: hidden;
|
|
|
|
color: var(--rio-local-fg);
|
|
background-color: var(--rio-local-bg-variant);
|
|
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
}
|
|
|
|
.rio-file-picker-area:not(.rio-file-picker-area-file-hover):hover {
|
|
background-color: var(--rio-local-bg-active);
|
|
}
|
|
|
|
.rio-file-picker-area-child-container {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.rio-file-picker-area-icon {
|
|
width: 3.5rem;
|
|
height: 3.5rem;
|
|
}
|
|
|
|
.rio-file-picker-area-column {
|
|
flex-grow: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.3rem;
|
|
}
|
|
|
|
.rio-file-picker-area-file-types {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.rio-file-picker-area-button > div {
|
|
color: var(--rio-local-text-color);
|
|
padding: 0.5rem 1rem;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.rio-file-picker-area-progress {
|
|
pointer-events: none;
|
|
position: absolute;
|
|
|
|
left: 0rem;
|
|
top: 0;
|
|
bottom: 0;
|
|
|
|
border-radius: 50%;
|
|
|
|
opacity: 0;
|
|
transition: opacity 0.3s;
|
|
}
|
|
|
|
.rio-file-picker-area-progress::after {
|
|
content: "";
|
|
display: block;
|
|
position: relative;
|
|
width: var(--progress);
|
|
height: 100%;
|
|
background: var(--rio-local-level-2-bg);
|
|
|
|
// This would be nice, but also causes the progress bar to animate when
|
|
// receding back to 0.
|
|
//
|
|
// transition: width 0.3s ease-in-out;
|
|
}
|
|
|
|
.rio-file-picker-area-file-hover {
|
|
cursor: copy;
|
|
color: var(--rio-local-level-2-bg);
|
|
}
|
|
|
|
.rio-file-picker-area::before {
|
|
pointer-events: none;
|
|
content: "";
|
|
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
border-radius: var(--rio-global-corner-radius-medium);
|
|
background: radial-gradient(
|
|
circle at var(--x) var(--y),
|
|
var(--rio-local-level-2-bg),
|
|
var(--rio-local-bg-active) 30rem
|
|
);
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.3s;
|
|
}
|
|
|
|
.rio-file-picker-area-file-hover::before {
|
|
opacity: 0.2;
|
|
}
|
|
|
|
.rio-file-picker-area > input {
|
|
display: none;
|
|
}
|
|
|
|
// Graph Editor
|
|
$graph-editor-node-padding: 0.7rem;
|
|
$graph-editor-port-size: 1.4rem;
|
|
|
|
.rio-graph-editor {
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.rio-graph-editor > * {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.rio-graph-editor::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
z-index: -1;
|
|
|
|
background-image: radial-gradient(
|
|
circle,
|
|
var(--rio-local-fg) 12%,
|
|
transparent 12%
|
|
);
|
|
background-size: 1.3rem 1.3rem;
|
|
|
|
opacity: 0.15;
|
|
|
|
& > * {
|
|
position: absolute;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.rio-graph-editor-selection {
|
|
pointer-events: none;
|
|
|
|
position: absolute;
|
|
z-index: 1;
|
|
|
|
left: 10rem;
|
|
top: 20rem;
|
|
width: 30rem;
|
|
height: 40rem;
|
|
|
|
border: 0.15rem solid var(--rio-global-primary-bg);
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
|
|
transition: opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
.rio-graph-editor-selection::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
|
|
box-shadow: inset 0 0 15rem 0 var(--rio-global-primary-bg);
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
|
|
opacity: 0.2;
|
|
}
|
|
|
|
.rio-graph-editor-node {
|
|
pointer-events: auto;
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
|
|
position: absolute;
|
|
min-width: 8rem;
|
|
|
|
background-color: var(--rio-global-secondary-bg);
|
|
border-radius: var(--rio-global-corner-radius-small)
|
|
var(--rio-global-corner-radius-small)
|
|
var(--rio-global-corner-radius-medium)
|
|
var(--rio-global-corner-radius-medium);
|
|
|
|
outline: 0 solid var(--rio-global-primary-bg);
|
|
|
|
transition:
|
|
background-color 0.1s ease-in-out,
|
|
box-shadow 0.1s ease-in-out,
|
|
outline 0.1s $transition-timing-overshoot;
|
|
|
|
&:has(.rio-graph-editor-node-header:hover) {
|
|
background-color: var(--rio-global-secondary-bg-active);
|
|
box-shadow: 0 0.2rem 0.6rem var(--rio-global-shadow-color);
|
|
}
|
|
}
|
|
|
|
.rio-graph-editor-node-header {
|
|
pointer-events: auto;
|
|
|
|
user-select: none;
|
|
|
|
font-weight: bold;
|
|
text-align: center;
|
|
padding: 0.3rem $graph-editor-node-padding 0.3rem $graph-editor-node-padding;
|
|
|
|
cursor: move;
|
|
|
|
color: var(--rio-global-secondary-fg);
|
|
}
|
|
|
|
.rio-graph-editor-node-body {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
gap: 0.5rem;
|
|
|
|
padding: $graph-editor-node-padding;
|
|
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
background-color: var(--rio-local-bg);
|
|
}
|
|
|
|
.rio-graph-editor-selected-node {
|
|
border-radius: var(--rio-global-corner-radius-small);
|
|
outline: 0.15rem solid var(--rio-global-primary-bg);
|
|
}
|
|
|
|
.rio-graph-editor-port {
|
|
position: relative;
|
|
}
|
|
|
|
.rio-graph-editor-port-circle {
|
|
position: absolute;
|
|
|
|
pointer-events: auto;
|
|
cursor: pointer;
|
|
|
|
width: $graph-editor-port-size;
|
|
height: $graph-editor-port-size;
|
|
|
|
aspect-ratio: 1/1;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.rio-graph-editor-input {
|
|
text-align: left;
|
|
}
|
|
|
|
.rio-graph-editor-output {
|
|
text-align: right;
|
|
}
|
|
|
|
.rio-graph-editor-input > .rio-graph-editor-port-circle {
|
|
left: 0;
|
|
transform: translateX(
|
|
calc(-1 * ($graph-editor-port-size / 2 + $graph-editor-node-padding))
|
|
);
|
|
}
|
|
|
|
.rio-graph-editor-output > .rio-graph-editor-port-circle {
|
|
right: 0;
|
|
transform: translateX(
|
|
calc($graph-editor-port-size / 2 + $graph-editor-node-padding)
|
|
);
|
|
}
|
|
|
|
.rio-graph-editor-port-circle::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 25%;
|
|
top: 25%;
|
|
right: 25%;
|
|
bottom: 25%;
|
|
|
|
border-radius: 50%;
|
|
background-color: var(--port-color);
|
|
|
|
transition:
|
|
left 0.1s ease-in-out,
|
|
top 0.1s ease-in-out,
|
|
right 0.1s ease-in-out,
|
|
bottom 0.1s ease-in-out;
|
|
}
|
|
|
|
.rio-graph-editor-port-circle:hover::after {
|
|
left: 15%;
|
|
top: 15%;
|
|
right: 15%;
|
|
bottom: 15%;
|
|
}
|
|
|
|
.rio-graph-editor-port-text {
|
|
pointer-events: none;
|
|
}
|