add new lesson mode and started code refraction
This commit is contained in:
@@ -6,13 +6,32 @@ $color-surface-light: hsl(221deg 17% 22%);
|
||||
$color-text-white: hsl(0deg 0% 100%);
|
||||
$color-text-grey: hsl(213deg 14% 70%);
|
||||
$color-border: hsl(0deg 0% 100% / 8%);
|
||||
$color-zinc-900: #18181b;
|
||||
$color-reading-box: rgb(255 255 255 / 3%);
|
||||
$color-stroke-drawn: #a1a1aa;
|
||||
$color-srs-1: hsl(0deg 100% 73%);
|
||||
$color-srs-2: hsl(39deg 98% 71%);
|
||||
$color-srs-3: hsl(163deg 85% 64%);
|
||||
$color-srs-4: hsl(206deg 92% 46%);
|
||||
$color-srs-5: hsl(244deg 100% 82%);
|
||||
$color-srs-6: hsl(247deg 72% 63%);
|
||||
$color-srs-7: $color-primary;
|
||||
$color-srs-8: hsl(339deg 97% 73%);
|
||||
$color-srs-9: hsl(331deg 78% 59%);
|
||||
$color-srs-10: hsl(51deg 100% 50%);
|
||||
$color-danger: hsl(0deg 85% 65%);
|
||||
$color-success: hsl(160deg 80% 45%);
|
||||
$color-stroke-inactive: hsl(0deg 0% 33%);
|
||||
$color-dot-base: hsl(0deg 0% 27%);
|
||||
$srs-colors: (
|
||||
1: $color-srs-1,
|
||||
2: $color-srs-2,
|
||||
3: $color-srs-3,
|
||||
4: $color-srs-4,
|
||||
5: $color-srs-5,
|
||||
6: $color-srs-6,
|
||||
7: $color-srs-7,
|
||||
8: $color-srs-8,
|
||||
9: $color-srs-9,
|
||||
10: $color-srs-10
|
||||
);
|
||||
|
||||
@@ -18,6 +18,9 @@ $z-dropdown: 50;
|
||||
$z-modal: 100;
|
||||
$z-tooltip: 200;
|
||||
$z-above: 2;
|
||||
|
||||
// Neue Z-Indizes aus dem Refactoring
|
||||
$z-play-btn: 10;
|
||||
$size-canvas: 300px;
|
||||
$size-kanji-preview: 200px;
|
||||
$size-icon-btn: 32px;
|
||||
@@ -26,12 +29,6 @@ $stroke-width-main: 3px;
|
||||
$stroke-width-arrow: 2px;
|
||||
$font-size-svg-number: 5px;
|
||||
$radius-xs: 2px;
|
||||
$radius-sm: 4px;
|
||||
$radius-md: 8px;
|
||||
$radius-lg: 12px;
|
||||
$radius-xl: 24px;
|
||||
$radius-pill: 999px;
|
||||
$radius-circle: 50%;
|
||||
$size-legend-box: 12px;
|
||||
$size-streak-dot: 24px;
|
||||
$size-srs-track: 24px;
|
||||
@@ -44,3 +41,14 @@ $padding-page-x: 24px;
|
||||
$breakpoint-md: 960px;
|
||||
$offset-fab: 20px;
|
||||
$size-heatmap-cell-height: 10px;
|
||||
$stroke-width-kanji: 6px;
|
||||
$opacity-kanji-hint: 0.5;
|
||||
$dash-kanji-hint: 10px 15px;
|
||||
|
||||
// --- NEUE VARIABLEN (Wichtig!) ---
|
||||
$size-hero-wrapper: 140px;
|
||||
$size-lesson-card-width: 450px;
|
||||
$size-lesson-card-min-height: 500px;
|
||||
$size-avatar-small: 32px;
|
||||
$size-button-large-height: 70px;
|
||||
$size-button-large-width: 280px;
|
||||
|
||||
@@ -1,23 +1,53 @@
|
||||
@use '../abstracts/variables' as *;
|
||||
@use '../abstracts/mixins' as *;
|
||||
|
||||
@mixin grid-overlay {
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border-color: $color-border;
|
||||
border-style: dashed;
|
||||
border-width: 0;
|
||||
z-index: $z-normal;
|
||||
}
|
||||
|
||||
&::before {
|
||||
top: 50%;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
&::after {
|
||||
left: 50%;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.canvas-container {
|
||||
position: relative;
|
||||
|
||||
@include flex-center;
|
||||
|
||||
margin-bottom: $spacing-xl;
|
||||
}
|
||||
|
||||
// The main drawing canvas wrapper
|
||||
.canvas-wrapper {
|
||||
position: relative;
|
||||
width: $size-canvas;
|
||||
height: $size-canvas;
|
||||
background: $color-surface;
|
||||
border-radius: $radius-lg;
|
||||
background: rgba($color-surface, 0.95);
|
||||
border: $border-width-md solid $color-surface-light;
|
||||
position: relative;
|
||||
cursor: crosshair;
|
||||
border: $border-subtle;
|
||||
box-shadow: $shadow-inset;
|
||||
overflow: hidden;
|
||||
cursor: crosshair;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
canvas {
|
||||
position: absolute;
|
||||
@@ -26,39 +56,66 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
touch-action: none;
|
||||
z-index: $z-above;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
position: absolute;
|
||||
color: $color-text-grey;
|
||||
z-index: $z-sticky;
|
||||
font-size: $font-sm;
|
||||
font-weight: $weight-medium;
|
||||
letter-spacing: $tracking-wide;
|
||||
// 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%);
|
||||
|
||||
.stroke-path.drawn {
|
||||
stroke: $color-text-white;
|
||||
filter: drop-shadow(0 0 2px rgb(255 255 255 / 25%));
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.svg-container {
|
||||
width: $size-kanji-preview;
|
||||
height: $size-kanji-preview;
|
||||
margin: 0 auto $spacing-lg;
|
||||
background: rgba($color-bg-dark, 0.2);
|
||||
border-radius: $radius-md;
|
||||
border: $border-subtle;
|
||||
position: relative;
|
||||
|
||||
@include flex-center;
|
||||
|
||||
overflow: hidden;
|
||||
.kanji-svg {
|
||||
z-index: $z-above;
|
||||
display: block;
|
||||
padding: 12%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.stroke-path {
|
||||
fill: none;
|
||||
stroke: $color-stroke-inactive;
|
||||
stroke-width: $stroke-width-main;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
transition: stroke $duration-normal;
|
||||
stroke-width: $stroke-width-main;
|
||||
transition:
|
||||
stroke 0.3s ease,
|
||||
opacity 0.3s ease;
|
||||
|
||||
&.drawn {
|
||||
stroke: $color-stroke-drawn;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
opacity: 0;
|
||||
@@ -70,10 +127,75 @@
|
||||
stroke-dashoffset: var(--len);
|
||||
animation: draw-stroke var(--duration) linear forwards;
|
||||
}
|
||||
}
|
||||
|
||||
&.drawn {
|
||||
stroke: $color-text-white;
|
||||
opacity: 1;
|
||||
.stroke-ghost {
|
||||
fill: none;
|
||||
stroke: $color-stroke-inactive;
|
||||
stroke-width: $stroke-width-main;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
opacity: 0.5;
|
||||
stroke-dasharray: 10 15;
|
||||
}
|
||||
|
||||
.stroke-badge-group {
|
||||
filter: drop-shadow(0 1px 2px rgb(0 0 0 / 50%));
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.stroke-badge-bg {
|
||||
fill: $color-primary;
|
||||
opacity: 0.9;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.stroke-badge-text {
|
||||
fill: $color-bg-dark;
|
||||
font-size: $font-size-svg-number;
|
||||
font-family: sans-serif;
|
||||
font-weight: $weight-black;
|
||||
user-select: none;
|
||||
text-anchor: middle;
|
||||
dominant-baseline: central;
|
||||
}
|
||||
|
||||
.stroke-arrow-line {
|
||||
fill: none;
|
||||
stroke: $color-primary;
|
||||
stroke-width: 1.5px;
|
||||
vector-effect: non-scaling-stroke;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
pointer-events: none;
|
||||
filter: drop-shadow(0 0 2px rgb(0 0 0 / 50%));
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
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);
|
||||
color: $color-primary;
|
||||
|
||||
@include flex-center;
|
||||
|
||||
cursor: pointer;
|
||||
z-index: $z-play-btn;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
background: rgba($color-primary, 0.2);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,65 +205,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
.stroke-start-circle {
|
||||
fill: $color-srs-1;
|
||||
}
|
||||
|
||||
.stroke-number {
|
||||
fill: $color-text-white;
|
||||
font-size: $font-size-svg-number;
|
||||
font-family: $font-family-sans;
|
||||
font-weight: $weight-bold;
|
||||
text-anchor: middle;
|
||||
dominant-baseline: middle;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.stroke-arrow-line {
|
||||
fill: none;
|
||||
stroke: rgba($color-secondary, 0.7);
|
||||
stroke-width: $stroke-width-arrow;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
color: $color-text-grey;
|
||||
font-size: $font-sm;
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
position: absolute;
|
||||
top: $spacing-sm;
|
||||
right: $spacing-sm;
|
||||
background: rgba($color-bg-dark, 0.3);
|
||||
border: $border-width-sm solid rgba($color-primary, 0.5);
|
||||
color: $color-primary;
|
||||
border-radius: $radius-circle;
|
||||
width: $size-icon-btn;
|
||||
height: $size-icon-btn;
|
||||
|
||||
@include flex-center;
|
||||
|
||||
cursor: pointer;
|
||||
transition: all $duration-fast ease;
|
||||
z-index: $z-sticky;
|
||||
backdrop-filter: $blur-sm;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
background: $color-primary;
|
||||
color: $color-bg-dark;
|
||||
border-color: $color-primary;
|
||||
box-shadow: $shadow-glow-base;
|
||||
@keyframes shake-x {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
20% {
|
||||
transform: translateX(-6px);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: $size-icon-small;
|
||||
height: $size-icon-small;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -6,26 +6,27 @@
|
||||
@include card-base;
|
||||
|
||||
border: $border-subtle;
|
||||
background-color: $color-surface !important;
|
||||
border-radius: $radius-xl !important;
|
||||
}
|
||||
|
||||
.level-0 {
|
||||
background-color: $bg-glass-subtle;
|
||||
.welcome-btn {
|
||||
height: $size-button-large-height !important;
|
||||
width: $size-button-large-width !important;
|
||||
|
||||
.v-chip {
|
||||
color: white !important;
|
||||
background-color: $color-surface !important;
|
||||
}
|
||||
}
|
||||
|
||||
.level-1 {
|
||||
background-color: color.mix($color-primary, $color-surface, 25%);
|
||||
.streak-shield-avatar {
|
||||
border: 1px solid currentcolor;
|
||||
background: rgb(255 255 255 / 5%);
|
||||
}
|
||||
|
||||
.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%);
|
||||
.streak-day-label {
|
||||
font-size: 9px !important;
|
||||
}
|
||||
|
||||
.heatmap-container {
|
||||
@@ -72,6 +73,26 @@
|
||||
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;
|
||||
@@ -153,22 +174,16 @@
|
||||
@include scrollbar;
|
||||
}
|
||||
|
||||
.gap-1 {
|
||||
gap: $spacing-xs;
|
||||
.srs-chart-container {
|
||||
gap: 8px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: $spacing-sm;
|
||||
}
|
||||
|
||||
.border-subtle {
|
||||
border: $border-subtle;
|
||||
}
|
||||
|
||||
.border-b-subtle {
|
||||
border-bottom: $border-subtle;
|
||||
}
|
||||
|
||||
.border-t-subtle {
|
||||
border-top: $border-subtle;
|
||||
.srs-track {
|
||||
@media (max-width: 400px) {
|
||||
width: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,3 +8,4 @@
|
||||
@use 'pages/dashboard';
|
||||
@use 'pages/review';
|
||||
@use 'pages/collection';
|
||||
@use 'pages/lesson';
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
:root {
|
||||
--v-theme-background: #{$color-bg-dark};
|
||||
--color-surface: #{$color-surface};
|
||||
|
||||
@each $level, $color in $srs-colors {
|
||||
--srs-#{$level}: #{$color};
|
||||
}
|
||||
}
|
||||
|
||||
body,
|
||||
@@ -59,3 +64,13 @@ html,
|
||||
opacity: $opacity-hover;
|
||||
}
|
||||
}
|
||||
|
||||
@each $level, $color in $srs-colors {
|
||||
.text-srs-#{$level} {
|
||||
color: var(--srs-#{$level}) !important;
|
||||
}
|
||||
|
||||
.bg-srs-#{$level} {
|
||||
background-color: var(--srs-#{$level}) !important;
|
||||
}
|
||||
}
|
||||
|
||||
78
client/src/styles/pages/_lesson.scss
Normal file
78
client/src/styles/pages/_lesson.scss
Normal file
@@ -0,0 +1,78 @@
|
||||
@use '../abstracts/variables' as *;
|
||||
@use '../abstracts/mixins' as *;
|
||||
|
||||
.page-container-center {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: $spacing-md;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.lesson-card {
|
||||
width: 100%;
|
||||
max-width: $size-lesson-card-width;
|
||||
border-radius: $radius-xl !important;
|
||||
border: $border-subtle;
|
||||
background-color: $color-surface !important;
|
||||
min-height: $size-lesson-card-min-height;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hero-wrapper {
|
||||
width: $size-hero-wrapper;
|
||||
height: $size-hero-wrapper;
|
||||
}
|
||||
|
||||
.radical-section {
|
||||
width: 100%;
|
||||
background: $color-zinc-900;
|
||||
border-radius: $radius-md;
|
||||
padding: $spacing-md;
|
||||
margin-bottom: $spacing-lg;
|
||||
}
|
||||
|
||||
.radical-chip {
|
||||
border-radius: $radius-md;
|
||||
border: $border-subtle;
|
||||
background-color: #27272a;
|
||||
|
||||
img {
|
||||
filter: invert(1);
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.readings-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: $spacing-lg;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.reading-box {
|
||||
background: $color-reading-box;
|
||||
padding: $spacing-lg;
|
||||
border-radius: $radius-lg;
|
||||
text-align: center;
|
||||
|
||||
.label {
|
||||
font-size: $font-xs;
|
||||
color: #666;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: $spacing-xs;
|
||||
}
|
||||
|
||||
.val {
|
||||
font-size: 1.1rem;
|
||||
font-weight: $weight-bold;
|
||||
}
|
||||
}
|
||||
|
||||
.lesson-canvas-wrapper {
|
||||
margin: 0 auto;
|
||||
}
|
||||
@@ -1,21 +1,25 @@
|
||||
@use '../abstracts/variables' as *;
|
||||
@use '../abstracts/mixins' as *;
|
||||
|
||||
.review-card {
|
||||
border: $border-subtle;
|
||||
background-color: $color-surface !important;
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
.text-shadow {
|
||||
text-shadow: $text-shadow;
|
||||
}
|
||||
|
||||
.canvas-wrapper {
|
||||
.review-canvas-area {
|
||||
position: relative;
|
||||
width: $size-canvas;
|
||||
height: $size-canvas;
|
||||
border-radius: $radius-lg;
|
||||
background: $bg-glass-dark;
|
||||
box-shadow: $shadow-inset;
|
||||
margin-bottom: $spacing-sm;
|
||||
|
||||
.next-fab {
|
||||
position: absolute;
|
||||
bottom: -#{$offset-fab};
|
||||
right: -#{$offset-fab};
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: $z-sticky;
|
||||
}
|
||||
}
|
||||
@@ -45,3 +49,15 @@
|
||||
opacity: 0;
|
||||
transform: translateY(-#{$dist-slide-sm});
|
||||
}
|
||||
|
||||
.opacity-80 {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.gap-2 {
|
||||
gap: $spacing-sm;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user