Merge pull request #15249 from overleaf/rd-odc-radio

Radio buttons for Onboarding Data Collection

GitOrigin-RevId: 8c4d1e965f3263b4c8a41c129c5c3d6e3ef10986
This commit is contained in:
Rebeka Dekany 2023-11-01 14:33:25 +01:00 committed by Copybot
parent af4b22fab5
commit a2946f8601
9 changed files with 207 additions and 3 deletions

View file

@ -457,6 +457,7 @@
"headers": "",
"help": "",
"help_improve_overleaf_fill_out_this_survey": "",
"helps_us_tailor_your_experience": "",
"hide_configuration": "",
"hide_document_preamble": "",
"hide_outline": "",
@ -839,6 +840,12 @@
"premium_plan_label": "",
"press_shortcut_to_open_advanced_reference_search": "",
"price": "",
"primarily_work_study_question": "",
"primarily_work_study_question_government": "",
"primarily_work_study_question_nonprofit_ngo": "",
"primarily_work_study_question_other": "",
"primarily_work_study_question_private_company": "",
"primarily_work_study_question_university_school": "",
"priority_support": "",
"private": "",
"problem_talking_to_publishing_service": "",

View file

@ -0,0 +1,42 @@
import React from 'react'
type RadioChipProps<ValueType> = {
checked?: boolean
disabled?: boolean
name: string
onChange: (value: ValueType) => void
required?: boolean
label: React.ReactElement | string
value: ValueType
}
const RadioChip = <T extends string>({
checked,
disabled,
name,
onChange,
label,
required,
value,
}: RadioChipProps<T>) => {
const handleChange = () => {
onChange(value)
}
return (
<label className="radio-chip" data-disabled={disabled ? 'true' : undefined}>
<input
checked={checked}
disabled={disabled}
name={name}
onChange={handleChange}
type="radio"
required={required}
value={value}
/>
{label}
</label>
)
}
export default RadioChip

View file

@ -0,0 +1,23 @@
import RadioChip from '../js/shared/components/radio-chip'
type Args = React.ComponentProps<typeof RadioChip>
export const RadioChipDefault = (args: Args) => {
return <RadioChip {...args} />
}
export const RadioChipDisabled = (args: Args) => {
return <RadioChip {...args} disabled />
}
export const RadioChipDisabledSelected = (args: Args) => {
return <RadioChip {...args} checked disabled />
}
export default {
title: 'Shared / Components / RadioChip',
component: RadioChip,
args: {
label: 'Option',
},
}

View file

@ -66,6 +66,7 @@
@import 'components/split-menu.less';
@import 'components/group-members.less';
@import 'components/stepper.less';
@import 'components/radio-chip.less';
// Components w/ JavaScript
@import 'components/modals.less';

View file

@ -0,0 +1,57 @@
.radio-chip {
background: @white;
border: 1px solid @neutral-60;
border-radius: 999px;
color: @neutral-90;
display: inline-flex;
font-weight: 400;
gap: 4px;
inline-size: fit-content;
line-height: 1.4;
padding: 8px 16px 8px 8px;
@media only screen and (max-width: @screen-sm-min) {
width: 100%;
}
&:hover {
background: @neutral-20;
}
&:focus-within {
box-shadow: 0px 0px 0px 2px @blue-30;
}
input[type='radio'] {
accent-color: @green-50;
height: 16px;
margin: 4px;
width: 15px;
}
}
.radio-chip[data-disabled='true'] {
border-color: @neutral-20;
&:hover {
background: @white;
cursor: not-allowed;
}
}
.radio-group-col-1 {
align-items: flex-start;
display: flex;
flex-direction: column;
gap: 16px;
}
.radio-group-col-2 {
display: grid;
grid-gap: 16px;
grid-template-columns: 1fr 1fr;
@media (max-width: @screen-sm-min) {
grid-template-columns: 1fr;
}
}

View file

@ -77,6 +77,7 @@
@import 'components/switch.less';
@import 'components/switcher.less';
@import 'components/stepper.less';
@import 'components/radio-chip.less';
// Components w/ JavaScript
@import 'components/modals.less';

