Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

Blocks

Invoice Page

Blocks

Invoice Page React block for Tailwind CSS v4

Inbox PageKPI Dashboard
Live props
State
defaultMode
status
defaultSendOpen
defaultShowErrors
loading
Content
productCurrency
userName
invoicesHref
locale
currency
Behavior
pricesIncludeVat
defaultEFactura
spvConnected
saveShortcut
sendShortcut
animateIn
Layout
linesLayout
stickyBar
Appearance
tone
radius
Code
import { InvoicePage } from "@/components/blocks/invoice-page"

<InvoicePage />
  1. Home
  2. Components
  3. Blocks
  4. Invoice Page
Pro

Invoice Page React block for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React invoice page to edit and view Romanian B2B invoices: client, series, VAT lines, totals, an A4 preview, sending and e-Factura.

Switch between Edit and Preview in the header (arrow keys move the segmented control). In edit mode pick the client in the search field (name, CUI or city; a full-height sheet on phones), or type a new name and choose New client to open a dialog where Look up in ANAF (or Enter in the CUI field) fills the company from its CUI; Change swaps the client. Pick the series (the number jumps to the next free one), the issue date (the due date keeps the same term), the due date with the +15, +30 and +45 days presets, and the currency: EUR converts every price at the BNR rate and shows the RON equivalent under the total. Edit the lines like a spreadsheet (product search, quantity, price, VAT rate, discount, drag or Move up / Move down to reorder, remove with undo; cards with an edit sheet on phones) and type the notes. The aside keeps the summary with VAT per rate and the total, the IBAN with a copy button, and the e-Factura switch in view while you scroll (on a laptop with a sidebar the lines take the full width under them instead). A draft saves itself 800 ms after the last change (Saving…, then Saved a few seconds ago); Ctrl or Cmd + S saves at once. Issue invoice checks the client, its CUI, the number (a taken one fails), the dates and the lines: the problems are listed in an alert whose links move focus to each field, and the lines get their own errors. Issuing uploads to SPV when the switch is on and turns to the preview: an A4 sheet in paper colours in both themes, scaled to the width on tablets and phones (pinch to zoom). Send opens the send dialog (a full-height sheet on phones): recipients as chips, CC, subject, message, the PDF attached and an SPV switch; Ctrl or Cmd + Enter sends. Download PDF opens the print dialog, which prints only the document. The ⋯ menu holds Duplicate (a new draft with the next number), Mark as paid (the badge pops), Issue credit note and Void invoice (undo in a toast for 5 seconds). Overdue invoices offer Send reminder; paid and cancelled ones are read-only. On phones a bar at the bottom shows the total with Issue, Send or Download.

Invoice Page is a Pro React block in the React blocks category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add invoice-page, together with Alert, Badge, Button, Combobox, Copy Button and 28 more and the npm packages motion, lucide-react, react-hook-form and zod.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add invoice-page

Invoice Page is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import InvoicePage from @/components/blocks/invoice-page.

// app/(admin)/invoices/[id]/page.tsx (the shell lives in app/(admin)/layout.tsx: <AdminShell>{children}</AdminShell>)
"use client"

import { InvoicePage, type InvoiceDocument } from "@/components/blocks/invoice-page"

export default function InvoiceRoute() {
  return (
    <InvoicePage
      onSave={async (invoice: InvoiceDocument) => {
        await fetch(`/api/invoices/${invoice.id}`, { method: "PUT", body: JSON.stringify(invoice) })
      }}
      onIssue={async (invoice) => {
        await fetch(`/api/invoices/${invoice.id}/issue`, { method: "POST" })
      }}
      onSend={async (invoice, payload) => {
        await fetch(`/api/invoices/${invoice.id}/send`, { method: "POST", body: JSON.stringify(payload) })
      }}
    />
  )
}

