diff --git a/src/components/FilePlaceholder/FilePlaceholder.stories.tsx b/src/components/FilePlaceholder/FilePlaceholder.stories.tsx new file mode 100644 index 0000000..9f62a4a --- /dev/null +++ b/src/components/FilePlaceholder/FilePlaceholder.stories.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import { FilePlaceholder } from '../FilePlaceholder'; +import readme from './README.md'; +import { text } from '@storybook/addon-knobs'; + +export default { title: 'Components/FilePlaceholder', component: FilePlaceholder, parameters: { readme } }; + +export const Basic = () => ; diff --git a/src/components/FilePlaceholder/FilePlaceholder.test.tsx b/src/components/FilePlaceholder/FilePlaceholder.test.tsx new file mode 100644 index 0000000..55fc92b --- /dev/null +++ b/src/components/FilePlaceholder/FilePlaceholder.test.tsx @@ -0,0 +1,29 @@ +import { mount, shallow } from 'enzyme'; +import React from 'react'; +import { spy } from 'sinon'; +import { FilePlaceholder } from '../FilePlaceholder'; + +describe('FilePlaceholder component', () => { + it('renders its contents', () => { + const filePlaceholder = shallow(); + expect(filePlaceholder.find('.ui__filePlaceholder')).toHaveLength(1); + }); + + it('snapshot renders default filePlaceholder', () => { + const filePlaceholder = shallow(); + expect(filePlaceholder).toMatchSnapshot(); + }); + + it('clicking filePlaceholder triggers onClick prop', () => { + const onClick = spy(); + shallow().simulate('click'); + expect(onClick.callCount).toBe(1); + }); + + it('clicking disabled filePlaceholder does not trigger onClick prop', () => { + const onClick = spy(); + // full DOM mount so `filePlaceholder` element will use disabled prop + mount().simulate('click'); + expect(onClick.callCount).toBe(0); + }); +}); diff --git a/src/components/FilePlaceholder/FilePlaceholder.tsx b/src/components/FilePlaceholder/FilePlaceholder.tsx new file mode 100644 index 0000000..c38af76 --- /dev/null +++ b/src/components/FilePlaceholder/FilePlaceholder.tsx @@ -0,0 +1,33 @@ +import classnames from 'classnames'; +import React, { FC } from 'react'; + +export interface FilePlaceholderProps { + /** + * Classname of the placeholder wrapper. + */ + className?: string; + /** + * The file extension to display on the placeholder. + */ + extension?: string; +} + +export const FilePlaceholder: FC = ({ className, extension }) => { + const filePlaceholderClass = classnames('ui__base ui__filePlaceholder', className); + + const formattedExtension = extension && `.${extension.replace(/^\./, '')}`; + + return ( +
+
+
+
+
+
+
+
+ + {formattedExtension ?
{formattedExtension}
: undefined} +
+ ); +}; diff --git a/src/components/FilePlaceholder/README.md b/src/components/FilePlaceholder/README.md new file mode 100644 index 0000000..36778e9 --- /dev/null +++ b/src/components/FilePlaceholder/README.md @@ -0,0 +1,3 @@ +Placeholder for files. You can include an extension to add it to the bottom of +the placeholder. These should be used when you are unable to generate thumbnails +for a given file, for example an unsupported file type. diff --git a/src/components/FilePlaceholder/_FilePlaceholder.scss b/src/components/FilePlaceholder/_FilePlaceholder.scss new file mode 100644 index 0000000..0daa346 --- /dev/null +++ b/src/components/FilePlaceholder/_FilePlaceholder.scss @@ -0,0 +1,57 @@ +.ui__filePlaceholder { + background-color: white; + padding: 10px; + height: 164px; + width: 128px; + position: relative; + + &__block { + background-color: #ccc; + + &--thumbnail { + width: 40px; + height: 40px; + float: left; + } + + &--line-sm { + margin-left: 50px; + margin-top: 10px; + height: 6px; + } + + &--line-xs { + margin-left: 50px; + margin-top: 10px; + width: 40px; + height: 6px; + } + + &--line-df { + margin-top: 20px; + width: 90px; + height: 6px; + } + + &--line-lg { + margin-top: 10px; + width: 90px; + height: 6px; + } + + &--line-lgx { + margin-top: 10px; + height: 6px; + } + } + + &__extension { + position: absolute; + color: #ccc; + text-align: center; + font-size: $font-size-large; + right: 10px; + left: 10px; + bottom: 10px; + } +} diff --git a/src/components/FilePlaceholder/index.ts b/src/components/FilePlaceholder/index.ts new file mode 100644 index 0000000..ea10327 --- /dev/null +++ b/src/components/FilePlaceholder/index.ts @@ -0,0 +1 @@ +export * from './FilePlaceholder'; diff --git a/src/components/FileSkeleton/FileSkeleton.tsx b/src/components/FileSkeleton/FileSkeleton.tsx index 6e58a1e..bd0cf29 100644 --- a/src/components/FileSkeleton/FileSkeleton.tsx +++ b/src/components/FileSkeleton/FileSkeleton.tsx @@ -3,7 +3,7 @@ import React from 'react'; export interface FileSkeletonProps { /** - * Classname of the skeleton wrapper + * Classname of the skeleton wrapper. */ className?: string; } diff --git a/src/components/index.ts b/src/components/index.ts index fe34c37..f4ec512 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -13,6 +13,7 @@ export * from './Draggable'; export * from './EditableText'; export * from './FileOrganizer'; export * from './FilePicker'; +export * from './FilePlaceholder'; export * from './FileSkeleton'; export * from './FocusTrap'; export * from './Icon'; diff --git a/src/index.scss b/src/index.scss index 9a99b62..5af798e 100755 --- a/src/index.scss +++ b/src/index.scss @@ -30,6 +30,7 @@ @import './components/EditableText/EditableText'; @import './components/FileOrganizer/FileOrganizer'; @import './components/FilePicker/FilePicker'; +@import './components/FilePlaceholder/FilePlaceholder'; @import './components/FileSkeleton/FileSkeleton'; @import './components/FocusTrap/FocusTrap'; @import './components/Icon/Icon';