View file

@ -32,7 +32,7 @@
}
#onboarding-data-collection {
width: 720px;
max-width: 720px;
padding: 24px;
margin: 0 auto;
background: #fff;
@ -40,9 +40,13 @@
flex-direction: column;
gap: 24px;
p {
.onboarding-question-title {
font-size: 20px;
margin-bottom: 5px;
}
p {
font-size: 16px;
margin-bottom: 16px;
}
.logo {
@ -60,6 +64,11 @@
justify-content: stretch;
gap: 24px;
@media (max-width: @screen-xs-max) {
flex-direction: column;
gap: 0;
}
.form-group {
flex-grow: 1;
}

View file

@ -732,6 +732,7 @@
"help_articles_matching": "Help articles matching your subject",
"help_improve_overleaf_fill_out_this_survey": "If you would like to help us improve Overleaf, please take a moment to fill out <0>this survey</0>.",
"help_us_spread_word": "Help us spread the word about __appName__",
"helps_us_tailor_your_experience": "This helps us tailor your Overleaf experience.",
"hide_configuration": "Hide configuration",
"hide_document_preamble": "Hide document preamble",
"hide_outline": "Hide File outline",
@ -1318,6 +1319,12 @@
"press_and_awards": "Press &amp; awards",
"press_shortcut_to_open_advanced_reference_search": "Press <strong>__ctrlSpace__</strong> or <strong>__altSpace__</strong> to open <strong>Advanced Reference Search</strong>",
"price": "Price",
"primarily_work_study_question": "Where do you primarily work or study?",
"primarily_work_study_question_government": "In the government",
"primarily_work_study_question_nonprofit_ngo": "In a nonprofit/NGO",
"primarily_work_study_question_other": "Other",
"primarily_work_study_question_private_company": "In a private company",
"primarily_work_study_question_university_school": "In a university or school",
"primary_email_check_question": "Is <0>__email__</0> still your email address?",
"priority_support": "Priority support",
"priority_support_info": "Our helpful Support team will prioritise and escalate your support requests where necessary.",

View file

@ -0,0 +1,57 @@
import { expect } from 'chai'
import { render, screen } from '@testing-library/react'
import RadioChip from '@/shared/components/radio-chip'
describe('<RadioChip />', function () {
const defaultProps = {
name: 'test',
label: 'Test',
value: 'testValue',
onChange: () => {},
}
describe('component renders and with label', function () {
it('renders and label is provided', function () {
render(<RadioChip {...defaultProps} />)
screen.getByText('Test')
})
})
describe('props', function () {
it('should be checked when the checked prop is provided', function () {
render(<RadioChip {...defaultProps} checked />)
const radioChip = screen.getByRole('radio') as HTMLInputElement
expect(radioChip.checked).to.equal(true)
})
it('should be disabled when the disabled prop is provided', function () {
render(<RadioChip {...defaultProps} disabled />)
const radioChip = screen.getByRole('radio') as HTMLInputElement
expect(radioChip.disabled).to.equal(true)
})
it('should have the required attribute when the required prop is provided', function () {
render(<RadioChip {...defaultProps} required />)
const radioChip = screen.getByRole('radio') as HTMLInputElement
expect(radioChip.required).to.equal(true)
})
it('should use the provided name prop', function () {
render(<RadioChip {...defaultProps} name="testName" />)
const radioChip = screen.getByRole('radio') as HTMLInputElement
expect(radioChip.name).to.equal('testName')
})
it('should use the provided value prop', function () {
render(<RadioChip {...defaultProps} />)
const radioChip = screen.getByRole('radio') as HTMLInputElement
expect(radioChip.value).to.equal('testValue')
})
it('should have the data-disabled attribute when the disabled prop is provided', function () {
render(<RadioChip {...defaultProps} disabled />)
const label = screen.getByText('Test')?.closest('label')
expect(label?.getAttribute('data-disabled')).to.equal('true')
})
})
})