{"id":24373679,"url":"https://github.com/chrs1885/capable","last_synced_at":"2025-04-06T00:10:27.927Z","repository":{"id":31670546,"uuid":"128437025","full_name":"chrs1885/Capable","owner":"chrs1885","description":"Unified accessibility API for iOS, macOS, tvOS \u0026 watchOS.","archived":false,"fork":false,"pushed_at":"2024-06-14T16:16:15.000Z","size":64898,"stargazers_count":265,"open_issues_count":1,"forks_count":19,"subscribers_count":8,"default_branch":"develop","last_synced_at":"2025-03-29T23:09:15.736Z","etag":null,"topics":["a11y","accessibility","colors","custom-fonts","dynamic-type","handicap","ios","macos","swift","tvos","watchos","wcag"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chrs1885.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-06T18:32:30.000Z","updated_at":"2025-02-18T14:03:08.000Z","dependencies_parsed_at":"2025-01-27T15:47:42.656Z","dependency_job_id":null,"html_url":"https://github.com/chrs1885/Capable","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrs1885%2FCapable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrs1885%2FCapable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrs1885%2FCapable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrs1885%2FCapable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrs1885","download_url":"https://codeload.github.com/chrs1885/Capable/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247415973,"owners_count":20935387,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a11y","accessibility","colors","custom-fonts","dynamic-type","handicap","ios","macos","swift","tvos","watchos","wcag"],"created_at":"2025-01-19T05:12:19.273Z","updated_at":"2025-04-06T00:10:27.892Z","avatar_url":"https://github.com/chrs1885.png","language":"Swift","readme":"\u003ccenter\u003e\u003cimg src=\"https://user-images.githubusercontent.com/1390908/41822361-a14fafd2-77ee-11e8-8aa6-f18960566d0c.png\" width=\"400\"\u003e\n\u003c/center\u003e\n\n---\n[![Awesome](https://camo.githubusercontent.com/13c4e50d88df7178ae1882a203ed57b641674f94/68747470733a2f2f63646e2e7261776769742e636f6d2f73696e647265736f726875732f617765736f6d652f643733303566333864323966656437386661383536353265336136336531353464643865383832392f6d656469612f62616467652e737667)](https://github.com/vsouza/awesome-ios#accessibility)\n![Swift](https://img.shields.io/badge/swift-5.0-red.svg)\n![Platforms](https://img.shields.io/cocoapods/p/Capable.svg)\n[![Cocoapods compatible](https://img.shields.io/cocoapods/v/Capable.svg)](https://cocoapods.org/pods/Capable)\n![SPM](https://img.shields.io/badge/SPM-compatible-ff59b4)\n[![Twitter](https://img.shields.io/badge/twitter-%40chr__wendt-58a1f2.svg)](https://twitter.com/chr_wendt)\n\n# Accessibility for iOS, macOS, tvOS, and watchOS\n\n## 🎉 What's new in Capable 2.0 🎉\n\nHere are the most important changes:\n\n* 🏛 New framework architecture and project structure that makes contributing support for upcoming accessibility settings easier.\n* 🎯 Focus on an unified API for Apple accessibility settings: While support for scalable fonts \u0026 handicap grouping was dropped entirely, the APIs for calculating high contrast color pairs based on WCAG 2.1 success criteria has moved to it's own repository [WCAG-Colors](https://github.com/chrs1885/WCAG-Colors).\n* ✅ Support for new accessibility APIs.\n\n### Research \u0026 React\n\n* [Get the user's accessibility settings](#accessibility-status)\n* [Get status of accessibility feature](#accessibility-status)\n* [Get notified about any changes](#notifications)\n* [Send status with your favorite analytics SDK](#send-status)\n\nHave you ever thought about improving accessibility within your 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. 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.\n\nWhile Apple's accessibility API are different across all platforms and might be located in a variety of system frameworks,\nCapable offers a unified and centralized API to get the current status of accessibility settings. This info can be sent to your analytics backend to learn, if people with specific handicaps are blocked from doing certain actions within your app. Furthermore, this data will help you to prioritize accessibility work.\n\nOnce 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.\n\n## Documentation\n\nCapable offers a whole lot of features along with a bunch of configurations. To find more about how to use them inside the [documentation](Documentation/Reference/README.md) section.\n\n## Installation\n\nThere are currently three different ways to integrate Capable into your apps.\n\n### CocoaPods\n\n```ruby\nuse_frameworks!\n\ntarget 'MyApp' do\n  pod 'Capable'\nend\n```\n\n### Carthage\n\n```ruby\ngithub \"chrs1885/Capable\"\n```\n\n### Swift Package Manager\n\n```ruby\ndependencies: [\n    .package(url: \"https://github.com/chrs1885/Capable.git\", from: \"2.0.1\")\n]\n```\n\n## Usage\n\n### Register for (specific) accessibility settings\n\nFirstly, you need to import the Capable framework in your class by adding the following import statement:\n\n```swift\nimport Capable\n```\n\nThere are two different ways to initialize the framework instance. You can either set it up to consider all accessibility features\n\n```swift\nlet capable = Capable()\n```\n\nor by passing in only specific feature names\n\n```swift\nlet capable = Capable(withFeatures: [.largerText, .boldText, .shakeToUndo])\n```\n\nYou can find a list of all accessibility features available on each platform in the [accessibility feature overview](#accessibility-feature-overview) section.\n\n\u003ca id=\"accessibility-status\"\u003e\u003c/a\u003e \n### Get accessibility status\n\nIf you are interested in a specific accessibility feature, you can retrieve its current status as follows:\n\n```swift\nlet capable = Capable()\nlet isVoiceOverEnabled: Bool = capable.isFeatureEnable(feature: .voiceOver)\n```\n\nTo get a dictionary of all features, that the `Capable` instance has been initialized with you can use:\n\n```swift\nlet capable = Capable()\nlet statusMap = capable.statusMap\n```\n\nThis will return each feature name (key) along with its current value as described in the [accessibility feature overview](#accessibility-feature-overview) section.\n\n\u003ca id=\"send-status\"\u003e\u003c/a\u003e \n### Send accessibility status\n\nThe `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.\n\n```swift\nfunc sendMetrics() {\n    let statusMap = self.capable.statusMap\n    let eventName = \"Capable features received\"\n    \n    // App Center\n    MSAnalytics.trackEvent(eventName, withProperties: statusMap)\n    \n    // Firebase\n    Analytics.logEvent(eventName, parameters: statusMap)\n    \n    // Fabric\n    Answers.logCustomEvent(withName: eventName, customAttributes: statusMap)\n}\n```\n\n\u003ca id=\"notifications\"\u003e\u003c/a\u003e \n### Listen for settings changes\n\nAfter 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:\n\n```swift\nNotificationCenter.default.addObserver(\n    self,\n    selector: #selector(self.featureStatusChanged),\n    name: .CapableFeatureStatusDidChange,\n    object: nil)\n```\n\nInside your `featureStatusChanged` you can parse the specific feature and value:\n\n```swift\n@objc private func featureStatusChanged(notification: NSNotification) {\n    if let featureStatus = notification.object as? FeatureStatus {\n        let feature = featureStatus.feature\n        let currentValue = featureStatus.statusString\n    }\n}\n```\n\n\u003ca id=\"feature-overview\"\u003e\u003c/a\u003e \n### Accessibility feature overview\n\nThe following table contains all features that are available:\n\n✅ API provided by Apple and fully supported by Capable\n\n☑️ API provided by Apple (status only, no notification) and fully supported by Capable\n\n❌ API provided by Apple but not supported by Capable due to missing system settings entry.\n\n|                               | iOS          | macOS | tvOS         | watchOS |\n| ----------------------------- |:-------------| :-----| :------------| :-------|\n| .assistiveTouch               | ✅           |       | ❌           |        |\n| .boldText                     | ✅           |       | ✅           | ☑️     |\n| .buttonShapes                 | ✅ *(iOS14)* |       | ❌           |        |\n| .closedCaptioning             | ✅           |       | ✅           |        |\n| .darkerSystemColors           | ✅           |       | ❌           |        |\n| .differentiateWithoutColor    | ✅ *(iOS13)* | ✅    | ❌           |        |\n| .fullKeyboardAccess           |              | ☑️    |              |        |\n| .grayscale                    | ✅           |       | ✅           |        |\n| .guidedAccess                 | ✅           |       | ❌           |        |\n| .hearingDevice                | ✅           |       |              |        |\n| .increaseContrast             |              | ✅    |              |        |\n| .invertColors                 | ✅           | ✅    | ✅           |        |\n| .largerText                   | ✅           |       | ❌           | ☑️     |\n| .monoAudio                    | ✅           |       | ✅           |        |\n| .onOffSwitchLabels            | ✅ *(iOS13)* |       | ❌           |        |\n| .prefersCrossFadeTransitions  | ✅ *(iOS14)* |       | ❌           |        |\n| .reduceMotion                 | ✅           | ✅    | ✅           | ✅     |\n| .reduceTransparency           | ✅           | ✅    | ✅           |        |\n| .shakeToUndo                  | ✅           |       | ❌           |        |\n| .speakScreen                  | ✅           |       | ❌           |        |\n| .speakSelection               | ✅           |       | ❌           |        |\n| .switchControl                | ✅           | ✅    | ✅           |        |\n| .videoAutoplay                | ✅ *(iOS13)* |       | ✅ *(iOS13)* |         |\n| .voiceOver                    | ✅           | ✅    | ✅           | ✅     |\n\nWhile most features can only have a `statusMap` value set to **enabled** or **disabled**, the `.largerText` and `.hearingDevice` feature do offer specific values:\n\n#### LargerText\n\n##### iOS\n\n* XS\n* S\n* M *(default)*\n* L\n* XL\n* XXL\n* XXXL\n* Accessibility M\n* Accessibility L\n* Accessibility XL\n* Accessibility XXL\n* Accessibility XXXL\n* Unknown\n\n##### watchOS\n\n* XS\n* S *(default watch with 38mm)*\n* L *(default watch with 42mm)*\n* XL\n* XXL\n* XXXL\n* Unknown\n\n#### HearingDevice\n\n* both\n* left\n* right\n* disabled\n\n\u003ca id=\"logging\"\u003e\u003c/a\u003e \n### Logging with OSLog\n\nThe 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. \n\nBy default, all messages will be logged automatically by using Apple's [Unified Logging System](https://developer.apple.com/documentation/os/logging). 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:\n\n```swift\n// Send error messages to your data backend\nCapable.onLog = { message, logType in\n    if logType == OSLogType.error {\n        sendLog(\"Capable Framework: \\(message)\")\n    }\n}\n```\n\nFurthermore, you can specify the minimum log level that should be considered when logging messages:\n\n```swift\n// Configure logger to only log warnings and errors (.default, .error, and .fault)\nCapable.minLogType = OSLogType.default\n```\n\nHere's a list of the supported log types, their order, and what kind of messages they are used for:\n\n| OSLogType | Usage                                                        |\n| ----------|:-------------------------------------------------------------|\n| .debug    | Verbose logging **\\***                                       |\n| .info     | Information regarding the framework setup and status changes |\n| .default  | Warnings that may lead to unwanted behavior                  |\n| .error    | Errors caused by the framework                               |\n| .fault    | Errors caused by the framework due to system issues **\\***   |\n\n*\\* Currently not being used by the framework when logging messages.*\n\n## Resources\n\n* [Apple - WWDC Session Videos](https://developer.apple.com/videos/frameworks/accessibility/\n)\n* [Apple - Accessibility for Developers](https://developer.apple.com/accessibility/)\n\n## Contributions\n\nWe'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](./.github/CONTRIBUTING.md).\n\n## License\n\nCapable is available under the MIT license. See the [LICENSE](LICENSE) file for more info.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrs1885%2Fcapable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrs1885%2Fcapable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrs1885%2Fcapable/lists"}