Skip to main content

Rate

Overview​

The Rate component provides a star/icon-based rating system.

It supports custom icons, sizes, and display options for building rating interfaces.


Import​

import { Rate } from '@allxsmith/bestax-bulma';

Usage​

Basic Rating​

A simple 5-star rating.

function example() {
  const [rating, setRating] = useState(3);
  return (
    <Block>
      <Rate value={rating} onChange={setRating} />
      <Paragraph mt="2">Rating: {rating} stars</Paragraph>
    </Block>
  );
}


With Score Display​

Rating showing the numeric score.

function example() {
  const [rating, setRating] = useState(4);
  return <Rate value={rating} onChange={setRating} showScore />;
}


With Text Labels​

Rating with descriptive text for each level.

function example() {
  const [rating, setRating] = useState(3);
  return (
    <Rate
      value={rating}
      onChange={setRating}
      showText
      texts={['Poor', 'Fair', 'Average', 'Good', 'Excellent']}
    />
  );
}


With Score and Text​

Both score and text displayed together.

function example() {
  const [rating, setRating] = useState(4);
  return (
    <Rate
      value={rating}
      onChange={setRating}
      showScore
      showText
      texts={['Terrible', 'Bad', 'OK', 'Good', 'Great']}
    />
  );
}


Size Variants​

Ratings in different sizes.

<Block display="flex" flexDirection="column" gap="4">
  <Rate defaultValue={3} size="small" />
  <Rate defaultValue={3} />
  <Rate defaultValue={3} size="medium" />
  <Rate defaultValue={3} size="large" />
</Block>


Custom Max Value​

Rating with more than 5 stars.

function example() {
  const [rating, setRating] = useState(7);
  return (
    <Block>
      <Rate value={rating} onChange={setRating} max={10} showScore />
      <Paragraph mt="2">Rating: {rating} out of 10</Paragraph>
    </Block>
  );
}


Spaced Icons​

Rating with spacing between stars.

<Rate defaultValue={3} spaced />


Disabled Rating​

A read-only rating display.

<Rate value={4} disabled showScore />


Custom Icons​

Rating with custom heart icons.

function example() {
  const [rating, setRating] = useState(3);

  const HeartIcon = ({ isActive }) => (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 24 24"
      fill={isActive ? 'currentColor' : 'none'}
      stroke="currentColor"
      strokeWidth={isActive ? 0 : 2}
      style={{ color: '#f14668' }}
    >
      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
    </svg>
  );

  return (
    <Rate
      value={rating}
      onChange={setRating}
      customIcon={({ isActive }) => <HeartIcon isActive={isActive} />}
      showScore
    />
  );
}


Context-Aware Rendering​

The Rate component is context-aware: it detects whether it is already inside a Field and adjusts its rendering accordingly. This means you can use it standalone with a label prop (it wraps itself in a Field), or inside a Field (it skips rendering its own).

Default (with label)​

The simplest usage — the component automatically renders its own Field wrapper.

<Rate label="Rating" defaultValue={3} />


With Field Wrapper​

When you need manual control over the Field layout (e.g., horizontal forms), wrap the component in Field. The component detects it's inside a Field and skips rendering its own.

function example() {
  return (
    <Field horizontal label="Rating">
      <Field.Body>
        <Field>
          <Rate defaultValue={3} />
        </Field>
      </Field.Body>
    </Field>
  );
}


With Field and Control Wrappers​

For full manual composition, wrap in both Field and Control. The component detects the Field context and renders only the rating element.

function example() {
  return (
    <Field horizontal label="Rating">
      <Field.Body>
        <Field>
          <Control iconLeftName="star">
            <Rate defaultValue={3} />
          </Control>
        </Field>
      </Field.Body>
    </Field>
  );
}


Controlled vs Uncontrolled​

Controlled Mode​

Use value and onChange to manage state externally:

const [rating, setRating] = useState(3);
<Rate value={rating} onChange={setRating} />;

Uncontrolled Mode​

Use defaultValue for internal state management:

<Rate defaultValue={3} />

Click Behavior​

Clicking the same star twice will deselect it (set value to 0). This allows users to clear their rating if needed.


Form Submission​

Rate is an HTML form element. Pass a name prop and the current rating value is rendered as a hidden <input type="hidden"> inside the component, so it's included in FormData on submit and posts to the server like any native input.

PropDescription
nameForm field name. When set, a hidden input is rendered.
formOptional id of the form this hidden input belongs to (use when the input lives outside the form element).

Submit the form below and inspect the resulting FormData entries:

function RateFormDemo() {
  const [submitted, setSubmitted] = React.useState('');
  return (
    <form
      onSubmit={e => {
        e.preventDefault();
        const fd = new FormData(e.currentTarget);
        setSubmitted(JSON.stringify(Array.from(fd.entries()), null, 2));
      }}
    >
      <Rate name="rating" defaultValue={3} showScore />
      <div style={{ marginTop: '1rem' }}>
        <button type="submit" className="button is-primary">
          Submit
        </button>
      </div>
      {submitted && <pre style={{ marginTop: '1rem' }}>{submitted}</pre>}
    </form>
  );
}


