65 lines
2.4 KiB
Plaintext
65 lines
2.4 KiB
Plaintext
---
|
|
import { Icon } from 'astro-icon/components'
|
|
|
|
import InputWrapper from './InputWrapper.astro'
|
|
|
|
import type { ComponentProps } from 'astro/types'
|
|
|
|
const ratings = [1, 2, 3, 4, 5] as const
|
|
|
|
type Props = Omit<ComponentProps<typeof InputWrapper>, 'children' | 'inputId' | 'required'> & {
|
|
value?: number | null
|
|
required?: boolean
|
|
id?: string
|
|
}
|
|
|
|
const { value, required, id, ...wrapperProps } = Astro.props
|
|
const actualValue = value !== undefined && value !== null ? Math.round(value) : null
|
|
const inputId = id ?? Astro.locals.makeId(`input-${wrapperProps.name}`)
|
|
---
|
|
|
|
<InputWrapper inputId={inputId} required={required} {...wrapperProps}>
|
|
<div
|
|
class="group/fieldset has-focus-visible:ring-day-200 has-focus-visible:ring-offset-night-700 relative flex items-center has-focus-visible:rounded-full has-focus-visible:ring-2 has-focus-visible:ring-offset-2 [&>*:has(~_*:hover)]:[&>[data-star]]:opacity-100!"
|
|
>
|
|
<label
|
|
aria-label="Clear"
|
|
class="has-focus-visible:before:bg-day-200 hover:before:bg-day-200 relative order-last block size-6 p-0.5 text-zinc-500 not-has-checked:cursor-pointer before:absolute before:inset-0.5 before:-z-1 before:rounded-full hover:text-black has-checked:before:hidden has-focus-visible:text-black has-focus-visible:before:block!"
|
|
>
|
|
<input
|
|
type="radio"
|
|
name={wrapperProps.name}
|
|
value=""
|
|
checked={actualValue === null}
|
|
class="peer sr-only"
|
|
/>
|
|
|
|
<Icon
|
|
name="ri:close-line"
|
|
class="size-full group-hover/fieldset:block group-has-focus-visible/fieldset:block peer-checked:hidden! peer-focus-visible:block! pointer-fine:hidden"
|
|
/>
|
|
</label>
|
|
|
|
{
|
|
ratings.toSorted().map((rating) => (
|
|
<label class="relative cursor-pointer [&:has(~_*_*:checked)]:[&>[data-star]]:opacity-100 [&:has(~_*:hover),&:hover]:[&>[data-star]]:opacity-100!">
|
|
<input
|
|
type="radio"
|
|
name={wrapperProps.name}
|
|
value={rating}
|
|
checked={actualValue === rating}
|
|
class="peer sr-only"
|
|
/>
|
|
|
|
<Icon name="ri:star-line" class="size-6 p-0.5 text-zinc-500" />
|
|
<Icon
|
|
name="ri:star-fill"
|
|
class="absolute top-0 left-0 size-6 p-0.5 text-yellow-400 not-peer-checked:opacity-0 group-hover/fieldset:opacity-0!"
|
|
data-star
|
|
/>
|
|
</label>
|
|
))
|
|
}
|
|
</div>
|
|
</InputWrapper>
|