VerifyKitv0.13.3

Customization

This guide covers theming, CSS variable overrides, toolbar configuration, feature flags, and worker setup.

Theme Modes

VerifyKit supports three theme modes: 'light', 'dark', and 'system'.

React

Set the theme via the VerifyKitProvider config:

tsx
<VerifyKitProvider config={{
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
  theme: { mode: 'system' },
}}>
  <App />
</VerifyKitProvider>

Toggle the theme at runtime using the defaultLayoutPlugin API:

tsx
const [layout] = useState(() => defaultLayoutPlugin())
 
layout.theme.toggleTheme()     // Toggle between light and dark
layout.theme.setTheme('dark')  // Set explicitly

Vanilla JS

Set the theme at creation time or change it later:

ts
const viewer = VerifyKit.create(el, {
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
  theme: { mode: 'system' },
})
 
// Change at runtime
viewer.setTheme('dark')

Listen for theme changes:

ts
viewer.on('themeChange', (mode) => {
  console.log('Theme changed to:', mode)
})

CSS Variables

VerifyKit's appearance is controlled by CSS custom properties defined on :root. You can override any variable to customize the look and feel.

Overriding via Provider Config

Pass CSS variable overrides through the theme configuration:

tsx
<VerifyKitProvider config={{
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
  theme: {
    mode: 'dark',
    overrides: {
      '--primary': '#6366f1',
      '--primary-hover': '#4f46e5',
    },
  },
}}>

Overriding via CSS

You can also override variables in your own stylesheet:

css
:root {
  --primary: #6366f1;
  --primary-hover: #4f46e5;
  --toolbar-bg: #1a1a2e;
}

Key Variable Categories

Layout

VariableDefaultDescription
--btn-base26pxBase button size, before --ui-scale
--toolbar-h-base36pxBase toolbar height, before --ui-scale
--btn-sizecalc(var(--btn-base) * var(--ui-scale, 1))Standard button size
--toolbar-heightcalc(var(--toolbar-h-base) * var(--ui-scale, 1))Height of the toolbar
--left-nav-width36pxWidth of the left navigation bar

--btn-size and --toolbar-height are derived — override --btn-base and --toolbar-h-base instead, and both the button and the toolbar stay in proportion under --ui-scale. The two bases respond to the environment:

Context--btn-base--toolbar-h-base
Default26px36px
(pointer: coarse) — touch40px48px
(max-height: 500px) — short viewport24px32px
Short and coarse36px42px

Colors — Surfaces

VariableLightDarkDescription
--surface-1#ffffff#1e1e1ePrimary surface background
--surface-2#f5f5f5#252525Secondary surface background
--surface-3#ececec#2d2d2dTertiary surface background
--doc-area-bg#e8e8e8#383838Document area background

Colors — Typography

VariableLightDarkDescription
--fg#1a1a1a#e0e0e0Primary text color
--fg-secondary#333333#ccccccSecondary text color
--fg-muted#595959#999999Muted text color
--fg-subtle#767676#666666Subtle text color

Accent / Interactive

VariableLightDarkDescription
--primary#0072c6#0072c6Primary accent color
--primary-hover#005ea3#005ea3Accent hover state
--primary-light#e5f1fcrgba(0,114,198,0.20)Light accent tint
--selected-bg#ddeafargba(0,114,198,0.25)Selected item background
--hover-bg#eff5fergba(255,255,255,0.07)Hover background
--focus-ringrgba(0,114,198,0.45)--Focus ring color

Borders

VariableLightDarkDescription
--border#d4d4d4#3c3c3cStandard border
--border-strong#b5b5b5#555555Stronger border

Toolbar

VariableLightDarkDescription
--toolbar-bg#ffffff#1d1d1dToolbar background
--toolbar-border#e0e0e0#0d0d0dToolbar border
--toolbar-text#555555rgba(255,255,255,0.55)Toolbar text
--toolbar-text-active#0072c6rgba(255,255,255,0.95)Active toolbar text
--toolbar-hover#f0f0f0rgba(255,255,255,0.08)Toolbar hover

Shadows

