> ## Documentation Index
> Fetch the complete documentation index at: https://docs.samplehc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Intro to Screens

> Creating interactive user interfaces within workflows

## 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:

```tsx ./src/screens/greeting-screen.tsx theme={null}
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:

```python ./src/workflow.py theme={null}
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")`

```python theme={null}
# 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:

```tsx ./src/screens/document-upload-screen.tsx theme={null}
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

## Screen ordering

By default, Sample will try to navigate to the screen that's most relevant to the user. In practice, this means navigating to the screen that's the closest next step. To override this behavior, you can set a `priority` option on a ScreenStep like so:

```python theme={null}
workflow.then(ScreenStep("screen-1", screen_path="./screens/screen-1.tsx", options={"priority": "10"}))
```

If there are multiple tasks in a worklist, users will be redirect to the highest priority screen.

<Note>
  Events functionality requires **workflows-py >= 0.1.22**.
</Note>
