Documentation menu

Documentation / Blocks & themes / blocks-practice-pack

Blocks Practice Pack

Package
@wabbit/tome-blocks-practice-pack
Version
v0.2.0
npm install @wabbit/tome-blocks-practice-pack
First install from our registry?
  1. Get a free registry token from your credentials page. Every install from our registry needs one, free packages included.

  2. Add the registry and your token to the .npmrc at the root of your project, with your token in place of YOUR_TOKEN:

    @wabbit:registry=https://npm.wabbit.com/
    //npm.wabbit.com/:_authToken=YOUR_TOKEN
Blocks & themesPreview

Practice blocks for Tome: a need picker, service cards and price rows, a people row with accepting status, offices with live open state and who is seen where, a person or topic page header, credentials, reviewed lines, a first-visit steps list and a book-or-call closing block, rendered from the @wabbit/tome-practice layer's people, offerings, topics and groups. Neutral by default and restyled through public data-* hooks.

Overview

Practice blocks for Tome: the blocks a business defined by its people, its services and its offices needs, rendered from the records of @wabbit/tome-practice so nothing a block prints is typed twice. A need picker that works without script, service cards and price rows, a row of people with accepting status, offices with live open state and who is seen where, the header of a person page or a topic page, credentials, a reviewed line that tells the truth about its age, related chips, a first-visit steps list and a book-or-call closing block.

Status: preview. Thirteen blocks and one server component. register() adds them as the practice-pack bundle, tier free. The pack is neutral on purpose: no word in a default, an option or a comment names a trade. The words ("person", "offering", "topic", the status words, the sample labels) come from the practice settings, and any block can override them for itself.

The pack is structure, not look. Every block emits public data-* hooks, and its base stylesheet sets layout and spacing from tokens only: no literal colour, no radius, no shadow. A theme is CSS plus a manifest that keys on those hooks.

Peer dependencies