VariableDefault (Light)Description
--shadow-xs0 1px 2px rgba(0,0,0,0.05)Extra small shadow
--shadow-sm0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04)Small shadow
--shadow-md0 4px 12px rgba(0,0,0,0.10), 0 2px 4px rgba(0,0,0,0.06)Medium shadow
--shadow-lg0 8px 28px rgba(0,0,0,0.14), 0 4px 10px rgba(0,0,0,0.08)Large shadow
--shadow-xl0 20px 48px rgba(0,0,0,0.18), 0 8px 16px rgba(0,0,0,0.10)Extra large shadow
--shadow-page0 1px 4px rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08)Page shadow

Semantic Status Colors

VariableLightDarkDescription
--color-valid#0d6b2c#4ade80Valid/success color
--color-invalid#b83016#f87171Invalid/error color
--color-warning#975300#fbbf24Warning color
--color-unknown#5a6370#9ca3afUnknown/neutral color

Status Surfaces (used by signature panels and banners)

VariableDescription
--surface-validBackground for valid status banners
--surface-invalidBackground for invalid status banners
--surface-warningBackground for warning/unknown status banners
--surface-valid-borderLeft stripe for valid signature cards
--surface-invalid-borderLeft stripe for invalid signature cards
--surface-warning-borderLeft stripe for warning/unknown signature cards
--bar-valid-bgDocument message bar — valid
--bar-invalid-bgDocument message bar — invalid
--bar-warn-bgDocument message bar — warning
--bar-unknown-bgDocument message bar — unknown

Panels, Tabs and Chrome

VariableLightDarkDescription
--panel-bg#f2f2f2#1e1e1eSidebar / signature panel background
--panel-header-bg#e2e2e2#252525Panel header strip
--panel-border#b8b8b8#3c3c3cPanel border
--tabbar-bg#e8e8e8#2a2a2aMulti-document tab strip background
--tabbar-border#d0d0d0#111111Tab strip border
--tabbar-textrgba(0,0,0,0.68)rgba(255,255,255,0.68)Tab label
--statusbar-bg#f3f3f3#1d1d1dBottom status bar background
--statusbar-textrgba(0,0,0,0.60)rgba(255,255,255,0.38)Status bar text
--statusbar-text-dimrgba(0,0,0,0.45)rgba(255,255,255,0.28)Status bar secondary text
--tooltip-bgrgba(10,10,10,0.92)rgba(50,50,50,0.94)Tooltip background
--tooltip-text#fafafa#f0f0f0Tooltip text
--selected-border#0072c6#0072c6Border of a selected item

Welcome Screen

Shown before a document is open, so these are the first colors a new user sees. Most default to other tokens — override those and the welcome screen follows.

VariableDefaultDescription
--welcome-bgvar(--surface-1)Welcome screen background
--welcome-bordervar(--border)Drop-zone border
--welcome-titlevar(--fg)Headline text
--welcome-subtitlevar(--fg-muted)Supporting text
--welcome-iconvar(--fg-subtle)Drop-zone icon
--welcome-drop-bgrgba(0,114,198,0.04) (dark 0.08)Drop-zone fill while dragging
--welcome-drop-borderrgba(0,114,198,0.30) (dark 0.40)Drop-zone border while dragging

Toolbar Configuration

React — defaultLayoutPlugin

Disable specific toolbar features using the disable option:

tsx
const [layout] = useState(() =>
  defaultLayoutPlugin({
    disable: {
      search: true,
      print: true,
      download: true,
      rotation: true,
      fullscreen: true,
      theme: true,
      selection: true,
      openFile: true,
      contextMenu: true,
      properties: true,
      shortcuts: true,
    },
  })
)

React — Individual Plugins

For maximum control, compose only the plugins you want:

tsx
import { zoomPlugin, pageNavigationPlugin, toolbarPlugin } from '@trexolab/verifykit-react'
 
const [zoom] = useState(() => zoomPlugin())
const [nav] = useState(() => pageNavigationPlugin())
const [toolbar] = useState(() => toolbarPlugin())
 
<Viewer fileBuffer={buffer} plugins={[zoom, nav, toolbar]} />

This gives you a minimal viewer with only zoom and page navigation -- no search, no print, no sidebar.

Zoom range

By default the viewer zooms between 25 % and 1000 % in 15 % increments — matching pdf.js and suitable for inspecting fine detail in signature stamps, seals and small print.

Override the range via the zoom option on defaultLayoutPlugin (batteries-included) or by passing options directly to zoomPlugin():

