Skip to content

Commit

Permalink
Add Skeleton component
Browse files Browse the repository at this point in the history
  • Loading branch information
david0xd committed Jan 16, 2025
1 parent 687b582 commit f584d23
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 3 deletions.
4 changes: 3 additions & 1 deletion packages/snaps-sdk/src/jsx/components/Row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createSnapComponent } from '../component';
import type { AddressElement } from './Address';
import type { ImageElement } from './Image';
import type { LinkElement } from './Link';
import type { SkeletonElement } from './Skeleton';
import type { TextElement } from './Text';
import type { ValueElement } from './Value';

Expand All @@ -13,7 +14,8 @@ export type RowChildren =
| ImageElement
| TextElement
| ValueElement
| LinkElement;
| LinkElement
| SkeletonElement;

/**
* The props of the {@link Row} component.
Expand Down
17 changes: 17 additions & 0 deletions packages/snaps-sdk/src/jsx/components/Skeleton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Skeleton } from './Skeleton';

describe('Skeleton', () => {
it('renders a skeleton component', () => {
const result = <Skeleton width={320} height={32} borderRadius="medium" />;

expect(result).toStrictEqual({
type: 'Skeleton',
key: null,
props: {
width: 320,
height: 32,
borderRadius: 'medium',
},
});
});
});
40 changes: 40 additions & 0 deletions packages/snaps-sdk/src/jsx/components/Skeleton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { createSnapComponent } from '../component';

/**
* Definition of Skeleton border radius.
*/
export type SkeletonBorderRadius = 'none' | 'medium' | 'full' | undefined;

/**
* The props of the {@link Skeleton} component.
*
* @param width - Width of the Skeleton.
* @param width - Height of the Skeleton.
* @param borderRadius - Border radius of the Skeleton.
*/
export type SkeletonProps = {
width: number | string;
height: number | string;
borderRadius?: SkeletonBorderRadius | undefined;
};

const TYPE = 'Skeleton';

/**
* A Skeleton component, which is used to display skeleton of loading content.
*
* @param props - The props of the component.
* @param props.width - Width of the Skeleton.
* @param props.width - Height of the Skeleton.
* @param props.borderRadius - Border radius of the Skeleton.
* @example
* <Skeleton height={32} width={50%} />
*/
export const Skeleton = createSnapComponent<SkeletonProps, typeof TYPE>(TYPE);

/**
* A Skeleton element.
*
* @see Skeleton
*/
export type SkeletonElement = ReturnType<typeof Skeleton>;
5 changes: 4 additions & 1 deletion packages/snaps-sdk/src/jsx/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type { ImageElement } from './Image';
import type { LinkElement } from './Link';
import type { RowElement } from './Row';
import type { SectionElement } from './Section';
import type { SkeletonElement } from './Skeleton';
import type { SpinnerElement } from './Spinner';
import type { TextElement } from './Text';
import type { TooltipElement } from './Tooltip';
Expand All @@ -41,6 +42,7 @@ export * from './Footer';
export * from './Container';
export * from './Section';
export * from './Banner';
export * from './Skeleton';

/**
* A built-in JSX element, which can be used in a Snap user interface.
Expand All @@ -66,4 +68,5 @@ export type JSXElement =
| SpinnerElement
| TextElement
| TooltipElement
| BannerElement;
| BannerElement
| SkeletonElement;
34 changes: 34 additions & 0 deletions packages/snaps-sdk/src/jsx/validation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
Section,
Avatar,
Banner,
Skeleton,
} from './components';
import {
AddressStruct,
Expand Down Expand Up @@ -72,6 +73,7 @@ import {
SectionStruct,
AvatarStruct,
BannerStruct,
SkeletonStruct,
} from './validation';

describe('KeyStruct', () => {
Expand Down Expand Up @@ -1618,3 +1620,35 @@ describe('BannerStruct', () => {
expect(is(value, BannerStruct)).toBe(false);
});
});

describe('SkeletonStruct', () => {
it.each([
<Skeleton width={320} height={32} />,
<Skeleton width="30%" height="30%" />,
<Skeleton width={32} height="30%" />,
<Skeleton width="30%" height={32} />,
<Skeleton width="30%" height={32} borderRadius="full" />,
<Skeleton width={32} height="30%" borderRadius="medium" />,
])(`validates a Skeleton element`, (value) => {
expect(is(value, SkeletonStruct)).toBe(true);
});

it.each([
'foo',
42,
null,
undefined,
{},
[],
// @ts-expect-error - Invalid props.
<Skeleton />,
// @ts-expect-error - Invalid props.
<Skeleton foo="bar">foo</Skeleton>,
// @ts-expect-error - Invalid props.
<Skeleton title={<Copyable value="bar" />} severity="info">
<Text>foo</Text>
</Skeleton>,
])('does not validate "%p"', (value) => {
expect(is(value, SkeletonStruct)).toBe(false);
});
});
16 changes: 15 additions & 1 deletion packages/snaps-sdk/src/jsx/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import type {
SnapsChildren,
StringElement,
} from './component';
import type { AvatarElement } from './components';
import type { AvatarElement, SkeletonElement } from './components';
import {
type AddressElement,
type BoldElement,
Expand Down Expand Up @@ -807,6 +807,17 @@ export const BannerStruct: Describe<BannerElement> = element('Banner', {
]),
});

/**
* A struct for the {@link SkeletonElement} type.
*/
export const SkeletonStruct: Describe<SkeletonElement> = element('Skeleton', {
width: union([number(), string()]),
height: union([number(), string()]),
borderRadius: optional(
nullUnion([literal('none'), literal('medium'), literal('full')]),
),
});

/**
* A struct for the {@link RowElement} type.
*/
Expand All @@ -818,6 +829,7 @@ export const RowStruct: Describe<RowElement> = element('Row', {
TextStruct,
ValueStruct,
LinkStruct,
SkeletonStruct,
]),
variant: optional(
nullUnion([literal('default'), literal('warning'), literal('critical')]),
Expand Down Expand Up @@ -863,6 +875,7 @@ export const BoxChildStruct = typedUnion([
SectionStruct,
AvatarStruct,
BannerStruct,
SkeletonStruct,
]);

/**
Expand Down Expand Up @@ -932,6 +945,7 @@ export const JSXElementStruct: Describe<JSXElement> = typedUnion([
SectionStruct,
AvatarStruct,
BannerStruct,
SkeletonStruct,
]);

/**
Expand Down

0 comments on commit f584d23

Please sign in to comment.