Skip to content

Commit 1557530

Browse files
authored
Merge pull request #221 from ITBooster-practice/feat/update-teams-page-skeletons-77
feature(web): добавлена скелетон карточка для team ( #77 )
2 parents 8dceb18 + a614bdc commit 1557530

File tree

10 files changed

+168
-17
lines changed

10 files changed

+168
-17
lines changed

apps/web/views/teams/lib/styles.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { cn } from '@repo/ui'
22

3+
export const teamPageGridClassName = 'grid gap-4 sm:grid-cols-2'
4+
35
export const teamPageHeaderClassName =
46
'mb-5 flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between'
57

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Skeleton } from '@repo/ui'
2+
3+
function TeamCardSkeleton() {
4+
return (
5+
<div className='flex h-[184px] w-full flex-col justify-center gap-4 rounded-[var(--radius-surface)] border border-border bg-card p-5'>
6+
{/* Icon + arrow */}
7+
<div className='flex items-start justify-between'>
8+
<Skeleton className='size-8 rounded-[calc(var(--radius-control)-2px)]' />
9+
<Skeleton className='size-4' />
10+
</div>
11+
12+
{/* Name + stats */}
13+
<div className='space-y-1.5'>
14+
<Skeleton className='h-5 w-2/5' />
15+
16+
<div className='flex flex-wrap items-center gap-x-4 gap-y-1'>
17+
<Skeleton className='h-4 w-20' />
18+
<Skeleton className='h-4 w-20' />
19+
</div>
20+
</div>
21+
22+
{/* Avatars */}
23+
<div className='flex items-center'>
24+
<div className='flex items-center -space-x-2'>
25+
{Array.from({ length: 4 }).map((_, i) => (
26+
<Skeleton key={i} className='size-6 rounded-full border-2 border-card' />
27+
))}
28+
</div>
29+
</div>
30+
</div>
31+
)
32+
}
33+
34+
export { TeamCardSkeleton }

apps/web/views/teams/ui/teams-page-view.tsx

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,23 @@
33
import { useRouter } from 'next/navigation'
44
import { useMemo } from 'react'
55

6-
import { Button, EmptyState, Skeleton } from '@repo/ui'
6+
import { Button, EmptyState } from '@repo/ui'
77
import { Plus, Users } from '@repo/ui/icons'
88

99
import { useTeamsList } from '@/shared/api/use-teams'
1010
import { ROUTES, teamRoutes } from '@/shared/config'
1111

1212
import { mapTeamListItemToTeamCardModel } from '../lib/mappers'
1313
import {
14+
teamPageGridClassName,
1415
teamPageHeaderClassName,
1516
teamPagePrimaryButtonClassName,
1617
teamPageSubtitleClassName,
1718
teamPageTitleClassName,
1819
} from '../lib/styles'
1920
import type { TeamCardModel } from '../model/types'
2021
import { TeamCard } from './team-card'
22+
import { TeamCardSkeleton } from './team-card-skeleton'
2123

