|
9 | 9 | import { customCss } from '$lib/stores/customCss'; |
10 | 10 | import { siteCustomization } from '$lib/stores/siteCustomization'; |
11 | 11 | import { primaryColor } from '$lib/stores/primaryColor'; |
| 12 | + import { fontScale, fontScaleOptions, type FontScaleLevel } from '$lib/stores/fontScale'; |
12 | 13 | import { storage } from '$lib/utils/localStorage'; |
13 | 14 |
|
14 | 15 | interface Props { |
|
30 | 31 | let currentNavbarDisplay = $state(navbarDisplay); |
31 | 32 | let currentHomepageLayout = $state(homepageLayout); |
32 | 33 | let currentCustomCss = $state(customCss); |
| 34 | + let currentFontScale = $state(fontScale); |
33 | 35 |
|
34 | 36 | // Form inputs |
35 | 37 | let cssInput = $state(''); |
|
120 | 122 | navbarDisplay.setMode((e.currentTarget as HTMLSelectElement).value as NavbarDisplayMode), |
121 | 123 | homepageChange: (e: Event) => |
122 | 124 | homepageLayout.setMode((e.currentTarget as HTMLSelectElement).value as HomepageLayoutMode), |
| 125 | + fontScaleChange: (e: Event) => |
| 126 | + fontScale.setLevel(parseInt((e.currentTarget as HTMLInputElement).value, 10) as FontScaleLevel), |
123 | 127 | linkClick: () => onClose?.(), |
124 | 128 |
|
125 | 129 | applyCustomCss: () => { |
|
272 | 276 | {/if} |
273 | 277 | </div> |
274 | 278 |
|
| 279 | + {#if standalone} |
| 280 | + <div class="settings-section font-size-section"> |
| 281 | + <h3>Font Scale</h3> |
| 282 | + <div class="font-scale-slider"> |
| 283 | + <input |
| 284 | + type="range" |
| 285 | + min="0" |
| 286 | + max="4" |
| 287 | + step="1" |
| 288 | + value={$currentFontScale} |
| 289 | + oninput={handlers.fontScaleChange} |
| 290 | + aria-label="Font scale" |
| 291 | + class="slider" |
| 292 | + /> |
| 293 | + <div class="slider-labels"> |
| 294 | + {#each fontScaleOptions as option (option.level)} |
| 295 | + <span class="slider-label" class:active={$currentFontScale === option.level}>{option.label}</span> |
| 296 | + {/each} |
| 297 | + </div> |
| 298 | + </div> |
| 299 | + </div> |
| 300 | + {/if} |
| 301 | + |
275 | 302 | <!-- Language Selection --> |
276 | 303 | <div class="settings-section language-section"> |
277 | 304 | <h3>Language</h3> |
|
548 | 575 | margin: 0; |
549 | 576 |
|
550 | 577 | &.theme-section { |
| 578 | + grid-row: span 3; |
| 579 | + } |
| 580 | + &.language-section { |
551 | 581 | grid-row: span 2; |
552 | 582 | } |
553 | 583 | &.accessibility-section { |
|
639 | 669 | color: var(--text-secondary); |
640 | 670 |
|
641 | 671 | &:hover:not(.disabled) { |
642 | | - background: var(--surface-hover); |
643 | 672 | border-color: var(--border-secondary); |
644 | 673 | } |
645 | | -
|
646 | | - &.active { |
647 | | - background: color-mix(in srgb, var(--color-primary), transparent 90%); |
648 | | - border-color: var(--color-primary); |
649 | | - color: var(--text-primary); |
650 | | - } |
651 | | -
|
652 | | - &.disabled { |
653 | | - opacity: 0.6; |
654 | | - cursor: not-allowed; |
655 | | - } |
656 | 674 | } |
657 | 675 |
|
658 | 676 | .theme-preview { |
|
662 | 680 | border: 1px solid var(--border-secondary); |
663 | 681 | } |
664 | 682 |
|
| 683 | + .font-scale-slider { |
| 684 | + display: flex; |
| 685 | + flex-direction: column; |
| 686 | + gap: var(--spacing-sm); |
| 687 | +
|
| 688 | + .slider { |
| 689 | + width: 100%; |
| 690 | + height: 0.375rem; |
| 691 | + background: linear-gradient(to right, var(--bg-tertiary) 0%, var(--border-primary) 50%, var(--bg-tertiary) 100%); |
| 692 | + border-radius: var(--radius-sm); |
| 693 | + outline: none; |
| 694 | + -webkit-appearance: none; |
| 695 | + appearance: none; |
| 696 | + cursor: pointer; |
| 697 | + position: relative; |
| 698 | +
|
| 699 | + &::-webkit-slider-thumb { |
| 700 | + -webkit-appearance: none; |
| 701 | + appearance: none; |
| 702 | + width: 1.25rem; |
| 703 | + height: 1.25rem; |
| 704 | + background: var(--color-primary); |
| 705 | + border: 2px solid var(--bg-secondary); |
| 706 | + border-radius: 50%; |
| 707 | + cursor: pointer; |
| 708 | + transition: all var(--transition-normal); |
| 709 | + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); |
| 710 | +
|
| 711 | + &:hover { |
| 712 | + transform: scale(1.1); |
| 713 | + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3); |
| 714 | + } |
| 715 | + } |
| 716 | +
|
| 717 | + &::-moz-range-thumb { |
| 718 | + width: 1.25rem; |
| 719 | + height: 1.25rem; |
| 720 | + background: var(--color-primary); |
| 721 | + border: 2px solid var(--bg-secondary); |
| 722 | + border-radius: 50%; |
| 723 | + cursor: pointer; |
| 724 | + transition: all var(--transition-normal); |
| 725 | + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); |
| 726 | +
|
| 727 | + &:hover { |
| 728 | + transform: scale(1.1); |
| 729 | + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3); |
| 730 | + } |
| 731 | + } |
| 732 | +
|
| 733 | + &:focus { |
| 734 | + &::-webkit-slider-thumb { |
| 735 | + outline: 2px solid var(--color-primary); |
| 736 | + outline-offset: 2px; |
| 737 | + } |
| 738 | + &::-moz-range-thumb { |
| 739 | + outline: 2px solid var(--color-primary); |
| 740 | + outline-offset: 2px; |
| 741 | + } |
| 742 | + } |
| 743 | + } |
| 744 | +
|
| 745 | + .slider-labels { |
| 746 | + display: flex; |
| 747 | + justify-content: space-between; |
| 748 | + font-size: var(--font-size-sm); |
| 749 | + color: var(--text-tertiary); |
| 750 | + margin-top: var(--spacing-xs); |
| 751 | +
|
| 752 | + .slider-label { |
| 753 | + flex: 1; |
| 754 | + text-align: center; |
| 755 | + transition: all var(--transition-fast); |
| 756 | + font-size: var(--font-size-xs); |
| 757 | +
|
| 758 | + &.active { |
| 759 | + color: var(--color-primary); |
| 760 | + font-weight: 500; |
| 761 | + } |
| 762 | +
|
| 763 | + &:first-child { |
| 764 | + text-align: left; |
| 765 | + } |
| 766 | + &:last-child { |
| 767 | + text-align: right; |
| 768 | + } |
| 769 | + } |
| 770 | + } |
| 771 | + } |
| 772 | +
|
665 | 773 | .language-dropdown { |
666 | 774 | gap: var(--spacing-xs); |
667 | 775 | display: grid; |
668 | 776 | grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); |
669 | 777 | } |
670 | 778 |
|
671 | | - .language-option { |
672 | | - padding: var(--spacing-sm); |
673 | | - background: var(--bg-tertiary); |
674 | | - border: 1px solid var(--border-primary); |
675 | | - border-radius: var(--radius-sm); |
676 | | - text-align: left; |
677 | | - cursor: pointer; |
678 | | - transition: all var(--transition-normal); |
679 | | - font-size: var(--font-size-sm); |
680 | | - color: var(--text-secondary); |
681 | | -
|
| 779 | + .language-option, |
| 780 | + .theme-option { |
682 | 781 | &:hover:not(.disabled) { |
683 | 782 | background: var(--surface-hover); |
684 | 783 | color: var(--text-primary); |
|
696 | 795 | } |
697 | 796 | } |
698 | 797 |
|
| 798 | + .language-option { |
| 799 | + padding: var(--spacing-sm); |
| 800 | + background: var(--bg-tertiary); |
| 801 | + border: 1px solid var(--border-primary); |
| 802 | + border-radius: var(--radius-sm); |
| 803 | + text-align: left; |
| 804 | + cursor: pointer; |
| 805 | + transition: all var(--transition-normal); |
| 806 | + font-size: var(--font-size-sm); |
| 807 | + color: var(--text-secondary); |
| 808 | + } |
| 809 | +
|
699 | 810 | .navbar-select-wrapper { |
700 | 811 | position: relative; |
701 | 812 | display: block; |
|
857 | 968 | overflow: hidden; |
858 | 969 | } |
859 | 970 |
|
860 | | - .show-more-btn { |
| 971 | + .show-more-btn, |
| 972 | + .custom-color-toggle { |
861 | 973 | display: flex; |
862 | 974 | align-items: center; |
863 | 975 | gap: var(--spacing-xs); |
864 | | - width: 100%; |
865 | 976 | padding: var(--spacing-sm); |
866 | 977 | background: transparent; |
867 | 978 | border: 1px solid var(--border-primary); |
|
870 | 981 | font-size: var(--font-size-xs); |
871 | 982 | cursor: pointer; |
872 | 983 | transition: all var(--transition-normal); |
873 | | - margin-top: var(--spacing-sm); |
874 | | - justify-content: center; |
875 | 984 |
|
876 | 985 | &:hover { |
877 | 986 | background: var(--surface-hover); |
878 | 987 | color: var(--text-primary); |
879 | 988 | border-color: var(--border-secondary); |
880 | 989 | } |
| 990 | + } |
| 991 | +
|
| 992 | + .show-more-btn { |
| 993 | + width: 100%; |
| 994 | + margin-top: var(--spacing-sm); |
| 995 | + justify-content: center; |
881 | 996 |
|
882 | 997 | &[aria-expanded='true'] { |
883 | 998 | color: var(--color-primary); |
|
1006 | 1121 |
|
1007 | 1122 | .custom-color-toggle { |
1008 | 1123 | flex: 1; |
1009 | | - display: flex; |
1010 | | - align-items: center; |
1011 | 1124 | justify-content: center; |
1012 | | - gap: var(--spacing-xs); |
1013 | 1125 | padding: var(--spacing-sm) var(--spacing-md); |
1014 | | - background: var(--bg-tertiary); |
1015 | | - border: 1px solid var(--border-primary); |
1016 | | - border-radius: var(--radius-sm); |
1017 | | - color: var(--text-secondary); |
1018 | 1126 | font-size: var(--font-size-sm); |
1019 | | - cursor: pointer; |
1020 | | - transition: all var(--transition-normal); |
1021 | | -
|
1022 | | - &:hover { |
1023 | | - background: var(--surface-hover); |
1024 | | - color: var(--text-primary); |
1025 | | - border-color: var(--border-secondary); |
1026 | | - } |
1027 | 1127 | } |
1028 | 1128 |
|
1029 | 1129 | .custom-color-inputs { |
|
0 commit comments