PeerRangeRequired
@wabbit/tome-blocks-core>=0.35.0 <1.0.0yes
@wabbit/tome-blocks-local-pack>=0.9.0 <1.0.0yes (the desk strip and the offices list wrap its locations model; 0.9.0 adds the per-office slot)
@wabbit/tome-core>=1.32.0 <2.0.0yes
@wabbit/tome-local>=0.4.0 <1.0.0yes (the local pack's own peer)
@wabbit/tome-practice>=0.2.0 <1.0.0yes (0.2.0 adds the roster and group reads the pack uses)
payload>=3.67.0yes
react>=19.0.0yes
react-dom>=19.0.0yes

Block styles read --tome-* tokens, so load the design tokens once in your global CSS, as with every Tome pack.

Register the block configs into your registries:

// payload.config.ts
import { BlockRegistry, BundleRegistry } from '@wabbit/tome-blocks-core/registry'
import { register } from '@wabbit/tome-blocks-practice-pack'

const blockRegistry = new BlockRegistry()
const bundleRegistry = new BundleRegistry()

register(blockRegistry, bundleRegistry)

Each block's block(config) takes the collection slugs it is built against, all defaulting to the layer's own: peopleSlug, offeringsSlug, topicsSlug, groupsSlug and locationsSlug (default local-locations; pass null for a site without locations and the office filters disappear), plus mediaCollection (default media), the collection the typed photos of the picker, steps, offering, people and guide lists are picked from. A photo is always an upload there, never a typed URL; its alt text and label stay separate fields.

Register the renderers once at app startup:

import { registerRenderers } from '@wabbit/tome-blocks-practice-pack/render/register'

registerRenderers()

Blocks

SlugNameVariantsWhat it renders
practice-desk-stripPractice Desk StripnoneEvery office with its open status, the main phone number and one book action. Wraps the local pack's desk strip.
practice-topic-pickerPractice Topic PickernoneOne tab per group, then that group's topics as full-row links beside the person a visitor would likely see. Radio inputs, so it works with JavaScript off and by keyboard.
practice-offering-listPractice Offering Listdoors, rows, detailThe offerings as photo cards, price rows or detail cards, with who offers each and a price that says from, a range or on request.
practice-stepsPractice StepsnoneThree to five connected, numbered steps, each with its time and who you will meet, then a photo and a what-to-bring list at equal height. Typed content.
practice-people-listPractice People Listrow, cards, compactThe people with a role line and offices, languages, accepting status and a book action; a waitlist note and a link to others for someone who is not accepting.
practice-officesPractice OfficesnoneEvery office with its own live open status, hours, directions and book action, plus who is seen at each. One office closes up into a single place. Wraps the local pack's locations list.
practice-guide-listPractice Guide ListnoneGuides as cards, each ending with a review footer: who reviewed it, when, and whether that is current.
practice-record-headerPractice Record Headerperson, topicThe top of a person page or a topic page, read from the record, with Book and Call. A person page adds an At a glance panel.
practice-pathPractice PathnoneA topic, the offering it leads to and the person who does it, as three linked nodes.
practice-reviewed-linePractice Reviewed Linemargin, cardWho reviewed a page and when, with a chip that stops saying "current" once the review ages.
practice-credentialsPractice CredentialsnoneA person's credentials as a ledger, with where to check each one.
practice-relatedPractice RelatedchipsRelated records as a row of link chips.
practice-bookPractice BooknoneBook and Call as equal tiles with a caption each, and the emergency line.

The blocks are listed in the block catalog under the practice-pack bundle.

Module surface

EntryWhat it is
@wabbit/tome-blocks-practice-packregister(), the block descriptors, makePracticeReadHook, practiceSourceFields, the layer seam and the data types. Imports Payload: block configs only.
@wabbit/tome-blocks-practice-pack/renderThe renderers, self-registering on import. Client-safe.
@wabbit/tome-blocks-practice-pack/render/registerrenderers and registerRenderers(), the explicit server-safe path.
@wabbit/tome-blocks-practice-pack/serverPracticeStatusAnnouncement, the multi-office status strip for chrome's announcementSlot.
@wabbit/tome-blocks-practice-pack/metaPayload-free block metadata and variants for a gallery.
@wabbit/tome-blocks-practice-pack/demogetDemoProps(slug, variant?): fictional, neutral demo data.

Server and client posture

Every block renderer is a server component and ships no script of its own. The picker is radio inputs and CSS. The status chips and hours that the desk strip and the offices list show are the local pack's small client islands, which keep a cached page true. The pack reads the practice layer through its ./server entry in one place, src/layer/server.ts (setPracticeServer swaps it in tests), and no renderer imports it, the layer root or Payload.

How a block gets its data

A record-reading block carries one virtual field, practiceData, with an afterRead hook that calls the layer through req.payload and writes plain data into it. One read per request is shared by every block on the page; a failed read logs a warning and the block falls back to its own typed fields, or to nothing. source chooses what the block shows (all, group, person, topic, current, inline, depending on the block). current is the record the page is the page for: place the block in a person's, topic's or offering's layout and it reads that record, or name one in the block.

Honest data is the rule everywhere: anything with no data hides and the layout closes up, a status with no value shows no chip, an expired status is gone, a number is printed only when the record chose to show it, and a sample record carries its label from the settings. The emergency line in practice-book is the business profile's urgentNotice (wording and up to two labeled numbers, read through the local layer's profile), hidden when it is empty; the numbers vary by country, so the profile ships it empty and the site writes it. Text typed in the block is an explicit override for that block alone. practice-people-list shows a link to check credentials when a person has a credential with a verification link, read with the roster.

Wording

Layer words (the status words, the sample labels, the review words, the duration word, "person", "offering", "topic") come from practice-settings. Every block that prints them also takes an optional labels group that wins for that block alone, for a demo that shares one starter's settings with another. A real site leaves it empty.

Wrapped local-pack blocks

practice-desk-strip and practice-offices wrap local-desk-strip and local-locations: their display fields (heading, show switches, status copy, time style, map, typed places) are those blocks' own, taken from their configs, and they render through the local pack's renderers. practice-offices adds the people through the locations list's per-office slot (renderOfficeExtra): a "Seen here" line is appended inside each office by matching the office name to the offices on the person records, with the typed days when the record has them. Set mapMode to live and register the live map once (see the local pack's live-map entry); until then the directions links stand alone.

Theme hooks

The public hook contract is the data-* attributes each renderer documents in its file header: a root data-practice-<name> with data-block-variant and a band tone data-practice-tone="ground|tint|wash|surface|field", a shared status chip data-practice-status with data-state, data-status-dot and data-status-text, tabular figures on data-practice-figure, and data-compliance-label for photo and sample labels. The class names are scoped and are not part of the contract.

