From 879862c0b540178bef8fdfbe626e6aaa24fe0b87 Mon Sep 17 00:00:00 2001 From: Chris Hart Date: Fri, 1 Dec 2017 12:27:32 -0500 Subject: [PATCH] feat(FileDrop): Add support for validation messages Enables FileDrop to accept the same `messages` prop that our other form input components accept. Fixes: INSTUI-862 Test plan: - The second FileDrop example should now appear with an `Invalid filetype` message and red/error border - Change the message type to `success` and confirm the text turns green - Test the input on a screenreader and confirm that the message is read when the input is focused via aria-describedby (does not work in NVDA due to screenreader/Firefox bug https://github.com/nvaccess/nvda/issues/5326) - Confirm that :focus, :hover, and error states can now be seen simultaneously Change-Id: Iec9d8e98c0ae9bbd99f0800689fd4dccfae9d522 Reviewed-on: https://gerrit.instructure.com/134365 Tested-by: Jenkins Reviewed-by: Jennifer Stern QA-Review: Dan Sasaki Product-Review: Chris Hart --- .../ui-core/src/components/FileDrop/README.md | 9 ++- .../ui-core/src/components/FileDrop/index.js | 37 ++++++++++++- .../src/components/FileDrop/styles.css | 55 ++++++++++++++----- .../ui-core/src/components/FileDrop/theme.js | 4 +- 4 files changed, 85 insertions(+), 20 deletions(-) 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 }