All Projects → chrs1885 → Capable

chrs1885 / Capable

Licence: mit
Keep track of accessibility settings, leverage high contrast colors, and use scalable fonts to enable users with disabilities to use your app.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Capable

Adg
Accessibility Developer Guide
Stars: ✭ 117 (-38.1%)
Mutual labels:  accessibility, a11y
Vue Announcer
A simple way with Vue to announce any useful information for screen readers.
Stars: ✭ 185 (-2.12%)
Mutual labels:  accessibility, a11y
Pa11y Webservice
Pa11y Webservice provides scheduled accessibility reports for multiple URLs
Stars: ✭ 122 (-35.45%)
Mutual labels:  accessibility, a11y
Acot
💎 Accessibility Testing Framework. More accessible web, all over the world.
Stars: ✭ 112 (-40.74%)
Mutual labels:  accessibility, a11y
Parvus
An accessible, open-source image lightbox with no dependencies.
Stars: ✭ 124 (-34.39%)
Mutual labels:  accessibility, a11y
Top People To Follow In Web Accessibility
A list of the top people to follow in web accessibility and web standards.
Stars: ✭ 117 (-38.1%)
Mutual labels:  accessibility, a11y
Skin
Pure CSS framework designed & developed by eBay for a branded, e-commerce marketplace.
Stars: ✭ 126 (-33.33%)
Mutual labels:  accessibility, a11y
Accordion
Accordion module created in pure javascript & CSS. Very useful to create FAQ lists on your website.
Stars: ✭ 94 (-50.26%)
Mutual labels:  accessibility, a11y
Empathy Prompts
💡 Ideas to help consider Inclusive Design principles when making things for others to use.
Stars: ✭ 173 (-8.47%)
Mutual labels:  accessibility, a11y
A11y Dialog
A very lightweight and flexible accessible modal dialog script.
Stars: ✭ 1,768 (+835.45%)
Mutual labels:  accessibility, a11y
Focusoverlay
Library for creating animated overlays on focused elements
Stars: ✭ 167 (-11.64%)
Mutual labels:  accessibility, a11y
Houdini
A simple, accessible show-and-hide/accordion script.
Stars: ✭ 148 (-21.69%)
Mutual labels:  accessibility, a11y
Lumberjack
An automated website accessibility scanner and cli
Stars: ✭ 109 (-42.33%)
Mutual labels:  accessibility, a11y
Visible
🦉 Accessibility testing framework at the next level
Stars: ✭ 164 (-13.23%)
Mutual labels:  accessibility, a11y
Ally.js
JavaScript library to help modern web applications with accessibility concerns
Stars: ✭ 1,447 (+665.61%)
Mutual labels:  accessibility, a11y
Ember A11y Testing
A suite of accessibility tests that can be run within the Ember testing framework
Stars: ✭ 125 (-33.86%)
Mutual labels:  accessibility, a11y
Launchy
Launchy: An Accessible Modal Window
Stars: ✭ 89 (-52.91%)
Mutual labels:  accessibility, a11y
Accessible Html Content Patterns
♿️ The full HTML5 Doctor Element Index as well as common markup patterns for quick reference.
Stars: ✭ 93 (-50.79%)
Mutual labels:  accessibility, a11y
Svelte Navigator
Simple, accessible routing for Svelte
Stars: ✭ 125 (-33.86%)
Mutual labels:  accessibility, a11y
Ebayui Core
Collection of Marko widgets; considered to be the core building blocks for all eBay components, pages & apps
Stars: ✭ 134 (-29.1%)
Mutual labels:  accessibility, a11y

Awesome Build Status Swift Platforms Cocoapods compatible SPM Carthage compatible codecov Twitter

Accessibility for iOS, macOS, tvOS, and watchOS

Check out the Example.xcworkspace to get a quick overview:

Example project overview

1) Research: Do I need to care about accessibility?

Have you ever thought about adopting accessibility features within you apps to gain your user base instead of spending a lot of time implementing features no-one really ever asked for?

Most of us did, however there has never been an easy way to tell if anyone benefits from that. Adjusting layouts to be usable for people with low vision can be quite complex in some situations and tracking the user's accessibility settings adds a lot of boilerplate code to your app.

What if there was a simple way to figure out if there's a real need to support accessibility right now. Or even better, which disability exists most across your user base.

2) React: Improve problematic screens

Once you've figured out that users with specific handicaps get stuck at a certain stage, you can make use of various Capable APIs to enable/disable accessibility support based on the user's accessibility settings or improve texts and colors used within your apps. Go back to step 1 to proof that the work helped users to succeed using your app.

3) Fault diagnosis

Each Capable feature is backed by the built-in logging system, which will keep you in the loop about what might have been going wrong. Even if you are using your own logging solution, the Capable logger is fully compatible with it!

Documentation

