feat: add required indicator support to Label component and apply to mandatory form fields

This commit is contained in:
Yoga Pangestu 2026-04-17 15:43:56 +07:00
parent a4a22e1cc5
commit d169e5a733
12 changed files with 52 additions and 47 deletions

View File

@ -5,8 +5,10 @@ import { cn } from "@/lib/utils"
function Label({
className,
required,
children,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
}: React.ComponentProps<typeof LabelPrimitive.Root> & { required?: boolean }) {
return (
<LabelPrimitive.Root
data-slot="label"
@ -15,7 +17,10 @@ function Label({
className
)}
{...props}
/>
>
{children}
{required && <span className="text-destructive font-bold">*</span>}
</LabelPrimitive.Root>
)
}

View File

@ -280,7 +280,7 @@ export default function ExpenseIndex({ expenses }: { expenses: Expense[] }) {
<form onSubmit={onSubmit}>
<FieldGroup>
<Field>
<Label htmlFor="name">Nama</Label>
<Label htmlFor="name" required>Nama</Label>
<Input
id="name"
name="name"
@ -294,7 +294,7 @@ export default function ExpenseIndex({ expenses }: { expenses: Expense[] }) {
</Field>
<Field>
<Label htmlFor="amount">Nominal</Label>
<Label htmlFor="amount" required>Nominal</Label>
<NumericFormat
id="amount"
customInput={Input}

View File

@ -205,7 +205,7 @@ export default function CategoryIndex({ categories }: { categories: Category[] }
<form onSubmit={onSubmit}>
<FieldGroup>
<Field>
<Label htmlFor="name">Nama</Label>
<Label htmlFor="name" required>Nama</Label>
<Input
id="name"
name="name"

View File

@ -132,7 +132,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
</CardHeader>
<CardContent className="space-y-6">
<Field>
<Label htmlFor="name">Nama</Label>
<Label htmlFor="name" required>Nama</Label>
<Input
id="name"
name="name"
@ -146,7 +146,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
</Field>
<Field>
<Label htmlFor="category_ids">Kategori</Label>
<Label htmlFor="category_ids" required>Kategori</Label>
<Combobox
multiple
autoHighlight
@ -205,7 +205,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Field>
<Label htmlFor="price_purchase">Harga Beli</Label>
<Label htmlFor="price_purchase" required>Harga Beli</Label>
<NumericFormat
id="price_purchase"
customInput={Input}
@ -226,7 +226,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
</Field>
<Field>
<Label htmlFor="price_distributor">Harga Distributor</Label>
<Label htmlFor="price_distributor" required>Harga Distributor</Label>
<NumericFormat
id="price_distributor"
customInput={Input}
@ -247,7 +247,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
</Field>
<Field>
<Label htmlFor="price_agent">Harga Agen</Label>
<Label htmlFor="price_agent" required>Harga Agen</Label>
<NumericFormat
id="price_agent"
customInput={Input}
@ -268,7 +268,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
</Field>
<Field>
<Label htmlFor="price_reseller">Harga Reseller</Label>
<Label htmlFor="price_reseller" required>Harga Reseller</Label>
<NumericFormat
id="price_reseller"
customInput={Input}
@ -289,7 +289,7 @@ export default function ProductCreate({ categories }: { categories: Category[] }
</Field>
<Field className="md:col-span-2">
<Label htmlFor="price_retail">Harga Retail</Label>
<Label htmlFor="price_retail" required>Harga Retail</Label>
<NumericFormat
id="price_retail"
customInput={Input}

View File

@ -180,7 +180,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
</CardHeader>
<CardContent className="space-y-6">
<Field>
<Label htmlFor="name">Nama</Label>
<Label htmlFor="name" required>Nama</Label>
<Input
id="name"
name="name"
@ -194,7 +194,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
</Field>
<Field>
<Label htmlFor="category_ids">Kategori</Label>
<Label htmlFor="category_ids" required>Kategori</Label>
<Combobox
multiple
autoHighlight
@ -253,7 +253,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Field>
<Label htmlFor="price_purchase">Harga Beli</Label>
<Label htmlFor="price_purchase" required>Harga Beli</Label>
<NumericFormat
id="price_purchase"
customInput={Input}
@ -274,7 +274,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
</Field>
<Field>
<Label htmlFor="price_distributor">Harga Distributor</Label>
<Label htmlFor="price_distributor" required>Harga Distributor</Label>
<NumericFormat
id="price_distributor"
customInput={Input}
@ -295,7 +295,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
</Field>
<Field>
<Label htmlFor="price_agent">Harga Agen</Label>
<Label htmlFor="price_agent" required>Harga Agen</Label>
<NumericFormat
id="price_agent"
customInput={Input}
@ -316,7 +316,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
</Field>
<Field>
<Label htmlFor="price_reseller">Harga Reseller</Label>
<Label htmlFor="price_reseller" required>Harga Reseller</Label>
<NumericFormat
id="price_reseller"
customInput={Input}
@ -337,7 +337,7 @@ export default function ProductEdit({ product, categories }: { product: Product,
</Field>
<Field className="md:col-span-2">
<Label htmlFor="price_retail">Harga Retail</Label>
<Label htmlFor="price_retail" required>Harga Retail</Label>
<NumericFormat
id="price_retail"
customInput={Input}

View File

@ -63,7 +63,7 @@ export default function UserCreate() {
</CardHeader>
<CardContent className="space-y-6">
<Field>
<Label htmlFor="full_name">Nama Lengkap</Label>
<Label htmlFor="full_name" required>Nama Lengkap</Label>
<Input
id="full_name"
name="full_name"
@ -77,7 +77,7 @@ export default function UserCreate() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Field>
<Label htmlFor="nik">NIK</Label>
<Label htmlFor="nik" required>NIK</Label>
<Input
id="nik"
name="nik"
@ -91,7 +91,7 @@ export default function UserCreate() {
</Field>
<Field>
<Label htmlFor="phone_number">Nomor Telepon</Label>
<Label htmlFor="phone_number" required>Nomor Telepon</Label>
<Input
id="phone_number"
name="phone_number"
@ -104,7 +104,7 @@ export default function UserCreate() {
</Field>
<Field>
<Label htmlFor="birth_place">Tempat Lahir</Label>
<Label htmlFor="birth_place" required>Tempat Lahir</Label>
<Input
id="birth_place"
name="birth_place"
@ -117,7 +117,7 @@ export default function UserCreate() {
</Field>
<Field>
<Label htmlFor="birth_date">Tanggal Lahir</Label>
<Label htmlFor="birth_date" required>Tanggal Lahir</Label>
<Popover open={isCalendarOpen} onOpenChange={setIsCalendarOpen}>
<PopoverTrigger asChild>
<Button
@ -158,7 +158,7 @@ export default function UserCreate() {
</div>
<Field>
<Label htmlFor="address">Alamat</Label>
<Label htmlFor="address" required>Alamat</Label>
<Textarea id='address' name='address' value={data.address} onChange={e => setData('address', e.target.value)} placeholder='Contoh: Kp. Bakan Sampeu' />
{errors.address && <p className="text-xs text-red-500">{errors.address}</p>}
</Field>
@ -173,7 +173,7 @@ export default function UserCreate() {
</CardHeader>
<CardContent className="space-y-6">
<Field>
<Label htmlFor="email">Alamat Surel</Label>
<Label htmlFor="email" required>Alamat Surel</Label>
<Input
id="email"
name="email"
@ -187,7 +187,7 @@ export default function UserCreate() {
</Field>
<Field>
<Label htmlFor="username">Nama Pengguna</Label>
<Label htmlFor="username" required>Nama Pengguna</Label>
<Input
id="username"
name="username"

View File

@ -64,7 +64,7 @@ export default function UserEdit({ user }: { user: any }) {
</CardHeader>
<CardContent className="space-y-6">
<Field>
<Label htmlFor="full_name">Nama Lengkap</Label>
<Label htmlFor="full_name" required>Nama Lengkap</Label>
<Input
id="full_name"
name="full_name"
@ -78,7 +78,7 @@ export default function UserEdit({ user }: { user: any }) {
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Field>
<Label htmlFor="nik">NIK</Label>
<Label htmlFor="nik" required>NIK</Label>
<Input
id="nik"
name="nik"
@ -92,7 +92,7 @@ export default function UserEdit({ user }: { user: any }) {
</Field>
<Field>
<Label htmlFor="phone_number">Nomor Telepon</Label>
<Label htmlFor="phone_number" required>Nomor Telepon</Label>
<Input
id="phone_number"
name="phone_number"
@ -105,7 +105,7 @@ export default function UserEdit({ user }: { user: any }) {
</Field>
<Field>
<Label htmlFor="birth_place">Tempat Lahir</Label>
<Label htmlFor="birth_place" required>Tempat Lahir</Label>
<Input
id="birth_place"
name="birth_place"
@ -118,7 +118,7 @@ export default function UserEdit({ user }: { user: any }) {
</Field>
<Field>
<Label htmlFor="birth_date">Tanggal Lahir</Label>
<Label htmlFor="birth_date" required>Tanggal Lahir</Label>
<Popover open={isCalendarOpen} onOpenChange={setIsCalendarOpen}>
<PopoverTrigger asChild>
<Button
@ -159,7 +159,7 @@ export default function UserEdit({ user }: { user: any }) {
</div>
<Field>
<Label htmlFor="address">Alamat</Label>
<Label htmlFor="address" required>Alamat</Label>
<Textarea id='address' name='address' value={data.address} onChange={e => setData('address', e.target.value)} placeholder='Contoh: Kp. Bakan Sampeu' />
{errors.address && <p className="text-xs text-red-500">{errors.address}</p>}
</Field>
@ -174,7 +174,7 @@ export default function UserEdit({ user }: { user: any }) {
</CardHeader>
<CardContent className="space-y-6">
<Field>
<Label htmlFor="email">Alamat Surel</Label>
<Label htmlFor="email" required>Alamat Surel</Label>
<Input
id="email"
name="email"
@ -188,7 +188,7 @@ export default function UserEdit({ user }: { user: any }) {
</Field>
<Field>
<Label htmlFor="username">Nama Pengguna</Label>
<Label htmlFor="username" required>Nama Pengguna</Label>
<Input
id="username"
name="username"

View File

@ -25,7 +25,7 @@ export default function ForgotPassword({ status }: { status?: string }) {
{({ processing, errors }) => (
<>
<div className="grid gap-2">
<Label htmlFor="email">Email address</Label>
<Label htmlFor="email" required>Email address</Label>
<Input
id="email"
type="email"

View File

@ -28,7 +28,7 @@ export default function Login({
<>
<div className="grid gap-6">
<div className="grid gap-2">
<Label htmlFor="email">Alamat Surel</Label>
<Label htmlFor="email" required>Alamat Surel</Label>
<Input
id="email"
type="email"
@ -44,7 +44,7 @@ export default function Login({
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Kata Sandi</Label>
<Label htmlFor="password" required>Kata Sandi</Label>
</div>
<PasswordInput
id="password"

View File

@ -23,7 +23,7 @@ export default function Register() {
<>
<div className="grid gap-6">
<div className="grid gap-2">
<Label htmlFor="name">Name</Label>
<Label htmlFor="name" required>Name</Label>
<Input
id="name"
type="text"
@ -41,7 +41,7 @@ export default function Register() {
</div>
<div className="grid gap-2">
<Label htmlFor="email">Email address</Label>
<Label htmlFor="email" required>Email address</Label>
<Input
id="email"
type="email"
@ -55,7 +55,7 @@ export default function Register() {
</div>
<div className="grid gap-2">
<Label htmlFor="password">Password</Label>
<Label htmlFor="password" required>Password</Label>
<PasswordInput
id="password"
required
@ -68,7 +68,7 @@ export default function Register() {
</div>
<div className="grid gap-2">
<Label htmlFor="password_confirmation">
<Label htmlFor="password_confirmation" required>
Confirm password
</Label>
<PasswordInput

View File

@ -41,7 +41,7 @@ export default function Profile({
{({ processing, errors }) => (
<>
<div className="grid gap-2">
<Label htmlFor="name">Name</Label>
<Label htmlFor="name" required>Name</Label>
<Input
id="name"
@ -60,7 +60,7 @@ export default function Profile({
</div>
<div className="grid gap-2">
<Label htmlFor="email">Email address</Label>
<Label htmlFor="email" required>Email address</Label>
<Input
id="email"

View File

@ -87,7 +87,7 @@ export default function Security({
{({ errors, processing }) => (
<>
<div className="grid gap-2">
<Label htmlFor="current_password">
<Label htmlFor="current_password" required>
Current password
</Label>
@ -104,7 +104,7 @@ export default function Security({
</div>
<div className="grid gap-2">
<Label htmlFor="password">New password</Label>
<Label htmlFor="password" required>New password</Label>
<PasswordInput
id="password"
@ -119,7 +119,7 @@ export default function Security({
</div>
<div className="grid gap-2">
<Label htmlFor="password_confirmation">
<Label htmlFor="password_confirmation" required>
Confirm password
</Label>