feat: replace loading spinners with skeletons
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { Stack } from "@mantine/core";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
|
||||
type LoadingSkeletonProps = PropsWithChildren<{
|
||||
label: string;
|
||||
}>;
|
||||
|
||||
const LoadingSkeleton: FC<LoadingSkeletonProps> = (props) => {
|
||||
const { children, label } = props;
|
||||
|
||||
return (
|
||||
<Stack aria-busy="true" aria-label={label} gap="md" role="status">
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export { LoadingSkeleton };
|
||||
@@ -1,21 +1,25 @@
|
||||
import { MantineProvider } from "@mantine/core";
|
||||
import { cleanup, render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { LoadingSkeleton } from "./LoadingSkeleton";
|
||||
import { StateView } from "./StateView";
|
||||
|
||||
describe("StateView", () => {
|
||||
afterEach(cleanup);
|
||||
|
||||
it("renders an accessible loading state with a loader", () => {
|
||||
it("renders an accessible structural loading region", () => {
|
||||
render(
|
||||
<MantineProvider>
|
||||
<StateView loading text="Пожалуйста, подождите." title="Загрузка" />
|
||||
<LoadingSkeleton label="Загрузка">
|
||||
<div />
|
||||
</LoadingSkeleton>
|
||||
</MantineProvider>,
|
||||
);
|
||||
|
||||
const status = screen.getByRole("status");
|
||||
expect(status).toHaveTextContent("Загрузка");
|
||||
expect(screen.getByLabelText("Загрузка")).toBeInTheDocument();
|
||||
expect(screen.getByRole("status", { name: "Загрузка" })).toHaveAttribute(
|
||||
"aria-busy",
|
||||
"true",
|
||||
);
|
||||
});
|
||||
|
||||
it("renders an accessible error state", () => {
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import { Button, Loader, Paper, Stack, Text, Title } from "@mantine/core";
|
||||
import { Button, Paper, Stack, Text, Title } from "@mantine/core";
|
||||
import type { FC, ReactNode } from "react";
|
||||
|
||||
type StateViewProps = {
|
||||
title: string;
|
||||
text: string;
|
||||
action?: ReactNode;
|
||||
loading?: boolean;
|
||||
error?: boolean;
|
||||
};
|
||||
|
||||
const StateView: FC<StateViewProps> = (props) => {
|
||||
const { title, text, action, loading = false, error = false } = props;
|
||||
const role = loading ? "status" : error ? "alert" : undefined;
|
||||
const { title, text, action, error = false } = props;
|
||||
const role = error ? "alert" : undefined;
|
||||
|
||||
return (
|
||||
<Paper p="xl" radius="md" shadow="xs" withBorder role={role}>
|
||||
<Stack align="flex-start" gap="sm">
|
||||
{loading ? <Loader aria-label={title} size="sm" /> : null}
|
||||
<Title order={2}>{title}</Title>
|
||||
<Text c="dimmed">{text}</Text>
|
||||
{action}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export { AppShell } from "./AppShell";
|
||||
export { LoadingSkeleton } from "./LoadingSkeleton";
|
||||
export { Button, StateView } from "./StateView";
|
||||
|
||||
Reference in New Issue
Block a user