Skip to content

Tutorial Part 2: The Power of Relations

In the last tutorial, we got a brief introduction to Bluefish: its marks, relations, and declarative references. In this tutorial, we'll see just how expressive relations can be. We'll progressively modify the label in the last tutorial until we've gone from this:

import "./styles.css";

document.getElementById("app").innerHTML = `
<h1>Hello world</h1>
`;

to this:

import "./styles.css";

document.getElementById("app").innerHTML = `
<h1>Hello world</h1>
`;

Along the way we'll encounter some other Bluefish relations: Arrow, Align, and Distribute. We'll also gain some more experience using name and Ref.

Flip label direction

One thing we can do without changing our spec very much is move the label below the planet by simplifying reversing the order of StackV's children:

tsx
// ...
      <Background background={() => <Rect stroke="black" stroke-width={3} fill="none" rx={10} />}>
        <StackV spacing={30}>
          <Text>Mercury</Text>
          <Ref select="mercury" />
          <Ref select="mercury" />
          <Text>Mercury</Text>
        </StackV>
      </Background>
// ...

label under planet

Change Background to Arrow

We can also change how we connect the label to the planet. Instead of using a Background, we can use an Arrow relation instead:

tsx
// ...
      <Background background={() => <Rect stroke="black" stroke-width={3} fill="none" rx={10} />}>
        <StackV spacing={30}>
          <Ref select="mercury" />
          <Text>Mercury</Text>
          <Text name="label">Mercury</Text>
        </StackV>
        <Arrow>
          <Ref select="label">
          <Ref select="mercury" />
        </Arrow>
      </Background>
// ...

label arrow

We named the Mercury label, deleted the Background, and added an Arrow relation whose children point at StackV's children.

CHALLENGE

Can figure out how to get back to the previous version of the diagram with Background by only changing two lines of code?

Distribute the label from the planets

Right now the label is inside the planets Background, but what if we want to place it outside? We could change the StackV spacing until it's large enough, but we would have to manually update it whenever we changed the Background or the sizes of the planets. Instead, we'll offset the label from the planets Background directly.

To do this, we first have to split StackV into its two constituent parts: vertical Distribute and horizontal Align:

tsx
<StackV spacing={30}>
<Distribute direction="vertical" spacing={30}>
  <Ref select="mercury" />
  <Text name="label">Mercury</Text>
</StackV>
</Distribute> 
<Align alignment="centerX">
  <Ref select="mercury" />
  <Ref select="label" />
</Align> 

This refactor doesn't change the diagram at all, but it does let us retarget the Distribute so we n offset it from the Background instead of the Mercury Circle. To do this, we'll first label the planets Background:

tsx
<Background padding={80} background={() => <Rect fill="#859fc9" />}>
<Background name="planets" padding={80} background={() => <Rect fill="#859fc9" />}>

Then we'll change the selection in the Distribute:

tsx
<Distribute direction="vertical" spacing={30}>
  <Ref select="mercury" />
  <Ref select="planets" />
  <Text name="label">Mercury</Text>
</Distribute>

mercury label outside background

Wrapping up

Huzzah! We modified the label in our planets diagram. Along the way we used Arrow, Align, and Distribute, three important Bluefish relations. We've also gained more experience naming elements and selecting them with Ref. Your final code should look like this:

import "./styles.css";

document.getElementById("app").innerHTML = `
<h1>Hello world</h1>
`;