big ui refractor

This commit is contained in:
Rene Kievits
2025-12-23 02:23:44 +01:00
parent 4428a2b7be
commit eaed23a678
62 changed files with 2662 additions and 815 deletions

View File

@@ -1,4 +1,4 @@
@use '../abstracts/variables' as *;
@use '../abstracts' as *;
.glow-btn {
box-shadow: $shadow-glow-base;
@@ -8,7 +8,7 @@
will-change: transform, box-shadow;
&:hover {
transform: translateY(-2px);
transform: translateY(-0.125rem);
box-shadow: $shadow-glow-hover;
}
@@ -24,3 +24,46 @@
cursor: not-allowed;
}
}
.lang-switch-wrapper {
position: relative;
display: flex;
width: 100%;
height: 3rem;
background-color: $bg-glass-subtle;
border-radius: $radius-lg;
overflow: hidden;
border: $border-width-sm solid rgba(255, 255, 255, 0.1);
}
.lang-glider {
position: absolute;
top: 0;
left: 0;
width: 33.33%;
height: 100%;
background-color: $color-primary;
transition: transform $duration-normal cubic-bezier(0.25, 0.8, 0.5, 1);
border-radius: calc($radius-lg - 1px);
z-index: 0;
}
.lang-btn {
flex: 1;
border: none;
background: transparent;
color: $color-text-grey;
font-weight: $weight-bold;
font-size: $font-sm;
cursor: pointer;
z-index: 1;
transition: color $duration-fast ease;
&:hover {
color: $color-text-white;
}
&.active {
color: $color-bg-dark;
}
}

View File

@@ -0,0 +1,26 @@
@use '../abstracts' as *;
.widget-card {
@include card-base;
border: $border-width-sm solid $color-border;
background-color: $color-surface !important;
border-radius: $radius-xl !important;
}
.lesson-card {
width: 100%;
max-width: $size-lesson-card-width;
border-radius: $radius-xl !important;
border: $border-width-sm solid $color-border;
background-color: $color-surface !important;
min-height: $size-lesson-card-min-height;
display: flex;
flex-direction: column;
}
.review-card {
border: $border-width-sm solid $color-border;
background-color: $color-surface !important;
width: 100%;
max-width: $size-review-card-max-width;
}

View File

@@ -0,0 +1,4 @@
@use 'buttons';
@use 'cards';
@use 'kanji/index' as kanji;
@use 'dashboard/index' as dashboard;

View File

