Skip to content

ARIA support ​

This section covers how to enable accessibility with UIExtension built-in features and related tooling. For ARIA specifications and best practices, see:

Enable accessibility in UIExtension ​

Load the aria add-on when initializing PDFUI:

javascript
new UIExtension.PDFUI({
    addons: [
        // .... other Add-on
        'path/to/lib/uix-addons/aria/addon.info.json' // Make sure that aria is loaded last.
    ]
    // ... other options
})

If your app loads add-ons through allInOne.js, aria is already included—no separate load is required:

javascript
new UIExtension.PDFUI({
    addons: 'path/to/lib/uix-addons/allInOne.js'
    // ... other options
})

For more on loading add-ons, see Add-ons overview.

Built-in UIExtension components ​

aria-label attribute ​

These built-in components add an aria-label attribute to the generated DOM when you set text or label. Click Run and test with a screen reader:

html
<html>
<template id="layout-template">
    <webpdf>
        <div>
            <div>
                <gtab text="XButton" group="aria-tab" body="tab1-body" active></gtab>
                <gtab text="Dropdown" group="aria-tab" body="tab2-body"></gtab>
                <gtab text="Slider" group="aria-tab" body="tab3-body"></gtab>
                <gtab text="Ribbon button" group="aria-tab" body="tab4-body"></gtab>
            </div>
            <div name="tab1-body">
                <xbutton text="button"></xbutton>
            </div>
            <div name="tab2-body">
                <dropdown text="Dropdown" style="width: 8em" separate="false">
                    <xbutton text="Dropdown item 1"></xbutton>
                    <xbutton text="Dropdown item 2"></xbutton>
                </dropdown>
            </div>
            <div name="tab3-body">
                <slider min="0" max="100" step="1" label="Slider label"></slider>
            </div>
            <div name="tab4-body">
                <ribbon-button text="Ribbon button"></ribbon-button>
            </div>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

Visually hidden content ​

Some content must be available to assistive technologies but hidden visually. Use the .fv__ui-aria-sr-only class—for example, to announce severity when color alone conveys meaning (danger, warning, and so on):

html
<p class="text-danger">
    <span class="fv__ui-aria-sr-only">Danger:</span>
    This action is not reversible.
</p>

ARIA directives ​

@aria:attr directive ​

Sets attributes that start with aria-. Syntax: @aria:attr.${aria-property-name} where aria-property-name is listed on MDN. The value is an expression:

html
<html>
<template id="layout-template">
    <webpdf>
        <div @var.value="50">
            <input @aria:attr.valuemax="1" @aria:attr.valuemin="0" @aria:attr.valuenow="value + '%'">
            <!--Result:
                <input aria-valuemax="1" aria-valuemin="0" aria-valuenow="50%" ...>
            -->

            <!-- source text -->
            <input @aria:attr.label="'source text'">
            <!--Result:
                <input aria-label="source text" ...>
            -->

            <!-- I18n key -->
            <input @aria:attr.label="'aria:labels.gotopage'|i18n">
            <!--Result:
                <input aria-label="Set page" ...>
            -->
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

@aria:label directive ​

Sets the aria-label attribute. The directive value is an i18n key.

html
<html>
<template id="layout-template">
    <webpdf>
        <div>
            <group-list>
                <group>
                    <input @aria:label="aria:labels.gotopage"
                           placeholder="@aria:label=&quot;aria:labels.gotopage&quot;">
                    <!--Result:
                        <input aria-label="Set page" ...>
                    -->

                    <!-- It is equivalent to: -->
                    <input @aria:attr.label="'aria:labels.gotopage'|i18n"
                           placeholder="@aria:attr.label=&quot;'aria:labels.gotopage'|i18n&quot;">
                    <!--Result:
                        <input aria-label="Set page" ...>
                    -->

                    <!-- source text -->
                    <input @aria:label="source text" placeholder="@aria:label=&quot;source text&quot;">
                    <!--Result:
                        <input aria-label="source text" ...>
                    -->
                    <!-- It is equivalent to: -->
                    <input @aria:attr.label="'source text'" placeholder="@aria:attr.label=&quot;'source text'&quot;">
                    <!--Result:
                        <input aria-label="source text" ...>
                    -->
                </group>
            </group-list>
            <group-list>
                <group>
                    <!-- It can set attributes at a location specified by the dropdown component -->
                    <!-- Set aria-label on the drop-down arrow -->
                    <dropdown @aria:label.caret="Toggle Dropdown" text="@aria:label.caret"></dropdown>
                </group>
                <group>
                    <!-- Set aria-label on icons -->
                    <dropdown icon-class="fv__icon-toolbar-hand" @aria:label.icon="Click dropdown icon"
                              text="@aria:label.icon"></dropdown>
                </group>
                <group>
                    <!-- Set aria-label on the input box -->
                    <dropdown
                            editable
                            @aria:label.editor="Click dropdown icon"
                            selected="1"
                            text="@aria:label.editor"
                    >
                        <dropdown-item>Item 2</dropdown-item>
                        <dropdown-item>Item 3</dropdown-item>
                        <dropdown-item>Item 1</dropdown-item>
                    </dropdown>
                </group>
                <group>
                    <!-- Set the aria-label of the list -->
                    <dropdown @aria:label.list="Items" text="@aria:label.list" separate="false">
                        <dropdown-item>Item 1</dropdown-item>
                        <dropdown-item>Item 2</dropdown-item>
                        <dropdown-item>Item 3</dropdown-item>
                    </dropdown>
                </group>
            </group-list>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

