Skip to main content

Our Commitment to Accessibility

tiCrypt is used by universities, national laboratories, and federal research institutions. Researchers, administrators, and system operators have diverse abilities and use a range of assistive technologies. Accessibility is a continuous effort, not a one-time audit.

βš™οΈ

Tested with Assistive Technology

Evaluated with Windows Magnifier, Microsoft Text-to-Speech, the ChromeVox screen reader, and the NC State Contrast Tool across Chrome and the tiCrypt Connect desktop application.

πŸ“‹

Measured Against WCAG 2.1

Conformance is evaluated at Level A and Level AA. These levels represent the baseline and enhanced accessibility requirements referenced by Section 508, EN 301 549, and university IT accessibility mandates.

πŸ”„

Continuously Updated

This report is updated as new features are released and accessibility improvements are implemented. The evaluation covers the tiCrypt web front-end and the tiCrypt Connect desktop application.

Standards Covered

tiCrypt is evaluated for conformance with WCAG 2.1 at Level A and Level AA. Level AAA criteria are not included because WCAG does not recommend Level AAA conformance as a general policy.

Evaluated

WCAG 2.1 Level A

30 success criteria covering fundamental accessibility requirements including keyboard access, text alternatives, and semantic structure.

Evaluated

WCAG 2.1 Level AA

20 additional criteria covering enhanced requirements including contrast ratios, resize, reflow, focus visibility, and consistent navigation.

Referenced

Section 508

U.S. federal accessibility standard. Section 508 incorporates WCAG 2.0 Level AA by reference. This evaluation covers the corresponding WCAG 2.1 criteria.

What You Can Do with tiCrypt

tiCrypt is designed to be operable across a range of abilities and input methods.

  • Navigate the entire interface using keyboard only
  • Use screen readers (ChromeVox, NVDA, VoiceOver)
  • Zoom up to 200% without loss of content or functionality
  • Adjust text spacing through browser settings
  • Operate in both landscape and portrait orientations
  • Use the interface at viewport widths as small as 320px
  • Navigate with consistent, predictable interaction patterns
  • Receive error messages in text alongside visual indicators
  • Access all functionality without relying on color alone

Voluntary Product Accessibility Template (VPAT)

How tiCrypt meets each WCAG 2.1 success criterion at LevelΒ A and LevelΒ AA, grouped by the four WCAG principles. Use the WCAG level and Conformance filters to narrow the list.

Remark
How the product meets the criterion.
Known gaps
Parts of the product that do not meet the criterion yet. Listed for every criterion marked Partially Supports.
Workaround
How users can get the same result today while a gap remains. Every Partially Supports criterion has one.
Code examples
Excerpts from the tiCrypt front-end source that support the remark, where available.

This VPAT covers the tiCrypt web front-end and the tiCrypt Connect desktop application. VNC and RDP sessions, managed by the host operating system, are out of scope, as is the video annotation tool, a custom feature built for a specific group of users. VPAT Version 2.5Rev.

Front-Endv2.17.15+
Back-Endv3.15.0+
UpdatedOctober 14, 2026

Level A30 criteria

  • 25Supports
  • 1Partially Supports
  • 4Not Applicable

Level AA20 criteria

  • 15Supports
  • 2Partially Supports
  • 3Not Applicable
WCAG level
Conformance

Showing 50 of 50 criteria

1. Perceivable

Information and user interface components must be presentable to users in ways they can perceive.

1.1.1 Non-text Content

Level ASupports

Images have text alternatives; decorative images, such as avatars next to the user's name and settings illustrations, have empty alt text. Icon-only buttons and links have accessible names: a shared directive uses the tooltip text as the name when a control has no name of its own, and other icon buttons have an explicit label. Icons are hidden from assistive technology, true/false table cells are read as Yes or No, and embedded frames have titles. The charts panel, whose canvases have no text alternative, is not shown to users.

Code examples (3)
An icon-only button named with aria-label; the icon inside is decorative.
<button mat-icon-button tc-overlay-close aria-label="Close overlay (Esc)">
<mat-icon svgIcon="close"></mat-icon>
</button>
The sign-in logo has alternative text.
<img class="logo" [src]="logoURL" alt="tiCrypt Login Logo" />
Icon-only buttons are named after their tooltip by one shared directive.
* MatTooltip only describes its host (aria-describedby), and mat-icon is
* aria-hidden, so an icon-only button whose purpose is only shown in its
* tooltip has no accessible name. This directive runs next to every
* matTooltip and, when the host is a button or link with no name of its own
* (aria-label, aria-labelledby, title or text), uses the tooltip message as
* its aria-label and keeps it in sync with the message.
*
* MatTooltip skips the aria-describedby when it matches the aria-label, so
* screen readers do not read the text twice.
*/
@Directive({
selector: "[matTooltip]",
})

1.2.1 Audio-only and Video-only (Prerecorded)

Level ANot Applicable

The tiCrypt application contains no prerecorded audio-only or video-only content supplied by Tera Insights. Its file preview can play audio and video files that users upload; alternatives for that content are the responsibility of the person who provides it. Tutorial videos on the documentation site are not part of the tiCrypt application.

Code examples (1)
The only audio in the application is user-uploaded files, played in the browser's native player.
@case ("audio") {
<!-- Audio -->
<audio controls controlsList="nodownload" [src]="url"></audio>
}

1.2.2 Captions (Prerecorded)

Level ANot Applicable

The tiCrypt application contains no prerecorded synchronized media supplied by Tera Insights. Its file preview plays audio and video files that users upload; captions for that content are the responsibility of the person who provides it, and the player does not display caption tracks. Tutorial videos on the documentation site are not part of the tiCrypt application.

1.2.3 Audio Description or Media Alternative (Prerecorded)

Level ANot Applicable

The tiCrypt application contains no prerecorded synchronized media supplied by Tera Insights. Its file preview plays audio and video files that users upload; audio descriptions or media alternatives for that content are the responsibility of the person who provides it. Tutorial videos on the documentation site are not part of the tiCrypt application. VNC and RDP sessions are live remote desktop connections, not prerecorded media.

1.2.4 Captions (Live)

Level AANot Applicable

tiCrypt does not provide live audio or video content. Its only media elements play stored audio and video files that users open in File Preview. VNC and RDP remote desktop sessions are live interactive connections managed by the host operating system and are out of scope, as stated in the report header.

1.2.5 Audio Description (Prerecorded)

Level AANot Applicable

tiCrypt does not ship prerecorded audio or video content of its own; product information is conveyed through text, tables and form controls. File Preview plays video and audio files that users upload; audio description for that content is the responsibility of its owner.

