Overview

Screen steps are user interface components that allow human interaction within a workflow. They are implemented as React components that use the useScreenFunctions hook to interact with the workflow system.

Basic Concepts

Screen steps work by:

  1. Pausing the workflow when the step is reached
  2. Rendering a React component to collect user input
  3. Collecting the user’s response through the React component
  4. Resuming the workflow with the collected data

This allows you to create workflows that combine automation with human decision-making and data entry.

Creating Your First Screen Step

Let’s start with a simple screen that greets a user and collects their confirmation:

./src/screens/greeting-screen.tsx
import ActionBar from "@/components/ui/action-bar";
import { useScreenFunctions } from "@samplehc/ui/contexts";

const GreetingScreen = ({ name }: { name: string }) => {
  const { handleComplete } = useScreenFunctions();
  
  return (
    <div>
      <h2>Hello, {name}!</h2>
      <p>Ready to continue with the workflow?</p>
      <ActionBar onConfirm={() => handleComplete({ result: "confirmed" })} />
    </div>
  );
};

export default GreetingScreen;

Adding Screen Steps to Workflows

Once you’ve created a screen component, add it to your workflow definition:

./src/workflow.py
from workflows_py.workflow import ScreenStep, Step, Workflow

workflow = Workflow()
workflow.then(
    Step("prepare-greeting", lambda ctx: {"user_name": "John"})
).then(
    ScreenStep("greeting", screen_path="./screens/greeting-screen.tsx", get_props=lambda ctx: {"name": ctx.get_step_result("prepare-greeting")["user_name"]})
)

The screen component receives props from the get_props function. In this example, the name prop comes from the user_name field returned by the "prepare-greeting" step.

The useScreenFunctions Hook

Screen components interact with the workflow system using the useScreenFunctions hook, which provides two essential functions:

  • handleComplete({ result: data }) - Completes the screen step and passes data to the workflow. The workflow continues to the next step.
  • handleCancel() - Cancels the screen step and stops workflow execution.

Screen Step Data Flow

Understanding how data flows through screen steps is crucial:

  1. Input Data: Screen components receive props from the previous workflow step’s output
  2. User Interaction: Users interact with the screen interface to provide input
  3. Completion Data: When handleComplete() is called, the data passed becomes the step’s output
  4. Next Step Access: Subsequent steps can access this data using ctx.get_step_result("step-id")
# Accessing screen step results in the next workflow step
workflow.then(
    ScreenStep("user-input", "./screens/input-screen.tsx")
).then(
    Step("process-input", lambda ctx: {
        "user_data": ctx.get_step_result("user-input")
    })
)

Advanced Example: Document Upload Screen

Here’s a more complex example that demonstrates form handling and file uploads:

./src/screens/document-upload-screen.tsx
import { useScreenFunctions } from "@samplehc/ui/contexts";
import { Form } from "@samplehc/ui/components";

const DocumentUploadScreen = () => {
  const { handleComplete, handleCancel } = useScreenFunctions();

  return (
    <div>
      <h2>Upload Documents</h2>
      <Form
        elements={[
          {
            key: "documents",
            label: "Documents",
            type: "document",
            allowMultiple: true,
            description: "Upload multiple PDF documents or a ZIP file",
          },
          {
            key: "accession_id",
            label: "Accession ID",
            type: "text",
            required: true,
          },
        ]}
        onSubmit={async (formData) => {
          await handleComplete({ 
            result: {
              documents: formData.documents,
              accessionId: formData.accession_id
            }
          });
        }}
        onCancel={() => handleCancel()}
      />
    </div>
  );
};

export default DocumentUploadScreen;

This screen:

  • Renders a form with document upload and text input fields
  • Validates required fields before submission
  • Structures the output data for easy access by subsequent workflow steps
  • Provides a cancel option for users

Best Practices

Design Clear Interfaces

  • Use descriptive labels and helpful descriptions for form fields
  • Provide clear instructions about what input is expected
  • Include visual feedback for loading states and form validation

Handle Errors Gracefully

  • Validate user input before calling handleComplete()
  • Display clear error messages for invalid inputs
  • Provide users with actionable guidance to resolve issues

Structure Output Data

  • Use consistent naming conventions for output data
  • Group related data into objects for easier access
  • Include all necessary information for downstream workflow steps

Consider User Experience

  • Keep forms focused and avoid overwhelming users with too many fields
  • Provide progress indicators for multi-step processes
  • Allow users to save drafts or return to previous steps when appropriate