@@ -1,189 +0,0 @@
@use '../abstracts/variables' as *;
@use '../abstracts/mixins' as *;
@use 'sass:color';
.widget-card {
@include card-base;
border: $border-subtle;
background-color: $color-surface !important;
border-radius: $radius-xl !important;
}
.welcome-btn {
height: $size-button-large-height !important;
width: $size-button-large-width !important;
.v-chip {
color: white !important;
background-color: $color-surface !important;
}
}
.streak-shield-avatar {
border: 1px solid currentcolor;
background: rgb(255 255 255 / 5%);
}
.streak-day-label {
font-size: 9px !important;
}
.heatmap-container {
width: 100%;
@include flex-center;
}
.heatmap-year {
display: grid;
grid-template-columns: repeat(53, 1fr);
gap: $gap-heatmap;
width: 100%;
}
.heatmap-week {
display: grid;
grid-template-rows: repeat(7, max-content);
gap: $gap-heatmap;
}
.heatmap-day-wrapper {
width: 100%;
}
.heatmap-cell {
width: 100%;
height: $size-heatmap-cell-height;
border-radius: $radius-xs;
transition:
opacity $duration-fast,
background-color $duration-fast;
&:hover {
opacity: $opacity-hover;
}
}
.today-cell {
border: $border-width-sm solid $color-text-white;
box-shadow: $shadow-glow-xs;
z-index: $z-above;
position: relative;
box-sizing: border-box;
}
.level-0 {
background-color: $bg-glass-subtle;
}
.level-1 {
background-color: color.mix($color-primary, $color-surface, 25%);
}
.level-2 {
background-color: color.mix($color-primary, $color-surface, 50%);
}
.level-3 {
background-color: $color-primary;
}
.level-4 {
background-color: color.scale($color-primary, $lightness: 40%);
}
.legend-container {
display: flex;
align-items: center;
gap: $spacing-xs;
}
.legend-box {
width: $size-legend-box;
height: $size-legend-box;
border-radius: $radius-xs;
}
.ghost-card {
background: $bg-glass-subtle;
border-radius: $radius-md;
padding: $spacing-sm;
text-align: center;
border: $border-width-sm solid $bg-glass-subtle;
display: flex;
flex-direction: column;
justify-content: center;
min-height: $size-ghost-min-height;
}
.srs-chart-container {
height: $size-chart-height;
width: 100%;
}
.srs-column {
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.srs-track {
width: $size-srs-track;
flex-grow: 1;
background: $bg-glass-light;
border-radius: $radius-md;
position: relative;
overflow: hidden;
display: flex;
align-items: flex-end;
margin: $spacing-xs 0;
}
.srs-fill {
width: 100%;
border-radius: $radius-sm;
transition: height 1s $ease-out-back;
min-height: 0;
}
.transition-text {
transition: color $duration-normal $ease-default;
}
.streak-dot {
width: $size-streak-dot;
height: $size-streak-dot;
border-radius: $radius-circle;
background: $bg-glass-strong;
@include flex-center;
transition: all $duration-normal;
&.active {
background: $color-primary;
box-shadow: $shadow-glow-active;
}
}
.forecast-list {
overflow-y: auto;
@include scrollbar;
}
.srs-chart-container {
gap: 8px;
@media (max-width: 600px) {
gap: 4px;
}
}
.srs-track {
@media (max-width: 400px) {
width: 6px;
}
}

View File

@@ -0,0 +1,8 @@
@use '../../abstracts' as *;
.accuracy-chart-wrapper {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}

View File

@@ -0,0 +1,55 @@
@use '../../abstracts' as *;
.srs-chart-container {
height: $size-chart-height;
width: 100%;
gap: $gap-srs-chart;
display: flex;
justify-content: space-between;
align-items: flex-end;
padding-inline: $spacing-2xs;
@media (max-width: $breakpoint-sm) {
gap: $gap-srs-chart-mobile;
}
}
.srs-column {
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
flex-grow: 1;
}
.srs-track {
width: $size-srs-track;
flex-grow: 1;
background: $bg-glass-light;
border-radius: $radius-md;
position: relative;
overflow: hidden;
display: flex;
align-items: flex-end;
margin: $spacing-xs 0;
@media (max-width: $breakpoint-xs) {
width: $size-srs-track-mobile;
}
}
.srs-fill {
width: 100%;
border-radius: $radius-sm;
transition: height $duration-chart $ease-out-back;
min-height: 0;
}
.transition-text {
transition: color $duration-normal $ease-default;
}
.srs-label {
font-size: $font-size-srs-label !important;
}

View File

@@ -0,0 +1,6 @@
@use '../../abstracts' as *;
.forecast-list {
overflow-y: auto;
@include scrollbar;
}

View File

@@ -0,0 +1,13 @@
@use '../../abstracts' as *;
.ghost-card {
background: $bg-glass-subtle;
border-radius: $radius-md;
padding: $spacing-sm;
text-align: center;
border: $border-width-sm solid $bg-glass-subtle;
display: flex;
flex-direction: column;
justify-content: center;
min-height: $size-ghost-min-height;
}

View File

@@ -0,0 +1,6 @@
@use '../../abstracts' as *;
.mastery-progress {
width: 100%;
margin-top: $spacing-sm;
}

View File

@@ -0,0 +1,73 @@
@use '../../abstracts' as *;
@use 'sass:color';
.heatmap-container {
width: 100%;
@include flex-center;
}
.heatmap-year {
display: grid;
grid-template-columns: repeat(53, 1fr);
gap: $gap-heatmap;
width: 100%;
}
.heatmap-week {
display: grid;
grid-template-rows: repeat(7, max-content);
gap: $gap-heatmap;
}
.heatmap-day-wrapper {
width: 100%;
}
.heatmap-cell {
width: 100%;
height: $size-heatmap-cell;
border-radius: $radius-xs;
transition:
opacity $duration-fast,
background-color $duration-fast;
&:hover {
opacity: $opacity-hover;
}
}
.today-cell {
border: $border-width-sm solid $color-text-white;
box-shadow: $shadow-glow-xs;
z-index: $z-above;
position: relative;
box-sizing: border-box;
}
.level-0 {
background-color: $bg-glass-subtle;
}
.level-1 {
background-color: color.mix($color-primary, $color-surface, 25%);
}
.level-2 {
background-color: color.mix($color-primary, $color-surface, 50%);
}
.level-3 {
background-color: $color-primary;
}
.level-4 {
background-color: color.scale($color-primary, $lightness: 40%);
}
.legend-container {
display: flex;
align-items: center;
gap: $spacing-xs;
}
.legend-box {
width: $size-legend-box;
height: $size-legend-box;
border-radius: $radius-xs;
}

View File

@@ -0,0 +1,24 @@
@use '../../abstracts' as *;
.streak-shield-avatar {
border: $border-width-sm solid currentcolor;
background: $bg-glass-subtle;
}
.streak-day-label {
font-size: $font-size-heatmap-label !important;
}
.streak-dot {
width: $size-streak-dot;
height: $size-streak-dot;
border-radius: $radius-circle;
background: $bg-glass-strong;
@include flex-center;
transition: all $duration-normal;
&.active {
background: $color-primary;
box-shadow: $shadow-glow-active;
}
}

View File

@@ -0,0 +1,82 @@
@use '../../abstracts' as *;
@use 'sass:color';
.zen-wrapper {
max-width: $breakpoint-md;
margin-inline: auto;
}
.zen-btn {
min-width: $size-button-large-width;
max-width: $size-zen-btn-max-width;
height: $size-button-zen-height !important;
transition: all $duration-normal cubic-bezier(0.25, 0.8, 0.5, 1);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
&:hover:not(:disabled) {
transform: translateY(-0.125rem);
background-color: rgba($color-text-white, 0.08) !important;
box-shadow: $shadow-md;
}
&.zen-disabled {
opacity: $opacity-inactive;
background-color: color.scale($color-surface, $lightness: 10%) !important;
border-color: $color-stroke-inactive !important;
box-shadow: none;
}
@media (max-width: $breakpoint-sm) {
height: auto !important;
padding: $spacing-sm !important;
min-height: $size-button-zen-height;
width: 100%;
max-width: 100%;
.zen-btn-content {
flex-wrap: wrap;
justify-content: flex-start;
}
.zen-counter {
margin-left: 0 !important;
margin-top: $spacing-xs;
flex-basis: 100%;
max-width: 100%;
justify-content: center;
height: 1.75rem;
}
.d-flex.flex-column {
flex-basis: auto;
flex-grow: 1;
}
}
}
.zen-counter {
@include flex-center;
font-size: $font-sm;
font-weight: $weight-black;
height: $size-icon-btn;
min-width: $size-icon-btn;
padding: 0 calc($spacing-md * 0.75);
border-radius: $radius-xl;
}
.line-height-tight {
line-height: $leading-tight;
margin-bottom: $spacing-2xs;
}
.opacity-80 {
opacity: $opacity-hover;
}
.letter-spacing-small {
letter-spacing: $tracking-tighter;
}
.letter-spacing-1 {
letter-spacing: 0.09375rem;
}

View File

@@ -0,0 +1,8 @@
@use 'widget-welcome';
@use 'widget-heatmap';
@use 'widget-ghosts';
@use 'widget-distribution';
@use 'widget-streak';
@use 'widget-forecast';
@use 'widget-accuracy';
@use 'widget-guru-mastery';

View File

@@ -0,0 +1,2 @@
@use 'kanji-canvas';
@use 'kanji-svg-viewer';

View File

@@ -0,0 +1,55 @@
@use '../../abstracts' as *;
.canvas-container {
position: relative;
@include flex-center;
}
.canvas-wrapper {
position: relative;
width: $size-canvas;
height: $size-canvas;
background: $color-surface;
border-radius: $radius-lg;
border: $border-width-sm solid $color-border;
box-shadow: $shadow-inset;
overflow: hidden;
cursor: crosshair;
display: flex;
align-items: center;
justify-content: center;
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
touch-action: none;
z-index: $z-above;
}
}
@keyframes shake-x {
0%,
100% {
transform: translateX(0);
}
20% {
transform: translateX(-0.375rem);
}
40% {
transform: translateX(0.375rem);
}
60% {
transform: translateX(-0.375rem);
}
80% {
transform: translateX(0.375rem);
}
}
.shake {
animation: shake-x 0.4s ease-in-out;
border-color: $color-danger !important;
}