tsx
// Batteries-included — default layout
const layout = defaultLayoutPlugin({
  zoom: { minScale: 0.5, maxScale: 4, step: 0.1 },
})
 
// À la carte — individual plugin
const [zoom] = useState(() => zoomPlugin({ minScale: 0.25, maxScale: 16 }))

The zoom dropdown only shows preset levels that fit inside the configured range, so there are never options the user cannot actually select. Ctrl+= / Ctrl+- and Ctrl+scroll respect the same bounds.

Vanilla exposes the same option:

ts
VerifyKit.create(el, {
  workerUrl: '…',
  zoom: { maxScale: 16 },
})

Feature Flags

Vanilla JS

The vanilla API exposes features as a flat configuration object. Each feature can be individually toggled:

ts
const viewer = VerifyKit.create(el, {
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
  features: {
    search: true,        // default: true
    print: true,         // default: true
    download: false,     // default: false
    signatures: true,    // default: true
    thumbnails: true,    // default: true
    fullscreen: true,    // default: true
    themeToggle: true,   // default: true
    openFile: false,     // default: false
    rotation: true,      // default: true
    contextMenu: true,   // default: true
    properties: true,    // default: true
    shortcuts: true,     // default: true
    highlights: true,    // default: true
  },
})

Internally, feature flags are mapped to defaultLayoutPlugin({ disable: {...} }).

Accessibility

UI Font Scale

VerifyKit includes a built-in UI font scale control that lets users adjust the size of all viewer text, toolbar buttons, and panel elements. This is an accessibility feature similar to browser zoom, but scoped to the viewer only.

A toolbar dropdown (Aa icon) is included by default. Users can choose from four presets:

ScaleMultiplierBase FontToolbar HeightButton Size
Compact0.88x11.4px31.7px22.9px
Default1.00x13.0px36.0px26.0px
Large1.15x15.0px41.4px29.9px
Extra Large1.30x16.9px46.8px33.8px

The user's preference is automatically saved to localStorage and restored on subsequent visits.

React

tsx
// Set initial scale via defaultLayoutPlugin
const [layout] = useState(() =>
  defaultLayoutPlugin({
    accessibility: { initialScale: 'large' },
  })
)
 
// Programmatic control
layout.accessibility.setFontScale('extra-large')
layout.accessibility.getFontScale() // 'extra-large'
 
// Disable the feature entirely
defaultLayoutPlugin({
  disable: { accessibility: true },
})

Vanilla JS

ts
const viewer = VerifyKit.create(el, {
  workerUrl: '...',
  features: { accessibility: true }, // default: true
})
 
viewer.setFontScale('large')
viewer.getFontScale() // 'large'
 
// Listen for changes
viewer.on('fontScaleChange', (scale) => {
  console.log('Font scale changed to:', scale)
})

Standalone Plugin

tsx
import { accessibilityPlugin } from '@trexolab/verifykit-react'
 
const a11y = accessibilityPlugin({
  initialScale: 'large',  // 'compact' | 'default' | 'large' | 'extra-large'
  persist: true,           // save to localStorage (default: true)
})
 
<Viewer plugins={[a11y, ...otherPlugins]} />
 
// API
a11y.api.setFontScale('extra-large')
a11y.api.getFontScale()

CSS Variables

The font scale works by setting a data-font-scale attribute on .verifykit-root and overriding the CSS design token variables. You can customize the scale factors with CSS:

css
/* Custom scale overrides */
.verifykit-root[data-font-scale="large"] {
  --ui-scale: 1.20;  /* adjust from default 1.15 */
  --font-base: calc(13px * 1.20);
}

--btn-size and --toolbar-height are calc(base * var(--ui-scale)), so they follow --ui-scale on their own — you only need to restate the font sizes, which do not derive from it.

Worker Configuration

VerifyKit uses a Web Worker to render PDF pages off the main thread. The workerUrl option is required -- it specifies the URL to the PDF.js worker script.

Use the legacy worker from unpkg:

React:

tsx
<VerifyKitProvider config={{
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
}}>

Vanilla JS:

ts
const viewer = VerifyKit.create(el, {
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
})

Self-Hosted Worker

Copy the worker file to your public directory and pass a local path:

