272 lines
8.0 KiB
Markdown
272 lines
8.0 KiB
Markdown
# 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](https://daisyui.com/components/rating) – Full reference for CSS classes.
|
||
|
||
## Live Examples
|
||
|
||
### Basic Rating
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-basic" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
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
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-heart" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
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
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-star2" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
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
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-readonly" class="bg-base-100 p-6 rounded-xl border border-base-300 flex items-center justify-center"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
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
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-review" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
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
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-variants" class="bg-base-100 p-6 rounded-xl border border-base-300 flex flex-col gap-6"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
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
|
||
|
||
<div class="card bg-base-200 border border-base-300 shadow-sm my-6">
|
||
<div class="card-body">
|
||
<h3 class="card-title text-sm uppercase opacity-50 mb-4">Live Demo</h3>
|
||
<div id="demo-feedback" class="bg-base-100 p-6 rounded-xl border border-base-300"></div>
|
||
</div>
|
||
</div>
|
||
|
||
```javascript
|
||
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');
|
||
``` |