Skip to content
Docxcelerate

← Registry

Signature block

Closing

The image is optional and the name is not, which is the right way round: a letter signed by nobody is a letter nobody owns, whereas a missing image is a rendering detail. Without one the block closes with the typed name.

npx dxcl add signature-block
exports SignatureBlock · resolves to 4 nodes
01

Preview data

the JSON this preview was built with
{
  "signatory": {
    "name": "Tomas Lindqvist",
    "role": "Centre Manager",
    "signatureImage": "assets/signature-lindqvist.png"
  }
}
02

Rendered preview

the component rendered on its own
Open ↗
Rendered by Docxcelerate at build time Open ↗
03

Resolved nodes

what a renderer receives — 4 nodes
closing paragraph · static Yours sincerely,
signature-image image · static
signatory-name paragraph · static Tomas Lindqvist
signatory-role paragraph · static Centre Manager
04

The files

what installing writes; the selected file is the component
nodes/signature-block.node.tsx Source
import { Image, type Nodes, Paragraph, useState } from "docxcelerate/template";

/**
 * How a letter ends: a closing line, a signature, and who signed it.
 *
 * The signature image is optional and the name is not, which is the right way
 * round — a letter signed by nobody is a letter nobody owns, whereas a missing
 * image is a rendering detail. Where there is no image the block simply closes
 * with the typed name.
 *
 * Installed by `dxcl add signature-block`.
 */

/** What this component reads. Add these fields to your document data type. */
export interface SignatoryData {
  signatory: {
    /** The person signing, as they should be printed. */
    name: string;
    /** Their role, printed beneath the name. */
    role: string;
    /** Path to a signature image, relative to the document project. */
    signatureImage?: string;
    /** How the letter closes. Defaults to "Yours sincerely". */
    closing?: string;
  };
}

export const SignatureBlock: Nodes = () => {
  const [signatory] = useState((data: SignatoryData) => data.signatory);

  return (
    <>
      <Paragraph id="closing">{signatory.closing ?? "Yours sincerely"},</Paragraph>
      {signatory.signatureImage && (
        <Image
          id="signature-image"
          src={signatory.signatureImage}
          alt={`Signature of ${signatory.name}`}
          width={160}
          height={54}
        />
      )}
      <Paragraph id="signatory-name">{signatory.name}</Paragraph>
      <Paragraph id="signatory-role">{signatory.role}</Paragraph>
    </>
  );
};