1.3.1 Info and Relationships

Level ASupports

Form fields use Angular Material form fields whose labels are programmatically associated with the input, and custom form controls take their names from the field label. Radio groups and checkbox lists have programmatic labels, label ids are unique, and repeated elements use per-item ids. Detail panels expose key/value lines as tables with row headers; panel, card, form section and wizard step titles are headings; and each main section has a level-one heading. Headings used only to style values, cells and control labels are presentational.

Code examples (3)
Angular Material links the visible mat-label to its input.
<mat-form-field>
<mat-label>Name</mat-label>
<input matInput type="text" formControlName="name" />
Data tables use thead and th header cells.
<table tc-table class="matrix bordered tc-bg-contrast">
<thead>
<tr>
<th tc-col="name 1fr">Name</th>
<th tc-col="desc 2fr">Description</th>
<th tc-col="value 1fr">Value</th>
</tr>
</thead>
Visual section titles are exposed as headings without changing their look.

/** Numbered step of a flat stepper ("1 Image", "2 Hardware"). */
@Directive({
selector: "div.tc-flat-step-header",
host: { role: "heading", "aria-level": "3" },
standalone: false,
})

1.3.2 Meaningful Sequence

Level ASupports

The DOM order of the main layout matches the visual order: the labelled main navigation comes before the main content, and lists, toolbars and forms are laid out in source order. CSS ordering is used in a few places, such as when a user moves the taskbar to the right or bottom, or to place a chart beside its legend; these changes do not alter meaning. Dialogs and menus are rendered in an Angular CDK overlay container, and focus moves into dialogs when they open.

Code examples (1)
The labelled navigation comes before the main content in the DOM.
<nav class="taskbar" aria-label="Main navigation">

1.3.3 Sensory Characteristics

Level ASupports

Instructions identify controls and items by their visible labels, such as New VM, Table or List, the user menu, the Terminal hub list and the folder tree; location words are given only as extra help, and no instruction uses an icon in place of a word. Escrow key parts the user holds are marked with a check mark as well as color, and the instruction names the check mark. Error and warning messages are given in text.

