From a111a79ea936e6b6177d86aab13a1a7607cb5dbf Mon Sep 17 00:00:00 2001 From: Mark Bouslog Date: Tue, 17 Dec 2024 11:24:45 -0600 Subject: [PATCH 1/9] lib-classifier: Refactor survey task Choice and Questions styling (#6478) * Refactor survey task choice colors, text size, spacing * Add info collapsible * Refactor Choice sections margins * Refactor Choice button borders * Refactor survey task tests per Choice layout changes * Fix more info align * Refactor choice cancel * Refactor Choice margin and padding * Refactor ConfusedWith button styling * Edit sub-heading color * Refactor QuestionInput margin and round * Edit Choice spacing * Refactor Question input label text color if dark theme and isChecked * Refactor Choice button spacing * Reduce spacing within Choice elements * Set question input spacing * Refactor Choice story container spacing * Remove unneeded a11yTitle * Refactor Choice heading and ConfusedWith button spacing * Add Carousel min height * Refactor info icons with aria-hidden --- .../tasks/survey/components/SurveyTask.js | 9 +- .../components/SurveyTask.userClicks.spec.js | 22 +- .../SurveyTask.userKeystrokes.spec.js | 6 +- .../components/components/Choice/Choice.js | 188 ++++++++++++------ .../components/Choice/Choice.spec.js | 39 +--- .../components/Choice/Choice.stories.js | 4 +- .../components/ConfusedWith/ConfusedWith.js | 27 ++- .../Choice/components/Questions/Questions.js | 7 + .../InputGroup/components/QuestionInput.js | 16 +- .../src/translations/en/plugins.json | 6 +- 10 files changed, 206 insertions(+), 118 deletions(-) diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.js b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.js index f2c0a4585e..5e270c99e2 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.js @@ -28,6 +28,13 @@ export function SurveyTask ({ setAnswers(answers) } + function handleCancel (selectedChoice) { + setAnswers({}) + setPreviousChoice(selectedChoice) + setSelectedChoice('') + annotation.setChoiceInProgress(false) + } + function handleChoice (selectedChoice) { if (selectedChoice === '') { annotation.setChoiceInProgress(false) @@ -94,8 +101,8 @@ export function SurveyTask ({ answers={answers} choiceId={selectedChoice} handleAnswers={handleAnswers} + handleCancel={handleCancel} handleChoice={handleChoice} - handleDelete={handleDelete} onIdentify={handleIdentify} task={task} /> diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userClicks.spec.js b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userClicks.spec.js index 5f9940237b..7d44169e3d 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userClicks.spec.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userClicks.spec.js @@ -173,9 +173,9 @@ describe('SurveyTask with user clicks', function () { await user.click(choiceButton) }) - it('should show the choice description', async function () { - const choiceDescription = screen.getByText('It\'s a fire. Pretty sure you know what this looks like.') - expect(choiceDescription).to.be.ok() + it('should show the "More info" button', async function () { + const choiceMoreInfoButton = screen.getByRole('button', { name: 'SurveyTask.Choice.moreInfo' }) + expect(choiceMoreInfoButton).to.be.ok() }) it('should show choice images', async function () { @@ -184,12 +184,12 @@ describe('SurveyTask with user clicks', function () { }) it('should show choices with closed choice focused when Not This button is clicked', async function () { - const notThisButton = screen.getByText('SurveyTask.Choice.notThis') + const cancelButton = screen.getByText('SurveyTask.Choice.cancel') // close choice (Fire) component - await user.click(notThisButton) - // confirm choice (Fire) description, and therefore choice, is not shown - const choiceDescription = screen.queryByText('It\'s a fire. Pretty sure you know what this looks like.') - expect(choiceDescription).to.be.null() + await user.click(cancelButton) + // confirm choice "More info" button is not shown, therefore choice is closed + const choiceMoreInfoButton = screen.queryByRole('button', { name: 'SurveyTask.Choice.moreInfo' }) + expect(choiceMoreInfoButton).to.be.null() // confirm choices are shown const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) @@ -202,9 +202,9 @@ describe('SurveyTask with user clicks', function () { const identifyButton = screen.getByTestId('choice-identify-button') // identify choice (Fire) and close choice (Fire) component await user.click(identifyButton) - // confirm choice (Fire) description, and therefore choice, is not shown - const choiceDescription = screen.queryByText('It\'s a fire. Pretty sure you know what this looks like.') - expect(choiceDescription).to.be.null() + // confirm choice "More info" button is not shown, therefore choice is closed + const choiceMoreInfoButton = screen.queryByRole('button', { name: 'SurveyTask.Choice.moreInfo' }) + expect(choiceMoreInfoButton).to.be.null() // confirm choices are shown const choiceButtons = document.querySelector('[role=menu]').querySelectorAll('[role=menuitemcheckbox]') expect(choiceButtons.length).to.equal(6) diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userKeystrokes.spec.js b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userKeystrokes.spec.js index 94bd40c112..0d46e3dfbf 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userKeystrokes.spec.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/SurveyTask.userKeystrokes.spec.js @@ -167,9 +167,9 @@ describe('SurveyTask with user keystrokes', function () { await user.keyboard('[Enter]') }) - it('should show the choice description', async function () { - const choiceDescription = screen.getByText('Not as awesome as a pangolin, but surprisingly big.') - expect(choiceDescription).to.be.ok() + it('should show the "more info" button', async function () { + const choiceMoreInfoButton = screen.getByRole('button', { name: 'SurveyTask.Choice.moreInfo' }) + expect(choiceMoreInfoButton).to.be.ok() }) it('should show choice images', async function () { diff --git a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js index 6a1b8a133a..c72d593d89 100644 --- a/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js +++ b/packages/lib-classifier/src/plugins/tasks/survey/components/components/Choice/Choice.js @@ -1,6 +1,7 @@ -import { Box, Button, Carousel, Heading, Paragraph } from 'grommet' +import { Box, Button, Carousel, Collapsible, Heading, Paragraph, Text } from 'grommet' +import { FormDown, FormUp } from 'grommet-icons' import PropTypes from 'prop-types' -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import styled from 'styled-components' import { useTranslation } from '@translations/i18n' import { PrimaryButton, Media } from '@zooniverse/react-components' @@ -18,15 +19,31 @@ const StyledBox = styled(Box)` } ` +const StyledButton = styled(Button)` + border: 1px solid ${props => props.theme.global.colors.brand}; + border-radius: 4px; + flex: 1 0; + margin-right: 1ch; + max-width: 350px; +` + +const StyledPrimaryButton = styled(PrimaryButton)` + border-radius: 4px; + flex: 1 0; +` + +const DEFAULT_HANDLER = () => true + function Choice({ answers = {}, choiceId = '', - handleAnswers = () => {}, - handleChoice = () => {}, - handleDelete = () => {}, - onIdentify = () => {}, + handleAnswers = DEFAULT_HANDLER, + handleCancel = DEFAULT_HANDLER, + handleChoice = DEFAULT_HANDLER, + onIdentify = DEFAULT_HANDLER, task }) { + const [showInfo, setShowInfo] = useState(false) const { choices, images, @@ -46,6 +63,25 @@ function Choice({ const choice = choices?.get(choiceId) || {} const questionIds = getQuestionIds(choiceId, task) const allowIdentify = allowIdentification(answers, choiceId, task) + const InfoLabel = ( + + {showInfo ? ( + <> + {t('SurveyTask.Choice.lessInfo')} + + ) function handleKeyDown (event) { if (event.key === 'Escape') { @@ -58,14 +94,12 @@ function Choice({ ref={choiceRef} aria-labelledby='choice-label' background={{ - dark: 'dark-1', - light: 'light-1' + dark: 'dark-3', + light: 'neutral-6' }} - elevation='large' flex='grow' forwardedAs='section' onKeyDown={handleKeyDown} - pad='small' tabIndex={0} > {choice.images?.length > 0 && ( @@ -73,8 +107,11 @@ function Choice({ alignSelf='center' controls='arrows' data-testid='choice-images' - height={{ max: 'medium' }} - width={{ max: 'medium' }} + height={{ + max: 'medium', + min: '160px' + }} + width='100%' > {choice.images.map((filename, index) => ( )} - - {strings.get(`choices.${choiceId}.label`)} - - {strings.get(`choices.${choiceId}.description`)} - {choice.confusionsOrder?.length > 0 && ( - - )} - {questionIds.length > 0 && ( - - )} -