Bike 2 Stylesheet feedback

OK – here are some random thoughts! :point_down:t2:

Also, so I don’t have to keep uploading a zip file here, the theme now has a Git repo.


In general, it was a bit difficult, as I don’t know Javascript, and kept thinking in CSS. :stuck_out_tongue: Claude helped me, as I gave it both the documentation on the web site and the .ts file, but it of course made a lot of mistakes as well. However, it did help me get things to try, which I could then tweak. Thanks to the automatic update of the Bike window, troubleshooting was OK.

One of the things it did, was to create a helper functino so I could use hex colours, and then add custom colours:

// Helper function to convert hex colors to Bike's Color format
function hexColor(hex, alpha = 1.0) {
  // Remove # if present
  hex = hex.replace(/^#/, "");

  // Parse the hex values
  let r = parseInt(hex.substring(0, 2), 16) / 255;
  let g = parseInt(hex.substring(2, 4), 16) / 255;
  let b = parseInt(hex.substring(4, 6), 16) / 255;

  return new Color(r, g, b, alpha);
} function getCustomColors(isDarkMode) {
  if (isDarkMode) {
    return {
      background: hexColor("#1a1e30"),
      text: hexColor("#d7dbea"),
      (Etc.)
    };
  } else {
    return {
      background: hexColor("#f8f9fb"),
      text: hexColor("#3e4a77"),
      (Etc.)
    };
  }
}

I do prefer HSL, though. :slightly_smiling_face:

  • I struggled quite a lot with selectors, as I didn’t know when to use .selector .@selector or just selector. Why is it parent() = true, but @type = heading? And I could probably do parent() = false, but what if I want to select things that arent’t headings?
  • As mentioned, just like with theme.hideControlsWhenTyping, I’d like an option like hideHandleWhenNoChildren.
  • I had to switch the order of the bold and the italics rule to get bold+italic to work.
  • I also don’t quite know what the things in parentheses mean, like (env, row).
  • It would be nice with something like layers in CSS, to decide priority. For instance, I’ve struggled with selection not playing nice with the background I want for code. The fix was to change the code background to have alpha, but that lead to another problem: (I also have one more code problem.)

I want to have code runs to have a background, but just behind the text, while I want code blocks/rows to have the colour all the way to the right.

The former works perfectly – but when the background has alpha, I can see where the different row backgrounds overlap. They also don’t align on the right side, for some reason. (And, where is the spacing change when something gets indented set? I would need to know that to be able to adapt the background offsets and heights to make it perfect.)


One of the things I did, was to colour the arrow.down.forward, in the header colour, when it’s in the header. What would’ve been logical for me, was to create an if statement inside the RowRule where that is set. But to get it to work, I instead made a separate rule like defineRowRule(".@type = heading and parent() = true and focused-root() = true", (env, row) => {}.

So, I had these two rules:

defineRowRule(".parent() = true and focused-root() = true", (env, row) => {}

and

defineRowRule(".@type = heading and parent() = true and focused-root() = true", (env, row) => {}

So when I wanted to also colour the handle for collapsed headings, I tried to think similarly, and create the second rule here, expanded from the first:

defineRowRule(".parent() = true and collapsed() = true", (env, row) => {}

defineRowRule(".@type = heading and .parent() = true and collapsed() = true", (env, row) => {}

That didn’t work, and I had to do this:

defineRowRule(".@type = heading and collapsed() = true", (env, row) => {}

However, this also selects when the heading is empty, even though it’s not a parent and not collapsed. :pensive::point_down:t2:

Still – I’m quite pleased with how it looks! And it’s so fun to see my own ideas merge with the Grosjean Polish™️. (Even though there’s still quite a lot of jank, as you know well.)

Here’s my theme, vs. the default. My goals:

  • I’ve tried to give it a softer look (while hopefully still be readable).
  • I also wanted to fix some of the annoyances I have with Bike 1.x:
    • Headings don’t stand out, as they look just like bold text.
    • I didn’t love that text in lists on Indent Level 1 was exactly the same as regular text on Indent Level 2.
    • I don’t think code stands out enough. (Bike is lovely at displaying and writing code. I’d totally use it as my code editor if I could. :stuck_out_tongue:)
    • I also think notes should stand out more (by standing out less :smiling_face:).

Lots of these could be achieved without changing the look quite as much, though! So I’m planning on making a greyscale version as well.


Oh, and I’ve also noticed that Bike struggles a bit with the text replacement from Raycast. Among other things, I use it for emoji – and Bike will create a new line, while other apps doesn’t. I think Raycast uses the clipboard somehow for the text replacement. :thinking:


Edit: Smart to move this over to a new thread! :ok_hand:t2:

2 Likes

Me too! Or at least struggle with how to model things.

First, if you are struggling make sure to test with Window > Outline Path Explorer. That should do a pretty good job of showing exactly what you’re path is matching.

What I have tried to do I model attributes that are part of Bike’s outline model using @ATTRIBUTENAME. Then I use function syntax such as selection() to read more dynamic state that is not stored in the outline.

I also use functions in some places where getting the same information using pure outline path syntax would be difficult. For example testing if a row has children rows in pure outline path syntax needs to be done like this:

.count(./*) > 0

I added the parent() function so that I could instead do .parent() = true, which I think is easier to understand, it’s also quite more performant to implement.

There’s nothing special or built in about theme.hideControlsWhenTyping. The only reason for it is so that Bike’s settings panel can effect the theme logic. It should be possible to hide handle when no children in current themes. That’s what you are going after right?

Each rule in the stylesheet is a function/closure. Those are the inputs to the rule function. The second parameter (row in this case) is the style before applying the rule… and the rules code updates that passed in style.

Ha, I’ve never heard of layers, but will take a look. I think the model of an ordered list of functions that transform styles is good enough for Bike, but the trick is how to organize those functions in nice ways. Right now is simples… each stylesheet has full control of all rules and ordering.

On the other hand it would be nice to build up a bit more structure/grouping of the functions. A make it easier for a new stylesheet to reuse functions from the built in stylesheet. To this point I’ve only thought “that would be nice”, but I haven’t got much further than that.

I’m going to respond to the code questions in a separate post… need to go do some other things, so might not get to it till tomorrow, but do plan to get to it.

Thanks, fixed for next release.

1 Like

Thanks for the reply! 🫶🏻

I was considering sharing two versions of my theme (when it’s done): One where the handles are there all the time (like now, which I assume most people would want?), and one where it’s not there if there are no children (like how I think I’d prefer it). But then I thought that it would be nice if that was a setting in the app’s setting screen instead, like hideControlsWhenTyping.

I’m pitching for a button here :smiling_face: :