diff --git a/packages/ui-core/src/components/FileDrop/README.md b/packages/ui-core/src/components/FileDrop/README.md index 9f9b94cdd4..b658e8be19 100644 --- a/packages/ui-core/src/components/FileDrop/README.md +++ b/packages/ui-core/src/components/FileDrop/README.md @@ -29,13 +29,17 @@ example: true ### Accept The `accept` prop dictates what type of files are allowed. It can be an array or comma-separated string of -[MIME type formats](https://en.wikipedia.org/wiki/Media_type#Common_examples) and/or file extensions +[MIME type formats](https://en.wikipedia.org/wiki/Media_type#Common_examples) and/or file extensions. + +FileDrop accepts the same `messages` prop as the other Instructure UI input components for providing +form validation feedback. If there are `error` messages in the `messages` array, FileDrop's border +will turn the theme's `rejectedColor`. ```js --- example: true --- - + @@ -43,6 +47,7 @@ example: true accept=".jpg" onDropAccepted={([file]) => { console.log(`File accepted ${file.name}`) }} onDropRejected={([file]) => { console.log(`File rejected ${file.name}`) }} + messages={[{ text: 'Invalid file type', type: 'error' }]} label={ 0) + } + + get invalid () { + return this.hasMessages && this.props.messages.findIndex((message) => { + return message.type === 'error' + }) >= 0 + } + getDataTransferItems (event, enablePreview) { let list = Array.prototype.slice.call(getEventFiles(event, this.fileInputEl)) this.fileInputEl.value = null @@ -325,7 +348,7 @@ export default class FileDrop extends Component { const id = this.props.id || this.defaultId const classes = { [styles.root]: true, - [styles.dragRejected]: this.state.isDragRejected, + [styles.dragRejected]: this.state.isDragRejected || this.invalid, [styles.dragAccepted]: this.state.isDragAccepted, [styles.focused]: this.state.focused } @@ -342,7 +365,9 @@ export default class FileDrop extends Component { onDrop={this.handleDrop} > - {this.renderLabel()} + + {this.renderLabel()} + + {(this.hasMessages) ? + + + + : null} ) } diff --git a/packages/ui-core/src/components/FileDrop/styles.css b/packages/ui-core/src/components/FileDrop/styles.css index b0de3af134..57275b9972 100644 --- a/packages/ui-core/src/components/FileDrop/styles.css +++ b/packages/ui-core/src/components/FileDrop/styles.css @@ -20,36 +20,63 @@ box-sizing: border-box; position: relative; z-index: 1; - overflow: hidden; text-align: center; border-radius: var(--borderRadius); - border: var(--borderWidth) solid transparent; + border: var(--borderWidth) var(--borderStyle) transparent; cursor: pointer; &:hover { border-color: var(--hoverBorderColor); - border-style: var(--hoverBorderStyle); + } + + &::before { + content: ""; + position: absolute; + top: -0.25rem; + left: -0.25rem; + right: -0.25rem; + bottom: -0.25rem; + border: var(--focusBorderWidth) var(--focusBorderStyle) var(--focusBorderColor); + border-radius: var(--borderRadius); + opacity: 0; + transform: scale(0.01); + transition: all 0.2s; } } +.layout { + display: block; + overflow: hidden; + border-radius: var(--borderRadius); +} + .focused { - .label { - border-color: var(--hoverBorderColor); - border-style: solid; + .label::before { + opacity: 1; + transform: scale(1); } } -.dragAccepted, -.dragRejected { +.dragAccepted { .label { - border-style: var(--focusBorderStyle); + border-color: var(--acceptedColor); } -} -.dragAccepted .label { - border-color: var(--acceptedColor); + &.focused { + .label::before { + border-color: var(--acceptedColor); + } + } } -.dragRejected .label { - border-color: var(--rejectedColor); +.dragRejected { + .label { + border-color: var(--rejectedColor); + } + + &.focused { + .label::before { + border-color: var(--rejectedColor); + } + } } diff --git a/packages/ui-core/src/components/FileDrop/theme.js b/packages/ui-core/src/components/FileDrop/theme.js index f24c5235a4..5909950446 100644 --- a/packages/ui-core/src/components/FileDrop/theme.js +++ b/packages/ui-core/src/components/FileDrop/theme.js @@ -3,9 +3,11 @@ export default function generator ({ borders, colors }) { backgroundColor: colors.white, borderRadius: borders.radiusLarge, borderWidth: borders.widthMedium, + borderStyle: 'dashed', hoverBorderColor: colors.brand, - hoverBorderStyle: 'dashed', + focusBorderWidth: borders.widthSmall, focusBorderStyle: 'solid', + focusBorderColor: colors.brand, acceptedColor: colors.brand, rejectedColor: colors.crimson }