Accessibility​

  • Uses role="radiogroup" for the container
  • Each star has role="radio" with aria-checked
  • Has aria-valuenow, aria-valuemin, and aria-valuemax
  • Full keyboard navigation with arrow keys
  • Home/End keys jump to 0/max values

  • Slider - For selecting numeric values with a range
  • Input - For text input

Additional Resources​

Pro Tip

Use the texts prop to provide context for each rating level, helping users understand what each star value means.


Props​

PropTypeDefaultDescription
namestring—Form field name. When set, a hidden input is rendered. Form field name. When provided, a hidden input is rendered so the rating value is submitted with the surrounding form.
formstring—Optional id of the form this hidden input belongs to (use when the input lives outside the form element).
valuenumber—Controlled value (0 to max). Controlled rating value.
defaultValuenumber0Default value for uncontrolled usage. Initial value for uncontrolled mode. Default: 0.
maxnumber5Maximum rating value. Maximum number of icons. Default: 5.
size'small' | 'medium' | 'large'—Size variant. Size modifier for the component.
disabledbooleanfalseWhether the rating is disabled.
showScorebooleanfalseShow the numeric score next to stars. Display the numeric score next to icons.
showTextbooleanfalseShow custom text based on value. Display text label for the current value.
textsstring[]—Array of text labels for each rating value. Text labels per rating level (used with showText).
onChange(value: number) => void—Callback when the rating changes.
customIcon(props: RateIconProps) => React.ReactNode—Custom icon renderer. Custom icon render function.
spacedbooleanfalseAdd spacing between icons.
rtlbooleanfalseRight-to-left direction. Render icons in right-to-left order.
iconNamestring—Custom icon name for the rating stars. Font icon name (e.g., 'star'). When set, renders <Icon> instead of default SVG.
iconLibrary'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols'—Icon library to use (defaults to ConfigProvider value or 'fa').
iconVariantstring—Icon style variant (e.g., 'solid', 'outlined').
iconFeaturesstring | string[]—Additional icon modifiers.
color'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'—Color of the active rating icons. Bulma color for active icons.
precisionnumber1Rating precision (e.g., 0.5 for half stars). Granularity: 1 for whole stars, 0.5 for half, 0.25 for quarter.
customTextstring—Custom text displayed next to the rating. Text displayed after score (e.g., "(128 reviews)").
labelReact.ReactNode—Field label, rendered above the widget.
labelSize'small' | 'normal' | 'medium' | 'large'—Size for the label (used in horizontal layouts).
labelPropsReact.LabelHTMLAttributes<HTMLLabelElement> & { [key: string]: unknown; }—Props for the label element.
horizontalbooleanfalseHorizontal field layout.
messageReact.ReactNode—Help/validation message below the input.
messageColor'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'—Bulma color for the message.
fieldClassNamestring—Additional CSS classes for the Field wrapper.
childrenReact.ReactNode—Content rendered inside the component.
classNamestring—Additional CSS classes.
refReact.Ref<HTMLElement>—Ref forwarded to the container element.
indexnumber—The index of this icon (0-based).
isActiveboolean—Whether this icon is currently active (filled).
isHoveredboolean—Whether this icon is currently hovered.
...All standard <div> attributes and Bulma helper props—See Helper Props

RateIconProps​

PropTypeDescription
indexnumberThe index of this icon (0-based).
isActivebooleanWhether this icon is currently active (filled).
isHoveredbooleanWhether this icon is currently hovered.
valuenumberThe current value.

CSS & Sass Variables​

Rate registers these variables on its own .rate element. Override them there (or via className) — a value set on an ancestor is only inherited, and loses to the component-level declaration. See Theme.

CSS VariableSass VariableDefault
--bulma-rate-color-inactive$rate-color-inactivevar(--bulma-grey-light)
--bulma-rate-color-active$rate-color-activehsl(48, 100%, 50%)
--bulma-rate-color-hover$rate-color-hoverhsl(48, 100%, 67%)
--bulma-rate-icon-size$rate-icon-size1.5em
--bulma-rate-icon-size-small$rate-icon-size-small1em
--bulma-rate-icon-size-medium$rate-icon-size-medium2em
--bulma-rate-icon-size-large$rate-icon-size-large2.5em
--bulma-rate-font-icon-size$rate-font-icon-size1.35em
--bulma-rate-font-icon-size-small$rate-font-icon-size-small0.9em
--bulma-rate-font-icon-size-medium$rate-font-icon-size-medium1.8em
--bulma-rate-font-icon-size-large$rate-font-icon-size-large2.25em
--bulma-rate-gap$rate-gap0.5rem
--bulma-rate-spaced-gap$rate-spaced-gap0.25rem
--bulma-rate-score-weight$rate-score-weight600
--bulma-rate-score-color$rate-score-colorvar(--bulma-text-strong)
--bulma-rate-text-color$rate-text-colorvar(--bulma-text)
--bulma-rate-text-size$rate-text-size0.875em
--bulma-rate-transition-duration$rate-transition-durationvar(--bulma-duration)
--bulma-rate-disabled-opacity$rate-disabled-opacity0.5
--bulma-rate-pop-scale$rate-pop-scale1.2