Weeknote: 2024-W18

07 May 2024

In last week’s note, I discussed the accessibility audit we’d just done; well, the rest of the week was spent fixing all the problems raised. Well, almost all.

Most of the list was quite small stuff (though there was quite a lot), but there are a few highlights that might be of interest.

I didn’t even know skip links were a thing, and you might not either. When navigating by keyboard, it’s sometimes a right pain to tab through a big list of things to get to the thing at the end that you want to get to. So, many sites include skip links, which skip ahead to the main content, or skip over a long list. Often these only appear when focused, which means that if you hit tab, up they pop.

I managed to get these coded up in a way that meant I could use them all over the site, so now, if you’re tabbing through, not only do you immediately get a “skip to main content” link, you also have skip links to skip over the model and tag lists, both of which are large and repetitive. Using the site with keyboard shortcuts was a really interesting new experience for me, and I highly recommend trying it to any web developer.

One of the hardest bits was making the image carousel on the model page accessible. Bootstrap’s default carousel accessibility is pretty good, but still has some gaps; getting it right for keyboard navigation and screen reader navigation is tricky. Helpfully the W3C ARIA guide has a great description of what’s needed for a properly accessible carousel, so I could make a big list and check off the features one by one.

This involved rebuilding bits of the bootstrap javascript myself, particularly around when things should pause, restart, and so on, and it took a whole day to get through the list.

In the end, there was one bit I couldn’t make work cleanly, which was that the auto-rotation should stop when the carousel gets keyboard focus. Unfortunately browser focus events don’t differentiate between keyboard or mouse focus, so the events kept getting tangled up and I couldn’t make it work right in both keyboard and mouse mode. In the end I decided that as the play/pause control was focused immediately, losing the auto-pause-on-focus for keyboad navigation was the right compromise.

If you’re using Bootstrap 5’s carousel, and want to reuse my work adding a play/pause control, a correct full set of aria tags, and the rest, here’s all the code. Maybe sometime I’ll push this upstream to bootstrap itself, but I don’t have time right now.

Bulk editing

One of the great things about the accessibility audit was that it was also a bit of user testing, and it quickly became obvious that the bulk editor was confusing as hell, especially on the file edit page. There were icons that looked like checkboxes, completely pointless columns, and bad labelling. All that is fixed now, so this should be friendlier for everyone. As I said last week, there’s no substitute for watching someone else use your site.

TODO

There are two big things left, which although I really want to move on to other tasks in order to get paid, I need to double down on and fix early this week.

Dodgy Accents

First off, while the site declares its language automatically in the lang attribute of the html tag, not everything is translated. New features normally go out in English only, then when volunteers get the translation done, it appears in the selected language. German in particular has a lot of gaps at the moment (let me know if you want to help!). Problem is that when using a screen reader, the software doesn’t know the languages has changed, so it will read the English text as if it was the other language, which will end up horribly mangling the words like it’s an episode of “‘Allo ‘Allo” (showing my age there, don’t worry if you don’t get the reference).

So, each untranslated string should have its own lang attribute to let the reader know. To do this, I need to extend Rails’ I18n::Fallback code so that untranslated strings get wrapped with a tag automatically. This is something that can benefit everyone, I think, so hopefully I’ll push it upstream into Rails core when it’s done.

3D content

The 3d content is also a tricky one. The audit raised that the 3d content can’t be focused or controlled with the keyboard, which is true. Unfortunately, as it is, I can’t fix this. In order to keep the performance up, I’m using a single canvas element for the entire window, and using a scissor test to only render the models in the right area. If you have multiple scenes, as Manyfold does, this avoids the page running out of WebGL contexts, as there’s only a limited amount available.

Unfortunately, this means that what do you even focus with the keyboard? The canvas isn’t really there and is definitely not in the correct DOM order.

So, before I can deal with this, I’ve got to change the way the renderer works. Fortunately, this is something I want to do for performance, though I didn’t really want to do it RIGHT NOW. Oh well.

The plan is to move the rendering offscreen, to a Web Worker, which will mean I can go back to individual canvases, and will increase performance by getting the rendering off the main document thread. This three.js page on OffscreenCanvas is my bible at the moment, while I work out how all this will work. It comes with a bunch of problems though that means it’s not just a lift-and-shift; for instance:

  • Many standard browser DOM Javascript methods aren’t available, which means the 3MF loader doesn’t work, amongst other things.
  • The OffscreenCanvas is completely detached from the main document, which means that resizing, visibility, and mouse and keyboard interaction events all need to be manually passed through to the web worker.

This has cost me way more time already than I intended, BUT, I do have an offscreen display that loads models and renders them; if I can get the interaction back and fix the 3MF loader, then we should be good to go. So, that’s today’s job - double down and get it done.

What’s next?

Once these are done I REALLY need to get some paid milestones under my belt. I will probably go back to the social side of things and get following and feeds in place, so that in multiuser mode you can follow other users, models, tags, etc, and see what’s updated. That’s then the last bit of groundwork for ActivityPub federation. There’s also a bit of design work to do for a new 3d model format based around progressive meshes, work on rewriting the upload process, and supporting cloud storage providers. Not sure which I’ll bite off first.