Skip to content

Latest commit

 

History

History
336 lines (243 loc) · 12.8 KB

File metadata and controls

336 lines (243 loc) · 12.8 KB

@gusto/embedded-react-sdk - Internal README

To install dependencies:

npm install

To run:

npm run dev

Local development

For components

If you just need to develop a component outside of its context within a workflow, you can use Storybook:

npm run storybook

For workflows

If you need to test your component within the larger context of a workflow, you'll need to setup Zenpayroll + GWS-Flows.

  • Follow setup instructions for Zenpayroll and start local dev server
    • In another tab run the following commands in Zenpayroll directory(these generate necessary partner account for gws-flows) :
    bundle exec rails runner "DevAccountCreator.new.create_dev_accounts"
    rake partners_api:dev_setup_for_gws_onboarding
    
  • Follow setup instructions in the readme for GWS Flows
  • in SDK, Run npm run dev:setup; if that fails, follow the instructions below to setup manually:
    • Run npm link ../gws-flows/node_modules/react in sdk folder - this is needed to avoid duplicate react instances in local development due to using npm/yarn link
    • In GWS-Flows project folder, run yarn link -r ../embedded-react-sdk
  • In SDK, run npm run dev

Now your local changes appear in GWS Flows.

To see the SDK running in GWS Flows, visit it locally and choose React SDK (New company) or React SDK (Company Onboarded) under Select a Type and click Create Demo

Components and Flows will be shown at the top of the page in a nav. Company Components will automatically appear as they are added. Select a Flow or Component to view it

How to leverage Translations

Translations are stored in /src/i18n.

The are broken out by locale (e.g. en), then by namespace, which is usually the name of the component they are used in. The source of truth is the en locale - the rest will be autogenerated by translation service.

After writing the new translations, run npm run interface to generate the types.

In your components, first use useI18n hook, which takes in component namespace and loads appropriate resource file into dictionary. After that use the useTranslation hook to access the translations in that component and any child components.

Translation Key Guidelines

Follow these conventions when creating or modifying translation keys:

Naming Convention

Use camelCase for all translation key names:

{
  "pageTitle": "Federal Tax Information",
  "federalEinLabel": "Federal EIN",
  "federalEinDescription": "Your company's Federal Employer Identification Number",
  "continueCta": "Continue"
}

Standard Suffixes

Use consistent suffixes to indicate the purpose of each key:

  • Cta - Call-to-action buttons (e.g., submitCta, continueCta, cancelCta)
  • Label - Form field labels (e.g., firstNameLabel, emailLabel)
  • Description - Help text or descriptions (e.g., federalEinDescription)
  • Title - Page or section headings (e.g., pageTitle, sectionTitle)
  • Placeholder - Input placeholders (e.g., emailPlaceholder)
  • Error - Error messages (e.g., requiredFieldError, invalidEmailError)

Grouping Related Keys

Group related keys using nested objects for better organization:

{
  "validations": {
    "firstName": "First name is required",
    "lastName": "Last name is required",
    "email": "Email address is required and must be valid",
    "address": {
      "street1": "Street address is required",
      "city": "City is required",
      "state": "State is required"
    }
  },
  "labels": {
    "openMenu": "Open menu",
    "menuLabel": "Menu"
  },
  "alerts": {
    "progressSaved": "Your progress has been saved",
    "errorEncountered": "There was a problem with your submission"
  }
}

Common grouping patterns:

  • validations - Form validation error messages
  • labels - Accessibility labels and field labels
  • alerts - Alert and notification messages
  • icons - Icon accessibility labels
  • table - Table-related labels (column headers, actions)

When to Use snake_case

Only use snake_case when required by external contracts:

  1. API Enum Values - When keys match backend API responses:
{
  "onboardingStatus": {
    "admin_onboarding_incomplete": "Admin-onboarding Incomplete",
    "self_onboarding_invited": "Self-onboarding: Invited"
  }
}
  1. i18next Pluralization - Required by i18next for plural forms:
{
  "priority_one": "{{count}}st",
  "priority_two": "{{count}}nd",
  "priority_few": "{{count}}rd",
  "priority_other": "{{count}}th"
}
  1. Programmatic Identifiers - When used as flow/step identifiers that match API:
{
  "stepTitles": {
    "add_addresses": "Add company addresses",
    "federal_tax_setup": "Company federal tax information"
  }
}

Examples

Good:

{
  "pageTitle": "Employee Profile",
  "continueCta": "Continue",
  "cancelCta": "Cancel",
  "validations": {
    "firstName": "First name is required",
    "emailFormat": "Email must be valid format"
  },
  "labels": {
    "personalInfo": "Personal Information"
  }
}

Avoid:

{
  "page_title": "Employee Profile", // ❌ Don't use snake_case
  "ContinueCTA": "Continue", // ❌ Don't capitalize suffix
  "validation_first_name": "First name...", // ❌ Don't use snake_case
  "first_name_validation": "First name...", // ❌ Poor grouping
  "lbl_personal_info": "Personal Info" // ❌ Don't abbreviate
}

Creating components

