1

We are building a kanban-board-like web application that looks somehow like this:

So we have swimlanes with items in them.

Currently we have a layout like this:

<ul>
    <ul class="swimlane">
        <li>Item a1</li>
    </ul>
    <ul class="swimlane">
        <li>Item b1</li>
        <li>Item b2</li>
        <li>Item b3</li>
    </ul>
    <ul class="swimlane">
        <li>Item c1</li>
        <li>Item c2</li>
    </ul>
</ul>

So we have a list off lanes which are themselves lists of items.

Now we are trying to make the board navigation accessible by allowing table navigation from nvda. Eg: clt+alt+left goes to the next* cell in the lane to the left.

In order to do that we looked at the aria roles grid, row and gridcell. But it seems, that these things only support row based layout but not column based ones. We don't really have rows that span all lanes. Every item can have an arbitrary height in theory.

Is there something like a column role or a workaround to achieve a similar thing?

* of course next is not always easy to determine, because the lanes can have a different number of items, so not every item has a left neighbour (eg. item b2 from the example)

Another solution would be to implement the table-navigation shortcuts of nvda by hand. But it seems that nvda captures these keystrokes before they reach the browser and my application. Would there be a way around that?

Third solution would be to use somehow similar shortcuts than nvda. But we would like to avoid that.

unor
  • 92,415
  • 26
  • 211
  • 360
Simon Lenz
  • 2,732
  • 5
  • 33
  • 39

2 Answers2

2

The ARIA roles to mimic a table do not have a way to specify what column an element should be in. The roles expect the DOM to be similar to how a real table is defined - row based. So you'd have to change the way your lists are defined so they are row based instead of column based.

(Note: Your picture doesn't match your code example. My example below is referencing your code example.)

So instead of having

<ul>
    <ul class="swimlane">
        <li>Item a1</li>
    </ul>
    <ul class="swimlane">
        <li>Item b1</li>
        <li>Item b2</li>
        <li>Item b3</li>
    </ul>
    <ul class="swimlane">
        <li>Item c1</li>
        <li>Item c2</li>
    </ul>
</ul>

You'd need

<ul>
    <ul>
        <li>Item a1</li>
        <li>Item b1</li>
        <li>Item c1</li>
    </ul>
    <ul>
        <li></li>
        <li>Item b2</li>
        <li>Item c2</li>
    </ul>
    <ul>
        <li></li>
        <li>Item b3</li>
        <li></li>
    </ul>
</ul>

And then you could use the table roles.

Note: A new table row was added in ARIA 1.1. Previously, only grid was available. If your table is not interactive (ie, just static text), then the table role (and cell role) should be used. If your table is interactive, like a spreadsheet that has cells that can be edited, then the grid role (and gridcell role) should be used. Having a link in your table cell is not considered interactive even though you can "interact" with the table by clicking on a link. I'm using the word "interactive" to mean the cells are editable.

<ul role="table">
    <ul role="row">
        <li role="cell">Item a1</li>
        <li role="cell">Item b1</li>
        <li role="cell">Item c1</li>
    </ul>
    <ul role="row">
        <li role="cell"></li>
        <li role="cell">Item b2</li>
        <li role="cell">Item c2</li>
    </ul>
    <ul role="row">
        <li role="cell"></li>
        <li role="cell">Item b3</li>
        <li role="cell"></li>
    </ul>
</ul>

Also, if you are defining a table, you really should have column headers too. The column headers can be contained in a role="row" or role="rowgroup". The rowgroup is analogous to having a <thead> but rowgroup currently doesn't pass on any extra semantic info to screen readers. I use it because it helps my column headers stand out in the code.

<ul role="table">
    <ul role="rowgroup">
        <li role="columnheader">To Do</li>
        <li role="columnheader">WIP (2)</li>
        <li role="columnheader">Done</li>
    </ul>
    <ul role="row">
        <li role="cell">Item a1</li>
        <li role="cell">Item b1</li>
        <li role="cell">Item c1</li>
    </ul>
    <ul role="row">
        <li role="cell"></li>
        <li role="cell">Item b2</li>
        <li role="cell">Item c2</li>
    </ul>
    <ul role="row">
        <li role="cell"></li>
        <li role="cell">Item b3</li>
        <li role="cell"></li>
    </ul>
</ul>
slugolicious
  • 15,824
  • 2
  • 29
  • 43
  • Thanks for you deliberations! Sadly changing the lists to row based isn't an option for us since the whole application expects columns everywhere. The more I think about it, I think the correct solution for us would be not to support table navigation at all, simply because we don't have a table. It's something else. But I think your solution would still be the correct way of doing things if I really want table navigation. So I will accept your answer. – Simon Lenz Apr 25 '18 at 07:40
  • 1
    FYI, navigating nested sublists is pretty easy with a screen reader so you don't have to mimic a table. Using 'L' to move to the next list and 'I' (eye) to move to the next list item works nicely. – slugolicious Apr 25 '18 at 18:32
0

Just my two cents not directly related with the main question but that I think can be helpful: Your code will not validate in a w3c validator like https://validator.w3.org

1) ul elements only allow li or script-supporting elements like script or template (as previously @unor states in its comment). You should not use ul as direct child for ul. This is the message the validator raises in this case:

Content model for element ul: Zero or more li and script-supporting elements.

2) ul elements can't have role grid or table. I don't know why, because it seems reasonable, but strictly talking, they can't. This is the error the validator will rise:

Error: Bad value table for attribute role on element ul.

You can check this for example in the Mozilla Developer website:

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul

Or some talk about this in this stack overflow topic:

HTML5 nav element vs. role="navigation"

But in your case, if you change your outer ul to a div, it would validate:

<div role="grid">
    <ul class="swimlane">
        <li>Item a1</li>
    </ul>
    <ul class="swimlane">
        <li>Item b1</li>
        <li>Item b2</li>
        <li>Item b3</li>
    </ul>
    <ul class="swimlane">
        <li>Item c1</li>
        <li>Item c2</li>
    </ul>
</div>

Although having a list of ul elements, you should perhaps better use a list of them, inside div:

<div role="grid">
 <ul>
  <li>
    <ul class="swimlane">
        <li>Item a1</li>
    </ul>
   </li>
   <li>
    <ul class="swimlane">
        <li>Item b1</li>
        <li>Item b2</li>
        <li>Item b3</li>
    </ul>
   </li>
   <li>
    <ul class="swimlane">
        <li>Item c1</li>
        <li>Item c2</li>
    </ul>
   </li>
</div>

Perhaps too verbose markup, and i would like to know the reason why ul can't be used with the role grid or table, as it seems something many people see as natural, seeing grids as a list of rows. It's hard to be semantic :/

tomasofen
  • 1,330
  • 2
  • 12
  • 16