Props

  • invoice
    InvoiceDocument

    The document, controlled ({ id, series, number, status, issueDate, dueDate, currency, client, supplier, lines, notes, paymentTerms, documentDiscount, sentToSpv, paidAt, issuedBy }); pair it with onInvoiceChange.

  • defaultInvoice
    InvoiceDocument

    The document while uncontrolled; defaults to INVOICE_PAGE_SAMPLE (draft CRP #2026-0412 to Tech Solutions SRL). createInvoiceDraft(now) gives an empty one.

  • onInvoiceChange
    (invoice: InvoiceDocument) => void

    Called with the whole document after every edit and status change.

  • mode
    "edit" | "preview"

    The view, controlled; pair it with onModeChange.

  • defaultModedefault "edit"
    "edit" | "preview"

    The first view while uncontrolled; when left out, edit for drafts and preview for every other status (the sample is a draft).

  • onModeChange
    (mode: InvoiceMode) => void

    Called when the segmented control, issuing or duplicating switches the view.

  • statusdefault "draft"
    "draft" | "issued" | "sent" | "paid" | "overdue" | "cancelled"

    Seeds the document's status on mount (a playground shortcut; the sample is a draft). Overdue moves the dates 3 days past due, paid sets today as the payment date.

  • clients
    InvoiceParty[]

    The client picker's options ({ id, name, cui, regCom, address, city, county, email, vatPayer, individual }); defaults to the 12 Northwind CRM clients (INVOICE_PAGE_CLIENTS).

  • products
    InvoiceProduct[]

    The line product search; defaults to the 7 Northwind CRM products and services (INVOICE_PAGE_PRODUCTS).

  • productCurrencydefault "RON"
    string

    The currency of the product prices; they are converted to the document's currency through exchangeRate.

  • supplier
    InvoiceParty

    The issuer printed on the document and shown in Payment; defaults to Northwind Soft SRL (RO40528170, Banca Transilvania).

  • series
    string[]

    The document series; defaults to ["CRP", "CRPX"] (labels.seriesHints describes each).

  • takenNumbers
    Record<string, string[]>

    Numbers already used per series: the next free one is suggested and a taken one fails validation; defaults to INVOICE_PAGE_TAKEN_NUMBERS.

  • exchangeRate
    { currency: string; rate: number; date: Date; source?: string }

    The foreign currency the Currency field offers and its RON rate; defaults to BNR 1 EUR = 4.9713 RON on 2026-09-24.

  • userNamedefault "Emma Carter"
    string

    Who signs: Prepared by on the document and the sender of the email, unless the invoice has issuedBy.

  • pricesIncludeVatdefault false
    boolean

    The price column holds prices with VAT (B2C); totals are computed backwards.

  • eFactura
    boolean

    The Send to SPV automatically on issue switch, controlled.

  • defaultEFacturadefault true
    boolean

    The SPV switch while uncontrolled: issuing uploads the invoice to e-Factura and marks it Sent to SPV.

  • onEFacturaChange
    (on: boolean) => void

    Called when the SPV switch flips.

  • spvConnecteddefault true
    boolean

    An ANAF certificate is linked; false disables the SPV switches and says Neconectat.

  • onSave
    (invoice: InvoiceDocument) => (void | Promise<unknown>)

    Saves the draft, 800 ms after the last change and on Ctrl or Cmd + S; simulated by default. A rejection shows Nu am putut salva.

  • onIssue
    (invoice: InvoiceDocument) => (void | Promise<unknown>)

    Issues a valid draft (blank lines removed); simulated by default. Then the status becomes Issued, or Sent to SPV with e-Factura on.

  • onSend
    (invoice: InvoiceDocument, payload: { to; cc; subject; message; spv }) => (void | Promise<unknown>)

    Sends from the dialog (a draft is issued first); simulated by default. A rejection shows its message in the dialog.

  • onDownload
    (invoice: InvoiceDocument) => void

    Download PDF; default window.print(), where Save as PDF gives a real PDF with only the document on it.

  • onMarkPaid
    (invoice: InvoiceDocument) => (void | Promise<unknown>)

    Mark as paid; simulated by default, then the status is Paid with today's date.

  • onDuplicate
    (invoice: InvoiceDocument) => (void | Promise<unknown>)

    Duplicate; simulated by default, then the page opens a new draft with the next number and today's dates.

  • onStorno
    (invoice: InvoiceDocument) => (void | Promise<unknown>)

    Emite storno for issued, sent, paid and overdue invoices; simulated by default with a toast.

  • onCancel
    (invoice: InvoiceDocument) => (void | Promise<unknown>)

    Void invoice: the status changes at once with an undo toast; a rejection rolls it back.

  • onRemind
    (invoice: InvoiceDocument) => (void | Promise<unknown>)

    Send reminder on overdue invoices; simulated by default with a toast.

  • onCreateClient
    (client: InvoiceParty) => (void | InvoiceParty | Promise<void | InvoiceParty>)

    Saves a client from the Client nou dialog; a returned party replaces the typed one. Simulated by default; the new client is selected.

  • linesLayoutdefault "auto"
    "auto" | "table" | "cards"

    The lines editor: auto shows the spreadsheet table wherever it gets 936px (from a page about 936px wide the lines span the full row under the client and the summary, from 1352px they sit beside the sticky summary), cards with an edit sheet below.

  • stickyBardefault true
    boolean

    The phone bar (below 768px) with the total and Issue, Send or Download; hide the shell's tab bar while it shows.

  • defaultSendOpendefault false
    boolean

    Opens the send dialog on mount (examples).

  • defaultShowErrorsdefault false
    boolean

    Starts with the issue checks shown, as after pressing Emite factura (examples).

  • saveShortcutdefault "mod+s"
    string

    Saves the draft; "" turns it off.

  • sendShortcutdefault "mod+enter"
    string

    Sends from the open send dialog, also while typing the message; "" turns it off.

  • invoicesHrefdefault "/invoices"
    string

    Where the breadcrumb's Facturi goes.

  • labels
    Partial<InvoicePageLabels>

    Every visible string, English by default (DEFAULT_INVOICE_PAGE_LABELS; INVOICE_PAGE_LABELS_EN is the same set under its older name). Nested keys pass strings to the composed items (lineItems, validation, datePicker, tagInput, stickyBar).

  • localedefault "en-US"
    string

    Intl locale for money, numbers and dates.

  • currencydefault "RON"
    string

    Seeds the document's currency on mount (the sample is in RON); EUR converts the prices at exchangeRate.

  • now
    Date | number

    The reference time for today, overdue days, payments and duplicates; default the live clock.

  • tonedefault "neutral"
    Tone

    The accent of the primary actions, the mode switch, the date pickers and the switches.

  • radiusdefault "md"
    "sm" | "md" | "lg"

    The panels' radius: 12, 16 or 24px.

  • loadingdefault false
    boolean

    The header, panels and aside as skeletons in the real layout.

  • animateIndefault true
    boolean

    The header and sections rise in once on mount; off in thumbnails and under reduced motion.

  • linkComponent
    (props: LinkComponentProps) => ReactNode

    The router link for the breadcrumb; default an <a> (or the LinkProvider's).

  • className
    string

    Classes for the root.

  • classNames
    Partial<Record<InvoicePageSlot, string>>

    Classes for header, alerts, edit, main, client, details, lines, notes, aside, summary, payment, efactura, preview, document, send and bar.

Parts

  • DEFAULT_INVOICE_PAGE_LABELS

    constant

    The English strings for every visible label, the default of labels. Type: InvoicePageLabels.

  • INVOICE_PAGE_LABELS_EN

    constant

    The same English strings under their older name, kept for existing imports.

  • INVOICE_PAGE_SAMPLE

    constant

    The demo invoice: draft CRP 2026-0412 from Northwind Soft SRL in RON, four lines at 21% and 11% VAT.

  • INVOICE_PAGE_SAMPLE_EN

    constant

    The same invoice in EUR with converted prices and an English payment note.

  • INVOICE_PAGE_SUPPLIER

    constant

    The sample supplier (Northwind Soft SRL) with its CUI, registry number, address and bank account.

  • INVOICE_PAGE_CLIENTS

    constant

    The sample clients offered by the client picker.

  • INVOICE_PAGE_ANAF_DIRECTORY

    constant

    The companies the demo's CUI lookup finds, standing in for the ANAF registry.

  • INVOICE_PAGE_PRODUCTS

    constant

    The product catalog for the line picker, priced in RON with their VAT rates and SKUs.

  • INVOICE_PAGE_PRODUCTS_EN

    constant

    The same catalog priced in EUR.

  • INVOICE_PAGE_SERIES

    constant

    The invoice series of the sample supplier: ["CRP", "CRPX"].

  • INVOICE_PAGE_TAKEN_NUMBERS

    constant

    Numbers already used per series; the next free one is suggested and a taken one fails validation.

  • INVOICE_PAGE_EXCHANGE_RATE

    constant

    The sample BNR rate for EUR (4.9713 RON on Sep 24, 2026), shown on foreign currency invoices.

  • INVOICE_PAGE_NOW

    constant

    The demo clock (Sep 24, 2026, 4:40 PM), so due dates and overdue days stay stable.

  • createInvoiceDraft

    function

    A new draft: (now?, { series, number, supplier, currency, issuedBy }?) => InvoiceDocument with no client and one empty line.

  • invoiceWithStatus

    function

    Moves an invoice to a status with matching dates: (invoice, status, now?) => InvoiceDocument (overdue, paid, sent).

  • InvoicePageProps

    type

    Props of InvoicePage, including the div attributes of the root.

  • InvoiceDocument

    type

    The invoice: series, number, status, dates, currency, client, supplier, lines, notes and discount.

  • InvoiceSendPayload

    type

    What onSend receives with the invoice: { to, cc, subject, message, spv }, spv sending it to e-Factura.

Examples

Open

Issued, previewed as the A4 document

status="issued", tone="brand": the printable sheet, scaled to fit on phones.

Open

Send dialog open

defaultSendOpen: recipients, subject and message prefilled; Ctrl or Cmd + Enter sends.

Open

A new draft, Issue pressed

No client, one empty line and a taken number: every error listed and linked to its field.

Open

Paid

status="paid" in edit mode: the success alert and read-only lines.

Open

Overdue

status="overdue": due 3 days ago, with Send reminder.

Open

Loading

loading: header, panels and aside as skeletons in the real layout.

Open

Export invoice in euro

locale="en-GB", an EUR invoice priced from the euro catalogue, with the RON equivalent at the BNR rate.

Dependencies

motionlucide-reactreact-hook-formzodalertbadgebuttoncomboboxcopy-buttondate-pickerdescription-listdialogdropdown-menuinputinvoice-line-itemskbdpage-headersegmented-controlselectsticky-cta-barswitchtag-inputtextareatoastuse-controllable-stateuse-media-queryuse-shortcutcommercedate-utilsform-validationinvoicingmotionnavigationnumber-formatrelative-timetonesui-config

Files

  • components/blocks/invoice-page.tsx
  • components/blocks/invoice-page-data.ts

FAQ

Is the React Invoice Page block free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Invoice Page?

Run npx wingo-ui@latest add invoice-page. It also adds the Wingo UI items it builds on (Alert, Badge, Button, Combobox, Copy Button and 28 more) and the npm packages motion, lucide-react, react-hook-form and zod. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/invoice-page.

How does Invoice Page behave on phones?

In edit mode pick the client in the search field (name, CUI or city; a full-height sheet on phones), or type a new name and choose New client to open a dialog where Look up in ANAF (or Enter in the CUI field) fills the company from its CUI; Change swaps the client.

See also

Invoice line itemsInvoicinglibAdmin ShellPage HeaderSticky CTA Bar

More React blocks

KPI DashboardListing Detail PageMarketplace Search PageMarketplace ShellOrder History PagePost Listing Wizard
All 26 React blocks

Articles using this component

  • React Invoice Template: Line Items, VAT and Print View

    Build it: screens and apps · Oct 16, 2026 · 10 min read

  • E-Factura VAT Calculation in TypeScript and React

    Build it: screens and apps · Oct 9, 2026 · 11 min read

PreviousInbox PageNext KPI Dashboard