---
myst:
html_meta:
"description": ""
"property=og:description": ""
"property=og:title": ""
"keywords": ""
---
(custom-widget-label)=
# Custom Widget
In this chapter we are going to build a custom widget.
The widget we are going to build is a rating widget with one to five stars.
## Setup The Content Type
We will add a rating field to the `Page` content type.
Go to the Plone Control Panel at .
Add a field called `Rating` with short name `rating` and type `Integer`.
Next we will create a file `components/RatingWidget/RatingWidget.jsx`.
We will start with a copy of the `components/manage/Widgets/TextWidget.jsx` file from Volto,
and rename the class to `RatingWidget`.
```jsx
/**
* RatingWidget component.
* @module components/RatingWidget/RatingWidget
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Form, Grid, Icon, Input, Label } from 'semantic-ui-react';
import { map } from 'lodash';
import { defineMessages, injectIntl, intlShape } from 'react-intl';
const messages = defineMessages({
default: {
id: 'Default',
defaultMessage: 'Default',
},
idTitle: {
id: 'Short Name',
defaultMessage: 'Short Name',
},
idDescription: {
id: 'Used for programmatic access to the fieldset.',
defaultMessage: 'Used for programmatic access to the fieldset.',
},
title: {
id: 'Title',
defaultMessage: 'Title',
},
description: {
id: 'Description',
defaultMessage: 'Description',
},
required: {
id: 'Required',
defaultMessage: 'Required',
},
});
/**
* RatingWidget component class.
* @function RatingWidget
* @returns {string} Markup of the component.
*/
const RatingWidget = ({
id,
title,
required,
description,
error,
value,
onChange,
onEdit,
onDelete,
intl,
}) => {
const schema = {
fieldsets: [
{
id: 'default',
title: intl.formatMessage(messages.default),
fields: ['title', 'id', 'description', 'required'],
},
],
properties: {
id: {
type: 'string',
title: intl.formatMessage(messages.idTitle),
description: intl.formatMessage(messages.idDescription),
},
title: {
type: 'string',
title: intl.formatMessage(messages.title),
},
description: {
type: 'string',
widget: 'textarea',
title: intl.formatMessage(messages.description),
},
required: {
type: 'boolean',
title: intl.formatMessage(messages.required),
},
},
required: ['id', 'title'],
};
return (
0}
className={description ? 'help' : ''}
>