Capable offers a whole lot of features along with a bunch of configurations. To find more about how to use them inside the documentation section.

Installation

There are currently four different ways to integrate Capable into your apps.

CocoaPods

use_frameworks!

target 'MyApp' do

  # all features + color and font extensions
  pod 'Capable'

  # all features, but exclude color and font extensions
  pod 'Capable/Features'
  
  # color extensions only
  pod 'Capable/Colors'

  # font extensions only
  pod 'Capable/Fonts'
end

Carthage

github "chrs1885/Capable"

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/chrs1885/Capable.git", from: "1.1.4")
]

Manually

Simply drop Capable.xcodeproj into your project. Also make sure to add Capable.framework to your app’s embedded frameworks found in the General tab of your main project.

Usage

Register for (specific) accessibility settings

Firstly, you need to import the Capable framework in your class by adding the following import statement:

import Capable

There are two different ways to initialize the framework instance. You can either set it up to consider all accessibility features

let capable = Capable()

or by passing in only specific feature names

let capable = Capable(withFeatures: [.largerText, .boldText, .shakeToUndo])

You can find a list of all accessibility features available on each platform in the accessibility feature overview section.

Get accessibility status

If you are interested in a specific accessibility feature, you can retrieve its current status as follows:

let capable = Capable()
let isVoiceOverEnabled: Bool = capable.isFeatureEnable(feature: .voiceOver)

To get a dictionary of all features, that the Capable instance has been initialized with you can use:

let capable = Capable()
let statusMap = capable.statusMap

This will return each feature name (key) along with its current value as described in the accessibility feature overview section.

Send accessibility status

The statusMap object is compatible with most analytic SDK APIs. Here's a quick example of how to send your data along with user properties or custom events.

func sendMetrics() {
    let statusMap = self.capable.statusMap
    let eventName = "Capable features received"
    
    // App Center
    MSAnalytics.trackEvent(eventName, withProperties: statusMap)
    
    // Firebase
    Analytics.logEvent(eventName, parameters: statusMap)
    
    // Fabric
    Answers.logCustomEvent(withName: eventName, customAttributes: statusMap)
}

Listen for settings changes

After initialization, notifications for all features that have been registered can be retrieved. To react to changes, you need to add your class as an observer as follows:

NotificationCenter.default.addObserver(
    self,
    selector: #selector(self.featureStatusChanged),
    name: .CapableFeatureStatusDidChange,
    object: nil)

Inside your featureStatusChanged you can parse the specific feature and value:

@objc private func featureStatusChanged(notification: NSNotification) {
    if let featureStatus = notification.object as? FeatureStatus {
        let feature = featureStatus.feature
        let currentValue = featureStatus.statusString
    }
}

High contrast colors (Capable UIColor/NSColor extension)

The Web Content Accessibility Guidelines (WCAG) define minimum contrast ratios for a text and its background. The Capable framework extends UIColor and NSColor with functionality to use WCAG conformant colors within your apps to help people with visual disabilities to perceive content.

Internally, the provided colors will be mapped to an equivalent of the sRGB color space. All functions will return nil and log warnings with further info in case any input color couldn't be converted. Also note that semi-transparent text colors will be blended with its background color. However, the alpha value of semi-transparent background colors will be ignored since the underlying color can't be determined.

Text colors

Get a high contrast text color for a given background color as follows:

let textColor = UIColor.getTextColor(onBackgroundColor: UIColor.red)!

This will return the text color with the highest possible contrast (black/white). Alternatively, you can define a list of possible text colors as well as a required conformance level. Since the WCAG requirements for contrast differ in text size and weight, you also need to provide the font used for the text. The following will return the first text color that satisfies the required conformance level (AA by default).

let textColor = UIColor.getTextColor(
    fromColors: [UIColor.red, UIColor.yellow],
    withFont: myLabel.font,
    onBackgroundColor: view.backgroundColor,
    conformanceLevel: .AA
)!

Background colors

This will also work the other way round. If you are looking for a high contrast background color:

let backgroundColor = UIColor.getBackgroundColor(forTextColor: UIColor.red)!

// or

let backgroundColor = UIColor.getBackgroundColor(
    fromColors: [UIColor.red, UIColor.yellow],
    forTextColor: myLabel.textColor,
    withFont: myLabel.font,
    conformanceLevel: .AA
)!

Image captions (iOS/tvOS/macOS)

Get a high contrast text color for any given background image as follows:

let textColor = UIColor.getTextColor(onBackgroundImage: myImage imageArea: .full)!

This will return the text color with the highest possible contrast (black/white) for a specific image area.

Alternatively, you can define a list of possible text colors as well as a required conformance level. Since the WCAG requirements for contrast differ in text size and weight, you also need to provide the font used for the text. The following will return the first text color that satisfies the required conformance level (AA by default).

