Files
accounted/components/ui/label.tsx
T
Mattsson f633349c8d feat(analytics): show form field labels in session replays (#1416)
* feat(analytics): show form field labels in session replays

Replays showed the sidebar after #1412 but form pages were still fully
masked, so you could not tell WHICH field a user was interacting with.
Tag the shared Label primitive (components/ui/label.tsx, used by every
form in the app) with data-ph-unmask: field labels are static i18n
chrome, and maskAllInputs keeps every typed value hidden.

The one Label whose text is user data, the user-defined dimension name
in LineDimensionFields, gets data-ph-mask, which wins even on the same
element because maskTextFn checks it first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(analytics): re-mask three Labels that render user data

Completing the audit the PR review asked for: a multiline sweep over
every Label child found three call sites whose label text is user
data, missed by the first single-line pass. Danger-zone confirm
labels interpolate the user's email (AccountDangerZone) and the
company name (CompanyDangerZone), and the periodisering auto-detect
row label is counterparty name + invoice number. All three now carry
data-ph-mask. Currency-code and row-count interpolations were
reviewed and left visible: categorical UI state, not books data.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 15:18:07 +02:00

31 lines
1.0 KiB
TypeScript

"use client"
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
// data-ph-unmask: form field labels are static i18n chrome, so session
// replays show WHICH field is being filled in while the typed value stays
// masked (see instrumentation-client.ts). A call site whose label text is
// user data must add data-ph-mask, which wins over this default.
<LabelPrimitive.Root
ref={ref}
data-ph-unmask=""
className={cn(labelVariants(), className)}
{...props}
/>
))
Label.displayName = LabelPrimitive.Root.displayName
export { Label }