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:
// ...
<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>
// ...
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:
// ...
<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>
// ...
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
:
<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
:
<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
:
<Distribute direction="vertical" spacing={30}>
<Ref select="mercury" />
<Ref select="planets" />
<Text name="label">Mercury</Text>
</Distribute>
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> `;