From 4db77af32f57f34f93f109e4195fc2ef2d511fe7 Mon Sep 17 00:00:00 2001 From: Daniel Lyons <72824209+DandyLyons@users.noreply.github.com> Date: Mon, 5 May 2025 11:50:50 -0600 Subject: [PATCH] Add a11y labels --- Package.resolved | 15 +++++++++++++++ .../DefaultCameraScreen+BottomBar.swift | 6 ++++++ ...faultCameraScreen+CameraOutputSwitch.swift | 14 +++++++++++++- .../DefaultCameraScreen+CaptureButton.swift | 2 ++ .../Camera/DefaultCameraScreen+TopBar.swift | 19 +++++++++++++++++++ .../DefaultCapturedMediaScreen.swift | 4 ++++ .../DefaultScreen+CloseButton.swift | 2 ++ 7 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 Package.resolved diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 000000000..baabc5060 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "8628b222c8e99b1566b2448a6c0b171754962f8e594eba418b8bdd4d6cb30bcf", + "pins" : [ + { + "identity" : "timer", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Mijick/Timer", + "state" : { + "revision" : "342371c33c3f084d82a4818447ba77d858064c85", + "version" : "2.0.0" + } + } + ], + "version" : 3 +} diff --git a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+BottomBar.swift b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+BottomBar.swift index 089c7e968..36809d6aa 100644 --- a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+BottomBar.swift +++ b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+BottomBar.swift @@ -49,6 +49,9 @@ private extension DefaultCameraScreen.BottomBar { ) .frame(maxWidth: .infinity, alignment: .leading) .transition(.scale) + .accessibilityLabel("Camera light") + .accessibilityHint("Toggles the camera light on or off.") + .accessibilityValue(parent.lightMode == .on ? "On" : "Off") }} @ViewBuilder func createCaptureButton() -> some View { if isCaptureButtonActive { DefaultCameraScreen.CaptureButton( @@ -68,6 +71,9 @@ private extension DefaultCameraScreen.BottomBar { ) .frame(maxWidth: .infinity, alignment: .trailing) .transition(.scale) + .accessibilityLabel("Camera chooser") + .accessibilityHint("Switches between front and back cameras.") + .accessibilityValue(parent.cameraPosition == .front ? "Front camera" : "Back camera") }} } diff --git a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CameraOutputSwitch.swift b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CameraOutputSwitch.swift index 1ff1822ca..dbd6b8a18 100644 --- a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CameraOutputSwitch.swift +++ b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CameraOutputSwitch.swift @@ -27,10 +27,22 @@ extension DefaultCameraScreen { struct CameraOutputSwitch: View { }} private extension DefaultCameraScreen.CameraOutputSwitch { func createOutputTypeButton(_ outputType: CameraOutputType) -> some View { - Button(icon: getOutputTypeButtonIcon(outputType), active: isOutputTypeButtonActive(outputType)) { + let a11yValue: LocalizedStringKey = switch outputType { + case .photo: "Photo" + case .video: "Video" + } + let a11yHint: LocalizedStringKey = switch outputType { + case .photo: "Switch to video mode" + case .video: "Switch to photo mode" + } + + return Button(icon: getOutputTypeButtonIcon(outputType), active: isOutputTypeButtonActive(outputType)) { parent.setOutputType(outputType) } .rotationEffect(parent.iconAngle) + .accessibilityLabel("Camera type") + .accessibilityValue(a11yValue) + .accessibilityHint(a11yHint) } } diff --git a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CaptureButton.swift b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CaptureButton.swift index 9ced15892..696214e28 100644 --- a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CaptureButton.swift +++ b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+CaptureButton.swift @@ -19,6 +19,8 @@ extension DefaultCameraScreen { struct CaptureButton: View { var body: some View { Button(action: action, label: createButtonLabel).buttonStyle(ButtonScaleStyle()) + .accessibilityLabel("Take picture") + .accessibilityHint("Takes a picture with the camera") } }} private extension DefaultCameraScreen.CaptureButton { diff --git a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+TopBar.swift b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+TopBar.swift index f4d19402f..87ea0f8c4 100644 --- a/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+TopBar.swift +++ b/Sources/Internal/UI/Default Screens/Camera/DefaultCameraScreen+TopBar.swift @@ -55,6 +55,9 @@ private extension DefaultCameraScreen.TopBar { iconRotationAngle: parent.iconAngle, action: changeGridVisibility ) + .accessibilityLabel("Grid") + .accessibilityValue("\(parent.isGridVisible ? "on" : "off")") + .accessibilityHint("Turns the grid guide \(parent.isGridVisible ? "off" : "on")") }} @ViewBuilder func createFlipOutputButton() -> some View { if isFlipOutputButtonActive { DefaultCameraScreen.TopButton( @@ -62,13 +65,29 @@ private extension DefaultCameraScreen.TopBar { iconRotationAngle: parent.iconAngle, action: changeMirrorOutput ) + .accessibilityLabel("Flip output \(parent.isOutputMirrored ? "on" : "off")") + .accessibilityHint("Flips the camera output horizontally.") }} @ViewBuilder func createFlashButton() -> some View { if isFlashButtonActive { + let a11yHint: LocalizedStringKey = switch parent.flashMode { + case .off: "Turns the camera flash on" + case .on: "Sets the camera flash to auto" + case .auto: "Turns the camera flash off" + } + let a11yValue: LocalizedStringKey = switch parent.flashMode { + case .off: "off" + case .on: "on" + case .auto: "auto" + } + DefaultCameraScreen.TopButton( icon: flashButtonIcon, iconRotationAngle: parent.iconAngle, action: changeFlashMode ) + .accessibilityLabel("Chnge flash mode") + .accessibilityHint(a11yHint) + .accessibilityValue(a11yValue) }} } diff --git a/Sources/Internal/UI/Default Screens/Captured Media/DefaultCapturedMediaScreen.swift b/Sources/Internal/UI/Default Screens/Captured Media/DefaultCapturedMediaScreen.swift index 1c3fbfa88..5e6eb6801 100644 --- a/Sources/Internal/UI/Default Screens/Captured Media/DefaultCapturedMediaScreen.swift +++ b/Sources/Internal/UI/Default Screens/Captured Media/DefaultCapturedMediaScreen.swift @@ -69,6 +69,8 @@ private extension DefaultCapturedMediaScreen { action: retakeAction ) .transition(.scale) + .accessibilityLabel("Retake") + .accessibilityHint("Retake the photo or video") }} @ViewBuilder func createSaveButton() -> some View { if isInitialized { BottomButton( @@ -79,6 +81,8 @@ private extension DefaultCapturedMediaScreen { action: acceptMediaAction ) .transition(.scale) + .accessibilityLabel("Accept") + .accessibilityHint("Accept the photo or video") }} } diff --git a/Sources/Internal/UI/Default Screens/Common Components/DefaultScreen+CloseButton.swift b/Sources/Internal/UI/Default Screens/Common Components/DefaultScreen+CloseButton.swift index 7b7746e4e..21ccbf045 100644 --- a/Sources/Internal/UI/Default Screens/Common Components/DefaultScreen+CloseButton.swift +++ b/Sources/Internal/UI/Default Screens/Common Components/DefaultScreen+CloseButton.swift @@ -17,6 +17,8 @@ struct CloseButton: View { var body: some View { Button(action: action, label: createButtonLabel) + .accessibilityLabel("Close") + .accessibilityHint("Closes the camera") } } private extension CloseButton {