KQ-1763 · MACRO/REPLY

Macro Reply

An agent's ticket view — the conversation, a customer sidebar with plan, fields and earlier tickets, and a reply box — where # opens the macros and picking one types its reply at a steady pace while every field it changes switches at its own moment: a wash sweeps the field, the old value rolls out and the new one rises on springs.snap, a set-by-macro dot pops on springs.flick, and a chip for the change lands in the reply's footer on snap, so nothing changes unseen even when the sidebar is a tab. Sent replies rise into the conversation on springs.glide. The reply is a combobox over the macro listbox (arrows, Enter or Tab to apply, Escape to close), any key finishes a typing macro, and Ctrl+Enter sends.

KQ-1763 · MACRO/REPLY

Charged twice after upgrading to Team

#3195 · Email · Mara Lindqvist

Open
  1. Mara Lindqvist52 min ago

    Hi, we upgraded Fernworks from Starter to Team on Monday and the card was charged twice: €240 on the 12th and €240 again on the 13th. Only one invoice shows on the billing page. Can you refund the second charge?
  2. Ines40 min ago

    Thanks Mara. I'm checking this with billing now and will come back to you here.
  3. Mara Lindqvist12 min ago

    Thanks. For reference, the second charge shows as BSN*BASINWORKS 4471 on our statement.
Sets

    open · type # for macros · ticket #3195 · mara lindqvist

    Install

    One command — the source lands in your repo. Or copy it from the Code tab.

    $ pnpm dlx shadcn@latest add @kinetiq/macro-reply

    Props

    sidebarSide
    "left" | "right"
    default "right"
    Which side the customer sidebar sits on; at narrow widths, which side its tab sits on.
    density
    "compact" | "cozy" | "roomy"
    default "cozy"
    Type size, paddings and gaps.
    accent
    "cobalt" | "jade" | "amber" | "mono"
    default "cobalt"
    The macro wash, typing hairline, change chips and Send.
    ticket
    MacroTicket
    default defaultMacroTicket
    Subject, number, channel, status, priority, tags and messages. Field changes from the host on the same ticket id flash like a macro's.
    customer
    MacroCustomer
    default defaultMacroCustomer
    The customer shown in the sidebar: name, email, plan, seats, since and earlier tickets.
    macros
    MacroDef[]
    default defaultMacros
    Each macro's name, reply text ({first}, {agent} and {number} are filled) and the fields it sets.
    agent
    string
    default "Theo"
    The agent replying; fills {agent} and signs sent messages.
    now
    number
    default defaultMacroNow
    The moment relative times count from, ms. Never read from the clock.
    status
    "ready" | "loading"
    default "ready"
    Loading draws skeletons in the same boxes.
    onApplyMacro
    (macro: MacroDef) => void
    default —
    A macro was applied, before it starts typing.
    onSend
    (reply: { text, fields, macroId }) => void | Promise
    default —
    The reply was sent with its fields. A promise holds Send; a rejection keeps the draft and offers Retry.
    onStatusChange
    (status, source: "macro" | "field" | "reopen") => void
    default —
    The ticket's status changed, and what changed it.
    onFieldsChange
    (fields: { status, priority, tags }) => void
    default —
    Any field changed, with all three.
    typeSpeed
    number
    default 90
    How fast a macro types, in characters a second.
    flash
    number
    default 640
    How long a changed field flashes, ms.
    height
    number
    default 540
    Height of the surface, px; the conversation scrolls inside it.
    placeholder
    string
    default "Reply to {first}… Type # for macros"
    The reply box's placeholder.
    disabled
    boolean
    default false
    Read only: nothing can be typed, applied or sent.
    className
    string
    default —
    Classes for the outer surface.
    ref
    Ref<MacroReplyHandle>
    default —
    applyMacro(id) applies a macro as if picked; focusReply() moves focus to the reply.