Skip to content

Commit 94cc0f4

Browse files
chore: update spinner to v4 design (#16603)
Update spinner to v4: - add new 32px size - update colour - add to `v4` test suite --------- Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
1 parent 8910b3a commit 94cc0f4

12 files changed

Lines changed: 130 additions & 42 deletions

File tree

packages/ui/src/elements/Hierarchy/ColumnBrowser/Column/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export const Column: React.FC<ColumnProps> = ({
8888

8989
{isLoading && (
9090
<div className={`${baseClass}__loading`}>
91-
<Spinner loadingText={null} size="small" />
91+
<Spinner loadingText={null} size="sm" />
9292
</div>
9393
)}
9494

packages/ui/src/elements/Hierarchy/Field/SelectedHierarchies.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export const SelectedHierarchies: React.FC<SelectedHierarchiesProps> = ({
126126
if (isInitialLoad) {
127127
return (
128128
<div className={`${baseClass}__loading`}>
129-
<Spinner size="small" />
129+
<Spinner size="sm" />
130130
</div>
131131
)
132132
}

packages/ui/src/elements/Hierarchy/Tree/TreeNode/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ export const TreeNode = ({
191191
</span>
192192
{isLoading && expanded && (
193193
<span className={`${baseClass}__loading`}>
194-
<Spinner loadingText={null} size="small" />
194+
<Spinner loadingText={null} size="sm" />
195195
</span>
196196
)}
197197
</div>

packages/ui/src/elements/Spinner/index.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
color: var(--color-icon-secondary);
77
}
88

9-
.spinner--small {
9+
.spinner--sm {
1010
gap: calc(var(--spacer-1) / 2);
1111
}
1212

13-
.spinner--small .spinner__text {
13+
.spinner--sm .spinner__text {
1414
font-size: var(--text-caption-font-size);
1515
}
1616
}

packages/ui/src/elements/Spinner/index.scss

Lines changed: 0 additions & 18 deletions
This file was deleted.

packages/ui/src/elements/Spinner/index.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,21 @@ export type SpinnerProps = {
1414
*/
1515
loadingText?: null | string
1616
/**
17-
* Size of the spinner
18-
* @default 'default'
17+
* Size of the spinner:
18+
* - sm: 16px icon
19+
* - md: 24px icon with smaller arc
20+
* - lg: 24px icon with larger arc
21+
* @default 'md'
1922
*/
20-
size?: 'default' | 'small'
23+
size?: 'lg' | 'md' | 'sm'
2124
}
2225

23-
export const Spinner: React.FC<SpinnerProps> = ({ loadingText, size = 'default' }) => {
26+
export const Spinner: React.FC<SpinnerProps> = ({ loadingText, size = 'md' }) => {
2427
const { t } = useTranslation()
2528

2629
return (
2730
<div className={[baseClass, `${baseClass}--${size}`].filter(Boolean).join(' ')}>
28-
<SpinnerIcon size={size === 'small' ? 16 : 24} />
31+
<SpinnerIcon size={size} />
2932

3033
{loadingText !== null && (
3134
<span className={`${baseClass}__text`}>{loadingText || `${t('general:loading')}...`}</span>

packages/ui/src/icons/Spinner/index.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@layer payload-default {
22
.icon--spinner {
3+
color: var(--color-icon-secondary);
34
animation: spinner-spin 0.6s linear infinite;
45
}
56

packages/ui/src/icons/Spinner/index.tsx

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,35 @@ import React from 'react'
33
import './index.css'
44

55
const paths = {
6-
16: 'M10.778 3.842a5 5 0 0 0-2.279-.817A.54.54 0 0 1 8 2.5a.47.47 0 0 1 .5-.48A6 6 0 1 1 2.02 8.5.47.47 0 0 1 2.5 8c.276 0 .497.224.525.499a5 5 0 1 0 7.753-4.657',
7-
24: 'M15.333 7.011a6 6 0 0 0-2.834-.99A.534.534 0 0 1 12 5.5c0-.276.224-.502.5-.482A7 7 0 1 1 5.018 12.5.473.473 0 0 1 5.5 12c.276 0 .498.224.52.5a6 6 0 1 0 9.313-5.489',
6+
// 16px spinner (sm) - from @figma/fpl-icons Icon16Spinner
7+
sm: 'M10.778 3.842a5 5 0 0 0-2.279-.817A.54.54 0 0 1 8 2.5a.47.47 0 0 1 .5-.48A6 6 0 1 1 2.02 8.5.47.47 0 0 1 2.5 8c.276 0 .497.224.525.499a5 5 0 1 0 7.753-4.657',
8+
// 24px spinner (md) - from @figma/fpl-icons Icon24Spinner
9+
md: 'M15.333 7.011a6 6 0 0 0-2.834-.99A.534.534 0 0 1 12 5.5c0-.276.224-.502.5-.482A7 7 0 1 1 5.018 12.5.473.473 0 0 1 5.5 12c.276 0 .498.224.52.5a6 6 0 1 0 9.313-5.489',
10+
// 24px spinner large (lg) - from @figma/fpl-icons Icon24SpinnerLarge
11+
lg: 'M16.445 5.348A8 8 0 0 0 12.5 4.016.525.525 0 0 1 12 3.5a.48.48 0 0 1 .5-.486A9 9 0 1 1 3.014 12.5.48.48 0 0 1 3.5 12c.276 0 .498.224.516.5a8 8 0 1 0 12.429-7.152',
12+
}
13+
14+
const sizes = {
15+
lg: 24,
16+
md: 24,
17+
sm: 16,
818
}
919

1020
export type SpinnerIconProps = {
1121
readonly className?: string
12-
readonly size?: 16 | 24
22+
readonly size?: 'lg' | 'md' | 'sm'
1323
}
1424

15-
export const SpinnerIcon: React.FC<SpinnerIconProps> = ({ className, size = 16 }) => {
25+
export const SpinnerIcon: React.FC<SpinnerIconProps> = ({ className, size = 'sm' }) => {
26+
const dimension = sizes[size]
27+
1628
return (
1729
<svg
1830
className={['icon icon--spinner', className].filter(Boolean).join(' ')}
1931
fill="none"
20-
height={size}
21-
viewBox={`0 0 ${size} ${size}`}
22-
width={size}
32+
height={dimension}
33+
viewBox={`0 0 ${dimension} ${dimension}`}
34+
width={dimension}
2335
xmlns="http://www.w3.org/2000/svg"
2436
>
2537
<path clipRule="evenodd" d={paths[size]} fill="currentColor" fillRule="evenodd" />

test/v4/baseConfig.ts

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import type { CollectionConfig, Config } from 'payload'
2-
3-
import fs from 'fs'
1+
import fs from 'node:fs/promises'
42
import { fileURLToPath } from 'node:url'
53
import path from 'path'
4+
import { type CollectionConfig, type Config } from 'payload'
65

76
import { resetDB } from '../__helpers/shared/clearAndSeed/reset.js'
87
import { devUser } from '../credentials.js'
@@ -11,13 +10,26 @@ import {
1110
blocksFieldsSlug,
1211
collectionSlugs,
1312
relationshipFieldsSlug,
13+
richTextFieldsSlug,
1414
tagsSlug,
1515
textFieldsSlug,
16+
uploadsSlug,
1617
} from './slugs.js'
1718

1819
const filename = fileURLToPath(import.meta.url)
1920
const dirname = path.dirname(filename)
2021

22+
// Load file at module level, manually construct to avoid file-type dynamic import issue
23+
const imagePath = path.resolve(dirname, '../lexical/collections/Upload/payload.jpg')
24+
const imageData = await fs.readFile(imagePath)
25+
const imageStat = await fs.stat(imagePath)
26+
const imageFile = {
27+
name: path.basename(imagePath),
28+
data: imageData,
29+
mimetype: 'image/jpeg',
30+
size: imageStat.size,
31+
}
32+
2133
import ArrayFields from './collections/Array/index.js'
2234
import Autosave from './collections/Autosave/index.js'
2335
import BlocksFields from './collections/Blocks/index.js'
@@ -47,6 +59,13 @@ import TextareaFields from './collections/Textarea/index.js'
4759
import Rubbish from './collections/Trash/index.js'
4860
import Uploads from './collections/Upload/index.js'
4961
import UploadFields from './collections/UploadField/index.js'
62+
import {
63+
codeContent,
64+
getRichTextContent,
65+
getTypographyContent,
66+
listsContent,
67+
tableContent,
68+
} from './seed/richTextData.js'
5069

5170
export const collections: CollectionConfig[] = [
5271
{
@@ -151,6 +170,45 @@ export const baseConfig: Partial<Config> = {
151170
createdPosts.push(created)
152171
}
153172

173+
const richTextCount = await payload.count({ collection: richTextFieldsSlug })
174+
if (richTextCount.totalDocs === 0) {
175+
const uploadDoc = await payload.create({
176+
collection: uploadsSlug,
177+
data: { alt: 'Farming image' },
178+
file: imageFile,
179+
})
180+
181+
const formattedUploadID =
182+
payload.db.defaultIDType === 'number' ? uploadDoc.id : `"${uploadDoc.id}"`
183+
184+
const devUserDoc = await payload.find({
185+
collection: 'users',
186+
where: { email: { equals: devUser.email } },
187+
limit: 1,
188+
})
189+
const userId = devUserDoc.docs[0]?.id
190+
const formattedUserID =
191+
userId !== undefined
192+
? payload.db.defaultIDType === 'number'
193+
? userId
194+
: `"${userId}"`
195+
: undefined
196+
197+
const richTextContent = getRichTextContent(formattedUploadID, formattedUserID)
198+
199+
await payload.create({
200+
collection: richTextFieldsSlug,
201+
data: {
202+
title: 'Data harvest \u2013 how AI and sensors are revolutionizing farming',
203+
content: richTextContent,
204+
lists: listsContent,
205+
typography: getTypographyContent(formattedUserID),
206+
table: tableContent,
207+
code: codeContent,
208+
},
209+
})
210+
}
211+
154212
// Seed relationship-fields to test join field
155213
await payload.create({
156214
collection: relationshipFieldsSlug,

test/v4/views/Components/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { ModalSection } from './sections/ModalSection.js'
2222
import { NoListResultsSection } from './sections/NoListResults.js'
2323
import { PillSection } from './sections/Pill.js'
2424
import { PopupSection } from './sections/Popup.js'
25+
import { SpinnerSection } from './sections/Spinner.js'
2526
import { ThumbnailCardSection } from './sections/ThumbnailCard.js'
2627
import { ToastSection } from './sections/ToastSection.js'
2728
import { TooltipSection } from './sections/Tooltip.js'
@@ -76,6 +77,7 @@ type ComponentId =
7677
| 'select'
7778
| 'select-field'
7879
| 'shimmer'
80+
| 'spinner'
7981
| 'text-field'
8082
| 'textarea'
8183
| 'textarea-field'
@@ -106,6 +108,7 @@ const componentOptions: ComponentOption[] = [
106108
{ category: 'primitives', label: 'Popup', value: 'popup' },
107109
{ category: 'primitives', label: 'Radio', value: 'radio' },
108110
{ category: 'primitives', label: 'Select', value: 'select' },
111+
{ category: 'primitives', label: 'Spinner', value: 'spinner' },
109112
{ category: 'primitives', label: 'Textarea', value: 'textarea' },
110113
{ category: 'primitives', label: 'Tooltip', value: 'tooltip' },
111114
// Patterns
@@ -246,6 +249,7 @@ export const ComponentsView: React.FC = () => {
246249
{shouldShow('input-stepper', 'primitives') && (
247250
<InputStepperSection selectedComponent="input-stepper" />
248251
)}
252+
{shouldShow('spinner', 'primitives') && <SpinnerSection selectedComponent="spinner" />}
249253

250254
{/* Patterns */}
251255
{(selectedCategory === 'all' || selectedCategory === 'patterns') &&

0 commit comments

Comments
 (0)