🎨(front) update theme and styles

Update theme customization hook and CalendarList styles
for improved visual consistency and dark mode support.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nathan Panchout
2026-01-25 20:35:14 +01:00
parent 8ce3848a6f
commit 4faa131878
2 changed files with 310 additions and 14 deletions

View File

@@ -12,12 +12,38 @@
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
&__section-title { &__toggle-btn {
font-size: 0.75rem; display: flex;
font-weight: 600; align-items: center;
gap: 0.25rem;
background: transparent;
border: none;
cursor: pointer;
padding: 0.25rem 0;
&:hover {
.calendar-list__section-title {
color: var(--c--theme--colors--greyscale-700);
}
}
}
&__toggle-icon {
font-size: 1.25rem;
color: var(--c--theme--colors--greyscale-600); color: var(--c--theme--colors--greyscale-600);
text-transform: uppercase; transition: transform 0.2s ease;
letter-spacing: 0.025em; transform: rotate(-90deg);
&--expanded {
transform: rotate(0deg);
}
}
&__section-title {
font-size: 0.875rem;
font-weight: 500;
color: var(--c--theme--colors--greyscale-800);
transition: color 0.15s;
} }
&__add-btn { &__add-btn {
@@ -46,19 +72,23 @@
&__items { &__items {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.25rem; gap: 0.125rem;
} }
&__item { &__item {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.5rem; gap: 0.5rem;
padding: 0.375rem 0.25rem; padding: 0.375rem 0.5rem;
border-radius: 4px; border-radius: 4px;
transition: background-color 0.15s; transition: background-color 0.15s;
&:hover { &:hover {
background-color: var(--c--theme--colors--greyscale-50); background-color: var(--c--theme--colors--greyscale-50);
.calendar-list__options-btn {
opacity: 1;
}
} }
// Override Cunningham checkbox styles for compact display // Override Cunningham checkbox styles for compact display
@@ -71,9 +101,16 @@
} }
} }
&__item-checkbox {
display: flex;
align-items: center;
gap: 0.25rem;
flex-shrink: 0;
}
&__color { &__color {
width: 0.75rem; width: 0.25rem;
height: 0.75rem; height: 1.25rem;
border-radius: 2px; border-radius: 2px;
flex-shrink: 0; flex-shrink: 0;
} }
@@ -81,12 +118,87 @@
&__name { &__name {
flex: 1; flex: 1;
font-size: 0.875rem; font-size: 0.875rem;
font-weight: 500;
color: var(--c--theme--colors--greyscale-800); color: var(--c--theme--colors--greyscale-800);
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
&__item-actions {
position: relative;
display: flex;
align-items: center;
}
&__options-btn {
display: flex;
align-items: center;
justify-content: center;
width: 1.5rem;
height: 1.5rem;
border: none;
background: transparent;
border-radius: 4px;
cursor: pointer;
color: var(--c--theme--colors--greyscale-500);
opacity: 0;
transition: opacity 0.15s, background-color 0.15s, color 0.15s;
&:hover {
background-color: var(--c--theme--colors--greyscale-200);
color: var(--c--theme--colors--greyscale-700);
}
.material-icons {
font-size: 1.125rem;
}
}
&__menu {
position: absolute;
top: 100%;
right: 0;
z-index: 100;
min-width: 140px;
background: white;
border: 1px solid var(--c--theme--colors--greyscale-200);
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
padding: 0.25rem 0;
margin-top: 0.25rem;
}
&__menu-item {
display: flex;
align-items: center;
gap: 0.5rem;
width: 100%;
padding: 0.5rem 0.75rem;
border: none;
background: transparent;
cursor: pointer;
font-size: 0.875rem;
color: var(--c--theme--colors--greyscale-700);
transition: background-color 0.15s;
&:hover {
background-color: var(--c--theme--colors--greyscale-50);
}
.material-icons {
font-size: 1rem;
}
&--danger {
color: var(--c--theme--colors--danger-500);
&:hover {
background-color: var(--c--theme--colors--danger-50);
}
}
}
&__badge { &__badge {
font-size: 0.625rem; font-size: 0.625rem;
padding: 0.125rem 0.375rem; padding: 0.125rem 0.375rem;
@@ -97,3 +209,188 @@
font-weight: 500; font-weight: 500;
} }
} }
// ============================================================================
// Calendar Modal Styles (for use with Cunningham Modal)
// ============================================================================
.calendar-modal {
&__content {
display: flex;
flex-direction: column;
gap: 1rem;
}
&__error {
margin-bottom: 8px;
padding: 12px 16px;
background-color: #fef2f2;
color: #dc2626;
border-radius: 8px;
font-size: 0.875rem;
border: 1px solid #fecaca;
}
&__success {
margin-bottom: 8px;
padding: 12px 16px;
background-color: #f0fdf4;
color: #16a34a;
border-radius: 8px;
font-size: 0.875rem;
border: 1px solid #bbf7d0;
}
&__field {
margin-bottom: 0;
}
&__label {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 8px;
font-weight: 500;
font-size: 0.875rem;
color: #374151;
.material-icons {
font-size: 1.125rem;
color: var(--c--theme--colors--greyscale-500);
}
}
&__colors {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
&__color-btn {
width: 32px;
height: 32px;
border: 3px solid transparent;
border-radius: 50%;
cursor: pointer;
transition: transform 0.15s, box-shadow 0.15s;
&:hover {
transform: scale(1.15);
}
&--selected {
border-color: #1f2937;
box-shadow: 0 0 0 2px white, 0 0 0 4px #9ca3af;
}
}
&__share-section {
margin-top: 0.5rem;
}
&__share-divider {
height: 1px;
background-color: var(--c--theme--colors--greyscale-200);
margin-bottom: 1rem;
}
&__share-input-row {
display: flex;
gap: 0.5rem;
align-items: flex-start;
> div:first-child {
flex: 1;
}
> button {
flex-shrink: 0;
margin-top: 0.25rem;
}
}
&__share-hint {
margin-top: 0.5rem;
font-size: 0.75rem;
color: var(--c--theme--colors--greyscale-500);
}
}
// ============================================================================
// Subscription URL Modal Styles
// ============================================================================
.subscription-modal {
display: flex;
flex-direction: column;
gap: 1rem;
&__description {
font-size: 0.875rem;
color: var(--c--theme--colors--greyscale-600);
margin: 0;
line-height: 1.5;
}
&__loading {
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
color: var(--c--theme--colors--greyscale-500);
font-size: 0.875rem;
}
&__url-container {
display: flex;
gap: 0.5rem;
align-items: stretch;
}
&__url-input {
flex: 1;
padding: 0.75rem;
border: 1px solid var(--c--theme--colors--greyscale-300);
border-radius: 4px;
font-family: monospace;
font-size: 0.75rem;
background-color: var(--c--theme--colors--greyscale-50);
color: var(--c--theme--colors--greyscale-700);
overflow: hidden;
text-overflow: ellipsis;
&:focus {
outline: none;
border-color: var(--c--theme--colors--primary-500);
}
}
&__warning {
display: flex;
align-items: flex-start;
gap: 0.5rem;
padding: 0.75rem;
background-color: #fef3c7;
border: 1px solid #fcd34d;
border-radius: 4px;
p {
margin: 0;
font-size: 0.75rem;
color: #92400e;
line-height: 1.4;
}
}
&__warning-icon {
color: #d97706;
font-size: 1.125rem;
flex-shrink: 0;
}
&__actions {
display: flex;
justify-content: flex-start;
padding-top: 0.5rem;
}
}

View File

@@ -1,5 +1,5 @@
import { useConfig } from "@/features/config/ConfigProvider"; import { useConfig } from "@/features/config/ConfigProvider";
import { ThemeCustomization } from "@/features/api/types"; import { ThemeCustomization, LocalizedRecord } from "@/features/api/types";
import { splitLocaleCode } from "@/features/i18n/utils"; import { splitLocaleCode } from "@/features/i18n/utils";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -7,10 +7,9 @@ export const useThemeCustomization = (key: keyof ThemeCustomization) => {
const { config } = useConfig(); const { config } = useConfig();
const { i18n } = useTranslation(); const { i18n } = useTranslation();
const language = splitLocaleCode(i18n.language).language; const language = splitLocaleCode(i18n.language).language;
const themeCustomization = config?.theme_customization?.[key]; const themeCustomization = config?.theme_customization?.[key] as LocalizedRecord | undefined;
return { return {
...themeCustomization?.default, ...(themeCustomization?.default ?? {}),
...(themeCustomization?.[language as keyof typeof themeCustomization] ?? ...(themeCustomization?.[language] ?? {}),
{}),
}; };
}; };