<rating-stars>
<fieldset>
<legend class="visually-hidden">Rate</legend>
<label data-key="1">
<input type="radio" class="visually-hidden" name="rating" value="1">
<span class="label">☆</span>
</label>
<label data-key="2">
<input type="radio" class="visually-hidden" name="rating" value="2">
<span class="label">☆</span>
</label>
<label data-key="3">
<input type="radio" class="visually-hidden" name="rating" value="3">
<span class="label">☆</span>
</label>
<label data-key="4">
<input type="radio" class="visually-hidden" name="rating" value="4">
<span class="label">☆</span>
</label>
<label data-key="5">
<input type="radio" class="visually-hidden" name="rating" value="5">
<span class="label">☆</span>
</label>
</fieldset>
</rating-stars>
rating-stars {
display: inline-block;
& fieldset {
display: flex;
border: none;
margin: 0;
padding: 0;
justify-content: center;
}
& label {
display: block;
cursor: pointer;
width: var(--input-height);
height: var(--input-height);
color: var(--color-primary);
font-size: var(--font-size-l);
border-radius: var(--space-xs);
text-align: center;
&:hover,
&:focus-within {
color: var(--color-primary-hover);
background-color: rgba(0, 0, 0, 0.05);
}
&:active {
color: var(--color-primary-active);
background-color: rgba(0, 0, 0, 0.1);
}
}
}
import {
type Component,
asInteger,
component,
emitEvent,
on,
setProperty,
setText,
} from '../../../'
export type RatingStarsProps = {
value: number
}
export default component(
'rating-stars',
{
value: asInteger(),
},
(el, { all }) => {
const getKey = (element: HTMLElement): number =>
parseInt(element.dataset['key'] || '0')
return [
emitEvent('change-rating', 'value'),
all(
'input',
setProperty('checked', target => el.value === getKey(target)),
on('change', e => {
e.stopPropagation()
const value = parseInt((e.currentTarget as HTMLInputElement)?.value)
el.value = value + 1
}),
),
all(
'.label',
setText(target => (getKey(target) <= el.value ? '★' : '☆')),
),
]
},
)
declare global {
interface HTMLElementTagNameMap {
'rating-stars': Component<RatingStarsProps>
}
interface HTMLElementEventMap {
'change-rating': CustomEvent<number>
}
}