Files
kycnotme/web/src/components/InputRating.astro
2025-05-19 21:31:29 +00:00

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>