@aria:labelledby directive ​

The @aria:labelledby directive generates aria-labelledby. Values use UIExtension selector syntax, not element id, because aria-labelledby references IDs and hand-written IDs can conflict globally. Selector syntax avoids that issue.

See aria-labelledby on MDN for details.

html
<html>
<template id="layout-template">
    <webpdf>
        <div>
            <span>Field</span>
            <!-- This is just for demonstration -->
            <span name="a-colon">:</span>
            <input type="text" @aria:labelledby="::parent()::childAt(0),a-colon">
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

In this example, @aria:labelledby="::parent()::childAt(0),,a-colon" labels the <input> with the two preceding <span> elements. See component selectors for selector syntax.

@aria:describedby directive ​

@aria:describedby works like @aria:labelledby; see aria-describedby on MDN .

html
<html>
<template id="layout-template">
    <webpdf>
        <div>
            <span>Field:</span>
            <input type="text" @aria:labelledby="::parent()::childAt(0)"
                   @aria:describedby="::nextSiblings(),more-description">
            <span class="fv__ui-aria-sr-only">
                    Description of text input.
                </span>
            <span class="fv__ui-aria-sr-only" name="more-description">
                    More description of text input.
                </span>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}

@aria:rel directive ​

Besides aria-labelledby and aria-describedby, ARIA defines many attributes that reference other elements. @aria:rel wraps the common ones:

@aria:circular-focus directive ​

Controls focus cycling within a component—typically a dialog or isolated UI region.

Click Run to try the example below.

html
<html>
<template id="layout-template">
    <webpdf>
        <div>
            <group-list>
                <group>
                    <xbutton>button 1</xbutton>
                    <xbutton>button 2</xbutton>
                    <xbutton>button 3</xbutton>
                </group>
                <group @aria:circular-focus>
                    <xbutton @tooltip
                             tooltip-title="Press 'Shift + Tab' will switch focus to 'button 6' instead of 'button 3'">
                        button 4
                    </xbutton>
                    <xbutton>button 5</xbutton>
                    <xbutton @tooltip tooltip-title="Press 'Tab' will switch focus to 'button 4' instead of 'button 7'">
                        button 6
                    </xbutton>
                </group>
                <group>
                    <xbutton>button 7</xbutton>
                </group>
            </group-list>
        </div>
        <div class="fv__ui-body">
            <viewer></viewer>
        </div>
    </webpdf>
</template>
</html>
<script>
    var CustomAppearance = UIExtension.appearances.Appearance.extend({
        getLayoutTemplate: function () {
            return document.getElementById('layout-template');
        },
        disableAll: function () {
        }
    });
    var libPath = window.top.location.origin + '/lib';
    var pdfui = new UIExtension.PDFUI({
        viewerOptions: {
            libPath: libPath,
            jr: {
                licenseSN: licenseSN,
                licenseKey: licenseKey
            }
        },
        renderTo: document.body,
        appearance: CustomAppearance,
        addons: libPath + '/uix-addons/allInOne.js'
    });
</script>
<style>
    input {
        width: 20em;
    }

    .fv__ui-dropdown {
        width: auto;
    }
</style>
json
{
  "iframeOptions": {
    "style": "height: 300px"
  }
}