2224
function TeamsPageView() {
2325
const router = useRouter()
@@ -56,19 +58,9 @@ function TeamsPageView() {
5658
</header>
5759

5860
{isLoading ? (
59-
<div
60-
className='grid gap-4 py-6 sm:grid-cols-2'
61-
data-testid='teams-page-skeleton'
62-
>
61+
<div className={teamPageGridClassName} data-testid='teams-page-skeleton'>
6362
{Array.from({ length: 4 }).map((_, index) => (
64-
<div
65-
key={`teams-skeleton-${index}`}
66-
className='space-y-3 rounded-[var(--radius-surface)] border border-border bg-card p-5'
67-
>
68-
<Skeleton className='h-6 w-40' />
69-
<Skeleton className='h-4 w-full' />
70-
<Skeleton className='h-4 w-28' />
71-
</div>
63+
<TeamCardSkeleton key={`teams-skeleton-${index}`} />
7264
))}
7365
</div>
7466
) : isError ? (
@@ -107,7 +99,7 @@ function TeamsPageView() {
10799
/>
108100
</div>
109101
) : (
110-
<section className='grid gap-4 sm:grid-cols-2'>
102+
<section className={teamPageGridClassName}>
111103
{sortedTeams.map((team) => (
112104
<TeamCard key={team.id} team={team} onOpen={handleOpenTeam} />
113105
))}

packages/ui/src/components/card.stories.tsx renamed to packages/ui/src/components/card/card.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
CardFooter,
99
CardAction,
1010
} from './card'
11-
import { Button } from './button'
11+
import { Button } from '../button'
1212

1313
const meta = {
1414
title: 'Shared/UI/Card',
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export {
2+
Card,
3+
CardHeader,
4+
CardFooter,
5+
CardTitle,
6+
CardAction,
7+
CardDescription,
8+
CardContent,
9+
} from './card'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { Skeleton } from './skeleton'
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import type { Meta, StoryObj } from '@storybook/react-vite'
2+
3+
import { Skeleton } from './skeleton'
4+
5+
const meta = {
6+
title: 'Shared/UI/Skeleton',
7+
component: Skeleton,
8+
tags: ['autodocs'],
9+
} satisfies Meta<typeof Skeleton>
10+
11+
export default meta
12+
type Story = StoryObj<typeof meta>
13+
14+
/** Строки текста — заголовок + параграф */
15+
export const TextLines: Story = {
16+
render: () => (
17+
<div className='flex flex-col gap-3'>
18+
<Skeleton className='h-6 w-48' />
19+
<div className='flex flex-col gap-2'>
20+
<Skeleton className='h-4 w-full' />
21+
<Skeleton className='h-4 w-4/5' />
22+
<Skeleton className='h-4 w-3/5' />
23+
</div>
24+
</div>
25+
),
26+
}
27+
28+
/** Аватар с именем */
29+
export const Avatar: Story = {
30+
render: () => (
31+
<div className='flex items-center gap-3'>
32+
<Skeleton className='size-10 rounded-full' />
33+
<div className='flex flex-col gap-1.5'>
34+
<Skeleton className='h-4 w-32' />
35+
<Skeleton className='h-3 w-20' />
36+
</div>
37+
</div>
38+
),
39+
}
40+
41+
/** Кнопки и бейджи */
42+
export const Controls: Story = {
43+
render: () => (
44+
<div className='flex flex-wrap items-center gap-2'>
45+
<Skeleton className='h-9 w-28 rounded-[var(--radius-control)]' />
46+
<Skeleton className='h-9 w-9 rounded-[var(--radius-control)]' />
47+
<Skeleton className='h-5 w-16 rounded-full' />
48+
<Skeleton className='h-5 w-20 rounded-full' />
49+
</div>
50+
),
51+
}
52+
53+
/** Сетка карточек */
54+
export const CardGrid: Story = {
55+
decorators: [
56+
(Story) => (
57+
<div style={{ width: '760px' }}>
58+
<Story />
59+
</div>
60+
),
61+
],
62+
render: () => (
63+
<div className='grid grid-cols-2 gap-4'>
64+
{Array.from({ length: 4 }).map((_, i) => (
65+
<div
66+
key={i}
67+
className='flex h-[184px] w-full flex-col justify-center gap-4 rounded-[var(--radius-surface)] border border-border bg-card p-5'
68+
>
69+
<div className='flex items-start justify-between'>
70+
<Skeleton className='size-8 rounded-[calc(var(--radius-control)-2px)]' />
71+
<Skeleton className='size-4' />
72+
</div>
73+
<div className='space-y-1.5'>
74+
<Skeleton className='h-5 w-2/5' />
75+
<div className='flex items-center gap-4'>
76+
<Skeleton className='h-4 w-20' />
77+
<Skeleton className='h-4 w-20' />
78+
</div>
79+
</div>
80+
<div className='flex items-center -space-x-2'>
81+
{Array.from({ length: 4 }).map((_, j) => (
82+
<Skeleton key={j} className='size-6 rounded-full border-2 border-card' />
83+
))}
84+
</div>
85+
</div>
86+
))}
87+
</div>
88+
),
89+
}
90+
91+
/** Список строк */
92+
export const RowList: Story = {
93+
decorators: [
94+
(Story) => (
95+
<div style={{ width: '600px' }}>
96+
<Story />
97+
</div>
98+
),
99+
],
100+
render: () => (
101+
<div className='rounded-[var(--radius-surface)] border border-border bg-card'>
102+
{Array.from({ length: 5 }).map((_, i) => (
103+
<div
104+
key={i}
105+
className='flex items-center gap-3 border-b border-border px-4 py-3 last:border-b-0'
106+
>
107+
<Skeleton className='h-4 w-14 shrink-0' />
108+
<Skeleton className='h-4 flex-1' />
109+
<Skeleton className='size-8 shrink-0 rounded-full' />
110+
</div>
111+
))}
112+
</div>
113+
),
114+
}
File renamed without changes.

packages/ui/tsconfig.storybook.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
"composite": true,
55
"outDir": "out-tsc/storybook",
66
"module": "esnext",
7-
"moduleResolution": "bundler",
8-
"jsx": "preserve"
7+
"moduleResolution": "bundler"
98
},
109
"exclude": [
1110
"src/**/*.spec.ts",

0 commit comments

Comments
 (0)