Block components

Block components are focused, reusable components that serve specific functionality. They follow these patterns:

  • Single Purpose: Each component should generally handle a specific task (e.g., list, form, etc.)
  • Base Component: Uses BaseComponent for consistent behavior and error handling
  • Compound Pattern: Exposes subcomponents (Head, List, Actions) for flexibility and composition

Examples

Flow components

Flow components compose block components and other flow components together using state machines to manage transitions. They follow these patterns:

  • State Management: Uses the Flow component with a state machine to handle transitions
  • Component Composition: Can compose both block components (e.g., list → form) and other flow components
  • Naming: Suffix with "Flow" (e.g., DocumentSigner, Locations)

For example, EmployeeOnboardingFlow composes both block components (profile, taxes) and other flow components (document signer) to create a complete onboarding experience.

Examples

Testing locally

You can run the test suite locally with the following command:

npm run test

Pull requests

When creating a pull request, use the provided PR template (.github/PULL_REQUEST_TEMPLATE.md). Here are the guidelines:

PR title format

Use conventional commits format for your PR title. PR titles are validated by CI and used for automatic semantic versioning.

Note: This PR title validation works alongside the existing commitlint check. Commitlint validates individual commit messages (enforced via husky pre-commit hook), while this workflow validates the PR title which is used for squash merge commits and version bumping.

Semantic versioning (semver) mapping

PR titles determine how the package version is bumped on merge, following semver.org specification:

During 0.x.x (pre-1.0 development):

Commit Type Version Bump When to Use
feat MINOR (0.1.0 → 0.2.0) New features or functionality
fix PATCH (0.1.0 → 0.1.1) Bug fixes
feat! or fix! (with !) MINOR (0.1.0 → 0.2.0) Breaking changes*
docs, chore, refactor, test, ci, style, perf, build, revert No bump Non-functional changes

*Per semver spec, during 0.x.x the API is considered unstable, so breaking changes bump MINOR instead of MAJOR. The jump to 1.0.0 will be an intentional decision when we're ready to declare a stable API.

Title examples

  • feat: add new component - New feature → MINOR bump
  • fix: resolve issue with form validation - Bug fix → PATCH bump
  • feat!: redesign JSX component props - Breaking change → MINOR bump (during 0.x.x)
  • chore: update dependencies - Maintenance → no version bump
  • refactor: simplify state machine logic - Code refactoring → no version bump
  • docs: update README - Documentation → no version bump

For work tied to a Jira ticket, include the ticket in the scope so the title still follows conventional commits:

  • feat(SDK-123): add payroll blocker alerts - MINOR bump
  • fix(SDK-456): correct date formatting - PATCH bump

PR description sections

  • Summary: Brief description of what the PR does and why
  • Changes: Briefly list only the most important changes (high-level only; do not enumerate every file-level change)
  • Demo: Screenshots or screen recordings showing the changes (when applicable)
  • Related: Links to Jira tickets, Figma designs, or related PRs
  • Testing: Instructions for reviewers to test the changes

Best practices

  • Keep PRs focused on a single concern when possible
  • Include visual demos (screenshots/videos) for UI changes
  • Link to relevant Jira tickets using the format [SDK-XXX](https://gustohq.atlassian.net/browse/SDK-XXX)
  • Add Storybook stories for new components
  • Include unit tests for new functionality
  • Run npm run test and npm run lint before submitting

Commits

All commits must follow commitlint enforced format: type(scope?): subject #scope is optional; multiple scopes are supported (current delimiter options: "/", "\" and ",") Following types are currently defined:

'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test'

Read more about conventional commits here

Documentation

You can find documentation on building with the Gusto Embedded React SDK in the docs directory within this repo here. Documentation is also hosted live alongside the Gusto Embedded API docs here.

Cutting a new release

Package versions and the changelog are automatically updated when PRs are merged to main, based on the PR title:

  1. Automatic version bumping: When a PR is merged (not when it's opened), the auto-version workflow reads the PR title and bumps package.json version accordingly:

    • feat: → MINOR bump
    • fix: → PATCH bump
    • feat!: or fix!: (with !) → MINOR bump (during 0.x.x pre-release)
    • Other types (docs, chore, etc.) → no version bump
  2. Automatic changelog updates: The workflow also adds an entry to CHANGELOG.md based on the PR title description:

    • feat → "Features & Enhancements" section
    • fix → "Fixes" section
    • Breaking changes (with !) → "Breaking Changes" section
    • Other types → "Chores & Maintenance" section

    Note: The changelog entry uses the description portion of your PR title (e.g., feat: add new component becomes "add new component" in the changelog). For breaking changes, consider including migration guidance in your PR description - the auto-generated changelog entry provides the "what" but the PR body can provide the "how to migrate".

  3. Publishing: After the version is bumped, run the Publish to NPM GitHub action here by clicking Run workflow

Manual release (if needed)

If you need to manually cut a release:

  • Update the version field in package.json
  • Update CHANGELOG.md with the changes
  • Run npm i and commit the new lockfile
  • Run the Publish to NPM GitHub action