Files
sigpro-ui/docs/components/rating.md
2026-04-06 03:19:15 +02:00

8.0 KiB
Raw Permalink Blame History

Rating

Star rating component with customizable count, icons, and read-only mode.

Tag

Rating

Props

Prop Type Default Description
value number | Signal<number> 0 Current rating value
count number | Signal<number> 5 Number of stars/items
mask string 'mask-star' Mask shape (mask-star, mask-star-2, mask-heart)
readonly boolean | Signal<boolean> false Disable interaction
class string '' Additional CSS classes (DaisyUI + Tailwind)
onchange function - Callback when rating changes

Styling

Rating supports all daisyUI Rating classes:

Category Keywords Description
Base rating Base rating container
Color rating-primary, rating-secondary, rating-accent, rating-info, rating-success, rating-warning, rating-error Rating color variants
Size rating-xs, rating-sm, rating-md, rating-lg Rating scale
Mask mask-star, mask-star-2, mask-heart Rating icon shapes

For further details, check the daisyUI Rating Documentation Full reference for CSS classes.

Live Examples

Basic Rating

Live Demo

const BasicDemo = () => {
  const rating = $(3);
  
  return Div({ class: 'flex flex-col gap-2 items-center' }, [
    Rating({
      value: rating,
      count: 5,
      onchange: (value) => rating(value)
    }),
    Div({ class: 'text-sm opacity-70' }, () => `Rating: ${rating()} / 5`)
  ]);
};
Mount(BasicDemo, '#demo-basic');

Heart Rating

Live Demo

const HeartDemo = () => {
  const rating = $(4);
  
  return Div({ class: 'flex flex-col gap-2 items-center' }, [
    Rating({
      value: rating,
      count: 5,
      mask: 'mask-heart',
      onchange: (value) => rating(value)
    }),
    Div({ class: 'text-sm opacity-70' }, () => `${rating()} hearts`)
  ]);
};
Mount(HeartDemo, '#demo-heart');

Star with Outline

Live Demo

const Star2Demo = () => {
  const rating = $(2);
  
  return Div({ class: 'flex flex-col gap-2 items-center' }, [
    Rating({
      value: rating,
      count: 5,
      mask: 'mask-star-2',
      onchange: (value) => rating(value)
    }),
    Div({ class: 'text-sm opacity-70' }, () => `${rating()} stars`)
  ]);
};
Mount(Star2Demo, '#demo-star2');

Read-only Rating

Live Demo

const ReadonlyDemo = () => {
  const rating = $(4.5);
  
  return Div({ class: 'flex flex-col gap-2 items-center' }, [
    Rating({
      value: rating,
      count: 5,
      readonly: true
    }),
    Div({ class: 'text-sm opacity-70' }, 'Average rating: 4.5/5 (read-only)')
  ]);
};
Mount(ReadonlyDemo, '#demo-readonly');

Product Review

Live Demo

const ReviewDemo = () => {
  const quality = $(4);
  const price = $(3);
  const support = $(5);
  
  const average = () => Math.round(((quality() + price() + support()) / 3) * 10) / 10;
  
  return Div({ class: 'flex flex-col gap-4' }, [
    Div({ class: 'text-lg font-bold' }, 'Product Review'),
    Div({ class: 'flex flex-col gap-2' }, [
      Div({ class: 'flex justify-between items-center' }, [
        Span({ class: 'text-sm w-24' }, 'Quality:'),
        Rating({
          value: quality,
          count: 5,
          onchange: (v) => quality(v)
        })
      ]),
      Div({ class: 'flex justify-between items-center' }, [
        Span({ class: 'text-sm w-24' }, 'Price:'),
        Rating({
          value: price,
          count: 5,
          onchange: (v) => price(v)
        })
      ]),
      Div({ class: 'flex justify-between items-center' }, [
        Span({ class: 'text-sm w-24' }, 'Support:'),
        Rating({
          value: support,
          count: 5,
          onchange: (v) => support(v)
        })
      ])
    ]),
    Div({ class: 'divider my-1' }),
    Div({ class: 'flex justify-between items-center' }, [
      Span({ class: 'font-bold' }, 'Overall:'),
      Div({ class: 'text-2xl font-bold text-primary' }, () => average())
    ])
  ]);
};
Mount(ReviewDemo, '#demo-review');

All Variants

Live Demo

const VariantsDemo = () => {
  return Div({ class: 'flex flex-col gap-6' }, [
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'Mask Star'),
      Rating({ value: $(3), count: 5, mask: 'mask-star' })
    ]),
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'Mask Star 2 (yellow)'),
      Rating({ value: $(4), count: 5, mask: 'mask-star-2', class: 'rating-warning' })
    ]),
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'Mask Heart'),
      Rating({ value: $(5), count: 5, mask: 'mask-heart', class: 'rating-error' })
    ]),
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'Half Stars (read-only)'),
      Rating({ value: $(3.5), count: 5, readonly: true })
    ])
  ]);
};
Mount(VariantsDemo, '#demo-variants');

Interactive Feedback

Live Demo

const FeedbackDemo = () => {
  const rating = $(0);
  
  const messages = {
    1: 'Very disappointed 😞',
    2: 'Could be better 😕',
    3: 'Good 👍',
    4: 'Very good 😊',
    5: 'Excellent! 🎉'
  };
  
  return Div({ class: 'flex flex-col gap-4 items-center' }, [
    Div({ class: 'text-center' }, [
      Div({ class: 'text-sm mb-2' }, 'How was your experience?'),
      Rating({
        value: rating,
        count: 5,
        onchange: (value) => {
          rating(value);
          if (value >= 4) {
            Toast('Thank you for your positive feedback!', 'alert-success', 2000);
          } else if (value <= 2) {
            Toast('We appreciate your feedback and will improve!', 'alert-warning', 2000);
          } else {
            Toast('Thanks for your rating!', 'alert-info', 2000);
          }
        }
      })
    ]),
    () => rating() > 0 
      ? Div({ class: 'alert alert-soft text-center' }, [
          messages[rating()] || `Rating: ${rating()} stars`
        ])
      : null
  ]);
};
Mount(FeedbackDemo, '#demo-feedback');