let textColor = UIColor.getTextColor(
    fromColors: [UIColor.red, UIColor.yellow],
    withFont: myLabel.font,
    onBackgroundImage: view.backgroundColor,
    imageArea: topLeft,
    conformanceLevel: .AA
)!

You can find an overview of all image areas available in the documentation.

Calculating contrast ratios & WCAG conformance levels

The contrast ratio of two opaque colors can be calculated as well:

let contrastRatio: CGFloat = UIColor.getContrastRatio(forTextColor: UIColor.red, onBackgroundColor: UIColor.yellow)!

Once the contrast ratio has been determined, you can check the resulting conformance level specified by WCAG as follows:

let passedConformanceLevel = ConformanceLevel(contrastRatio: contrastRatio, fontSize: myLabel.font.pointSize, isBoldFont: true)

Here's an overview of available conformance levels:

Level Contrast ratio Font size
.A Not specified for text color -
.AA 3.0 18.0 (or 14.0 and bold)
4.5 14.0
.AAA 4.5 18.0 (or 14.0 and bold)
.AAA 7.0 14.0
.failed .AA/.AAA not satisfied -

Dynamic Type with custom fonts (Capable UIFont extension)

Supporting Dynamic Type along with different OS versions such as iOS 10 and iOS 11 (watchOS 3 and watchOS 4) can be a huge pain, since both versions provide different APIs.

Capable easily auto scales system fonts as well as your custom fonts by providing one line of code:

let myLabel = UILabel(frame: frame)

// Scalable custom font
let myCustomFont = UIFont(name: "Custom Font Name", size: defaultFontSize)!
myLabel.font = UIFont.scaledFont(for: myCustomFont)

// or
myLabel.font = UIFont.scaledFont(withName: "Custom Font Name", ofSize: defaultFontSize)

// Scalable system font
myLabel.font = UIFont.scaledSystemFont(ofSize: defaultFontSize)

// Scalable italic system font
myLabel.font = UIFont.scaledItalicSystemFont(ofSize: defaultFontSize)

// Scalable bold system font
myLabel.font = UIFont.scaledBoldSystemFont(ofSize: defaultFontSize)

While these extension APIs are available on tvOS as well, setting the font size in the system settings is not supported on this platforms.

Logging with OSLog

The Capable framework provides a logging mechanism that lets you keep track of what's going on under the hood. You'll get information regarding your current setup, warnings about anything that might cause issues further on, and errors that will lead to misbehavior.

By default, all messages will be logged automatically by using Apple's Unified Logging System. However, it also integrates with your specific logging environment by providing a custom closure that will be called instead. For example, you may want to send all errors coming from the Capable framework to your analytics service:

// Send error messages to your data backend
Capable.onLog = { message, logType in
    if logType == OSLogType.error {
        sendLog("Capable Framework: \(message)")
    }
}

Furthermore, you can specify the minimum log level that should be considered when logging messages:

// Configure logger to only log warnings and errors (.default, .error, and .fault)
Capable.minLogType = OSLogType.default

Here's a list of the supported log types, their order, and what kind of messages they are used for:

OSLogType Usage
.debug Verbose logging *
.info Information regarding the framework setup and status changes
.default Warnings that may lead to unwanted behavior
.error Errors caused by the framework
.fault Errors caused by the framework due to system issues *

* Currently not being used by the framework when logging messages.

Accessibility feature overview

The following table contains all features that are available AND settable on each platform.

iOS macOS tvOS watchOS
.assistiveTouch
.boldText  ✅*
.closedCaptioning
.darkerSystemColors
.differentiateWithoutColor
.fullKeyboardAccess  ✅*
.grayscale
.guidedAccess
.hearingDevice
.increaseContrast
.invertColors
.largerText  ✅*
.monoAudio
.onOffSwitchLabels
.reduceMotion
.reduceTransparency
.shakeToUndo
.speakScreen
.speakSelection
.switchControl
.videoAutoplay
.voiceOver

* Feature status can be read but notifications are not available.

While most features can only have a statusMap value set to enabled or disabled, the .largerText and .hearingDevice feature do offer specific values:

LargerText

iOS

  • XS
  • S
  • M (default)
  • L
  • XL
  • XXL
  • XXXL
  • Accessibility M
  • Accessibility L
  • Accessibility XL
  • Accessibility XXL
  • Accessibility XXXL
  • Unknown

watchOS

  • XS
  • S (default watch with 38mm)
  • L (default watch with 42mm)
  • XL
  • XXL
  • XXXL
  • Unknown

HearingDevice

  • both
  • left
  • right
  • disabled

Resources

Contributions

We'd love to see you contributing to this project by proposing or adding features, reporting bugs, or spreading the word. Please have a quick look at our contribution guidelines.

License

Capable is available under the MIT license. See the LICENSE file for more info.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].