Skip to main content

Learn Bluefish

In this short tutorial, you'll learn how to use Bluefish to make the planets diagram!

The planets diagram consists of a row of four circles that represent the first four terrestrial planets. There is box behind them and a label for Mercury. There is also an arrow pointing from the label to Mercury.

You will learn
  • How to write a Bluefish specification using JSX.
  • How to use common Bluefish elements (like Circle) and relations (like Align).
  • How to use the Ref component to reference other components.

Writing Bluefish Specifications with JSX

info

Bluefish's JSX syntax is only available in SolidJS environments. If you are working in other environments like Svelte or Observable, you will instead need to use Bluefish's function syntax.

(This section of the tutorial is based on React's documentation.)

To write a Bluefish specification (or spec), you typically use JSX syntax. JSX is a syntax extension to JavaScript that lets you write HTML-like code in JavaScript. For example, the following is JSX code:

<h1>Hello, world!</h1>

We typically call an element like h1 a component. Components are the building blocks of Bluefish specifications.

JSX is stricter than HTML. You have to close tags like <br />. Your component also can't return multiple JSX tags. You have to wrap them into a shared parent, like a <div>...</div> or an empty <>...</> wrapper:

<>
<h1>Hello, world!</h1>
<br />
<p>This is a paragraph.</p>
</>

Unlike built-in HTML components, Bluefish components are written with capital letters, like Circle or Row. Bluefish components can only be used within a Bluefish specification, which is scoped by a <Bluefish> component.

<Bluefish>
<Circle cx={20} cy={30} r={15} fill="#EBE3CF" stroke-width={3} stroke="black" />
</Bluefish>

Your First Bluefish Diagram

1. Make a Circle

It's time to add your first Bluefish component! The first thing we'll do is draw the planet Mercury. Replace the Text component in the editor with the code below.

<Circle cx={20} cy={30} r={15} fill="#EBE3CF" stroke-width={3} stroke="black" />

2. Add the Other Planets

Now we can add the other planets. Append this code below the Mercury circle.

<Circle cx={100} cy={30} r={36} fill="#DC933C" stroke-width={3} stroke="black" />
<Circle cx={160} cy={30} r={38} fill="#179DD7" stroke-width={3} stroke="black" />
<Circle cx={280} cy={30} r={21} fill="#F1CF8E" stroke-width={3} stroke="black" />
info

It's hard to make the circles evenly spaced by hand. See if you can do it!

3. Put Circles in a StackH

Instead of placing the circles manually, we can use a StackH component to position them. StackH distributes its children horizontally and aligns them vertically.

Add the StackH component to the diagram and put the Circles inside it.

<StackH spacing={50}>circles go here</StackH>

Then delete the positions (cx and cy) on the Circles. For example,

<Circle cx={20} cy={30} r={15} fill="#EBE3CF" stroke-width={3} stroke="black" />

should become

<Circle r={15} fill="#EBE3CF" stroke-width={3} stroke="black" />
info

Try changing the spacing or the size of the circles. What happens?

4. Add a Background

To add a background, we can wrap the StackH in a Background component.

<Background padding={20}>stackH goes here</Background>

5. Add a Label

Now it's time to add a label to the Mercury circle. So far, we've been building a hierarchical tree of components. But now we need to reference the circle that's in the stack in order to position it.

To do so, we'll first name the circle, then we'll select it later in the code. To name the first circle in the row, we'll add a name prop to it.

<Circle name="mercury" ... />

Then we can add a label by making a StackV with Text for the label and a Ref to the planet. Place this below the Background component, but inside the Bluefish component.

<StackV spacing={20}>
<Text>Mercury</Text>
<Ref select="mercury" />
</StackV>

6. Add an Arrow

Now let's draw an arrow from the label to the planet. To do so, we'll first name the label:

<Text name="label">Mercury</Text>

Then we'll add an Arrow component, pointing from the label to the planet. We can place this below the StackV component, but inside the Bluefish component.

<Arrow>
<Ref select="label" />
<Ref select="mercury" />
</Arrow>

7. Improve the label spacing

We want the label to always be outside the background box, but right now the label is spaced relative to the planet. We can replace the StackV component with horizontal Align and vertical Distribute to position the label more precisely.

First, replace the StackV component with an Align.

<Align alignment="centerX">Keep the same children as StackV</Align>

Then we'll name the planets earlier in the diagram:

<Background name="planets" ... >
...
</Background>

Then add a Distribute. We can place this below the Align and above the Arrow:

<Distribute direction="vertical" spacing={20}>
<Ref select="label" />
<Ref select="planets" />
</Distribute>
import { Bluefish, Group, StackH, Circle, Text, Ref, Background, Arrow, StackV, Align, Distribute } from "@bluefish-js/solid";

const App = () => {
  return (
    <Bluefish>
      <Text>TODO: Starting writing your code here!</Text>
    </Bluefish>
  );
};

export default App;

Simple Variations

Here are some simple variations on the diagram to test your knowledge. If you want to reveal the answer, click "Open Sandbox" on the variation. We've provided the solution to the tutorial above in the sandbox on your right.

import { Bluefish, Group, StackH, StackV, Circle, Text, Ref, Background, Arrow, Align, Distribute, Rect } from "@bluefish-js/solid";

const App = () => {
  return (
    <Bluefish>
      <Background padding={20}>
        <StackH spacing={50}>
          <Circle name="mercury" r={15} fill="#EBE3CF" stroke-width={3} stroke="black" />
          <Circle r={36} fill="#DC933C" stroke-width={3} stroke="black" />
          <Circle r={38} fill="#179DD7" stroke-width={3} stroke="black" />
          <Circle r={21} fill="#F1CF8E" stroke-width={3} stroke="black" />
        </StackH>
      </Background>
      <Align alignment="centerX">
        <Text name="label">Mercury</Text>
        <Ref select="mercury" />
      </Align>
      <Distribute direction="vertical" spacing={60}>
        <Ref select="label" />
        <Ref select="mercury" />
      </Distribute>
      <Arrow>
        <Ref select="label" />
        <Ref select="mercury" />
      </Arrow>
    </Bluefish>
  );
};

export default App;