--- 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' : ''} >