Playroom Prototyping

This guide aims to teach you how to make your Playroom designs interactive, and assumes you already have a basic level of familiarity with Playroom.

Introducing state

Braid components, when used in Playroom, manage their own state internally by default. For example, if you use a Checkbox component, you’re able to toggle the checkbox on and off.
<Checkbox label="Checkbox" />
So the checkbox works in isolation, but what if we wanted it to control other parts of the UI? Well, first we need to provide a stateName prop to our checkbox, which then allows us to ask for its state elsewhere in our prototype using the getState function.
As a minimal example, let’s make the checkbox toggle the visibility of another element:
<Stack space="medium">
  <Checkbox label="Checkbox" stateName="myCheckbox" />

  {getState("myCheckbox") && (
    <Notice tone="positive">
      <Text>Good job! You checked the checkbox!</Text>
    </Notice>
  )}
</Stack>
We could also use the checkbox state to toggle the visibility of two alternate elements:
<Stack space="medium">
  <Checkbox label="Checkbox" stateName="myCheckbox" />

  {getState("myCheckbox") ? (
    <Notice tone="positive">
      <Text>Good job! You checked the checkbox!</Text>
    </Notice>
  ) : (
    <Notice tone="critical">
      <Text>Oops! You haven’t checked the checkbox!</Text>
    </Notice>
  )}
</Stack>
By default, all state values are blank until the user interacts with something. While this is usually fine in simple prototypes, you’re likely to find scenarios where you need the state to have a default value. For example, we might want our checkbox to be checked by default. To support this, our Playrooom provides a setDefaultState function which should be called before rendering anything to the screen:
{setDefaultState("myCheckbox", true)}

<Stack space="medium">
  <Checkbox label="Checkbox" stateName="myCheckbox" />

  {getState("myCheckbox") ? (
    <Notice tone="positive">
      <Text>Good job! You checked the checkbox!</Text>
    </Notice>
  ) : (
    <Notice tone="critical">
      <Text>Oops! You haven’t checked the checkbox!</Text>
    </Notice>
  )}
</Stack>
We can bind to more complicated state too, like text values within TextField components:
<Card>
  <Stack space="large">
    <TextField label="First name" stateName="firstName" />
    <TextField label="Last name" stateName="lastName" />

    {getState("firstName") && getState("lastName") ? (
      <Heading level="4">
        👋 Hello {getState("firstName")} {getState("lastName")}!
      </Heading>
    ) : null}
  </Stack>
</Card>
It’s not just about form elements either. For example, we might want to provide a Button that, via an onClick handler, toggles the open state of a Drawer.
In this example we’re making use of the toggleState function to set the state to true if the drawer is hidden.
<Card>
  <Actions>
    <Button onClick={() => toggleState("myDrawer")}>Open drawer</Button>
  </Actions>

  <Drawer title="Drawer" stateName="myDrawer">
    <Placeholder height={100} />
  </Drawer>
</Card>

Navigating between screens

We can also leverage state to simulate having multiple screens by using a piece of state called screen.
In this example we’re making use of the setState function to choose the desired screen, and the resetState function to go back to the original screen.

Home

{setDefaultState("screen", "Home")}

{getState("screen") === "Home" && (
  <Card>
    <Stack space="large">
      <Heading level="3">Home</Heading>
      <Actions>
        <Button onClick={() => setState("screen", "Welcome")}>Sign in</Button>
      </Actions>
    </Stack>
  </Card>
)}

{getState("screen") === "Welcome" && (
  <Card>
    <Stack space="large">
      <Heading level="3">👋 Welcome!</Heading>
      <Placeholder height={100} />
      <Actions>
        <Button onClick={() => resetState("screen")}>Sign out</Button>
      </Actions>
    </Stack>
  </Card>
)}

What’s next?

If you’ve come this far, it’s likely that you’ll still have some questions. Please reach out so we can give you a hand, and hopefully feed improvements back to the site. We’re going to keep iterating on the prototyping experience over time, so any feedback you have would be greatly appreciated!