fix: react-doctor control-has-associated-label -12 (wholesale files)
Add aria-labels to 11 wholesale client controls + 1 portal search clear.
This commit is contained in:
@@ -772,6 +772,7 @@ function CustomersTab({ customers, products, brandId, onMsg, registrations = [],
|
||||
<button type="button"
|
||||
onClick={() => openPriceSheetModal([c.id])}
|
||||
title="Send price sheet"
|
||||
aria-label="Send price sheet"
|
||||
className="inline-flex items-center justify-center rounded-xl w-9 h-9 text-[var(--admin-accent)] hover:text-[var(--admin-accent-text)] hover:bg-[var(--admin-accent-light)] transition-colors"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.75}><path strokeLinecap="round" strokeLinejoin="round" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>
|
||||
@@ -780,6 +781,7 @@ function CustomersTab({ customers, products, brandId, onMsg, registrations = [],
|
||||
<button type="button"
|
||||
onClick={(e) => toggleCustomerActions(c.id, e)}
|
||||
title="More actions"
|
||||
aria-label="More actions"
|
||||
className="inline-flex items-center justify-center rounded-xl w-9 h-9 text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)] hover:bg-[var(--admin-bg-subtle)] transition-colors"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><circle cx="10" cy="4" r="1.5"/><circle cx="10" cy="10" r="1.5"/><circle cx="10" cy="16" r="1.5"/></svg>
|
||||
@@ -936,7 +938,7 @@ function CustomerPricingPanel({ customer, products, onClose, onMsg }: {
|
||||
<h2 className="text-lg font-bold text-[var(--admin-text-primary)]">Pricing Overrides</h2>
|
||||
<p className="text-sm text-[var(--admin-text-muted)]">{customer.company_name}</p>
|
||||
</div>
|
||||
<button type="button" onClick={onClose} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)]">
|
||||
<button type="button" onClick={onClose} aria-label="Close pricing overrides" className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)]">
|
||||
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
@@ -1060,7 +1062,7 @@ function PriceSheetModal({
|
||||
{customerCount === 1 ? "1 customer" : `${customerCount} customers`}
|
||||
</p>
|
||||
</div>
|
||||
<button type="button" onClick={onClose} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)]">
|
||||
<button type="button" onClick={onClose} aria-label="Close send price sheet" className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)]">
|
||||
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
@@ -1329,6 +1331,7 @@ function ProductsTab({ products, brandId, onMsg, onRefresh }: {
|
||||
<button type="button"
|
||||
onClick={(e) => toggleProductActions(p.id, e)}
|
||||
title="More actions"
|
||||
aria-label="More actions"
|
||||
className="inline-flex items-center justify-center rounded-xl w-9 h-9 text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)] hover:bg-[var(--admin-bg-subtle)] transition-colors"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><circle cx="10" cy="4" r="1.5"/><circle cx="10" cy="10" r="1.5"/><circle cx="10" cy="16" r="1.5"/></svg>
|
||||
@@ -1732,6 +1735,7 @@ function OrdersTab({ orders, customers, brandId, onMsg, onRefresh }: {
|
||||
<button type="button"
|
||||
onClick={(e) => toggleActions(o.id, e)}
|
||||
title="More actions"
|
||||
aria-label="More actions"
|
||||
className="inline-flex items-center justify-center rounded-xl w-9 h-9 text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)] hover:bg-[var(--admin-bg-subtle)] transition-colors"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><circle cx="10" cy="4" r="1.5"/><circle cx="10" cy="10" r="1.5"/><circle cx="10" cy="16" r="1.5"/></svg>
|
||||
@@ -2019,6 +2023,7 @@ function SettingsTab({ settings, brandId, onMsg, onRefresh, canManageSettings }:
|
||||
</div>
|
||||
<button type="button"
|
||||
onClick={() => setForm(f => ({ ...f, requireApproval: !f.requireApproval }))}
|
||||
aria-label="Toggle require approval"
|
||||
className={`relative inline-flex h-7 w-12 items-center rounded-full transition-colors ${form.requireApproval ? "bg-[var(--admin-accent)]" : "bg-[var(--admin-border)]"}`}
|
||||
>
|
||||
<span className={`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${form.requireApproval ? "translate-x-6" : "translate-x-1"}`} />
|
||||
@@ -2032,6 +2037,7 @@ function SettingsTab({ settings, brandId, onMsg, onRefresh, canManageSettings }:
|
||||
</div>
|
||||
<button type="button"
|
||||
onClick={() => setForm(f => ({ ...f, wholesaleEnabled: !f.wholesaleEnabled }))}
|
||||
aria-label="Toggle wholesale portal"
|
||||
className={`relative inline-flex h-7 w-12 items-center rounded-full transition-colors ${form.wholesaleEnabled ? "bg-[var(--admin-accent)]" : "bg-[var(--admin-border)]"}`}
|
||||
>
|
||||
<span className={`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${form.wholesaleEnabled ? "translate-x-6" : "translate-x-1"}`} />
|
||||
@@ -2057,6 +2063,7 @@ function SettingsTab({ settings, brandId, onMsg, onRefresh, canManageSettings }:
|
||||
</div>
|
||||
<button type="button"
|
||||
onClick={() => setForm(f => ({ ...f, squareSyncEnabled: !f.squareSyncEnabled }))}
|
||||
aria-label="Toggle square sync"
|
||||
className={`relative inline-flex h-7 w-12 items-center rounded-full transition-colors ${form.squareSyncEnabled ? "bg-[var(--admin-accent)]" : "bg-[var(--admin-border)]"}`}
|
||||
>
|
||||
<span className={`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${form.squareSyncEnabled ? "translate-x-6" : "translate-x-1"}`} />
|
||||
@@ -2147,6 +2154,7 @@ function SettingsTab({ settings, brandId, onMsg, onRefresh, canManageSettings }:
|
||||
onChange={e => updateRecipientName(idx, e.target.value)}
|
||||
className="rounded-xl border border-[var(--admin-border)] px-2.5 py-1.5 text-xs w-36 outline-none focus:border-[var(--admin-accent)]" />
|
||||
<button type="button" onClick={() => removeRecipient(idx)}
|
||||
aria-label="Remove recipient"
|
||||
className="text-[var(--admin-danger)] hover:text-[var(--admin-danger)] text-xs font-medium px-2 py-1 rounded-lg hover:bg-[var(--admin-danger-light)] transition-colors"
|
||||
title="Remove recipient">
|
||||
<svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
|
||||
@@ -2280,6 +2288,7 @@ function WebhookSettingsSection({ brandId, onMsg }: {
|
||||
</div>
|
||||
<button type="button"
|
||||
onClick={() => setSettings(s => ({ ...s, enabled: !s.enabled }))}
|
||||
aria-label="Toggle webhook"
|
||||
className={`relative inline-flex h-7 w-12 items-center rounded-full transition-colors ${settings.enabled ? "bg-[var(--admin-accent)]" : "bg-[var(--admin-border)]"}`}
|
||||
>
|
||||
<span className={`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${settings.enabled ? "translate-x-6" : "translate-x-1"}`} />
|
||||
|
||||
@@ -172,6 +172,7 @@ function SearchBar({ value, onChange, placeholder }: {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onChange("")}
|
||||
aria-label="Clear search"
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
||||
|
||||
@@ -293,7 +293,7 @@ export default function OrdersTab({ orders, customers, brandId, onMsg, onRefresh
|
||||
<thead className="bg-[var(--admin-bg-subtle)] text-[var(--admin-text-muted)]">
|
||||
<tr>
|
||||
<th className="px-5 py-3 font-semibold text-left w-10">
|
||||
<input id="fld-search" type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={toggleAll} className="rounded" />
|
||||
<input id="fld-search" type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={toggleAll} aria-label="Select all orders" className="rounded" />
|
||||
</th>
|
||||
<th className="px-5 py-3 font-semibold text-left">Invoice</th>
|
||||
<th className="px-5 py-3 font-semibold text-left">Customer</th>
|
||||
@@ -312,7 +312,7 @@ export default function OrdersTab({ orders, customers, brandId, onMsg, onRefresh
|
||||
) : filtered.map(o => (
|
||||
<tr key={o.id} className={`hover:bg-[var(--admin-bg-subtle)] ${selected.has(o.id) ? "bg-[var(--admin-accent-light)]" : ""}`}>
|
||||
<td className="px-5 py-3">
|
||||
<input type="checkbox" checked={selected.has(o.id)} onChange={() => toggleSelect(o.id)} className="rounded" />
|
||||
<input type="checkbox" checked={selected.has(o.id)} onChange={() => toggleSelect(o.id)} aria-label={`Select order ${o.invoice_number ?? o.id}`} className="rounded" />
|
||||
</td>
|
||||
<td className="px-5 py-3 font-mono text-xs text-[var(--admin-text-muted)]">{o.invoice_number ?? "—"}</td>
|
||||
<td className="px-5 py-3 font-medium text-[var(--admin-text-primary)]">{o.company_name}</td>
|
||||
@@ -372,6 +372,7 @@ export default function OrdersTab({ orders, customers, brandId, onMsg, onRefresh
|
||||
<button type="button"
|
||||
onClick={(e) => toggleActions(o.id, e)}
|
||||
title="More actions"
|
||||
aria-label={`More actions for order ${o.invoice_number ?? o.id}`}
|
||||
className="inline-flex items-center justify-center rounded-xl w-9 h-9 text-[var(--admin-text-muted)] hover:text-[var(--admin-text-secondary)] hover:bg-[var(--admin-bg-subtle)] transition-colors"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><circle cx="10" cy="4" r="1.5"/><circle cx="10" cy="10" r="1.5"/><circle cx="10" cy="16" r="1.5"/></svg>
|
||||
|
||||
Reference in New Issue
Block a user