Code examples (3)
An error state is stated in text next to its icon.
} @else {
<h4 class="row tc-error">
<mat-icon class="tc-16px tc-error margin-right-half" svgIcon="alert-circle-outline"></mat-icon>
Hardware profile missing or inaccessible
</h4>
Validation errors are shown as text.
@if (nameFC.invalid) {
<mat-error> {{ nameFC.errorMessage }} </mat-error>
}
Instructions name the control by its visible label.
Click New VM above to get started.

1.3.4 Orientation

Level AASupports

tiCrypt does not restrict display orientation. The viewport meta tag and web app manifest do not lock orientation, and no style or script locks the screen orientation, so content is displayed in portrait or landscape as the browser or device presents it.

Code examples (1)
The viewport meta tag locks neither orientation nor zoom.
<meta name="viewport" content="width=device-width, initial-scale=1" />

1.3.5 Identify Input Purpose

Level AASupports

Fields that collect the user's own information declare their purpose with HTML autocomplete tokens (username, given-name, family-name, email and organization-title) on the registration and escrow registration pages, and on the Edit information form when users edit their own details. When an administrator edits another user, autofill is turned off. Email fields use type="email". Password, passphrase and key-file fields intentionally carry no autofill token.

Code examples (1)
Fields that ask for the user's own information declare their purpose with an autocomplete token.
<mat-form-field>
<mat-label>First Name*</mat-label>
<input
matInput
type="text"
formControlName="firstName"
autocomplete="given-name"
/>

1.4.1 Use of Color

Level ASupports

Color is not the only visual means of conveying information. Selected rows and tiles, current navigation and list items, and keyboard cursors show a bar, frame or outline in addition to any color change, in all four themes. VM state is written as text in detail headers and lists and shown with a distinct shape for each state. User account states use distinct icons with text, links within text are underlined, and form errors appear as text.

Code examples (5)
User account states use different icon shapes, not only different colors.
export const STATE_TO_ICON: { readonly [State in UserState]: ColoredIcon } = [
new ColoredIcon("check-circle", "var(--green)"), // Active
new ColoredIcon("close-circle", "var(--error)"), // Inactive
Ownership chips show the role name in text.
<div class="listitem-title-chip active" [class.owner]="vmConf?.owners.length === 1">
<mat-icon class="tc-16px" svgIcon="crown"></mat-icon>

<span>
{{ vmConf?.owners.length > 1 ? "Co-owner" : "Owner" }}
</span>
A VM error is drawn as an exclamation-mark icon, not only as a red dot.
@if (!isUnknown()) {
@if (stateClass() === "error") {
<!-- An exclamation mark, not only the color, sets an error apart from running -->
<mat-icon
class="tc-16px dot-icon tc-error"
svgIcon="alert-circle"
[matTooltip]="computeTooltip()"
/>
} @else {
<div
class="dot"
[class]="stateClass()"
[matTooltip]="computeTooltip()"
></div>
}
The VM state has a text name that screen readers read without hovering.
host: { role: "img", "[attr.aria-label]": "stateLabel()" },
Selected rows show a bar on their leading edge in addition to the color tint.
// bar on the leading edge, so selection is not shown by the tint's color alone (WCAG 1.4.1)
& > :first-child {
box-shadow: inset 4px 0 0 var(--action-primary);
}

1.4.2 Audio Control

Level ASupports

tiCrypt does not play notification sounds, alert tones or background audio. Audio is heard only when a user opens an audio or video file in the file preview. Audio files use the browser's native player and do not start automatically. Video files start playing when opened, and the player provides pause, mute and a volume slider that work independently of the system volume. tiCrypt Connect adds no audio playback of its own.

Code examples (2)
The video player sets its own volume, independently of the system volume.
setVolume(): void {
this.player.volume = this.volume / 100;
this.computeVolumeIcon();
}
Audio files use native controls and do not autoplay.
<audio controls controlsList="nodownload" [src]="url"></audio>

1.4.3 Contrast (Minimum)

Level AASupports

tiCrypt has four color themes: Classic, Dark, Cool Gray and High Contrast. Each theme defines its colors as CSS custom properties, with separate colors for text and for filled backgrounds under white text. From front-end 2.17.15, every measured text color meets 4.5:1 in all four themes, including the hover states of colored text, and an automated test checks the theme colors on every change.

Color contrast details and measurements
Code examples (4)
Each theme defines light text colors and darker -fill colors as CSS custom properties (Dark theme shown).
// text colors are light enough for 4.5:1 on the backgrounds and hovers below (WCAG AA);
// the -fill colors are dark enough for white text on top of them
--action-primary: #{$blue-100};
--action-primary-fill: #{$blue-800};

--accent: #{$indigo-500};
--accent-yellow: #{$yellow-600};

--error: #{$red-200};
--error-fill: #{$red-800};
--warn: #{$orange-300};
--warn-fill: #{$deeporange-900};
--ok: #{$green-200};
--ok-fill: #{$green-800};
The Classic theme uses dark text colors that pass on its light backgrounds and their hover tints.
// text colors are dark enough for 4.5:1 on the backgrounds and their own hovers below (WCAG AA);
// the -fill colors are dark enough for white text on top of them
--action-primary: #{$blue-900};
--action-primary-fill: #{$blue-700};

--error: #{$red-900};
--error-fill: #{$red-700};
--warn: #{$deeporange-900};
--warn-fill: #{$deeporange-900};
--ok: #{$green-900};
--ok-fill: #{$green-800};
Filled buttons put white text on the -fill color, never on the text color.
.mdc-button--raised.tc-primary {
background: var(--action-primary-fill) !important;

&:hover {
background: var(--contrast) !important;
}
}
An automated test reads the theme files and fails if any text color drops below 4.5:1 on a background or hover state.
test(`${theme}: text colors have 4.5:1 on the backgrounds and their hovers`, () => {
for (const [fg, hovers] of Object.entries(TEXT)) {
for (const bg of backgrounds) {
for (const hover of [undefined, ...hovers]) {
const value = worst(vars, fg, bg, hover);
assert.ok(value >= 4.5, `--${fg} on --${bg}${hover ? ` + --${hover}` : ""} is ${value.toFixed(2)}:1`);
}
}
}
});

1.4.4 Resize Text

Level AASupports

Text can be enlarged to 200% with the browser's zoom, which tiCrypt does not block: the viewport does not restrict scaling, and font sizes are mostly set in rem units. Ctrl/Cmd+Plus, Ctrl/Cmd+Minus and Ctrl/Cmd+mouse wheel apply tiCrypt's own zoom, which enlarges the root font size.

1.4.5 Images of Text

Level AASupports

Interface text is rendered as HTML text, not as images of text. The sign-in logo is an image with alt text and is a logotype, which is exempt. System Settings shows small illustrations, some of them screenshots, beside each setting's name and description, which are provided as text.

1.4.10 Reflow

Level AAPartially Supports

Dialogs are limited to 80% of the viewport width, and the notifications panel is limited to the viewport width.

Known gaps
  • tiCrypt is designed for desktop widths and has no width-based layout breakpoints.
  • Several screens use fixed widths wider than 320 CSS pixels, such as the 32rem sign-in form and the 48rem search panel, and the page body does not scroll, so some content is clipped at 320 CSS pixels.
  • Data tables, terminals and remote desktops require two-dimensional layout.
Workaround

To enlarge content without narrowing the layout, use the operating system's magnifier (Windows Magnifier or macOS Zoom), which enlarges the screen while tiCrypt keeps its desktop layout, or tiCrypt's own zoom (Ctrl or Command with Plus and Minus), which enlarges text up to 150%.

1.4.11 Non-text Contrast

Level AAPartially Supports

Checkbox and radio outlines use the primary text color, progress bars have a full-length outline in the secondary text color, keyboard focus shows a 2px outline in the theme's action color, and selected rows and items show a bar at their leading edge. An automated test checks primary-colored icons and bars and the warning color at 3:1 in the Classic, Dark and Cool Gray themes. The High Contrast theme draws all borders in white.

Known gaps
  • Text field outlines at rest, bordered buttons, and hover tints use a 12% overlay of about 1.3 to 1.5:1.
Workaround

Choose the High Contrast theme in User settings: it draws every text field outline, button border and focus indicator in white on a black background.

Code examples (2)
Checkbox and radio outlines are 2px in the primary text color.
background: transparent !important;
border-color: var(--text-primary) !important;

position: static !important;

border-width: 0.125rem !important;
Progress bars have a full-length outline, so the empty part stands out from the background.
mat-progress-bar {
// the tinted track barely shows on the card behind it, so outline the full length instead (3:1)
@include mat.progress-bar-overrides((
track-color: transparent,
));

outline: 1px solid var(--text-secondary);

1.4.12 Text Spacing

Level AASupports

Font sizes and spacing are set mostly in rem units, and the interface does not fix letter or word spacing, so users can increase line height, paragraph spacing, letter spacing and word spacing through browser settings or user style sheets.

1.4.13 Content on Hover or Focus

Level AASupports

Tooltips are Angular Material tooltips, which close with Escape, stay open while the pointer moves onto them, and remain until hover or focus moves away. Menus, select lists and autocomplete panels are Angular Material or CDK overlays that close with Escape, as does tiCrypt's context menu. The video player controls appear when the mouse moves over the player and stay visible while the pointer rests on them or one of them has keyboard focus.

Code examples (2)
The context menu closes with Escape and returns focus.
overlayRef.keydownEvents().subscribe((ev) => {
if (ev.keyCode === ESCAPE && !hasModifierKey(ev)) {
menuRef.dispose();
this.currentMenu = undefined;
if (origin) {
(origin.nativeElement.offsetParent as HTMLElement).focus();
}
}
The video player controls stay visible while one of them has keyboard focus.
// keyboard focus on a control keeps the controls up; a mouse click does not (no :focus-visible)
&.hover .actions-container,
& .actions-container:has(:focus-visible) {
opacity: 1 !important;
}

2. Operable

User interface components and navigation must be operable.

2.1.1 Keyboard

Level ASupports

All functionality is operable from the keyboard. Sortable table headers are focusable, sort with Enter or Space and expose aria-sort. Lists, tiles, table rows, settings, cards and menu triggers are focusable and activated with Enter or Space, and folder trees use the arrow keys. Vault items can be moved or copied through a folder-picker dialog, custom fields reordered with Move up and Move down buttons, and table auto-refresh turned on with a toggle button. Video seeking uses skip buttons and keyboard shortcuts.

Code examples (4)
The Vault file table is a single Tab stop.
<table
id="vault-table"
tc-table
[class.compact]="compactTable"
[sortBy]="sortBy"
(sortByChange)="sortBy = $event; sortRows()"
tabindex="0"
Space on the highlighted Vault row opens its actions menu; Enter opens the item and arrow keys move between rows.
this.keydownListner = (event) => {
if (event.key === " ") {
event.preventDefault();
if (this.viewing?.[this.rowIndex]) {
this.rightClick(
this.viewing[this.rowIndex],
new MouseEvent('click', {}),
this.tableRows.toArray()[this.rowIndex]);
Items that open a detail panel can be focused and opened with Enter, the same as a click.
@HostListener("keydown", ["$event"])
onKeydown(ev: KeyboardEvent): void {
// Only when the host itself has focus, so Enter on a button or field inside it,
// or on a nested detail link, keeps doing what it does
if (!this.needsKeyboard || ev.key !== "Enter" || ev.target !== this.host) {
return;
}

// The key is used up here; the click below follows the propagateClick rule
ev.preventDefault();
ev.stopPropagation();

// Run every click handler on the host, as a mouse click would
this.host.click();
Sortable table headers sort with Enter or Space.
@HostListener("keydown", ["$event"])
onKeydown(event: KeyboardEvent): void {
if (
event.target === this.elem &&
(event.key === "Enter" || event.key === " ") &&
this.keyboardSortable
) {
event.preventDefault();
event.stopPropagation();
this.table.columnClicked(this.column);

2.1.2 No Keyboard Trap

Level ASupports

Dialogs keep focus inside while open, return focus to the triggering element when closed, and most close with Escape; dialogs that do not close with Escape provide their own buttons. Overlay panels close with Escape. In the VM terminal, Tab, Shift+Tab and Escape go to the remote shell, and Ctrl+Shift+F moves focus to the next control without sending input to the shell; a hint under each terminal, the Terminal keybindings menu and the Terminal hub help describe it.

Code examples (3)
Dialogs close with Escape unless they provide their own buttons, and focus returns to the trigger.
config.disableClose = disableCancel;
config.hasBackdrop = true;
config.restoreFocus = true;
config.role = "dialog";
Overlay panels close with Escape.
this.keydownSub = this.overlayRef
.keydownEvents()
.subscribe((ev) => {
if (ev.key === "Escape") {
this.close();
}
});
Ctrl+Shift+F leaves the VM terminal without sending input to the shell.
this.term.attachCustomKeyEventHandler((ev) => {
const key = ev.key.toLowerCase();
if (
key === "f" &&
ev.ctrlKey &&
ev.shiftKey &&
!ev.altKey &&
!ev.metaKey
) {
ev.preventDefault();
ev.stopPropagation();
if (ev.type === "keydown") {
this.leaveTerminal();

2.1.4 Character Key Shortcuts

Level ASupports

Keyboard shortcuts are listed in a help dialog opened with ?, and they do not run while focus is in a text field, select element or editable area. Single-character shortcuts, such as T for tasks, ? for the shortcut list, N for a new item and Space in the video player, can be turned off with the "Single-key keyboard shortcuts" switch in User settings, saved for each user. When it is off, only shortcuts that use Ctrl, Alt or Command work.

Code examples (2)
The table export shortcut only runs while focus is inside the table.
this.hotkeys
.addShortcut({ keys: "e", description: "Open CSV Menu" })
.subscribe((e) => {
if (!this.hasFocusWithin()) {
return;
}
this.csvTrigger?.open();
}),
Single-character shortcuts only run while the user preference allows them; the key otherwise keeps its normal action.
addShortcut(options: Hotkey): Observable<KeyboardEvent> {
if (!isSingleKeyShortcut(options.keys)) {
return super.addShortcut(options);
}

// Keep the key's normal action (e.g. Space pressing a button) while the shortcut is off
const preventDefault = options.preventDefault ?? true;
return super.addShortcut({ ...options, preventDefault: false }).pipe(
filter(() => this.singleKeyShortcuts),
tap((e) => {
if (preventDefault) e?.preventDefault();

2.2.1 Timing Adjustable

Level APartially Supports

An inactivity timeout locks the screen; the institution's administrator sets it between 1 and 1440 minutes. Clicks and key presses count as activity. One minute before the lock (or at half the timeout when it is under two minutes) an alert dialog takes focus, shows the time left and offers a Keep working button that resets the timer, as many times as needed. After the lock, the user re-enters their password and continues where they left off. Status messages remain in Message History.

Known gaps
  • Once the screen is locked, the session ends after a period set by the administrator without a further warning.
Workaround

Work in progress is kept while the screen is locked, so unlocking with your password before the session ends loses nothing. Users who need more time can ask their administrator to lengthen the Session timeout and Private Key Timeout in System Settings (up to 1440 minutes).

Code examples (3)
Administrators set the inactivity timeout between 1 and 1440 minutes.
<mat-form-field class="system-setting-field">
<mat-label>Minutes</mat-label>
<input matInput type="number" formControlName="value" min="1" max="1440" />
</mat-form-field>
The time remaining before the lock is shown in the user menu.
<!-- Session timer -->
<span matTooltip="Time until session is locked">
<mat-icon class="tc-18px" svgIcon="monitor"></mat-icon>
{{ timeToLockout | date: "mm:ss" }}
</span>
A warning before the inactivity lock shows the time left and lets the user keep working with one action.
<h2 mat-dialog-title>Your session is about to lock</h2>

<p mat-dialog-content [id]="descriptionID">
You have been inactive, so your session will lock in
<span role="timer">{{ secondsToLock }} {{ secondsToLock === 1 ? "second" : "seconds" }}</span>
and you will need your password to unlock it. Select Keep working to stay
unlocked.
</p>

<mat-dialog-actions>
<div class="flex"></div>

<button mat-button class="tc-primary" (click)="keepWorking()">
Keep working
</button>
</mat-dialog-actions>

2.2.2 Pause, Stop, Hide

Level ASupports

The tiCrypt web application and tiCrypt Connect contain no carousels, scrolling text or auto-advancing content. Animations run once and last one second or less, such as a brief highlight when a task finishes. Progress spinners appear only while an operation is running. Live status such as VM state, task progress and storage usage updates automatically because it reflects current system state. Automatic table refresh is off until the user turns it on and can be turned off the same way.

Code examples (2)
Animations run once and last one second.
.task-item.task-success {
animation: task-flash-ok 1s ease-out 0s;
}

.task-item.task-failure {
animation: task-flash-error 1s ease-out 0s;
}
Automatic table refresh is a user toggle and is off by default.
refreshContinously(): void {
if (this.refreshCancel) {
this.cancelAutoRefresh();
} else {
this.refreshCancel = window.setInterval(() => {
this.refresh(false);
}, 3_000);
}

2.3.1 Three Flashes or Below Threshold

Level ASupports

The application contains no flashing content. Animations are single, short transitions; for example, a task row fades to a highlight color and back once over one second when it completes or fails. Loading indicators use Angular Material progress spinners and bars. Video files that users open in the built-in player are user content.

Code examples (1)
The strongest state change: a single fade to a highlight color and back over one second.
@keyframes task-flash-ok {
0% {
background: transparent;
}

50% {
background: var(--hover-extra-ok);
}

2.4.1 Bypass Blocks

Level ASupports

A "Skip to main content" link is the first focusable element on every signed-in page, in the browser and in tiCrypt Connect. It is hidden until it receives keyboard focus and then appears at the top of the window; activating it moves focus to the page content, which is a main landmark. In the browser, the section links are in a navigation landmark labelled "Main navigation".

Code examples (3)
The toolbar is a navigation landmark.
<nav class="taskbar" aria-label="Main navigation">
A skip link is the first focusable element and moves focus to the page content.
<a class="skip-link" href="#main-content" (click)="$event.preventDefault(); mainContent.focus()">Skip to main content</a>
The page content is a main landmark that can receive focus.
<main id="main-content" tabindex="-1" #mainContent>
<router-outlet></router-outlet>
</main>

2.4.2 Page Titled

Level ASupports

The browser tab title names the current page, followed by the deployment name set by the institution, for example "Vault - tiCrypt", "Virtual Machines - tiCrypt", "Management - tiCrypt" and "Log in - tiCrypt". The title changes whenever the user moves to another section. When there are unread notifications, their count comes first, for example "(3) Vault - tiCrypt".

Code examples (2)
Each section route has a title.
{
path: "vault",
title: "Vault",
component: VaultView,
},
{
path: "management",
title: "Management",
component: ManagementWrapper,
canActivate: [RouteGuard],
},
The browser tab title names the current section, then the deployment name, with the unread count first.
private render(): void {
document.title =
(this.unread > 0 ? `(${this.unread}) ` : "") +
(this.section ? `${this.section} - ` : "") +
this.settings.appName;
}

2.4.3 Focus Order

Level ASupports

Dialogs and full-page panels, including the unlock and MFA panels, move focus to their first control when opened, keep Tab inside while open, and return focus to the control that opened them when closed or minimized. The actions menu takes focus when opened from the keyboard and supports the arrow keys. All content of the terms-of-use, CUI and last sign-in dialogs is in the Tab order, and no control uses a positive tabindex. Elsewhere, focus follows the on-screen order.

Code examples (2)
Dialogs keep focus inside while open and return it to the trigger when closed.
config.hasBackdrop = true;
config.restoreFocus = true;
config.role = "dialog";
Panels move focus inside when opened and keep Tab within them.
private trapFocus(
overlayRef: cdk.OverlayRef,
focusedOutside: (element: HTMLElement) => void,
): FocusTrap {
const pane = overlayRef.overlayElement;
const focusTrap = this.focusTrapFactory.create(pane);
afterNextRender(
() => {
const closed = !pane.isConnected;
if (closed || pane.contains(document.activeElement)) return;

const outside = focusedElement();
if (outside) focusedOutside(outside);
if (!focusTrap.focusInitialElement()) {
pane.tabIndex = -1;
pane.focus();
}

2.4.4 Link Purpose (In Context)

Level ASupports

Text links and menu items describe their destination or action, for example "Create new user account" and context-menu items named after the action. Each main navigation link (Vault, Virtual Machines, Management), in the browser and in the tiCrypt Connect title bar, is named after its label, also when only its icon is shown. One file-preview message uses the link text "link", explained by its surrounding sentence.

Code examples (2)
Menu items carry the action name as text.
<button class="context-menu-item" (click)="actionClicked(action)">
<mat-icon
[class]="'tc-18px ' + action.color"
[svgIcon]="action.icon"
></mat-icon>

{{ action.name }}
</button>
Each navigation link is named after its label, also when only the icon is shown.
role="tab"
aria-label="Vault"
matTooltip="Vault"
[matTooltipPosition]="vertical ? 'right' : 'below'"
>
<mat-icon svgIcon="safe-square-outline"></mat-icon>

<span>Vault</span>
</a>

2.4.5 Multiple Ways

Level AASupports

The three main sections (Vault, Virtual Machines, Management) are linked from a persistent navigation bar on every screen, and Alt+Left and Alt+Right cycle between them. Within a section, sub-views are reached from its side panel or menu, and lists have a search filter to locate their items.

Code examples (1)
Alt+Left and Alt+Right cycle through the main sections.
this.hotkeys
.addShortcut({
keys: "alt.left",
description: "Change Navigation Left",
})
.subscribe((e) => this.changeNavigation(e, navRoutes)),

2.4.6 Headings and Labels

Level AASupports

Most dialogs have a descriptive title marked up as an h2 heading, and panels use h2 to h4 headings that name their content. Form fields have visible labels (Angular Material labels on almost all form fields). In grid tables, column headers expose sort direction with aria-sort; in simpler tables, sort direction is shown by an arrow only. Some toolbar search fields are identified by placeholder text only.

Code examples (2)
Dialog titles are h2 headings.
<h2 class="tc-modal-header" mat-dialog-title>{{ input.title }}</h2>
Form fields have visible labels.
<mat-form-field>
<mat-label>First Name*</mat-label>
<input
matInput
type="text"
formControlName="firstName"
/>

2.4.7 Focus Visible

Level AASupports

Every focusable control shows a 2px solid outline, offset 2px, when it receives keyboard focus. The outline uses the theme's action color, which has at least 3:1 contrast against the page backgrounds in all four themes; on blue toolbars it uses the toolbar's text color. Form fields mark focus with their highlighted border, and video player controls stay visible while one of them has keyboard focus.

Code examples (2)
A visible focus outline on form inputs.
&:focus:not([disabled]) {
outline: 1px solid var(--primary);
}
Every control shows a 2px outline in the theme's action color when it receives keyboard focus.
:focus-visible:not([tabindex="-1"], [class^="ag-"], [class*=" ag-"], .mat-mdc-form-field-infix *) {
outline: 2px solid var(--action-primary) !important;
outline-offset: 2px !important;
}

2.5.1 Pointer Gestures

Level ASupports

No function requires multipoint or path-based gestures. Files and directories can be uploaded with the Upload button menu as well as by drag-and-drop. The video timeline can be set with a single click or the arrow keys as well as by dragging. Other drag interactions, such as resizing panels and reordering custom fields, depend only on start and end points.

Code examples (2)
Files and directories can be uploaded from a button menu as well as by drag-and-drop.
<button mat-menu-item class="context-menu-item" (tc-import-file)="vaultExplorer?.upload($event)">
<mat-icon svgIcon="file-multiple"></mat-icon>
Files
</button>
<button mat-menu-item class="context-menu-item" (tc-import-directory)="vaultExplorer?.upload($event)">
<mat-icon svgIcon="folder"></mat-icon>
Directories
Arrow keys seek the video without a pointer.
this.hotKeys
.addShortcut({
keys: "left",
description: "Seek left 3s",
})
.subscribe(() => {
this.skip(-3);
}),

2.5.2 Pointer Cancellation

Level ASupports

Controls act on the click event, which completes when the pointer is released, and dragging the video timeline sets the position on release. The long-press action of a table's Refresh button (turn automatic refresh on or off) runs when the button is released after being held, and moving the pointer off the button before releasing cancels it.

Code examples (2)
Dragging the video timeline sets the position when the pointer is released.
timelineUp(event: MouseEvent) {
if (this.time !== this.player.currentTime) {
this.player.currentTime = this.time;
}
this.dragging = false;
}
The long-press action runs on release, and leaving the button before release cancels it.
this.sub = mouseDown$
.pipe(
switchMap(() => {
const pressedAt = Date.now();
return mouseUp$.pipe(
take(1),
takeUntil(mouseLeave$),
filter(() => Date.now() - pressedAt >= this.duration),
);
}),
)
.subscribe(() => this.longPress.emit());

2.5.3 Label in Name

Level ASupports

Controls with visible text use that text as their accessible name, and where an aria-label is added it contains the visible text or tooltip, for example the Select all button, the main navigation links and the drive selector's "Clear selected drive" button. An automated test checks every template for an aria-label that does not contain its element's tooltip text.

Code examples (1)
The aria-label is bound to the same string as the visible text.
(click)="toggleSelectAll()"
[attr.aria-label]="state ? deselectText : selectText"
[class.compact]="compact"
>
<mat-icon [svgIcon]="selIndicatorIcon"></mat-icon>

@if (!compact) {
<span>{{ state ? deselectText : selectText }}</span>

2.5.4 Motion Actuation

Level ANot Applicable

tiCrypt does not use device motion or orientation sensors, and no function is triggered by shaking, tilting or other device motion.

3. Understandable

Information and the operation of the user interface must be understandable.

3.1.1 Language of Page

Level ASupports

The root html element sets lang="en" on the application page and on the inbox and multi-factor authentication pages. All interface text is written in English; the product has no translation layer.

Code examples (1)
The application page declares English as its language.
<!doctype html>
<html lang="en">

3.1.2 Language of Parts

Level AANot Applicable

The interface is in English and the page language is set with lang="en". There are no passages in other languages. Technical terms such as SFTP, BitLocker and Slurm, and command-line examples, are not foreign-language content. Content entered by users or administrators, such as file names and login messages, is displayed as entered.

3.2.1 On Focus

Level ASupports

Receiving focus does not navigate, submit a form or open a dialog. Focus handlers only update the visual focus state or move focus inside the same widget, for example from the file list to its current row. Sidebar and navigation items act only when the user activates them by click or keyboard.

Code examples (2)
Focusing the file list only records which row has focus; nothing opens.
this.focusListner = (ev: Event) => {
this.focusService.push(table);
this.focused.add(this.viewing[this.rowIndex]?.entryName);
};
Opening a file or folder needs an explicit Enter key press.
if (event.key === "Enter") {
event.preventDefault();
this.doubleClick(this.viewing[this.rowIndex]);
return;

3.2.2 On Input

Level ASupports

Changing a field value does not navigate, submit a form or open a dialog. Filter, sort and view selectors update the current list in place, and forms submit only from an explicit button or the Enter key.

Code examples (2)
A filter selector only re-filters the list on the same page.
<mat-select
class="filter-select margin-right-half"
[(value)]="filterType"
(selectionChange)="updateQuery()"
>
Forms submit only through a submit button or the Enter key, not when a value changes.
<form
id="group-rename-form"
class="tc-modal-body"
mat-dialog-content
[formGroup]="form"
(ngSubmit)="renameGroup()"
>

3.2.3 Consistent Navigation

Level AASupports

The main navigation (Vault, Virtual Machines, Management) is rendered once by the main page layout, so it appears in the same place and order in every section; links the user has no permission for are omitted. Users can move the navigation bar to the top, left, right or bottom of the window in theme settings, and the chosen position applies to all sections.

Code examples (2)
One navigation bar with a fixed link order wraps every section.
<a
class="nav-link"
routerLink="/vault"
routerLinkActive
#vault="routerLinkActive"
The navigation bar position is a user preference that applies everywhere.
export type ToolbarPosition = "top" | "left" | "right" | "bottom";

3.2.4 Consistent Identification

Level AASupports

Actions are defined with a shared model that pairs each action with an icon and a name, and are rendered by the same toolbar, context menu and confirmation components in every section. Deletion generally uses the delete icon with the label "Delete", and permanent deletion uses the delete-forever icon. Wording varies in a few places, for example "Delete" in the Vault trash and "Permanently delete" in the VM file explorer.

Code examples (1)
One shared action model (icon and name) feeds toolbars and context menus in every section.
export interface ActionSpec {
icon: string; // Icon to display in compact view. This is a material icon name.
name: string; // Name of the action, displayed in compact view

3.3.1 Error Identification

Level ASupports

When a form field fails validation, a text message below the field states the problem, for example "You must enter a name", "Must be between 1 and 1440 minutes" or "Must be after today". The message is announced through a polite live region and linked to the input with aria-describedby, and Angular Material sets aria-invalid on the input. This includes the custom field editor's choice input. Error text is not hidden by compact field styling.

Code examples (3)
A validation message is shown in text with the field.
@if (nameFC.invalid) {
<mat-error> {{ nameFC.errorMessage }} </mat-error>
}
Validators return a specific message, which the form shows as the error.
if (strVal.length > maxLength) {
const msg = `May not exceed ${maxLength} characters`;
this.errorMessage = msg;
return ngFormsError(msg);
Validated fields show a text error message.
<mat-form-field>
<mat-label>Name</mat-label>
<input matInput type="text" formControlName="name" />
@if (nameFC.invalid) {
<mat-error> {{ nameFC.errorMessage }} </mat-error>
}

3.3.2 Labels or Instructions

Level ASupports

Form fields have visible labels, and format rules and limits appear as hint text below the field. Required fields are marked with an asterisk and expose their required state to assistive technology, including custom size, duration, time, list and item selector inputs, whose inputs are tied to the field label. Search boxes, toolbar filters and view-mode drop-downs have accessible names, and placeholders are not used as the only label. Registration and VM setup show numbered steps.

Code examples (3)
A visible label, with the field marked required.
<mat-form-field>
<mat-label>Email Address</mat-label>
<input
matInput
type="email"
formControlName="email"
[required]="true"
/>
The VM setup form shows numbered steps with titles.
<div class="tc-flat-step-header">
<span class="number"> 3 </span>

Home drive
</div>
Form controls report their required state, so fields show the asterisk and set aria-required.
override hasValidator(validator: NgFormsValidator): boolean {
return (
isRequiredValidator(validator, this.overrideRequired ?? this.required) ||
super.hasValidator(validator)
);
}

3.3.3 Error Suggestion

Level AASupports

Validation messages state what is expected: required fields, maximum length ("May not exceed N characters") and format rules such as "Must be a valid IPv4 address". Weak passwords show a suggestion from the zxcvbn strength checker, and mismatched passwords show "Passwords do not match". Storage and transfer limits state the allowed or available size. Key-file errors at sign-in say what is wrong with the file; failed password attempts show a generic message for security reasons.

Code examples (3)
Format rules carry a human-readable description that becomes the error message.
export const MAC_ADDRESS_PATTERN: PatternRule = {
regex: /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/,
desc: "Must be of the form XX:XX:XX:XX:XX:XX where X's are HEX digits",
};
A weak password shows the strength checker's suggestion.
return score < minStrength
? feedback?.suggestions?.[0] || "Not strong enough"
Upload size errors state the available and required space.
this.error = `Available space is ${formatBytes(available)} bytes but you need ${formatBytes(this.totalSize)} bytes`;

3.3.4 Error Prevention (Legal, Financial, Data)

Level AASupports

Destructive actions open a confirmation dialog that names the action and the number of affected items, with Cancel focused first; some require typing a confirmation phrase. This includes deleting teams, projects, certifications or VM configurations from an onboard template and removing everyone else's access to a drive. Files deleted in the Vault go to trash and can be restored before permanent deletion.

Code examples (3)
Permanent deletion states the item count and consequences before it runs.
this.modals.confirmFirst({
title: `Delete ${entries.length} item(s) permanently from trash`,
body: "The selected items will be permanently deleted.",
notice: DELETE_CONSEQUENCES,
acceptLabel: "Delete items",
destructive: true
Confirmation dialogs focus Cancel first.
<button mat-button modal-cancel cdkFocusInitial>Cancel</button>
Deleting entries from an onboard template asks for confirmation and names the number of items.
private confirmDeleteFromTemplate(
count: number,
singular: string,
plural: string,
): Promise<void> {
const quantity = count === 1 ? `1 ${singular}` : `${count} ${plural}`;
return this.modals.confirmFirst({
title: `Delete ${quantity} from the onboard template?`,
body: `The selected ${count === 1 ? singular : plural} will be removed from the onboard template. Users who were already onboarded are not affected.`,
destructive: true,
acceptLabel: `Delete ${quantity}`,
});
}

4. Robust

Content must be robust enough to be interpreted by a wide variety of user agents, including assistive technologies.

4.1.1 Parsing

Level ASupports

Per the WCAG 2.1 errata and WCAG 2.2, this criterion is always satisfied for content using HTML. The interface is built from Angular templates, and Angular's compiler rejects mismatched tags at build time. Issues that affect assistive technology, such as repeated IDs or controls nested inside other controls, are reported under 1.3.1 and 4.1.2.

4.1.2 Name, Role, Value

Level ASupports

Standard Angular Material and CDK components expose name, role and state. Folder trees use tree and treeitem roles with level, expanded and selected states; file tables are grids and file tiles are listboxes, both reporting selection; accordion headers report whether they are expanded; navigation items mark the current view; and toggles report their pressed state. No control is nested inside another button or menu item, and icon-only buttons, radio buttons and frames have accessible names.

Code examples (2)
Material checkboxes expose their role, checked state and text name.
<mat-checkbox
class="permission-checkbox"
[checked]="perm[4]"
[disabled]="!havePermission(perm)"
(change)="toggle(cat, perm)"
>
{{ perm[2] }}
</mat-checkbox>
Folder tree rows expose their role, level, expanded and selected state.
<div
class="tc-ft-row s36 layout-row border-radius"
role="treeitem"
[attr.aria-level]="level + 1"
[attr.aria-expanded]="node.noExpand ? null : node.isOpen"
[attr.aria-selected]="isDeepestVisibleAncestor(node)"

4.1.3 Status Messages

Level AASupports

Success and error notifications are Angular Material snack bars, announced through a polite live region, and recent messages can be reviewed in Message History. Sign-in and unlock failure messages appear in a status region that is always present, inline notices are polite status regions, and the task tray announces when a background task starts, finishes, fails, is canceled or can be undone. Form field errors are in Angular Material's polite live region.

Code examples (4)
Notifications use Angular Material snack bars, announced through a polite live region.
const snackBarRef = this.snackBar.open(message, optAction?.name, {
panelClass: "tc-snack-bar-" + theme,
duration,
});
The VM configuration wizard's drive steps are a polite live region.
<div class="tc-flat-step" aria-live="polite" id="homeDrive" [class.disabled]="!brickFC?.getValue()">
The sign-in error appears in a status region that is always present, so screen readers announce it.
<!-- Stays in the DOM so screen readers announce the sign-in error -->
<div role="status" [class.fake-password]="!!passwordFC.loginError">
@if (passwordFC.loginError) {
<span>{{ passwordFC.loginError }}</span>
}
</div>
Inline notices are polite status regions.
// Polite live region, so screen readers announce notices that appear or change
host: { role: "status" },

Color Contrast Details

How the tiCrypt front-end meets WCAG 2.1 success criteria 1.4.3 Contrast (Minimum) and 1.4.11 Non-text Contrast, measured for front-end 2.17.15.

How colors are defined

Users choose one of four themes: Classic, Dark, Cool Gray or High Contrast. Every theme sets the same named colors (CSS custom properties) to its own values, and components only use those names, so each screen follows the selected theme.

On a dark background, colored text has to be light, while white text needs a dark color behind it. No single color can do both, so each action and status color has two values: a text color used on page backgrounds (for example --error) and a fill color used behind white text (--error-fill) on filled buttons, notifications, alerts, badges and checked checkboxes.

Measured contrast by component

Each component was rendered in Chrome from the compiled tiCrypt stylesheet, in every theme and on both page background colors; the table shows the lower result. Ratios use the WCAG 2.x relative luminance formula, the same calculation used by contrast checkers such as the NC State Contrast Tool. Text needs 4.5:1; icons and the graphical parts of controls need 3:1. The sample in each cell shows the measured colors.

ComponentClassicDarkCool GrayHigh Contrast
Body textText on the page background, needs 4.5:1
14.97:1βœ“ Pass#202020 on #F5F5F5
11.39:1βœ“ Pass#FFFFFF on #163B64
14.06:1βœ“ Pass#EFEFEF on #212121
21.00:1βœ“ Pass#FFFFFF on #000000
Secondary text (descriptions, hints)Text on the page background, needs 4.5:1
6.51:1βœ“ Pass#585858 on #F5F5F5
7.90:1βœ“ Pass#D0D8E0 on #163B64
10.71:1βœ“ Pass#D3D3D3 on #212121
21.00:1βœ“ Pass#FFFFFF on #000000
Blue text and outlined buttons (Download, Change, Manage member(s))Text on the page background, needs 4.5:1
7.92:1βœ“ Pass#0D47A1 on #F5F5F5
8.11:1βœ“ Pass#BBDEFB on #163B64
9.20:1βœ“ Pass#90CAF9 on #212121
21.00:1βœ“ Pass#FFFFFF on #000000
Form field error messagesText on the page background, needs 4.5:1
6.03:1βœ“ Pass#B71C1C on #F5F5F5
5.29:1βœ“ Pass#EF9A9A on #163B64
7.48:1βœ“ Pass#EF9A9A on #212121
21.00:1βœ“ Pass#FFFFFF on #000000
Red text and actions (Delete, Remove)Text on the page background, needs 4.5:1
6.03:1βœ“ Pass#B71C1C on #F5F5F5
5.29:1βœ“ Pass#EF9A9A on #163B64
7.48:1βœ“ Pass#EF9A9A on #212121
6.58:1βœ“ Pass#FF5252 on #000000
Warning textText on the page background, needs 4.5:1
5.14:1βœ“ Pass#BF360C on #F5F5F5
6.58:1βœ“ Pass#FFB74D on #163B64
6.79:1βœ“ Pass#FB8C00 on #212121
5.92:1βœ“ Pass#FF3D00 on #000000
Success textText on the page background, needs 4.5:1
7.22:1βœ“ Pass#1B5E20 on #F5F5F5
6.93:1βœ“ Pass#A5D6A7 on #163B64
9.80:1βœ“ Pass#A5D6A7 on #212121
21.00:1βœ“ Pass#FFFFFF on #000000
Filled blue buttons (Save, Upload)Text on a filled color, needs 4.5:1
4.60:1βœ“ Pass#FFFFFF on #1976D2
5.75:1βœ“ Pass#FFFFFF on #1565C0
5.75:1βœ“ Pass#FFFFFF on #1565C0
21.00:1βœ“ Pass#000000 on #FFFFFF
Selected rows and list items, Upload Files button, blue toolbarsText on a filled color, needs 4.5:1
4.60:1βœ“ Pass#FFFFFF on #1976D2
4.60:1βœ“ Pass#FFFFFF on #1976D2
4.60:1βœ“ Pass#FFFFFF on #1976D2
21.00:1βœ“ Pass#FFFFFF on #000000
Filled red buttonsText on a filled color, needs 4.5:1
4.98:1βœ“ Pass#FFFFFF on #D32F2F
5.62:1βœ“ Pass#FFFFFF on #C62828
5.62:1βœ“ Pass#FFFFFF on #C62828
5.48:1βœ“ Pass#FFFFFF on #D50000
Filled orange buttonsText on a filled color, needs 4.5:1
5.60:1βœ“ Pass#FFFFFF on #BF360C
5.60:1βœ“ Pass#FFFFFF on #BF360C
5.60:1βœ“ Pass#FFFFFF on #BF360C
4.74:1βœ“ Pass#FFFFFF on #DD2C00
Success notificationsText on a filled color, needs 4.5:1
5.13:1βœ“ Pass#FFFFFF on #2E7D32
5.13:1βœ“ Pass#FFFFFF on #2E7D32
5.13:1βœ“ Pass#FFFFFF on #2E7D32
21.00:1βœ“ Pass#000000 on #FFFFFF
Blue action icons in menus and listsIcon or graphic, WCAG 1.4.11, needs 3:1
3.37:1βœ“ Pass#1E88E5 on #F5F5F5
3.65:1βœ“ Pass#2196F3 on #163B64
5.15:1βœ“ Pass#2196F3 on #212121
21.00:1βœ“ Pass#FFFFFF on #000000
Progress bar outline (quotas, password strength)Icon or graphic, WCAG 1.4.11, needs 3:1
6.51:1βœ“ Pass#585858 on #F5F5F5
7.90:1βœ“ Pass#D0D8E0 on #163B64
10.71:1βœ“ Pass#D3D3D3 on #212121
21.00:1βœ“ Pass#FFFFFF on #000000

How contrast is kept in place

  • An automated test in the front-end repository (tests/theme-contrast.test.mjs) reads all four theme files. It fails if a text color drops below 4.5:1 on a page background or on its hover state, if text drops below 4.5:1 on a fill color, if an icon or bar color drops below 3:1, or if a theme is missing a fill color.
  • Filled buttons, checked checkboxes, notifications, alerts, count badges and completed steps use the fill colors, so their white text keeps 4.5:1.
  • Form field error messages use the theme's error text color rather than the default Material red.
  • Progress bars, such as quota usage and password strength, have a 1px outline in the theme's secondary text color, so their full length stands out from the background.

Theme-specific choices

  • Classic uses the darkest shades of blue, red, orange and green for colored text, so the text keeps 4.5:1 on white, on light grey and on its own hover tint.
  • High Contrast shows all text in white on black. Filled red and orange buttons keep white text, and filled white controls such as success notifications use black text.
  • The warning part of progress bars uses each theme's warning color.

Conformance Level Definitions

TermDefinition
SupportsThe product has at least one method that meets the criterion without known defects or meets with equivalent facilitation.
Partially SupportsSome functionality of the product does not meet the criterion.
Does Not SupportThe majority of product functionality does not meet the criterion.
Not ApplicableThe criterion is not relevant to the product.

Accessibility Feedback

If you encounter an accessibility barrier in tiCrypt, or if you need this report in an alternative format, contact us. We take accessibility feedback seriously and will respond to all inquiries.

support@terainsights.com