Skip to content

Conversation

@kbangelov
Copy link
Contributor

@kbangelov kbangelov commented Dec 9, 2025

Resolves

https://scratchfoundation.atlassian.net/browse/UEPR-336

Proposed Changes

I have added role and aria-label tags for the elements to be considered as landmarks and be navigated through with a screen reader easily. I have separated the page into three parts :

  • navigation/menu bar (role = navigation)
  • editor (role = main)
  • Stage and Target (role = complementary)

Those three I have separated into the following:
Editor:

  • Editor tabs (region)
  • Backpack (region)

Stage and Target:

  • Stage (region)
  • Target (region)

Issue With Separating Editor into "editor tabs" and "editor panel"

I intended to do that as well. However I found no viable way to do it. TabList and TabPanel are some MIT code imported as a node module. So I can't really edit them to accommodate props "role" and "ariaLabel" as seen in some of the components in the code. I didn't find any way to overwrite the roles these components receive at a later point and wrapping them in a semantic html component breaks the css. Thus there are the following approaches:

  • Edit css so it doesn't break the page when these 2 components are wrapped in some other html one
  • Leave it as "roledescription" which should get read out loud when tabbing, however I don't think it is considered as a landmark and I could not test it to prove that it does indeed do that, only when hovered, which might not be ok
  • Some solution that overwrites the "role" and "aria-label" attributes all the way to the DOM return (data-role and data-aria-label didn't seem to do the trick)

Reason for Changes

None of them were focusable so far.

To be tested with a proper screen reader but it seems to work

I have not fully tested whether they can be navigated through quickly as landmarks yet, because the only semi-adequate screen reader I found was an extension which doesn't let me tab from landmark to landmark but reads them out loud when hovered. Also another extension for landmarks does find all 7 described above. So I have tested it to the best of my abilities, still a check from a proper screen will be much appreciated.

@kbangelov kbangelov requested a review from a team as a code owner December 9, 2025 13:54
@kbangelov kbangelov force-pushed the task/uepr-336-implement-semantic-layout-in-the-editor branch from a5c5012 to 45d5ac7 Compare December 10, 2025 14:03
@kbangelov kbangelov force-pushed the task/uepr-336-implement-semantic-layout-in-the-editor branch from cc004e0 to 48a10bd Compare December 11, 2025 13:53
@kbangelov kbangelov requested a review from KManolov3 December 11, 2025 13:56
onMouseLeave,
onMore
onMore,
ariaRole
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Let's sort properties alphabetically when possible for readibility

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I clearly forgot about it while changing the name

b) for combined stage menu + stage + sprite/stage selectors
*/
flex-direction: row;
height: 100%;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine this was no longer needed because of the body-wrapper css class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that class being on the inside used to say "make up 100% of the body wrapper height"

/>
<Tab
className={tabClassNames.tab}
aria-label="Code Editor Tab"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rather meant for the aria-labels to be on the components rendering the tabs (so the <Box wrapping the Blocks, the <CostumeTab component, the <SoundTab component). I see that I wasn't very clear what I meant in my previous comment, sorry about that.

In the case of the <Tab components, we shouldn't have an issue there, as the messages describing them (e.g. the FormattedMessage below translates into a Code , should make their purpose clear.

loading,
manuallySaveThumbnails,
onUpdateProjectThumbnail,
ariaRole,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: see comment above about alphabetical prop ordering

className={classNames(styles.stageAndTargetWrapper, styles[stageSize])}
className={styles.targetWrapper}
role="region"
aria-label="Target"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: "Target" -> "Target Pane"

selectedTabClassName={tabClassNames.tabSelected}
selectedTabPanelClassName={tabClassNames.tabPanelSelected}
onSelect={onActivateTab}
role="region"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the element directly under the "main" landmark be a separate region is probably redundant.

Instead, I am split between either not having any regions, besides the backpack in it, or:

  • the <TabList becomes a region
  • the rendered tab content (the <Box wrapping the Blocks, the <CostumeTab component, the <SoundTab component) also become regions - and only the active one will be rendered (and so selectable) at a single time

As I don't have a strong argument against doing it, I think the latter option (defining additional regions) should be the one to go with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants