diff --git a/components/index.ts b/components/index.ts index 71452012f..1b8b4ec49 100644 --- a/components/index.ts +++ b/components/index.ts @@ -141,6 +141,9 @@ export type { SpacerProps } from './spacer' export { default as Spinner } from './spinner' export type { SpinnerProps } from './spinner' +export { default as Skeleton } from './skeleton' +export type { SkeletonProps } from './skeleton' + export { default as Table } from './table' export type { TableProps, TableColumnProps } from './table' diff --git a/components/skeleton/__tests__/index.test.tsx b/components/skeleton/__tests__/index.test.tsx new file mode 100644 index 000000000..e7462ddad --- /dev/null +++ b/components/skeleton/__tests__/index.test.tsx @@ -0,0 +1,36 @@ +import React from 'react' +import { mount } from 'enzyme' +import Skeleton from '../index' + +describe('Skeleton', () => { + it('should render correctly when nested', () => { + const wrapper = mount( + + + + col + + , + ) + expect(() => wrapper.unmount()).not.toThrow() + }) + + it('should ignore height and width when children are shown', () => { + const wrapper = mount(); + + const rendered = wrapper.find('.skeleton').html(); + expect(rendered).not.toContain('width: 50px;'); + expect(rendered).not.toContain('height: 50px;'); + }) + + it('should render different components', () => { + let wrapper = mount() + expect(wrapper.find('p').length).not.toBe(0) + + wrapper = mount() + expect(wrapper.find('details').length).not.toBe(0) + + wrapper = mount() + expect(wrapper.find('h1').length).not.toBe(0) + }) +}) diff --git a/components/skeleton/index.ts b/components/skeleton/index.ts new file mode 100644 index 000000000..2356ae04c --- /dev/null +++ b/components/skeleton/index.ts @@ -0,0 +1,4 @@ +import Skeleton from './skeleton' + +export type { SkeletonProps } from './skeleton' +export default Skeleton diff --git a/components/skeleton/skeleton.tsx b/components/skeleton/skeleton.tsx new file mode 100644 index 000000000..315e27b6b --- /dev/null +++ b/components/skeleton/skeleton.tsx @@ -0,0 +1,145 @@ +import React from 'react' +import useTheme from '../use-theme' +import { useScale, withScale } from '../use-scale' +import useClasses from '../use-classes' + +interface Props { + width?: number + squared?: boolean + rounded?: boolean + component?: keyof JSX.IntrinsicElements + className?: string + show?: boolean + minHeight?: number + animate?: boolean + height?: number +} + +const defaultProps = { + squared: false, + rounded: false, + component: 'span' as keyof JSX.IntrinsicElements, + className: '', + show: false, + minHeight: 24, + animate: true, +} + +type NativeAttrs = Omit, keyof Props> +export type SkeletonProps = Props & NativeAttrs + +const SkeletonComponent: React.FC> = ({ + component, + children, + width, + squared, + rounded, + show, + minHeight, + className, + animate, + height, + ...props +}: React.PropsWithChildren & typeof defaultProps) => { + const Component = component + let theme = useTheme() + const { SCALES } = useScale() + const classes = useClasses( + 'skeleton', + { rounded, squared, show, stop: !animate, hasChildren: !!children }, + className, + ) + + return ( + + {children} + + + ) +} + +SkeletonComponent.defaultProps = defaultProps +SkeletonComponent.displayName = 'GeistCol' +const Skeleton = withScale(SkeletonComponent) +export default Skeleton diff --git a/lib/data/metadata-en-us.json b/lib/data/metadata-en-us.json index 71714437f..4cee4b7ba 100644 --- a/lib/data/metadata-en-us.json +++ b/lib/data/metadata-en-us.json @@ -1 +1 @@ -[{"name":"guide","children":[{"name":"Getting Started","children":[{"name":"Introduction","url":"/en-us/guide/introduction","index":5,"group":"Getting Started"},{"name":"Installation","url":"/en-us/guide/installation","index":10,"group":"Getting Started"},{"name":"Bundle Size","url":"/en-us/guide/bundle-size","index":11,"group":"Getting Started"},{"name":"Server Render","url":"/en-us/guide/server-render","index":15,"group":"Getting Started"}]},{"name":"Customization","children":[{"name":"Colors","url":"/en-us/guide/colors","index":20,"group":"Customization"},{"name":"Themes","url":"/en-us/guide/themes","index":25,"group":"Customization"},{"name":"Scale","url":"/en-us/guide/scale","index":30,"group":"Customization"}]}]},{"name":"components","children":[{"name":"General","children":[{"name":"Text","url":"/en-us/components/text","index":10,"group":"General"},{"name":"Button","url":"/en-us/components/button","index":100,"group":"General"},{"name":"Code","url":"/en-us/components/code","index":100,"group":"General"},{"name":"Icons","url":"/en-us/components/icons","index":100,"group":"General"}]},{"name":"Layout","children":[{"name":"Grid","url":"/en-us/components/grid","index":100,"group":"Layout"},{"name":"Page","url":"/en-us/components/page","index":100,"group":"Layout"},{"name":"Spacer","url":"/en-us/components/spacer","index":100,"group":"Layout"}]},{"name":"Surfaces","children":[{"name":"Card","url":"/en-us/components/card","index":100,"group":"Surfaces"},{"name":"Collapse","url":"/en-us/components/collapse","index":100,"group":"Surfaces"},{"name":"Fieldset","url":"/en-us/components/fieldset","index":100,"group":"Surfaces"}]},{"name":"Data Entry","children":[{"name":"AutoComplete","url":"/en-us/components/auto-complete","index":100,"group":"Data Entry"},{"name":"Button Group","url":"/en-us/components/button-group","index":100,"group":"Data Entry"},{"name":"Checkbox","url":"/en-us/components/checkbox","index":100,"group":"Data Entry"},{"name":"Input","url":"/en-us/components/input","index":100,"group":"Data Entry"},{"name":"Radio","url":"/en-us/components/radio","index":100,"group":"Data Entry"},{"name":"Select","url":"/en-us/components/select","index":100,"group":"Data Entry"},{"name":"Slider","url":"/en-us/components/slider","index":100,"group":"Data Entry"},{"name":"Textarea","url":"/en-us/components/textarea","index":100,"group":"Data Entry"},{"name":"Toggle","url":"/en-us/components/toggle","index":100,"group":"Data Entry"}]},{"name":"Data Display","children":[{"name":"Avatar","url":"/en-us/components/avatar","index":100,"group":"Data Display"},{"name":"Badge","url":"/en-us/components/badge","index":100,"group":"Data Display"},{"name":"Capacity","url":"/en-us/components/capacity","index":100,"group":"Data Display"},{"name":"Description","url":"/en-us/components/description","index":100,"group":"Data Display"},{"name":"Display","url":"/en-us/components/display","index":100,"group":"Data Display"},{"name":"Dot","url":"/en-us/components/dot","index":100,"group":"Data Display"},{"name":"File Tree","url":"/en-us/components/file-tree","index":100,"group":"Data Display"},{"name":"Image","url":"/en-us/components/image","index":100,"group":"Data Display"},{"name":"Keyboard","url":"/en-us/components/keyboard","index":100,"group":"Data Display"},{"name":"Popover","url":"/en-us/components/popover","index":100,"group":"Data Display"},{"name":"Table","url":"/en-us/components/table","index":100,"group":"Data Display"},{"name":"Tag","url":"/en-us/components/tag","index":100,"group":"Data Display"},{"name":"Tooltip","url":"/en-us/components/tooltip","index":100,"group":"Data Display"},{"name":"User","url":"/en-us/components/user","index":100,"group":"Data Display"}]},{"name":"Feedback","children":[{"name":"Drawer","url":"/en-us/components/drawer","index":100,"group":"Feedback"},{"name":"Loading","url":"/en-us/components/loading","index":100,"group":"Feedback"},{"name":"Modal","url":"/en-us/components/modal","index":100,"group":"Feedback"},{"name":"Note","url":"/en-us/components/note","index":100,"group":"Feedback"},{"name":"Progress","url":"/en-us/components/progress","index":100,"group":"Feedback"},{"name":"Rating","url":"/en-us/components/rating","index":100,"group":"Feedback"},{"name":"Spinner","url":"/en-us/components/spinner","index":100,"group":"Feedback"},{"name":"Toast","url":"/en-us/components/toast","index":100,"group":"Feedback"}]},{"name":"Navigation","children":[{"name":"Breadcrumbs","url":"/en-us/components/breadcrumbs","index":100,"group":"Navigation"},{"name":"Link","url":"/en-us/components/link","index":100,"group":"Navigation"},{"name":"Pagination","url":"/en-us/components/pagination","index":100,"group":"Navigation"},{"name":"Tabs","url":"/en-us/components/tabs","index":100,"group":"Navigation"},{"name":"Button Dropdown","url":"/en-us/components/button-dropdown","index":101,"group":"Navigation"}]},{"name":"Others","children":[{"name":"Divider","url":"/en-us/components/divider","index":100,"group":"Others"},{"name":"Snippet","url":"/en-us/components/snippet","index":100,"group":"Others"}]}]},{"name":"hooks","children":[{"name":"Enhancement","children":[{"name":"useKeyboard","url":"/en-us/hooks/use-keyboard","index":5,"group":"Enhancement"},{"name":"useInput","url":"/en-us/hooks/use-input","index":10,"group":"Enhancement"},{"name":"useModal","url":"/en-us/hooks/use-modal","index":11,"group":"Enhancement"},{"name":"useTabs","url":"/en-us/hooks/use-tabs","index":11,"group":"Enhancement"},{"name":"useToast","url":"/en-us/hooks/use-toast","index":12,"group":"Enhancement"}]},{"name":"Utilities","children":[{"name":"useBodyScroll","url":"/en-us/hooks/use-body-scroll","index":100,"group":"Utilities"},{"name":"useClickAway","url":"/en-us/hooks/use-click-away","index":100,"group":"Utilities"},{"name":"useClipboard","url":"/en-us/hooks/use-clipboard","index":100,"group":"Utilities"},{"name":"useMediaQuery","url":"/en-us/hooks/use-media-query","index":100,"group":"Utilities"}]},{"name":"Development","children":[{"name":"useTheme","url":"/en-us/hooks/use-theme","index":100,"group":"Development"},{"name":"useCurrentState","url":"/en-us/hooks/use-current-state","index":101,"group":"Development"},{"name":"useScale","url":"/en-us/hooks/use-scale","index":103,"group":"Development"},{"name":"useClasses","url":"/en-us/hooks/use-classes","index":104,"group":"Development"}]}]}] +[{"name":"guide","children":[{"name":"Getting Started","children":[{"name":"Introduction","url":"/en-us/guide/introduction","index":5,"group":"Getting Started"},{"name":"Installation","url":"/en-us/guide/installation","index":10,"group":"Getting Started"},{"name":"Bundle Size","url":"/en-us/guide/bundle-size","index":11,"group":"Getting Started"},{"name":"Server Render","url":"/en-us/guide/server-render","index":15,"group":"Getting Started"}]},{"name":"Customization","children":[{"name":"Colors","url":"/en-us/guide/colors","index":20,"group":"Customization"},{"name":"Themes","url":"/en-us/guide/themes","index":25,"group":"Customization"},{"name":"Scale","url":"/en-us/guide/scale","index":30,"group":"Customization"}]}]},{"name":"components","children":[{"name":"General","children":[{"name":"Text","url":"/en-us/components/text","index":10,"group":"General"},{"name":"Button","url":"/en-us/components/button","index":100,"group":"General"},{"name":"Code","url":"/en-us/components/code","index":100,"group":"General"},{"name":"Icons","url":"/en-us/components/icons","index":100,"group":"General"}]},{"name":"Layout","children":[{"name":"Grid","url":"/en-us/components/grid","index":100,"group":"Layout"},{"name":"Page","url":"/en-us/components/page","index":100,"group":"Layout"},{"name":"Spacer","url":"/en-us/components/spacer","index":100,"group":"Layout"}]},{"name":"Surfaces","children":[{"name":"Card","url":"/en-us/components/card","index":100,"group":"Surfaces"},{"name":"Collapse","url":"/en-us/components/collapse","index":100,"group":"Surfaces"},{"name":"Fieldset","url":"/en-us/components/fieldset","index":100,"group":"Surfaces"}]},{"name":"Data Entry","children":[{"name":"AutoComplete","url":"/en-us/components/auto-complete","index":100,"group":"Data Entry"},{"name":"Button Group","url":"/en-us/components/button-group","index":100,"group":"Data Entry"},{"name":"Checkbox","url":"/en-us/components/checkbox","index":100,"group":"Data Entry"},{"name":"Input","url":"/en-us/components/input","index":100,"group":"Data Entry"},{"name":"Radio","url":"/en-us/components/radio","index":100,"group":"Data Entry"},{"name":"Select","url":"/en-us/components/select","index":100,"group":"Data Entry"},{"name":"Slider","url":"/en-us/components/slider","index":100,"group":"Data Entry"},{"name":"Textarea","url":"/en-us/components/textarea","index":100,"group":"Data Entry"},{"name":"Toggle","url":"/en-us/components/toggle","index":100,"group":"Data Entry"}]},{"name":"Data Display","children":[{"name":"Avatar","url":"/en-us/components/avatar","index":100,"group":"Data Display"},{"name":"Badge","url":"/en-us/components/badge","index":100,"group":"Data Display"},{"name":"Capacity","url":"/en-us/components/capacity","index":100,"group":"Data Display"},{"name":"Description","url":"/en-us/components/description","index":100,"group":"Data Display"},{"name":"Display","url":"/en-us/components/display","index":100,"group":"Data Display"},{"name":"Dot","url":"/en-us/components/dot","index":100,"group":"Data Display"},{"name":"File Tree","url":"/en-us/components/file-tree","index":100,"group":"Data Display"},{"name":"Image","url":"/en-us/components/image","index":100,"group":"Data Display"},{"name":"Keyboard","url":"/en-us/components/keyboard","index":100,"group":"Data Display"},{"name":"Popover","url":"/en-us/components/popover","index":100,"group":"Data Display"},{"name":"Skeleton","url":"/en-us/components/skeleton","index":100,"group":"Data Display"},{"name":"Table","url":"/en-us/components/table","index":100,"group":"Data Display"},{"name":"Tag","url":"/en-us/components/tag","index":100,"group":"Data Display"},{"name":"Tooltip","url":"/en-us/components/tooltip","index":100,"group":"Data Display"},{"name":"User","url":"/en-us/components/user","index":100,"group":"Data Display"}]},{"name":"Feedback","children":[{"name":"Drawer","url":"/en-us/components/drawer","index":100,"group":"Feedback"},{"name":"Loading","url":"/en-us/components/loading","index":100,"group":"Feedback"},{"name":"Modal","url":"/en-us/components/modal","index":100,"group":"Feedback"},{"name":"Note","url":"/en-us/components/note","index":100,"group":"Feedback"},{"name":"Progress","url":"/en-us/components/progress","index":100,"group":"Feedback"},{"name":"Rating","url":"/en-us/components/rating","index":100,"group":"Feedback"},{"name":"Spinner","url":"/en-us/components/spinner","index":100,"group":"Feedback"},{"name":"Toast","url":"/en-us/components/toast","index":100,"group":"Feedback"}]},{"name":"Navigation","children":[{"name":"Breadcrumbs","url":"/en-us/components/breadcrumbs","index":100,"group":"Navigation"},{"name":"Link","url":"/en-us/components/link","index":100,"group":"Navigation"},{"name":"Pagination","url":"/en-us/components/pagination","index":100,"group":"Navigation"},{"name":"Tabs","url":"/en-us/components/tabs","index":100,"group":"Navigation"},{"name":"Button Dropdown","url":"/en-us/components/button-dropdown","index":101,"group":"Navigation"}]},{"name":"Others","children":[{"name":"Divider","url":"/en-us/components/divider","index":100,"group":"Others"},{"name":"Snippet","url":"/en-us/components/snippet","index":100,"group":"Others"}]}]},{"name":"hooks","children":[{"name":"Enhancement","children":[{"name":"useKeyboard","url":"/en-us/hooks/use-keyboard","index":5,"group":"Enhancement"},{"name":"useInput","url":"/en-us/hooks/use-input","index":10,"group":"Enhancement"},{"name":"useModal","url":"/en-us/hooks/use-modal","index":11,"group":"Enhancement"},{"name":"useTabs","url":"/en-us/hooks/use-tabs","index":11,"group":"Enhancement"},{"name":"useToast","url":"/en-us/hooks/use-toast","index":12,"group":"Enhancement"}]},{"name":"Utilities","children":[{"name":"useBodyScroll","url":"/en-us/hooks/use-body-scroll","index":100,"group":"Utilities"},{"name":"useClickAway","url":"/en-us/hooks/use-click-away","index":100,"group":"Utilities"},{"name":"useClipboard","url":"/en-us/hooks/use-clipboard","index":100,"group":"Utilities"},{"name":"useMediaQuery","url":"/en-us/hooks/use-media-query","index":100,"group":"Utilities"}]},{"name":"Development","children":[{"name":"useTheme","url":"/en-us/hooks/use-theme","index":100,"group":"Development"},{"name":"useCurrentState","url":"/en-us/hooks/use-current-state","index":101,"group":"Development"},{"name":"useScale","url":"/en-us/hooks/use-scale","index":103,"group":"Development"},{"name":"useClasses","url":"/en-us/hooks/use-classes","index":104,"group":"Development"}]}]}] diff --git a/pages/en-us/components/skeleton.mdx b/pages/en-us/components/skeleton.mdx new file mode 100644 index 000000000..08173de07 --- /dev/null +++ b/pages/en-us/components/skeleton.mdx @@ -0,0 +1,75 @@ +import { Skeleton, Button, Grid } from 'components' +import { Layout, Playground, Attributes } from 'lib/components' + +export const meta = { + title: 'Skeleton', + group: 'Data Display', +} + + +## Skeleton + +Show a placeholder in place of content that is loading. + + +`} +/> + + + + + + + + + +`} +/> + + +`} +/> + + +`} +/> + + +`} +/> + + +Skeleton.Props + +| Attribute | Description | Type | Accepted values | Default | +| ----------- | ------------------------------------------- | ---------------- | ------------------ | ------- | +| **animate** | enable animation | `boolean` | - | `true` | +| **rounded** | show round skeleton | `boolean` | - | `false` | +| **show** | show children | `boolean` | - | `false` | +| **animate** | enable loading animation | `boolean` | - | `false` | +| ... | native props | `HTMLAttributes` | `'className', ...` | - | + + + +export default ({ children }) => {children}