bash
npm pack pdfjs-dist@5.5.207 --pack-destination /tmp \
  && tar -xzOf /tmp/pdfjs-dist-5.5.207.tgz package/legacy/build/pdf.worker.min.mjs \
     > public/pdf.worker.min.mjs

React:

tsx
<VerifyKitProvider config={{ workerUrl: '/pdf.worker.min.mjs' }}>

Vanilla JS:

ts
const viewer = VerifyKit.create(el, {
  workerUrl: '/pdf.worker.min.mjs',
})

Important: The worker version must match the pdfjs-dist version used by VerifyKit (5.5.207). Using a mismatched version will cause rendering errors.

CMap and Standard Font URLs

For non-Latin text support (CJK, Arabic, Hebrew, etc.), VerifyKit loads CMap and font files at runtime. Copy them to your public directory:

bash
cp -r node_modules/@trexolab/verifykit-react/cmaps public/cmaps
cp -r node_modules/@trexolab/verifykit-react/standard_fonts public/standard_fonts

Customize the paths if you serve them from a different location:

tsx
<VerifyKitProvider config={{
  workerUrl: 'https://unpkg.com/pdfjs-dist@5.5.207/legacy/build/pdf.worker.min.mjs',
  cMapUrl: '/assets/cmaps/',
  standardFontDataUrl: '/assets/standard_fonts/',
}}>

The defaults are /cmaps/ and /standard_fonts/.

Content Security Policy

If your application uses a strict CSP, you may need to add these directives:

Content-Security-Policy:
  worker-src 'self' https://unpkg.com;
  script-src 'self' 'wasm-unsafe-eval';
  • worker-src 'self' https://unpkg.com -- Required if using the CDN-hosted worker. If self-hosting the worker, worker-src 'self' is sufficient.
  • script-src 'wasm-unsafe-eval' -- Required for WebAssembly compilation.

Signature Appearance Icons

After verification, VerifyKit draws the status icon on the signature field itself, inside the PDF canvas -- a green checkmark for valid, a red cross for invalid, a yellow question mark for unknown -- the same place Acrobat draws it. The icon reflects the verdict the signature actually got, not the placeholder the signing tool left in the file.

This applies to the signature appearance styles produced by Acrobat and the common signing tools. Where a field cannot carry a status icon, VerifyKit leaves it as it is rather than drawing something misleading over it; see Troubleshooting if an icon does not change.

The icon artwork is fixed in the build. If you need a custom icon set for a white-labelled deployment, get in touch.

ts
import { swapSignatureAppearances, hasAcro6Appearances } from '@trexolab/verifykit-react'
 
// After verification
const result = await verifier.verify(pdfBytes)
const hasAcro6 = await hasAcro6Appearances(pdfBytes)
 
if (hasAcro6 || result.signatures.some(s => s.isVisible)) {
  const modifiedPdf = await swapSignatureAppearances(pdfBytes, result.signatures)
  // Use modifiedPdf for display in PDF.js
}

Keyboard Shortcuts

VerifyKit includes built-in keyboard shortcuts for navigation, zoom, tools, and document actions.

Built-in Shortcuts

CategoryShortcutAction
NavigationPageUp / P / KPrevious page
PageDown / N / JNext page
HomeFirst page
EndLast page
ZoomCtrl+=Zoom in
Ctrl+-Zoom out
Ctrl+0Fit page
Ctrl+1Actual size (100%)
Ctrl+2Fit width
ToolsHToggle hand tool
SToggle text select
ViewRRotate clockwise
Shift+RRotate counter-clockwise
F5Toggle fullscreen
SearchCtrl+FToggle find bar
F3Find next
ActionsCtrl+SDownload PDF
Ctrl+PPrint
Ctrl+OOpen file
Help?Show keyboard shortcuts

Tool shortcuts (H, S, Ctrl+F, F5) are toggles — press once to activate, press again to deactivate.

Registering Custom Shortcuts

Plugins can register additional shortcuts via the ViewerPluginContext:

ts
function myPlugin(): ViewerPlugin {
  return {
    name: 'my-plugin',
    install(ctx) {
      ctx.registerShortcut({
        id: 'my-action',
        key: 'g',
        ctrl: true,
        description: 'Go to page',
        handler(e) {
          e.preventDefault()
          // your action
        },
      })
    },
  }
}