View File

@@ -1,7 +1,19 @@
@use '../abstracts/variables' as *;
@use '../abstracts/mixins' as *;
@use '../../abstracts' as *;
@use 'sass:color';
.svg-container {
width: 100%;
height: 100%;
position: relative;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: $color-surface;
border-radius: $radius-lg;
border: $border-width-sm solid $color-border;
box-shadow: $shadow-inset;
@mixin grid-overlay {
&::before,
&::after {
content: '';
@@ -15,78 +27,26 @@
&::before {
top: 50%;
left: 10px;
right: 10px;
border-top-width: 1px;
left: $size-play-btn-offset;
right: $size-play-btn-offset;
border-top-width: $border-width-sm;
}
&::after {
left: 50%;
top: 10px;
bottom: 10px;
border-left-width: 1px;
top: $size-play-btn-offset;
bottom: $size-play-btn-offset;
border-left-width: $border-width-sm;
}
}
.canvas-container {
position: relative;
@include flex-center;
}
// The main drawing canvas wrapper
.canvas-wrapper {
position: relative;
width: $size-canvas;
height: $size-canvas;
background: $color-surface;
border-radius: $radius-lg;
border: $border-subtle;
box-shadow: $shadow-inset;
overflow: hidden;
cursor: crosshair;
display: flex;
align-items: center;
justify-content: center;
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
touch-action: none;
z-index: $z-above;
}
}
// The SVG Viewer wrapper (Review/Lesson/Collection)
.svg-container {
width: 100%;
height: 100%;
position: relative;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
// --- Unified Styles to match Canvas ---
background: $color-surface;
border-radius: $radius-lg; // Matches canvas-wrapper
border: $border-subtle; // Matches canvas-wrapper
box-shadow: $shadow-inset; // Matches canvas-wrapper
// -------------------------------------
@include grid-overlay;
&.hero-mode {
background: linear-gradient(145deg, $color-surface, #18181b);
border: 2px solid $color-border;
box-shadow: 0 4px 20px rgb(0 0 0 / 40%);
background: linear-gradient(145deg, $color-surface, $color-zinc-900);
border: $border-width-md solid $color-border;
box-shadow: 0 0.25rem 1.25rem hsl(0deg 0% 0% / 40%);
.stroke-path.drawn {
stroke: $color-text-white;
filter: drop-shadow(0 0 2px rgb(255 255 255 / 25%));
filter: drop-shadow(0 0 0.125rem hsl(0deg 0% 100% / 25%));
}
&::before,
@@ -110,17 +70,15 @@
stroke-linejoin: round;
stroke-width: $stroke-width-main;
transition:
stroke 0.3s ease,
opacity 0.3s ease;
stroke $duration-normal ease,
opacity $duration-normal ease;
&.drawn {
stroke: $color-stroke-drawn;
}
&.hidden {
opacity: 0;
}
&.animating {
stroke: $color-primary;
stroke-dasharray: var(--len);
@@ -136,18 +94,18 @@
stroke-linecap: round;
stroke-linejoin: round;
opacity: 0.5;
stroke-dasharray: 10 15;
stroke-dasharray: 0.625rem 0.9375rem;
}
.stroke-badge-group {
filter: drop-shadow(0 1px 2px rgb(0 0 0 / 50%));
filter: drop-shadow(0 0.0625rem 0.125rem hsl(0deg 0% 0% / 50%));
pointer-events: none;
}
.stroke-badge-bg {
fill: $color-primary;
opacity: 0.9;
transition: transform 0.2s ease;
transition: transform $duration-fast ease;
}
.stroke-badge-text {
@@ -168,34 +126,31 @@
stroke-linecap: round;
stroke-linejoin: round;
pointer-events: none;
filter: drop-shadow(0 0 2px rgb(0 0 0 / 50%));
filter: drop-shadow(0 0 0.125rem hsl(0deg 0% 0% / 50%));
}
.play-btn {
position: absolute;
top: 10px;
right: 10px;
top: $size-play-btn-offset;
right: $size-play-btn-offset;
width: $size-icon-btn;
height: $size-icon-btn;
border-radius: $radius-circle;
background: rgb(255 255 255 / 10%);
border: 1px solid rgba($color-primary, 0.3);
background: $bg-glass-strong;
border: 1px solid color.change($color-primary, $alpha: 0.3);
color: $color-primary;
@include flex-center;
cursor: pointer;
z-index: $z-play-btn;
transition: all 0.2s ease;
transition: all $duration-fast ease;
&:hover {
transform: scale(1.05);
background: rgba($color-primary, 0.2);
background: color.change($color-primary, $alpha: 0.2);
}
svg {
width: 18px;
height: 18px;
width: $size-icon-small;
height: $size-icon-small;
}
}
@@ -204,31 +159,3 @@
stroke-dashoffset: 0;
}
}
@keyframes shake-x {
0%,
100% {
transform: translateX(0);
}
20% {
transform: translateX(-6px);
}
40% {
transform: translateX(6px);
}
60% {
transform: translateX(-6px);
}
80% {
transform: translateX(6px);
}
}
.shake {
animation: shake-x 0.4s ease-in-out;
border-color: $color-danger !important;
}