Block reference

practice-desk-strip

Every office, whether it is open right now, the main number and a book action, in one line under a hero.

When to use
  • Directly under the hero of a home page
  • Above an offices list, as the short version of it
Page types
  • landing
  • marketing
  • about
How to use

Leave Data on the site's locations and the strip reads every published office. The number is the one typed here, else the business profile's, else the primary office's; the book action is the one typed here, else the primary office's. An office without hours shows no status, because nothing true can be said about it.

Pairs with
  • practice-topic-picker
  • practice-offices
Precedes
  • practice-topic-picker
Avoid when
  • The site has one office and no phone: a plain button is enough
Register in

marketing-landing

practice-topic-picker

Asks what brings a visitor in and answers with the group's topics and the person they would likely see. The tabs are radio inputs, so it works with JavaScript off and by keyboard.

When to use
  • A home page that sends visitors to the page for what they came for
  • A services overview grouped by need
Page types
  • landing
  • marketing
  • about
How to use

Leave Data on Groups and the block reads every group that has a published topic. Each group shows its descriptor under the tab, its topics as rows and one lead person (the group's chosen lead, else the first person on its topics). A group with no topic is not offered, a lead with no status shows none, and no lead hides the person slot. Up to eight groups.

Pairs with
  • practice-offering-list
  • practice-people-list
  • practice-desk-strip
Follows
  • practice-desk-strip
Precedes
  • practice-offering-list
Avoid when
  • There is only one group: a plain list of topics is clearer
Register in

marketing-landing

practice-offering-list

What is offered, who offers it and what it costs, from the offering records, so nothing is typed twice.

When to use
  • A home page band of the kinds of work
  • A price list
  • The offerings a person or a topic leads to
Page types
  • landing
  • marketing
  • pricing
How to use

Choose a layout. doors: large cards with a photo, the summary and who offers it. rows: title, duration and price on one line. detail: one card per offering with a price row and a link. Source picks all offerings, one group, one person's, one topic's, or the current record's. An offering without a price shows none and the row closes up.

Pairs with
  • practice-topic-picker
  • practice-people-list
  • practice-steps
Follows
  • practice-topic-picker
Precedes
  • practice-steps
Avoid when
  • No offering has been entered: the block renders nothing, so leave it off
Register in

marketing-landing

practice-steps

What happens, start to finish, the first time someone comes in, with the time each step takes and who they meet.

When to use
  • A home page band between the offerings and the people
  • A new-visitor page
Page types
  • landing
  • marketing
  • about
How to use

Add three to five steps, each with a title, a sentence, a time and who is there. Add a photo and a bring list for the pair under the steps; leave either empty and the other takes the full width. Figures typed here are examples: tick Sample figures to label them.

Pairs with
  • practice-offering-list
  • practice-people-list
Follows
  • practice-offering-list
Precedes
  • practice-people-list
Avoid when
  • There is no real process to describe
Register in

marketing-landing

practice-people-list

Who works here, what they do, which offices they are at, the languages they speak and whether they are taking new clients, from the people records.

When to use
  • A home page row of the people
  • The people who answer a topic or offer a service
  • Everyone at one office
Page types
  • landing
  • marketing
  • about
How to use

Choose a layout (row, cards or compact) and a source: everyone, one offering's, one topic's, one office's or the current record's. Status, languages and the book action each have a switch. A person with no status shows none; one who is not accepting shows the note in place of a book action.

Pairs with
  • practice-topic-picker
  • practice-offices
  • practice-offering-list
Follows
  • practice-steps
Avoid when
  • A single person is the page: use practice-record-header
Register in

marketing-landing

practice-offices

Every office, whether it is open now, how to get there and who is seen there.

When to use
  • A find-us band on a home page
  • The offices where one person sees people, on their page
Page types
  • landing
  • marketing
  • about
How to use

Leave Data on All offices, or choose one person's (or the current person's) offices. Seen here lists the people at each office, with the days when the record has them. A hidden address shows the town only, with no directions link and no pin. Map: live needs the live map wired once (see the local pack's live-map entry); until then the directions links stand alone.

Pairs with
  • practice-desk-strip
  • practice-people-list
Follows
  • practice-people-list
Avoid when
  • The site has no locations: the block renders nothing
Register in

marketing-landing

practice-guide-list

The newest guides, each with who reviewed it and when, from the topic records.

When to use
  • A home page band of three guides
  • The guides in one group
Page types
  • landing
  • marketing
  • blog
How to use

Source recent shows the most recently reviewed topics; group shows one group's. The footer's wording and the aging interval come from the practice settings.

Pairs with
  • practice-reviewed-line
  • practice-topic-picker
Precedes
  • practice-offices
Avoid when
  • No topic has a body worth reading
Register in

marketing-landing

practice-record-header

The first thing on a person's page or a topic's page, built from the record so nothing is typed twice.

When to use
  • The top of a person page
  • The top of a topic page
Page types
  • about
  • marketing
How to use

Place it first in the record's layout and it reads that record. person: portrait, name with honorific and post-nominals, role line, summary, language tags, status, Book and Call, and an At a glance panel. topic: the title, the summary and Book with the person who leads it. A person who is closed shows the status and the call action only.

Pairs with
  • practice-path
  • practice-credentials
  • practice-book
Precedes
  • practice-path
Avoid when
  • The page is not the page for a record
Register in

marketing-landing

practice-path

The short answer to what is wrong, what kind of help, and who does it, as one connected line.

When to use
  • Under the header of a topic page
Page types
  • about
  • marketing
How to use

Place it in a topic's layout. The offering is the topic's first, and the person is that offering's first person, otherwise the topic's first direct person. Reorder the records to change the path.

Pairs with
  • practice-record-header
  • practice-people-list
Follows
  • practice-record-header
Avoid when
  • The page is not a topic
Register in

marketing-landing

practice-reviewed-line

A review stamp that tells the truth about its own age.

When to use
  • Beside the body of a topic page
  • Under a guide card
Page types
  • about
  • marketing
  • blog
How to use

Place it in a topic's layout. The review interval is set once in the practice settings; leave it empty and no line ever ages. A page with no review shows nothing.

Pairs with
  • practice-record-header
  • practice-guide-list
Follows
  • practice-record-header
Avoid when
  • The page has no reviewer
Register in

marketing-landing

practice-credentials

The credentials a person holds and where a visitor can check each one.

When to use
  • A person page, under the header
Page types
  • about
  • marketing
How to use

Place it in a person's layout. A number is printed only when the credential row ticks Show the number. The verification link and its label come from the record.

Pairs with
  • practice-record-header
  • practice-related
Follows
  • practice-record-header
Avoid when
  • The person has no credentials entered
Register in

marketing-landing

practice-related

Chips linking to the records connected to this one.

When to use
  • People are seen for: on a person page
  • Other people on a topic page
Page types
  • about
  • marketing
How to use

Choose what the chips list: topics, offerings or people. With no related record the block renders nothing, heading included.

Pairs with
  • practice-record-header
  • practice-credentials
Follows
  • practice-credentials
Avoid when
  • The page is not the page for a record
Register in

marketing-landing

practice-book

Book or call, as equal choices, with the urgent line always in view.

When to use
  • The end of a person page
  • The end of a topic page
Page types
  • about
  • marketing
  • landing
How to use

Place it last in the record's layout. On a topic page it books with the person who leads the topic. The emergency line is typed here and always printed; leave it empty only if the site shows it elsewhere. Neither tile is hidden when the other is missing: a tile without a destination is left out and the other stands alone.

Pairs with
  • practice-record-header
  • practice-offices
Follows
  • practice-offices
Avoid when
  • The page is not a person or a topic
Register in

marketing-landing

Exports

Import path
@wabbit/tome-blocks-practice-pack
@wabbit/tome-blocks-practice-pack/render
@wabbit/tome-blocks-practice-pack/render/register
@wabbit/tome-blocks-practice-pack/server
@wabbit/tome-blocks-practice-pack/demo
@wabbit/tome-blocks-practice-pack/meta

Changelog

0.2.xMinor

  • A site that holds more than one practice in the same records can now limit each practice block to its own, and the price list can sit beside the plans the practice accepts.

    The blocks that list records (the need picker, offerings, people, offices, guides and related chips) take an optional slug prefix, scope; empty shows every record and the output is unchanged. A scoped need picker drops a tab with no topics left and shows no lead person from outside the scope.

    The rows layout of the offering list prints each row's time as a subtitle under its title, and, when the practice settings list accepted plans, puts the price list in a panel beside a "Plans we accept" panel with a note and a call action you can write; with no plans listed the rows take the full width as before. The offices block passes through the new hours word of the local pack, and "Seen here" separates people with semicolons when names carry credentials or days, so a comma is never part of a name.

  • The phone menu button now says what it will do: while the menu is open it is named "Close navigation menu" (settable with triggerCloseLabel) and reports aria-expanded; a credential kind prints in sentence case ("License", not "license").

    The rename applies only to a trigger whose own name starts with "Open"; a trigger with another name keeps it, and a closed menu renders exactly as before.

  • A page can now carry a breadcrumb trail, an urgent or important notice, and prose set beside its review line and a callout, all from blocks an editor composes.

    The new breadcrumb block is a labeled navigation landmark holding an ordered list of links that ends in the current page (aria-current="page"); labels wrap at any width, every link is at least 44px tall, an unsafe link shows as text, and no structured data is emitted. The post-notice block gains an optional tone (standard, important, urgent) and a headingLevel: a toned notice gets a mark before its heading and a heavier edge, never color alone, it stays a static note (no alert role), and an untoned notice renders byte for byte as before.

    The practice pack's reviewed line is now nestable, so it can sit in a layout grid; build the reading layout with a layout grid in its feature-and-sidebar arrangement holding a text block, the reviewed line and a notice. The block catalog lists the new block.

  • The offering list's price list now sits on the page ground beside the plans panel and prints its sample tag once, in the panel's header.

    With accepted plans listed, the rows layout defaults to the ground tone instead of the tint, so the two panels read as panels, and "Demo figures" is one tag in the price list's header instead of a tag on every row. With no plans listed nothing changes.

  • The header status strip now updates itself like the desk strip, and a map that cannot load says so.

    The multi-office strip in the chrome announcement slot (PracticeStatusAnnouncement) is still rendered on the server, but its status line is now a small client island that recomputes from the same hours on mount, every 30 seconds and when the tab comes back, so a cached page can no longer say "Open now" after closing time while the desk strip below it says closed. Its first render equals the server's, so nothing flickers.

    When the map's tiles or style are blocked, the maps providers print a plain sentence ("The map could not load. The directions links still work.", settable with failedMessage) beside the directions links instead of failing silently.

0.1.xMinor

  • New package: @wabbit/tome-blocks-practice-pack, the free block pack for businesses defined by their people, services and offices, reading the records of @wabbit/tome-practice.
    • Thirteen blocks, registered as the practice-pack bundle (tier free): practice-desk-strip, practice-topic-picker, practice-offering-list (doors, rows, detail), practice-steps, practice-people-list (row, cards, compact), practice-offices, practice-guide-list, practice-record-header (person, topic), practice-path, practice-reviewed-line (margin, card), practice-credentials, practice-related (chips) and practice-book. Plus PracticeStatusAnnouncement at @wabbit/tome-blocks-practice-pack/server, a multi-office status strip for chrome's announcementSlot.
    • Neutral: no default, option or comment names a trade. The words come from the practice settings; every block that prints them also takes an optional labels group that wins for that block alone.
    • Structure, not look: every block emits public data-* hooks (a root data-practice-<name>, a band tone, a shared status chip, tabular figures), and its base stylesheet sets layout and spacing from tokens only, with no literal colour, radius or shadow.
    • Honest data: anything with no data hides and the layout closes up; a status with no value shows no chip; a number prints only when the record chose to show it; sample records carry their label from the settings.
    • practice-topic-picker works without JavaScript (radio inputs and CSS), is keyboard accessible with a group label, and shows a closed lead's status with a call action.
    • practice-desk-strip and practice-offices wrap the local pack's local-desk-strip and local-locations, so @wabbit/tome-blocks-local-pack 0.9.0 or later is a required peer; practice-offices adds a "Seen here" line to each office through the list's per-office slot.
    • practice-book shows the business profile's urgent notice (hidden when empty); text typed in the block overrides it. Typed photos are uploads to the media collection (mediaCollection, default media), never URLs. practice-people-list links to a person's credential verification page when there is one.
    • Requires @wabbit/tome-practice 0.2.0 or later (the roster and group reads).

Full changelog across all packages