Centralize and use global spacing variables
This commit improves UI consistency. It also improves maintainability by
removing "magic values" in favor of standardized spacing throughout the
application.
- Adjust spacing variables to match the convention.
- Add `_spacing.scss` to define a centralized set of spacing variables, both
absolute and relative, to standardize the spacing throughout the application.
This new approach ensures a consistent spacing logic across all components and
layouts, facilitating easier maintenance and scalability of the styling codebase.
- Update various SCSS styles to utilize the new spacing variables. This change
harmonizes the spacing across different parts of the application, aligning with
the new design system's principles.
- Slightly adjust existing padding/margin/gaps for better consistency.
Other supporting changes per component:
- RatingCircle: Update style names to match convention and simplify
hacky way to inject circle width value through CSS variables. Add
tests for the new behavior and refactor existing tests for easier
extensibility.
- TheFooter: Add small gap when footer items wrap.
- HiearchicalTreeNode: Refactor variables to separate caret size clearly
from padding applied.
- App: Make padding responsive as initial behavior of v0.13.0 before
5d940b57ef.
- ModalDialog: Use responsive absolute values instead of percentage.
- HorizontalResizeSlider:
- Use `v-bind` instead of hacky way to inject SCSS values through variables.
- Remove `verticalMargin` property to simplify its styling.
- Move `src/presentation/assets/styles/components/_card.scss` closer to
components that it styles. Update structure documentation.
The centralization of spacing definitions will aid in future design
adjustments, ensuring that updates to spacing can be made swiftly and
uniformly across the application. It's a step towards a more maintainable
and scalable frontend architecture.
This commit is contained in:
@@ -14,14 +14,13 @@ The presentation layer uses an event-driven architecture for bidirectional react
|
|||||||
- [**`main.ts`**](./../src/presentation/main.ts): Starts Vue app.
|
- [**`main.ts`**](./../src/presentation/main.ts): Starts Vue app.
|
||||||
- [**`index.html`**](./../src/presentation/index.html): The `index.html` entry file, located at the root of the project as required by Vite
|
- [**`index.html`**](./../src/presentation/index.html): The `index.html` entry file, located at the root of the project as required by Vite
|
||||||
- [**`bootstrapping/`**](./../src/presentation/bootstrapping/): Registers Vue components and plugins.
|
- [**`bootstrapping/`**](./../src/presentation/bootstrapping/): Registers Vue components and plugins.
|
||||||
- [**`components/`**](./../src/presentation/components/): Contains Vue components and helpers.
|
- [**`components/`**](./../src/presentation/components/): Contains Vue components, helpers and styles coupled to Vue components.
|
||||||
- [**`Shared/`**](./../src/presentation/components/Shared): Contains shared Vue components and helpers.
|
- [**`Shared/`**](./../src/presentation/components/Shared): Contains shared Vue components and helpers.
|
||||||
- [**`Hooks`**](../src/presentation/components/Shared/Hooks): Hooks used by components through [dependency injection](#dependency-injections).
|
- [**`Hooks`**](../src/presentation/components/Shared/Hooks): Hooks used by components through [dependency injection](#dependency-injections).
|
||||||
- [**`/public/`**](../src/presentation/public/): Contains static assets.
|
- [**`/public/`**](../src/presentation/public/): Contains static assets.
|
||||||
- [**`assets/`**](./../src/presentation/assets/styles/): Contains assets processed by Vite.
|
- [**`assets/`**](./../src/presentation/assets/styles/): Contains assets processed by Vite.
|
||||||
- [**`fonts/`**](./../src/presentation/assets/fonts/): Contains fonts.
|
- [**`fonts/`**](./../src/presentation/assets/fonts/): Contains fonts.
|
||||||
- [**`styles/`**](./../src/presentation/assets/styles/): Contains shared styles.
|
- [**`styles/`**](./../src/presentation/assets/styles/): Contains shared styles.
|
||||||
- [**`components/`**](./../src/presentation/assets/styles/components): Contains styles coupled to Vue components.
|
|
||||||
- [**`main.scss`**](./../src/presentation/assets/styles/main.scss): Main Sass file, imported by other components as single entrypoint..
|
- [**`main.scss`**](./../src/presentation/assets/styles/main.scss): Main Sass file, imported by other components as single entrypoint..
|
||||||
- [**`electron/`**](./../src/presentation/electron/): Contains Electron code.
|
- [**`electron/`**](./../src/presentation/electron/): Contains Electron code.
|
||||||
- [`/main/` **`index.ts`**](./../src/presentation/main.ts): Main entry for Electron, managing application windows and lifecycle events.
|
- [`/main/` **`index.ts`**](./../src/presentation/main.ts): Main entry for Electron, managing application windows and lifecycle events.
|
||||||
@@ -38,6 +37,13 @@ The presentation layer uses an event-driven architecture for bidirectional react
|
|||||||
They should also have different visual state when hovering/touching on them that indicates that they are being clicked, which helps with accessibility.
|
They should also have different visual state when hovering/touching on them that indicates that they are being clicked, which helps with accessibility.
|
||||||
- **Borders**:
|
- **Borders**:
|
||||||
privacy.sexy prefers sharper edges in its design language.
|
privacy.sexy prefers sharper edges in its design language.
|
||||||
|
- **Fonts**:
|
||||||
|
- Use the primary font for regular text and monospace font for code or specific data.
|
||||||
|
- Use cursive and logo fonts solely for branding.
|
||||||
|
- Refer to [standardized font size variables](../src/presentation/assets/styles/_typography.scss) for font sizing, avoiding arbitrary `px`, `em`, `rem`, or percentage values.
|
||||||
|
- **Spacing**:
|
||||||
|
Use [global spacing variables](../src/presentation/assets/styles/_spacing.scss) for consistent margin, padding, and gap definitions.
|
||||||
|
This provides uniform spatial distribution and alignment of elements, enhancing visual harmony and making the UI more scalable and maintainable.
|
||||||
|
|
||||||
## Application data
|
## Application data
|
||||||
|
|
||||||
|
|||||||
16
src/presentation/assets/styles/_spacing.scss
Normal file
16
src/presentation/assets/styles/_spacing.scss
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Use for fixed-size elements where consistent spacing is important
|
||||||
|
// regardless of context.
|
||||||
|
$spacing-absolute-xx-small: 3px;
|
||||||
|
$spacing-absolute-x-small : 4px;
|
||||||
|
$spacing-absolute-small : 6px;
|
||||||
|
$spacing-absolute-medium : 10px;
|
||||||
|
$spacing-absolute-large : 15px;
|
||||||
|
$spacing-absolute-x-large : 20px;
|
||||||
|
$spacing-absolute-xx-large: 30px;
|
||||||
|
|
||||||
|
// Use for elements with text content where spacing should
|
||||||
|
// scale with text size.
|
||||||
|
$spacing-relative-x-small : 0.25em;
|
||||||
|
$spacing-relative-small : 0.5em;
|
||||||
|
$spacing-relative-medium : 1em;
|
||||||
|
$spacing-relative-large : 2em;
|
||||||
@@ -5,16 +5,15 @@
|
|||||||
CSS Base applies a style foundation for HTML elements that is consistent for baseline browsers
|
CSS Base applies a style foundation for HTML elements that is consistent for baseline browsers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "@/presentation/assets/styles/colors" as *;
|
@use "../colors" as *;
|
||||||
@use "@/presentation/assets/styles/mixins" as *;
|
@use "../mixins" as *;
|
||||||
@use "@/presentation/assets/styles/vite-path" as *;
|
@use "../vite-path" as *;
|
||||||
@use "@/presentation/assets/styles/typography" as *;
|
@use "../typography" as *;
|
||||||
|
@use "../spacing" as *;
|
||||||
@use "_code-styling" as *;
|
@use "_code-styling" as *;
|
||||||
@use "_margin-padding" as *;
|
@use "_margin-padding" as *;
|
||||||
@use "_link-styling" as *;
|
@use "_link-styling" as *;
|
||||||
|
|
||||||
$base-spacing: 1em;
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
@@ -22,7 +21,7 @@ $base-spacing: 1em;
|
|||||||
body {
|
body {
|
||||||
background: $color-background;
|
background: $color-background;
|
||||||
@include base-font-style;
|
@include base-font-style;
|
||||||
@include apply-uniform-spacing($base-spacing: $base-spacing)
|
@include apply-uniform-spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@@ -30,12 +29,12 @@ input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
blockquote {
|
blockquote {
|
||||||
padding: 0 $base-spacing;
|
padding: 0 $spacing-relative-medium;
|
||||||
border-left: .25em solid $color-primary;
|
border-left: $spacing-absolute-x-small solid $color-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include style-code-elements(
|
@include style-code-elements(
|
||||||
$code-block-padding: $base-spacing,
|
$code-block-padding: $spacing-relative-medium,
|
||||||
$color-background: $color-primary-darker,
|
$color-background: $color-primary-darker,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@use 'sass:math';
|
@use 'sass:math';
|
||||||
|
@use "../spacing" as *;
|
||||||
|
|
||||||
@mixin no-margin($selectors) {
|
@mixin no-margin($selectors) {
|
||||||
#{$selectors} {
|
#{$selectors} {
|
||||||
@@ -26,7 +27,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin apply-uniform-vertical-spacing($base-vertical-spacing) {
|
@mixin apply-uniform-vertical-spacing {
|
||||||
/* Reset default top/bottom margins added by browser. */
|
/* Reset default top/bottom margins added by browser. */
|
||||||
@include no-margin('p');
|
@include no-margin('p');
|
||||||
@include no-margin('h1, h2, h3, h4, h5, h6');
|
@include no-margin('h1, h2, h3, h4, h5, h6');
|
||||||
@@ -36,29 +37,27 @@
|
|||||||
@include no-margin('ul, ol');
|
@include no-margin('ul, ol');
|
||||||
|
|
||||||
/* Add spacing between elements using `margin-bottom` only (bottom-up instead of top-down strategy). */
|
/* Add spacing between elements using `margin-bottom` only (bottom-up instead of top-down strategy). */
|
||||||
$small-vertical-spacing: math.div($base-vertical-spacing, 2);
|
@include bottom-margin('p', $spacing-relative-medium);
|
||||||
@include bottom-margin('p', $base-vertical-spacing);
|
@include bottom-margin('li > p', $spacing-relative-small); // Reduce margin for paragraphs directly within list items to visually group related content.
|
||||||
@include bottom-margin('li > p', $small-vertical-spacing); // Reduce margin for paragraphs directly within list items to visually group related content.
|
@include bottom-margin('h1, h2, h3, h4, h5, h6', $spacing-relative-small);
|
||||||
@include bottom-margin('h1, h2, h3, h4, h5, h6', $small-vertical-spacing);
|
@include bottom-margin('ul, ol', $spacing-relative-medium);
|
||||||
@include bottom-margin('ul, ol', $base-vertical-spacing);
|
@include bottom-margin('li', $spacing-relative-small);
|
||||||
@include bottom-margin('li', $small-vertical-spacing);
|
@include bottom-margin('table', $spacing-relative-medium);
|
||||||
@include bottom-margin('table', $base-vertical-spacing);
|
@include bottom-margin('blockquote', $spacing-relative-medium);
|
||||||
@include bottom-margin('blockquote', $base-vertical-spacing);
|
@include bottom-margin('pre', $spacing-relative-medium);
|
||||||
@include bottom-margin('pre', $base-vertical-spacing);
|
@include bottom-margin('article', $spacing-relative-medium);
|
||||||
@include bottom-margin('article', $base-vertical-spacing);
|
@include bottom-margin('hr', $spacing-relative-medium);
|
||||||
@include bottom-margin('hr', $base-vertical-spacing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin apply-uniform-horizontal-spacing($base-horizontal-spacing) {
|
@mixin apply-uniform-horizontal-spacing {
|
||||||
/* Reset default left/right paddings added by browser. */
|
/* Reset default left/right paddings added by browser. */
|
||||||
@include no-padding('ul, ol');
|
@include no-padding('ul, ol');
|
||||||
|
|
||||||
/* Add spacing for list items. */
|
/* Add spacing for list items. */
|
||||||
$large-horizontal-spacing: $base-horizontal-spacing * 2;
|
@include left-padding('ul, ol', $spacing-relative-large);
|
||||||
@include left-padding('ul, ol', $large-horizontal-spacing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin apply-uniform-spacing($base-spacing) {
|
@mixin apply-uniform-spacing {
|
||||||
@include apply-uniform-vertical-spacing($base-spacing);
|
@include apply-uniform-vertical-spacing;
|
||||||
@include apply-uniform-horizontal-spacing($base-spacing);
|
@include apply-uniform-horizontal-spacing;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
$card-gap: 15px;
|
|
||||||
@@ -5,6 +5,5 @@
|
|||||||
@forward "./media";
|
@forward "./media";
|
||||||
@forward "./colors";
|
@forward "./colors";
|
||||||
@forward "./base";
|
@forward "./base";
|
||||||
|
@forward "./spacing";
|
||||||
@forward "./mixins";
|
@forward "./mixins";
|
||||||
|
|
||||||
@forward "./components/card";
|
|
||||||
|
|||||||
@@ -53,21 +53,26 @@ function getOptionalDevToolkitComponent(): Component | undefined {
|
|||||||
@use 'sass:math';
|
@use 'sass:math';
|
||||||
|
|
||||||
@mixin responsive-spacing {
|
@mixin responsive-spacing {
|
||||||
$spacing-absolute-small: math.div($base-spacing, 2);
|
|
||||||
$spacing-absolute-extra-small: math.div($base-spacing, 4);
|
|
||||||
// Avoid using percentage-based values for spacing the avoid unintended layout shifts.
|
// Avoid using percentage-based values for spacing the avoid unintended layout shifts.
|
||||||
margin-left: $base-spacing;
|
margin-left: $spacing-absolute-medium;
|
||||||
margin-right: $base-spacing;
|
margin-right: $spacing-absolute-medium;
|
||||||
|
padding: $spacing-absolute-xx-large;
|
||||||
@media screen and (max-width: $media-screen-big-width) {
|
@media screen and (max-width: $media-screen-big-width) {
|
||||||
margin-left: $spacing-absolute-small;
|
margin-left: $spacing-absolute-small;
|
||||||
margin-right: $spacing-absolute-small;
|
margin-right: $spacing-absolute-small;
|
||||||
|
padding: $spacing-absolute-x-large;
|
||||||
}
|
}
|
||||||
@media screen and (max-width: $media-screen-medium-width) {
|
@media screen and (max-width: $media-screen-medium-width) {
|
||||||
margin-left: $spacing-absolute-extra-small;
|
margin-left: $spacing-absolute-x-small;
|
||||||
margin-right: $spacing-absolute-extra-small;
|
margin-right: $spacing-absolute-x-small;
|
||||||
|
padding: $spacing-absolute-medium;
|
||||||
}
|
}
|
||||||
|
@media screen and (max-width: $media-screen-small-width) {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
padding: $spacing-absolute-small;
|
padding: $spacing-absolute-small;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
@@ -83,10 +88,10 @@ function getOptionalDevToolkitComponent(): Component | undefined {
|
|||||||
display:flex;
|
display:flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
.app__row {
|
.app__row {
|
||||||
margin-bottom: 10px;
|
margin-bottom: $spacing-absolute-large;
|
||||||
}
|
}
|
||||||
.app__code-buttons {
|
.app__code-buttons {
|
||||||
padding-bottom: 10px;
|
padding-bottom: $spacing-absolute-medium;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ export default defineComponent({
|
|||||||
color: $color-on-secondary;
|
color: $color-on-secondary;
|
||||||
|
|
||||||
border: none;
|
border: none;
|
||||||
padding: 20px;
|
|
||||||
transition-duration: 0.4s;
|
transition-duration: 0.4s;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 3px 9px $color-primary-darkest;
|
box-shadow: 0 3px 9px $color-primary-darkest;
|
||||||
|
|||||||
@@ -54,14 +54,14 @@ export default defineComponent({
|
|||||||
|
|
||||||
.copyable-command {
|
.copyable-command {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
padding: 0.25em;
|
padding: $spacing-relative-x-small;
|
||||||
font-size: $font-size-absolute-small;
|
font-size: $font-size-absolute-small;
|
||||||
.dollar {
|
.dollar {
|
||||||
margin-right: 0.5rem;
|
margin-right: $spacing-relative-small;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
.copy-action-container {
|
.copy-action-container {
|
||||||
margin-left: 1rem;
|
margin-left: $spacing-relative-medium;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -34,12 +34,15 @@ export default defineComponent({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 30px;
|
gap: $spacing-absolute-xx-large;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-button {
|
.code-button {
|
||||||
width: 10%;
|
width: 10%;
|
||||||
min-width: 90px;
|
min-width: 90px;
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ interface DevAction {
|
|||||||
right: 0;
|
right: 0;
|
||||||
background-color: rgba($color-on-surface, 0.5);
|
background-color: rgba($color-on-surface, 0.5);
|
||||||
color: $color-on-primary;
|
color: $color-on-primary;
|
||||||
padding: 10px;
|
padding: $spacing-absolute-medium;
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
|
|
||||||
display:flex;
|
display:flex;
|
||||||
@@ -113,14 +113,14 @@ interface DevAction {
|
|||||||
.action-buttons {
|
.action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: $spacing-absolute-medium;
|
||||||
@include reset-ul;
|
@include reset-ul;
|
||||||
|
|
||||||
.action-button {
|
.action-button {
|
||||||
@include reset-button;
|
@include reset-button;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
padding: 5px 10px;
|
padding: $spacing-absolute-x-small $spacing-absolute-medium;
|
||||||
background-color: $color-primary;
|
background-color: $color-primary;
|
||||||
color: $color-on-primary;
|
color: $color-on-primary;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default defineComponent({
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
$gap: 0.25rem;
|
$gap: $spacing-relative-x-small;
|
||||||
.list {
|
.list {
|
||||||
display: flex;
|
display: flex;
|
||||||
:deep(.items) {
|
:deep(.items) {
|
||||||
|
|||||||
@@ -37,8 +37,10 @@ export default defineComponent({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
.circle-rating {
|
.circle-rating {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: 0.2em;
|
gap: $spacing-relative-x-small;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<svg
|
<span class="circle-container">
|
||||||
:style="{
|
<svg :viewBox="viewBox">
|
||||||
'--circle-stroke-width': `${circleStrokeWidthInPx}px`,
|
|
||||||
}"
|
|
||||||
:viewBox="viewBox"
|
|
||||||
>
|
|
||||||
<circle
|
<circle
|
||||||
:cx="circleRadiusInPx"
|
:cx="circleRadiusInPx"
|
||||||
:cy="circleRadiusInPx"
|
:cy="circleRadiusInPx"
|
||||||
:r="circleRadiusWithoutStrokeInPx"
|
:r="circleRadiusWithoutStrokeInPx"
|
||||||
|
:stroke-width="circleStrokeWidthStyleValue"
|
||||||
:class="{
|
:class="{
|
||||||
filled,
|
filled,
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -43,10 +41,13 @@ export default defineComponent({
|
|||||||
const height = circleDiameterInPx + circleStrokeWidthInPx;
|
const height = circleDiameterInPx + circleStrokeWidthInPx;
|
||||||
return `${minX} ${minY} ${width} ${height}`;
|
return `${minX} ${minY} ${width} ${height}`;
|
||||||
});
|
});
|
||||||
|
const circleStrokeWidthStyleValue = computed(() => {
|
||||||
|
return `${circleStrokeWidthInPx}px`;
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
circleRadiusInPx,
|
circleRadiusInPx,
|
||||||
circleDiameterInPx,
|
circleDiameterInPx,
|
||||||
circleStrokeWidthInPx,
|
circleStrokeWidthStyleValue,
|
||||||
circleRadiusWithoutStrokeInPx,
|
circleRadiusWithoutStrokeInPx,
|
||||||
viewBox,
|
viewBox,
|
||||||
};
|
};
|
||||||
@@ -55,17 +56,18 @@ export default defineComponent({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
$circleColor: currentColor;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
$circleHeight: 0.8em;
|
|
||||||
$circleStrokeWidth: var(--circle-stroke-width);
|
$circle-color: currentColor;
|
||||||
|
$circle-height: $font-size-relative-smaller;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
height: $circleHeight;
|
font-size: $circle-height;
|
||||||
|
height: 1em;
|
||||||
circle {
|
circle {
|
||||||
stroke: $circleColor;
|
stroke: $circle-color;
|
||||||
stroke-width: $circleStrokeWidth;
|
|
||||||
&.filled {
|
&.filled {
|
||||||
fill: $circleColor;
|
fill: $circle-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
@mixin horizontal-stack {
|
@mixin horizontal-stack {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5em;
|
gap: $spacing-relative-small;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin apply-icon-color($color) {
|
@mixin apply-icon-color($color) {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
@mixin horizontal-stack {
|
@mixin horizontal-stack {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5em;
|
gap: $spacing-relative-small;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin apply-icon-color($color) {
|
@mixin apply-icon-color($color) {
|
||||||
|
|||||||
@@ -70,8 +70,6 @@ export default defineComponent({
|
|||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
@use 'sass:math';
|
@use 'sass:math';
|
||||||
|
|
||||||
$spacing-small: math.div($base-spacing, 2);
|
|
||||||
|
|
||||||
@mixin center-middle-flex-item {
|
@mixin center-middle-flex-item {
|
||||||
&:first-child, &:last-child {
|
&:first-child, &:last-child {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@@ -87,12 +85,12 @@ $responsive-alignment-breakpoint: $media-screen-medium-width;
|
|||||||
.scripts-menu {
|
.scripts-menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
column-gap: $base-spacing;
|
column-gap: $spacing-relative-medium;
|
||||||
row-gap: $base-spacing;
|
row-gap: $spacing-relative-small;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: $spacing-small;
|
margin-left: $spacing-absolute-small;
|
||||||
margin-right: $spacing-small;
|
margin-right: $spacing-absolute-small;
|
||||||
@media screen and (max-width: $responsive-alignment-breakpoint) {
|
@media screen and (max-width: $responsive-alignment-breakpoint) {
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
@@ -106,7 +104,7 @@ $responsive-alignment-breakpoint: $media-screen-medium-width;
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
row-gap: 0.5em;
|
row-gap: $spacing-relative-x-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div class="slider">
|
||||||
class="slider"
|
|
||||||
:style="{
|
|
||||||
'--vertical-margin': verticalMargin,
|
|
||||||
'--first-min-width': firstMinWidth,
|
|
||||||
'--first-initial-width': firstInitialWidth,
|
|
||||||
'--second-min-width': secondMinWidth,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div ref="firstElement" class="first">
|
<div ref="firstElement" class="first">
|
||||||
<slot name="first" />
|
<slot name="first" />
|
||||||
</div>
|
</div>
|
||||||
@@ -27,10 +19,6 @@ export default defineComponent({
|
|||||||
SliderHandle,
|
SliderHandle,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
verticalMargin: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
firstMinWidth: {
|
firstMinWidth: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
@@ -71,21 +59,18 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
.first {
|
.first {
|
||||||
min-width: var(--first-min-width);
|
min-width: v-bind(firstMinWidth);
|
||||||
width: var(--first-initial-width);
|
width: v-bind(firstInitialWidth);
|
||||||
}
|
}
|
||||||
.second {
|
.second {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: var(--second-min-width);
|
min-width: v-bind(secondMinWidth);
|
||||||
}
|
}
|
||||||
@media screen and (max-width: $media-vertical-view-breakpoint) {
|
@media screen and (max-width: $media-vertical-view-breakpoint) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
.first {
|
.first {
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
}
|
}
|
||||||
.second {
|
|
||||||
margin-top: var(--vertical-margin);
|
|
||||||
}
|
|
||||||
.handle {
|
.handle {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ $cursor : v-bind(cursorCssValue);
|
|||||||
.icon {
|
.icon {
|
||||||
color: $color;
|
color: $color;
|
||||||
}
|
}
|
||||||
margin-right: 5px;
|
margin-right: $spacing-absolute-small;
|
||||||
margin-left: 5px;
|
margin-left: $spacing-absolute-small;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
<div class="script-area">
|
<div class="script-area">
|
||||||
<TheScriptsMenu @view-changed="currentView = $event" />
|
<TheScriptsMenu @view-changed="currentView = $event" />
|
||||||
<HorizontalResizeSlider
|
<HorizontalResizeSlider
|
||||||
class="row"
|
class="horizontal-slider"
|
||||||
vertical-margin="15px"
|
|
||||||
first-initial-width="55%"
|
first-initial-width="55%"
|
||||||
first-min-width="20%"
|
first-min-width="20%"
|
||||||
second-min-width="20%"
|
second-min-width="20%"
|
||||||
@@ -42,9 +41,17 @@ export default defineComponent({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
.script-area {
|
.script-area {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: $spacing-absolute-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-slider {
|
||||||
|
// Add row gap between lines on mobile (smaller screens)
|
||||||
|
// when the slider turns into rows.
|
||||||
|
row-gap: $spacing-absolute-large;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ function isClickable(element: Element) {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
@use "./card-gap" as *;
|
||||||
|
|
||||||
.cards {
|
.cards {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -135,7 +136,7 @@ function isClickable(element: Element) {
|
|||||||
It ensures that there's room to grow, so the animation is shown without overflowing
|
It ensures that there's room to grow, so the animation is shown without overflowing
|
||||||
with scrollbars.
|
with scrollbars.
|
||||||
*/
|
*/
|
||||||
padding: 10px;
|
padding: $spacing-absolute-medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
|
|||||||
@@ -138,9 +138,10 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
@use "./card-gap" as *;
|
||||||
|
|
||||||
$card-inner-padding : 30px;
|
$card-inner-padding : $spacing-absolute-xx-large;
|
||||||
$expanded-margin-top : 30px;
|
$expanded-margin-top : $spacing-absolute-xx-large;
|
||||||
$card-horizontal-gap : $card-gap;
|
$card-horizontal-gap : $card-gap;
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
@@ -178,13 +179,13 @@ $card-horizontal-gap : $card-gap;
|
|||||||
.card__inner__selection_indicator {
|
.card__inner__selection_indicator {
|
||||||
height: $card-inner-padding;
|
height: $card-inner-padding;
|
||||||
margin-right: -$card-inner-padding;
|
margin-right: -$card-inner-padding;
|
||||||
padding-right: 10px;
|
padding-right: $spacing-absolute-medium;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
.card__inner__expand-icon {
|
.card__inner__expand-icon {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: .25em;
|
margin-top: $spacing-relative-x-small;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
font-size: $font-size-absolute-normal;
|
font-size: $font-size-absolute-normal;
|
||||||
}
|
}
|
||||||
@@ -209,7 +210,7 @@ $card-horizontal-gap : $card-gap;
|
|||||||
.card__expander__close-button {
|
.card__expander__close-button {
|
||||||
font-size: $font-size-absolute-large;
|
font-size: $font-size-absolute-large;
|
||||||
align-self: flex-end;
|
align-self: flex-end;
|
||||||
margin-right: 0.25em;
|
margin-right: $spacing-absolute-small;
|
||||||
@include clickable;
|
@include clickable;
|
||||||
color: $color-primary-light;
|
color: $color-primary-light;
|
||||||
@include hover-or-touch {
|
@include hover-or-touch {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
|
$card-gap: $spacing-absolute-large;
|
||||||
@@ -128,10 +128,7 @@ export default defineComponent({
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
$margin-inner: 4px;
|
|
||||||
|
|
||||||
.scripts-view {
|
.scripts-view {
|
||||||
margin-top: $margin-inner;
|
|
||||||
@media screen and (min-width: $media-vertical-view-breakpoint) {
|
@media screen and (min-width: $media-vertical-view-breakpoint) {
|
||||||
// so the current code is always visible
|
// so the current code is always visible
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
@@ -143,16 +140,17 @@ $margin-inner: 4px;
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
background-color: $color-scripts-bg;
|
background-color: $color-scripts-bg;
|
||||||
|
padding-top: $spacing-absolute-large;
|
||||||
|
padding-bottom:$spacing-absolute-large;
|
||||||
.search__query {
|
.search__query {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 1em;
|
|
||||||
color: $color-primary-light;
|
color: $color-primary-light;
|
||||||
.search__query__close-button {
|
.search__query__close-button {
|
||||||
font-size: $font-size-absolute-large;
|
font-size: $font-size-absolute-large;
|
||||||
margin-left: 0.25rem;
|
margin-left: $spacing-relative-x-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.search-no-matches {
|
.search-no-matches {
|
||||||
@@ -161,11 +159,9 @@ $margin-inner: 4px;
|
|||||||
word-break:break-word;
|
word-break:break-word;
|
||||||
color: $color-on-primary;
|
color: $color-on-primary;
|
||||||
font-size: $font-size-absolute-large;
|
font-size: $font-size-absolute-large;
|
||||||
padding:10px;
|
padding: $spacing-absolute-medium;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
> div {
|
gap: $spacing-relative-small;
|
||||||
padding-bottom:13px;
|
|
||||||
}
|
|
||||||
a {
|
a {
|
||||||
color: $color-primary;
|
color: $color-primary;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default defineComponent({
|
|||||||
flex: 1; // Expands the container to fill available horizontal space, enabling alignment of child items.
|
flex: 1; // Expands the container to fill available horizontal space, enabling alignment of child items.
|
||||||
max-width: 100%; // Prevents horizontal expansion of inner content (e.g., when a code block is shown)
|
max-width: 100%; // Prevents horizontal expansion of inner content (e.g., when a code block is shown)
|
||||||
*:not(:first-child) {
|
*:not(:first-child) {
|
||||||
margin-left: 5px;
|
margin-left: $spacing-absolute-small;
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -80,10 +80,10 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
.docs {
|
.docs {
|
||||||
background: $color-primary-darkest;
|
background: $color-primary-darkest;
|
||||||
margin-top: 0.25em;
|
margin-top: $spacing-relative-x-small;
|
||||||
color: $color-on-primary;
|
color: $color-on-primary;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
padding: 0.5em;
|
padding: $spacing-absolute-medium;
|
||||||
&-collapsed {
|
&-collapsed {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default defineComponent({
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.node-content-item:not(:first-child) {
|
.node-content-item:not(:first-child) {
|
||||||
margin-left: 5px;
|
margin-left: $spacing-relative-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
v-model="isReverted"
|
v-model="isReverted"
|
||||||
:stop-click-propagation="true"
|
:stop-click-propagation="true"
|
||||||
:label="'Revert'"
|
label="Revert"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -83,12 +83,12 @@ $color-text-unchecked : $color-on-primary;
|
|||||||
$color-text-checked : $color-on-secondary;
|
$color-text-checked : $color-on-secondary;
|
||||||
$color-bg-unchecked : $color-primary;
|
$color-bg-unchecked : $color-primary;
|
||||||
$color-bg-checked : $color-secondary;
|
$color-bg-checked : $color-secondary;
|
||||||
$padding-horizontal : calc($font-size * 0.4);
|
$padding-horizontal : $spacing-relative-small;
|
||||||
$padding-vertical : calc($font-size * 0.3);
|
$padding-vertical : $spacing-absolute-small;
|
||||||
$size-height : calc($font-size + ($padding-vertical * 2));
|
$size-height : calc($font-size + ($padding-vertical * 2));
|
||||||
$size-circle : math.div($size-height * 2, 3);
|
$size-circle : calc($size-height * 2/3);
|
||||||
|
|
||||||
$gap-between-circle-and-text : 0.25em;
|
$gap-between-circle-and-text : $spacing-relative-x-small;
|
||||||
|
|
||||||
@mixin locateNearCircle($direction: 'left') {
|
@mixin locateNearCircle($direction: 'left') {
|
||||||
$circle-width: calc(#{$size-circle} + #{$padding-horizontal});
|
$circle-width: calc(#{$size-circle} + #{$padding-horizontal});
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ export default defineComponent({
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
$padding: 20px;
|
$padding-horizontal : $spacing-absolute-large;
|
||||||
|
$padding-vertical : $spacing-absolute-x-large;
|
||||||
|
|
||||||
.scripts-tree-container {
|
.scripts-tree-container {
|
||||||
display: flex; // We could provide `block`, but `flex` is more versatile.
|
display: flex; // We could provide `block`, but `flex` is more versatile.
|
||||||
@@ -84,11 +85,11 @@ $padding: 20px;
|
|||||||
|
|
||||||
flex: 1; // Expands the container to fill available horizontal space, enabling alignment of child items.
|
flex: 1; // Expands the container to fill available horizontal space, enabling alignment of child items.
|
||||||
|
|
||||||
padding-bottom: $padding;
|
padding-bottom: $padding-vertical;
|
||||||
padding-left: $padding;
|
padding-left: $padding-horizontal;
|
||||||
padding-right: $padding;
|
padding-right: $padding-horizontal;
|
||||||
&.top-padding {
|
&.top-padding {
|
||||||
padding-top: $padding;
|
padding-top: $padding-vertical;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
:tree-root="treeRoot"
|
:tree-root="treeRoot"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="expand-collapse-arrow"
|
class="expand-collapse-caret"
|
||||||
:class="{
|
:class="{
|
||||||
expanded: isExpanded,
|
expanded: isExpanded,
|
||||||
'has-children': hasChildren,
|
'has-children': hasChildren,
|
||||||
@@ -141,10 +141,13 @@ export default defineComponent({
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.expand-collapse-arrow {
|
.expand-collapse-caret {
|
||||||
|
$caret-size: 24px;
|
||||||
|
$padding-right: $spacing-absolute-small;
|
||||||
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: 30px;
|
height: $caret-size;
|
||||||
margin-left: 30px;
|
margin-left: $caret-size + $padding-right;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
|
||||||
@include clickable;
|
@include clickable;
|
||||||
@@ -157,25 +160,32 @@ export default defineComponent({
|
|||||||
|
|
||||||
&.has-children {
|
&.has-children {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
width: 30px;
|
width: $caret-size + $padding-right;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
$caret-dimension: $caret-size * 0.375;
|
||||||
|
$caret-stroke-width: 1.5px;
|
||||||
&:after {
|
&:after {
|
||||||
border: 1.5px solid $color-node-arrow;
|
border: $caret-stroke-width solid $color-node-arrow;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
left: 9px;
|
left: $caret-dimension;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
height: 9px;
|
height: $caret-dimension;
|
||||||
width: 9px;
|
width: $caret-dimension;
|
||||||
transform: rotate(-45deg) translateY(-50%) translateX(0);
|
transform:
|
||||||
|
rotate(-45deg)
|
||||||
|
translateY(-50%)
|
||||||
|
translateX($caret-dimension * 0.2);
|
||||||
transition: transform .25s;
|
transition: transform .25s;
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.expanded:after {
|
&.expanded:after {
|
||||||
transform: rotate(45deg) translateY(-50%) translateX(-5px);
|
transform:
|
||||||
|
rotate(45deg)
|
||||||
|
translateY(-50%)
|
||||||
|
translateX($caret-dimension * -0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,18 +76,18 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.node {
|
.node {
|
||||||
margin-bottom: 3px;
|
margin-bottom: $spacing-absolute-xx-small;
|
||||||
margin-top: 3px;
|
margin-top: $spacing-absolute-xx-small;
|
||||||
padding-bottom: 3px;
|
padding-bottom: $spacing-absolute-xx-small;
|
||||||
padding-top: 3px;
|
padding-top: $spacing-absolute-xx-small;
|
||||||
padding-right: 6px;
|
padding-right: $spacing-absolute-small;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex; // We could provide `block`, but `flex` is more versatile.
|
display: flex; // We could provide `block`, but `flex` is more versatile.
|
||||||
color: $color-node-fg;
|
color: $color-node-fg;
|
||||||
padding-left: 9px;
|
padding-left: $spacing-relative-small;
|
||||||
padding-right: 6px;
|
padding-right: $spacing-absolute-x-small;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
.flat-button {
|
.flat-button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
gap: 0.5em;
|
gap: $spacing-relative-small;
|
||||||
&.disabled {
|
&.disabled {
|
||||||
@include flat-button($disabled: true);
|
@include flat-button($disabled: true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default defineComponent({
|
|||||||
$modal-content-transition-duration: 400ms;
|
$modal-content-transition-duration: 400ms;
|
||||||
$modal-content-color-shadow: $color-on-surface;
|
$modal-content-color-shadow: $color-on-surface;
|
||||||
$modal-content-color-background: $color-surface;
|
$modal-content-color-background: $color-surface;
|
||||||
$modal-content-offset-upward: 20px;
|
$modal-content-offset-upward: $spacing-absolute-x-large;
|
||||||
|
|
||||||
@mixin scrollable() {
|
@mixin scrollable() {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
@@ -63,19 +63,25 @@ export default defineComponent({
|
|||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
.dialog {
|
.dialog {
|
||||||
margin-bottom: 10px;
|
margin-bottom: $spacing-absolute-medium;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
margin: 5%;
|
margin: $spacing-absolute-xx-large;
|
||||||
|
@media screen and (max-width: $media-screen-big-width) {
|
||||||
|
margin: $spacing-absolute-x-large;
|
||||||
|
}
|
||||||
|
@media screen and (max-width: $media-screen-medium-width) {
|
||||||
|
margin: $spacing-absolute-large;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog__close-button {
|
.dialog__close-button {
|
||||||
color: $color-primary-dark;
|
color: $color-primary-dark;
|
||||||
width: auto;
|
width: auto;
|
||||||
font-size: $font-size-absolute-large;
|
font-size: $font-size-absolute-large;
|
||||||
margin-right: 0.25em;
|
margin-right: $spacing-absolute-small;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ $color-tooltip-background: $color-primary-darkest;
|
|||||||
background: $color-tooltip-background;
|
background: $color-tooltip-background;
|
||||||
color: $color-on-primary;
|
color: $color-on-primary;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
padding: 12px 10px;
|
padding: $spacing-absolute-large $spacing-absolute-medium;
|
||||||
|
|
||||||
// Explicitly set font styling for tooltips to prevent inconsistent appearances due to style inheritance from trigger elements.
|
// Explicitly set font styling for tooltips to prevent inconsistent appearances due to style inheritance from trigger elements.
|
||||||
@include base-font-style;
|
@include base-font-style;
|
||||||
@@ -230,8 +230,8 @@ $color-tooltip-background: $color-primary-darkest;
|
|||||||
and balanced layout.
|
and balanced layout.
|
||||||
Avoiding setting vertical margin as it disrupts the arrow rendering.
|
Avoiding setting vertical margin as it disrupts the arrow rendering.
|
||||||
*/
|
*/
|
||||||
margin-left: 2px;
|
margin-left: $spacing-absolute-xx-small;
|
||||||
margin-right: 2px;
|
margin-right: $spacing-absolute-xx-small;
|
||||||
|
|
||||||
// Setting max-width increases readability and consistency reducing overlap and clutter.
|
// Setting max-width increases readability and consistency reducing overlap and clutter.
|
||||||
@include set-property-ch-value-with-fallback(
|
@include set-property-ch-value-with-fallback(
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
.description {
|
.description {
|
||||||
&__icon {
|
&__icon {
|
||||||
margin-right: 0.5em;
|
margin-right: $spacing-relative-small;
|
||||||
}
|
}
|
||||||
&__text {
|
&__text {
|
||||||
margin-right: 0.3em;
|
margin-right: $spacing-relative-x-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ export default defineComponent({
|
|||||||
&:not(:first-child)::before {
|
&:not(:first-child)::before {
|
||||||
content: "|";
|
content: "|";
|
||||||
font-size: $font-size-absolute-x-small;
|
font-size: $font-size-absolute-x-small;
|
||||||
padding: 0 5px;
|
padding: 0 $spacing-relative-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export default defineComponent({
|
|||||||
@use "@/presentation/assets/styles/main" as *;
|
@use "@/presentation/assets/styles/main" as *;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
margin-right: 0.5em;
|
margin-right: $spacing-relative-small;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
@@ -119,18 +119,19 @@ export default defineComponent({
|
|||||||
@media screen and (max-width: $media-screen-big-width) {
|
@media screen and (max-width: $media-screen-big-width) {
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
column-gap: $spacing-relative-medium;
|
||||||
&:not(:first-child) {
|
&:not(:first-child) {
|
||||||
margin-top: 0.7em;
|
margin-top: $spacing-relative-small;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
&__item:not(:first-child) {
|
&__item:not(:first-child) {
|
||||||
&::before {
|
&::before {
|
||||||
content: "|";
|
content: "|";
|
||||||
padding: 0 5px;
|
padding: 0 $spacing-relative-small;
|
||||||
}
|
}
|
||||||
@media screen and (max-width: $media-screen-big-width) {
|
@media screen and (max-width: $media-screen-big-width) {
|
||||||
margin-top: 3px;
|
margin-top: $spacing-absolute-xx-small;
|
||||||
&::before {
|
&::before {
|
||||||
content: "";
|
content: "";
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
@@ -106,10 +106,9 @@ export default defineComponent({
|
|||||||
min-width: 60px;
|
min-width: 60px;
|
||||||
border: 1.5px solid $color-primary;
|
border: 1.5px solid $color-primary;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
height: 36px;
|
|
||||||
border-radius: 3px 0 0 3px;
|
border-radius: 3px 0 0 3px;
|
||||||
padding-left:10px;
|
padding-left: $spacing-absolute-medium;
|
||||||
padding-right:10px;
|
padding-right: $spacing-absolute-medium;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: $color-primary;
|
color: $color-primary;
|
||||||
font-size: $font-size-absolute-normal;
|
font-size: $font-size-absolute-normal;
|
||||||
@@ -127,6 +126,6 @@ export default defineComponent({
|
|||||||
color: $color-on-primary;
|
color: $color-on-primary;
|
||||||
border-radius: 0 5px 5px 0;
|
border-radius: 0 5px 5px 0;
|
||||||
font-size: $font-size-absolute-large;
|
font-size: $font-size-absolute-large;
|
||||||
padding:5px;
|
padding: $spacing-absolute-x-small;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ logger.logLabeledInformation('Scheduled test duration', convertMillisecondsToHum
|
|||||||
logger.logTestSectionEndDelimiter();
|
logger.logTestSectionEndDelimiter();
|
||||||
test(`all URLs (${urls.length}) should be alive`, async () => {
|
test(`all URLs (${urls.length}) should be alive`, async () => {
|
||||||
// act
|
// act
|
||||||
console.log('URLS', urls); // TODO: Delete
|
|
||||||
const results = await getUrlStatusesInParallel(urls, requestOptions);
|
const results = await getUrlStatusesInParallel(urls, requestOptions);
|
||||||
// assert
|
// assert
|
||||||
const deadUrls = results.filter((r) => r.code === undefined || !isOkStatusCode(r.code));
|
const deadUrls = results.filter((r) => r.code === undefined || !isOkStatusCode(r.code));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import RatingCircle from '@/presentation/components/Scripts/Menu/Recommendation/Rating/RatingCircle.vue';
|
import RatingCircle from '@/presentation/components/Scripts/Menu/Recommendation/Rating/RatingCircle.vue';
|
||||||
|
import { formatAssertionMessage } from '@tests/shared/FormatAssertionMessage';
|
||||||
|
|
||||||
const DOM_SVG_SELECTOR = 'svg';
|
const DOM_SVG_SELECTOR = 'svg';
|
||||||
const DOM_CIRCLE_SELECTOR = `${DOM_SVG_SELECTOR} > circle`;
|
const DOM_CIRCLE_SELECTOR = `${DOM_SVG_SELECTOR} > circle`;
|
||||||
@@ -39,12 +40,6 @@ describe('RatingCircle.vue', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('SVG and circle styles', () => {
|
describe('SVG and circle styles', () => {
|
||||||
it('sets --circle-stroke-width style correctly', () => {
|
|
||||||
const wrapper = shallowMount(RatingCircle);
|
|
||||||
const svgElement = wrapper.find(DOM_SVG_SELECTOR).element;
|
|
||||||
expect(svgElement.style.getPropertyValue('--circle-stroke-width')).to.equal('2px');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders circle with correct fill attribute when filled prop is true', () => {
|
it('renders circle with correct fill attribute when filled prop is true', () => {
|
||||||
const wrapper = shallowMount(RatingCircle, {
|
const wrapper = shallowMount(RatingCircle, {
|
||||||
propsData: {
|
propsData: {
|
||||||
@@ -58,32 +53,49 @@ describe('RatingCircle.vue', () => {
|
|||||||
|
|
||||||
it('renders circle with the correct viewBox property', () => {
|
it('renders circle with the correct viewBox property', () => {
|
||||||
const wrapper = shallowMount(RatingCircle);
|
const wrapper = shallowMount(RatingCircle);
|
||||||
const circle = wrapper.find(DOM_SVG_SELECTOR);
|
const circleElement = wrapper.find(DOM_SVG_SELECTOR);
|
||||||
|
|
||||||
expect(circle.attributes('viewBox')).to.equal('-1 -1 22 22');
|
expect(circleElement.attributes('viewBox')).to.equal('-1 -1 22 22');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('circle attributes', () => {
|
describe('circle attributes', () => {
|
||||||
it('renders circle with the correct cx attribute', () => {
|
const testScenarios: ReadonlyArray<{
|
||||||
|
readonly attributeKey: string;
|
||||||
|
readonly expectedValue: string;
|
||||||
|
}> = [
|
||||||
|
{
|
||||||
|
attributeKey: 'stroke-width',
|
||||||
|
expectedValue: '2px', // Based on circleStrokeWidthInPx = 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributeKey: 'cx',
|
||||||
|
expectedValue: '10', // Based on circleDiameterInPx = 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributeKey: 'cy',
|
||||||
|
expectedValue: '10', // Based on circleStrokeWidthInPx = 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributeKey: 'r',
|
||||||
|
expectedValue: '9', // Based on circleRadiusWithoutStrokeInPx = circleDiameterInPx / 2 - circleStrokeWidthInPx / 2
|
||||||
|
},
|
||||||
|
];
|
||||||
|
testScenarios.forEach(({
|
||||||
|
attributeKey, expectedValue,
|
||||||
|
}) => {
|
||||||
|
it(`renders circle with the correct ${attributeKey} attribute`, () => {
|
||||||
|
// act
|
||||||
const wrapper = shallowMount(RatingCircle);
|
const wrapper = shallowMount(RatingCircle);
|
||||||
const circleElement = wrapper.find(DOM_CIRCLE_SELECTOR);
|
const circleElement = wrapper.find(DOM_CIRCLE_SELECTOR);
|
||||||
|
const actualValue = circleElement.attributes(attributeKey);
|
||||||
expect(circleElement.attributes('cx')).to.equal('10'); // Based on circleDiameterInPx = 20
|
// assert
|
||||||
});
|
expect(actualValue).to.equal(expectedValue, formatAssertionMessage([
|
||||||
|
`Expected value: ${expectedValue}`,
|
||||||
it('renders circle with the correct cy attribute', () => {
|
`Actual value: ${actualValue}`,
|
||||||
const wrapper = shallowMount(RatingCircle);
|
`Attribute: ${attributeKey}`,
|
||||||
const circleElement = wrapper.find(DOM_CIRCLE_SELECTOR);
|
]));
|
||||||
|
});
|
||||||
expect(circleElement.attributes('cy')).to.equal('10'); // Based on circleDiameterInPx = 20
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders circle with the correct r attribute', () => {
|
|
||||||
const wrapper = shallowMount(RatingCircle);
|
|
||||||
const circleElement = wrapper.find(DOM_CIRCLE_SELECTOR);
|
|
||||||
|
|
||||||
expect(circleElement.attributes('r')).to.equal('9'); // Based on circleRadiusWithoutStrokeInPx = circleDiameterInPx / 2 - circleStrokeWidthInPx / 2
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user