Feedback
Default feedback form
The information on the GDPR should be obligatorily shown to the users from Europe. See the component's guide for the styles and its content.
tsx
import React from 'react';
import FeedbackForm from 'intergalactic/feedback-form';
import Input from 'intergalactic/input';
import { Box, Flex } from 'intergalactic/flex-box';
import Link from 'intergalactic/link';
import Dropdown from 'intergalactic/dropdown';
import ChatM from 'intergalactic/icon/Chat/m';
import Textarea from 'intergalactic/textarea';
import { Text } from 'intergalactic/typography';
import Button, { ButtonLink } from 'intergalactic/button';
const validate = {
description: (value = '') => {
const splitText = value.split(' ');
const numberSpaces = splitText.reduce((acc, item) => {
if (!item.length) {
acc += 1;
}
return acc;
}, 0);
if ([...value].length - numberSpaces < 10) {
return 'Your feedback must contain at least 10 characters.';
}
},
email: (value = '') => {
validate.description(value);
if (!/.+@.+\..+/i.test(String(value).toLowerCase())) {
return 'Please enter valid email.\t';
}
},
};
class Feedback extends React.PureComponent<{
status: string;
onSubmit: (data: any) => void;
onCancel: () => void;
onChange: (event: any, trigger: string) => void;
value: { description: string; email: string };
}> {
handleChange = (fn) => (_, e) => {
fn(e);
this.props.onChange(e, e.currentTarget.id);
};
render() {
const { status, onSubmit, onCancel, value } = this.props;
if (status === 'success') {
return <FeedbackForm.Success>Thank you for your feedback!</FeedbackForm.Success>;
}
return (
<FeedbackForm onSubmit={onSubmit} loading={status === 'loading'}>
<Box p={4}>
<Flex tag='label' direction='column' htmlFor='suggestions'>
<Text mb={2} size={200}>
Tell us your suggestion or report an issue
</Text>
<FeedbackForm.Item
name='description'
validate={validate.description}
initialValue={''}
placement='left-start'
flip={{
fallbackPlacements: ['right-start', 'bottom'],
}}
validateOnBlur={value.description === '' ? false : true}
>
{({ input }) => (
<Textarea
{...input}
autoFocus
h={80}
onChange={this.handleChange(input.onChange)}
id='description'
/>
)}
</FeedbackForm.Item>
</Flex>
<Flex tag='label' mt={4} direction='column' htmlFor='email'>
<Text mb={2} size={200}>
Reply-to email
</Text>
<FeedbackForm.Item
name='email'
validate={validate.email}
initialValue={''}
validateOnBlur={value.email === '' ? false : true}
>
{({ input }) => (
<Input state={input.state}>
<Input.Value {...input} onChange={this.handleChange(input.onChange)} id='email' />
</Input>
)}
</FeedbackForm.Item>
</Flex>
<Box mt={2}>
<Text size={200} color='text-secondary'>
We will only use this email to respond to you on your feedback.{' '}
<Link href='https://www.semrush.com/company/legal/privacy-policy/'>
Privacy Policy
</Link>
</Text>
</Box>
<Flex mt={4}>
<FeedbackForm.Submit>Send feedback</FeedbackForm.Submit>
<FeedbackForm.Cancel onClick={onCancel}>Cancel</FeedbackForm.Cancel>
</Flex>
</Box>
<FeedbackForm.Notice hidden={status === 'failed'}>
You can also send us an email to <Link>backlink.audit@semrush.com</Link>
</FeedbackForm.Notice>
<FeedbackForm.Notice hidden={status !== 'failed'} theme='danger'>
Your message has not been sent.
</FeedbackForm.Notice>
</FeedbackForm>
);
}
}
class FeedbackLink extends React.PureComponent {
state = { status: 'default', value: { description: '', email: '' } };
timeout: any;
onSubmit = () => {
this.requestServer('success', 1000);
this.setState({ status: 'loading' });
};
onChange = (e, trigger) => {
const { value } = e.currentTarget;
this.setState({ value: { ...this.state.value, [trigger]: value } });
};
requestServer = (status, time = 500, cb = () => {}) => {
this.timeout = setTimeout(() => {
this.setState({ status });
cb();
}, time);
};
componentWillUnmount() {
clearTimeout(this.timeout);
}
render() {
const { status, value } = this.state;
return (
<Dropdown>
<Dropdown.Trigger tag={ButtonLink} addonLeft={ChatM}>
Send feedback
</Dropdown.Trigger>
<Dropdown.Popper
role={'dialog'}
aria-label={'Feedback form'}
aria-modal={'true'}
tabIndex={-1}
>
{(_props, { visible }) => (
<Feedback
status={status}
onCancel={() => visible(false)}
onSubmit={() => this.onSubmit()}
value={value}
onChange={this.onChange}
/>
)}
</Dropdown.Popper>
</Dropdown>
);
}
}
const Demo = FeedbackLink;
export default Demo;
Feedback form example
Refer for more details about forms in the Form.
tsx
import React from 'react';
import FeedbackForm from 'intergalactic/feedback-form';
import Input from 'intergalactic/input';
import InputNumber from 'intergalactic/input-number';
import Radio, { RadioGroup } from 'intergalactic/radio';
import Select from 'intergalactic/select';
import { Text } from 'intergalactic/typography';
import { Flex, Box } from 'intergalactic/flex-box';
type Data = {
title: string;
campaign: string;
call: boolean;
day: number;
};
const validate = (values: Data) => {
if (!values) return {};
const errors: Partial<Record<keyof Data, string>> = {};
if (!values.title) {
errors.title = 'Title is required';
}
if (!values.campaign) {
errors.campaign = 'Campaign is required';
}
if (!values.call) {
errors.call = 'To pick to call or not is required';
}
if (!values.day || values.day <= 0) {
errors.day = 'Invalid day value';
}
return errors;
};
const Demo = () => (
<FeedbackForm validate={validate} p={1} onSubmit={() => ({})}>
<Box tag={'label'} htmlFor='acitivty'>
<Text mb={2} tag='p' size={200}>
Activity
</Text>
<FeedbackForm.Item name='title'>
{({ input }) => {
const { state, className, ...other } = input;
return (
<Input state={state} className={className}>
<Input.Value
{...other}
placeholder='Activity title'
id='acitivty'
autoComplete='off'
/>
</Input>
);
}}
</FeedbackForm.Item>
</Box>
<Box tag={'label'} htmlFor='campaign' mt={4}>
<Text mb={2} tag='p' size={200}>
Campaign
</Text>
<FeedbackForm.Item name='campaign'>
{({ input }) => (
<Select onChange={input.onChange} state={input.state} placeholder='Select campaign'>
<Select.Trigger id='campaign' {...input} />
<Select.Menu>
{Array(4)
.fill(0)
.map((item, ind) => (
<Select.Option
value={`Company ${ind}`}
key={ind}
>{`Company ${ind}`}</Select.Option>
))}
</Select.Menu>
</Select>
)}
</FeedbackForm.Item>
</Box>
<Box tag={'label'} htmlFor='day' mt={4}>
<Text mb={2} tag='p' size={200}>
Day
</Text>
<FeedbackForm.Item name='day'>
{({ input }) => {
const { state, className, ...other } = input;
return (
<InputNumber state={state} className={className}>
<InputNumber.Value id='day' {...other} placeholder='Enter day' autoComplete='off' />
</InputNumber>
);
}}
</FeedbackForm.Item>
</Box>
<FeedbackForm.Item name='call'>
{({ input }) => (
<RadioGroup {...input}>
<Flex direction='column' gap={1} my={4}>
<Radio>
<Radio.Value value='yes' />
<Radio.Text>Call me</Radio.Text>
</Radio>
<Radio>
<Radio.Value value='no' />
<Radio.Text>Don't call me!</Radio.Text>
</Radio>
</Flex>
</RadioGroup>
)}
</FeedbackForm.Item>
<FeedbackForm.Submit>Submit this strange form</FeedbackForm.Submit>
</FeedbackForm>
);
export default Demo;