Compare commits

..

2 Commits

Author SHA1 Message Date
Anton
f7b611bbbe fix(frontend): prevent calendar loading layout shift
Some checks failed
CI / build-and-test (pull_request) Has been cancelled
2026-04-27 14:02:20 +03:00
55fc23ec64 Merge pull request 'fix frontend calendar race states' (#28) from codex/calendar-race-ui-fixes into main
Some checks failed
CI / build-and-test (push) Has been cancelled
Reviewed-on: #28
2026-04-27 09:32:39 +00:00
2 changed files with 47 additions and 14 deletions

View File

@@ -228,6 +228,25 @@ export function RacesPage(): JSX.Element {
}),
[races],
);
const statusMessage = useMemo(() => {
if (errorMessage && !isLoading) {
return errorMessage;
}
if (isLoading) {
return "Загружаем данные...";
}
if (viewMode === "calendar" && monthFilter === "") {
return "Выберите месяц, чтобы увидеть его крупным планом.";
}
return "";
}, [errorMessage, isLoading, monthFilter, viewMode]);
const statusClassName = [
"races-status__message",
!statusMessage ? "races-status__message--empty" : "",
errorMessage && !isLoading ? "races-status__message--error" : "",
]
.filter(Boolean)
.join(" ");
if (errorMessage && races.length === 0 && !isLoading) {
return (
@@ -301,21 +320,16 @@ export function RacesPage(): JSX.Element {
</div>
</section>
{errorMessage && !isLoading ? (
<p className="page__subtitle page__subtitle--error" role="alert" style={{ marginTop: "var(--space-4)" }}>
{errorMessage}
<div className="races-status" aria-live="polite">
<p
className={statusClassName}
role={errorMessage && !isLoading ? "alert" : undefined}
aria-busy={isLoading || undefined}
aria-hidden={!statusMessage || undefined}
>
{statusMessage || "\u00a0"}
</p>
) : null}
{viewMode === "calendar" && monthFilter === "" ? (
<p className="page__subtitle races-cal__filter-hint">Выберите месяц, чтобы увидеть его крупным планом.</p>
) : null}
{isLoading ? (
<p className="page__subtitle" aria-busy="true">
Загружаем данные...
</p>
) : null}
</div>
{viewMode === "list" ? (
<div className="race-lists">

View File

@@ -967,6 +967,25 @@ a {
margin-top: var(--space-6);
}
.races-status {
min-height: calc(var(--line-height-base) * var(--font-size-caption));
margin-top: var(--space-4);
}
.races-status__message {
margin: 0;
color: var(--color-text-muted);
font-size: var(--font-size-caption);
}
.races-status__message--empty {
visibility: hidden;
}
.races-status__message--error {
color: var(--color-danger);
}
.races-cal__filter-hint {
margin-top: var(--space-3);
color: var(--color-text-muted);