KQ-1761 · POINT/AND/TELL
Point and Tell
Feedback that points: Point turns the page into targets, and hovering — or Tab, which cycles through the parts while point mode is on — finds the smallest part under the pointer while one fine measuring outline travels to its box on springs.snap, with its size in a tag and guides out to the page's edges. A click or Enter pins it: a crop of the page lifts off at the part's own box and flies into its slot in the form on springs.glide on one uniform scale while the outline flashes. Crops are the page drawn again and scaled, sensitive values are masked in every crop, Escape leaves point mode, and Send shows sending, sent and failed — a failure keeps the note and every pin.
Tab and Shift Tab move between parts of the page, Enter or Space pins or unpins the part, Escape leaves point mode.
point mode off
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/point-and-tell
Props
- targets
- PointTarget[]
- default defaultPointTargets
- The page's parts as { id, label, kind, rect: { x, y, w, h } in percent of a 16:10 page, text?, sensitive? }; each kind (header, nav, heading, field, select, button, chart, table, card, note, badge) draws itself.
- pageLabel
- string
- default "Fieldline · Equipment checkout"
- Names the page in its frame's bar and the point-mode group.
- form
- PointForm
- default —
- The form's words: { heading, prompt, placeholder, sendLabel }, defaulting to Feedback, a one-line prompt, "What should we know?" and Send.
- pointing / defaultPointing
- boolean
- default — / false
- Whether point mode is on, controlled or initial.
- onPointingChange
- (pointing: boolean) => void
- default —
- Fires from the button, key or send that turned point mode on or off.
- pins / defaultPins
- string[]
- default — / []
- The pinned target ids in pin order, controlled or initial.
- onPinsChange
- (pins: string[]) => void
- default —
- Fires with every pin after one is added or removed.
- onPoint
- (target: PointTarget) => void
- default —
- A part of the page was pinned.
- onSubmit
- (feedback: { message: string; targets: PointTarget[] }) => void | Promise<unknown>
- default —
- Send was pressed. Return a promise to show sending; a rejection shows the failure and keeps the note and pins.
- onCancel
- () => void
- default —
- Cancel was pressed; pins and note are cleared.
- outlineStyle
- "measure" | "dashed" | "corners"
- default "measure"
- The pointing outline: a fine box with corner ticks, guides and a size tag; a dashed box with the tag; or four corner brackets.
- maskStyle
- "blur" | "bars" | "dots"
- default "blur"
- How sensitive values look in crops: blurred, covered by solid bars, or replaced by dots. The live page is untouched.
- accent
- string
- default "var(--accent-bright)"
- Outline, guides, pin numbers, the point-mode tint and Send — any CSS colour.
- maxPins
- number
- default 4
- The most parts that can be pinned at once.
- maxHeight
- number
- default 540
- Tallest the surface grows before it scrolls inside, in px.
- disabled
- boolean
- default false
- Nothing can be pointed at, pinned or sent.
- className
- string
- default —
- Classes for the surface.
| Prop | Type | Default | Description |
|---|---|---|---|
| targets | PointTarget[] | defaultPointTargets | The page's parts as { id, label, kind, rect: { x, y, w, h } in percent of a 16:10 page, text?, sensitive? }; each kind (header, nav, heading, field, select, button, chart, table, card, note, badge) draws itself. |
| pageLabel | string | "Fieldline · Equipment checkout" | Names the page in its frame's bar and the point-mode group. |
| form | PointForm | — | The form's words: { heading, prompt, placeholder, sendLabel }, defaulting to Feedback, a one-line prompt, "What should we know?" and Send. |
| pointing / defaultPointing | boolean | — / false | Whether point mode is on, controlled or initial. |
| onPointingChange | (pointing: boolean) => void | — | Fires from the button, key or send that turned point mode on or off. |
| pins / defaultPins | string[] | — / [] | The pinned target ids in pin order, controlled or initial. |
| onPinsChange | (pins: string[]) => void | — | Fires with every pin after one is added or removed. |
| onPoint | (target: PointTarget) => void | — | A part of the page was pinned. |
| onSubmit | (feedback: { message: string; targets: PointTarget[] }) => void | Promise<unknown> | — | Send was pressed. Return a promise to show sending; a rejection shows the failure and keeps the note and pins. |
| onCancel | () => void | — | Cancel was pressed; pins and note are cleared. |
| outlineStyle | "measure" | "dashed" | "corners" | "measure" | The pointing outline: a fine box with corner ticks, guides and a size tag; a dashed box with the tag; or four corner brackets. |
| maskStyle | "blur" | "bars" | "dots" | "blur" | How sensitive values look in crops: blurred, covered by solid bars, or replaced by dots. The live page is untouched. |
| accent | string | "var(--accent-bright)" | Outline, guides, pin numbers, the point-mode tint and Send — any CSS colour. |
| maxPins | number | 4 | The most parts that can be pinned at once. |
| maxHeight | number | 540 | Tallest the surface grows before it scrolls inside, in px. |
| disabled | boolean | false | Nothing can be pointed at, pinned or sent. |
| className | string | — | Classes for the surface. |