Skip to content

2. Rules

jonathandewitt-dev edited this page Jul 20, 2020 · 6 revisions

Documentation - The rules property

Rules are akin to CSS rules, in that they are a set of properties that apply to every element matching the given selector. But instead of styles, attributes are applied. Just like CSS, when an element's attributes are changed, the rules are reevaluated. In other words, if your rule is attached to .nav and you remove class="nav" dynamically, any attributes applied by that rule will be removed along with it. If it is added back again later, the attributes will apply once more. CSS selector specificity rules apply as well, thanks to this helpful package. Any attributes applied inline are prioritized above all other rules. There is no equivalent !important override, and may or may not be available in a future version, since the use of !important is strongly discouraged anyway.


Selectors

To add rules, add the rules property to the root of the config object passed into the main function. Inside this property, assign an object using CSS selectors (in quotes) as keys, and another object as each one's value. The rest of this document outlines the properties that may be used as part of each rule.

addAccessibilityRules({
  rules: {
    '.nav': {
      // your rules will be defined here
    }
  }
})

The aria Property

You can add aria-* attributes by assigning an object to the aria property, in which you may provide any number of ARIA attributes minus the aria- prefix. In other words, { hidden: true } will become aria-hidden="true".

addAccessibilityRules({
  rules: {
    '.nav': {
      aria: {
        hidden: true,
        label: 'example'
      }
    }
  }
})

The above will output the following HTML in the browser:

<div class="nav" aria-hidden="true" aria-label="example"></div>

The attr Property

You can also add any other attributes you may need in the attr property, since not all features related to accessibility are covered by ARIA, such as alt or tabindex. In fact, it may be best to shy away from ARIA in many cases anyway.

addAccessibilityRules({
  rules: {
    '.nav': {
      attr: {
        alt: 'example',
        tabindex: 0
      }
    }
  }
})

The above will output the following HTML in the browser:

<div class="nav" alt="example" tabindex="0"></div>

NOTE: Flexibility was an important factor in the creation of this package, hence, these rules have very few limitations. You may not use these rules to define certain attributes, including class, id, style or any on[event] listener. Do not abuse this feature. If any attributes are not directly related to accessibility, they should not be defined here. If you must change the appearance or functionality of an element, you should use a class toggle within a method instead.


The screenReaderOnly Property

With attributes out of the way, there's just one more HTML feature that may be used specifically for screen reader-only text; invisible text that only screen readers can see. aria-label doesn't work consistently across screen readers, and isn't necessarily intended to be a solution for every kind of screen reader text. For this reason, many people opt to create a visually hidden text element in their markup, but that ends up creating more clutter. Instead, you can once again add it to the accessibility layer with the handy property called screenReaderOnly, to which you can pass a text string. This will generate a span tag and prepend to the beginning of the current element. Use it with caution, as it may interfere with certain CSS selectors, for example :first-child. Just like everything else, this element will be removed if the selector no longer matches the element, and its text will be replaced by any rule with a more specific selector.

addAccessibilityRules({
  rules: {
    '.nav': {
      screenReaderOnly: 'example'
    }
  }
})

The above will output the following HTML in the browser:

<div class="nav">
  <span style="position: absolute; z-index: -9999999; opacity: 0;">example</span>
</div>

The mouse property

Instead of attributes, this property will assign event listeners. The possible keys inside the mouse object are click, enter, and leave, which correspond directly to the JavaScript events click, mouseenter, and mouseleave, respectively. The value for each one is expected to be an array of strings which represent methods defined in the methods object, which you can read about in the methods documentation.

addAccessibilityRules({
  rules: {
    '.itemWithSubmenu': {
      mouse: {
        click: ['expand', 'stayExpanded'],
        enter: ['expand'],
        leave: ['collapse']
      }
    }
  }
})

The keyboard property

The keyboard property works almost exactly like the mouse property, except each item in the keyboard object always assigns to the same event, (keydown by default.) Instead, each property represents exactly which key was pressed. Once again, the values are expected to be an array of strings representing methods.

addAccessibilityRules({
  rules: {
    '.itemWithSubmenu': {
      keyboard: {
        Enter: ['expand', 'stayExpanded'],
        ArrowDown: ['expand', 'focusFirstItem'],
        Escape: ['collapse']
      }
    }
  }
})

The keyboardEvent property

In most cases, the keydown event should work fine for all the methods listed in the keyboard property, but if for some reason you need to use keypress or keyup, you can use the keyboardEvent property to override it. Keep in mind, this property is not a child of keyboard. Instead, it's a sibling defined at the root of the rule.

addAccessibilityRules({
  rules: {
    '.itemWithSubmenu': {
      keyboard: {/* ... */},
      keyboardEvent: 'keyup'
    }
  }
})