Skip to content

Commit

Permalink
feat: add accessibility
Browse files Browse the repository at this point in the history
  • Loading branch information
UrazAkgultan committed Jan 22, 2023
1 parent 33c7541 commit 3109960
Show file tree
Hide file tree
Showing 21 changed files with 404 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<description />
<returnType type="Boolean" />
</property>
<property key="accessible" type="enumeration" defaultValue="yes">
<property key="accessible" type="enumeration" defaultValue="no">
<caption>Accessible</caption>
<description />
<enumerationValues>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ export function getPreview(values: BottomSheetPreviewProps, isDarkMode: boolean)
};
}

export function getProperties(values: any, defaultProperties: Properties): Properties {
export function getProperties(values: BottomSheetPreviewProps, defaultProperties: Properties): Properties {
if (values.type === "modal") {
if (values.modalRendering === "basic") {
hidePropertyIn(defaultProperties, values, "accessible");
hidePropertiesIn(defaultProperties, values, ["smallContent", "largeContent", "fullscreenContent"]);
} else {
hidePropertiesIn(defaultProperties, values, [
Expand All @@ -112,10 +113,23 @@ export function getProperties(values: any, defaultProperties: Properties): Prope
hidePropertyIn(defaultProperties, values, "fullscreenContent");
}
}

if (values.accessible === "no" || (values.type === "modal" && values.modalRendering === "basic")) {
hidePropertyIn(defaultProperties, values, "screenReaderCaption");
hidePropertyIn(defaultProperties, values, "screenReaderHint");
}

values.itemsBasic.forEach((item, index) => {
if (item.modalAccessible === "no") {
hidePropertyIn(defaultProperties, values, "itemsBasic", index, "modalScreenReaderCaption");
hidePropertyIn(defaultProperties, values, "itemsBasic", index, "modalScreenReaderHint");
}
});

return defaultProperties;
}

export function check(values: any): Problem[] {
export function check(values: BottomSheetPreviewProps): Problem[] {
const errors: Problem[] = [];
if (values.type === "modal") {
if (!values.triggerAttribute) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export function BottomSheet(props: BottomSheetProps<BottomSheetStyle>): ReactEle
if (props.type === "expanding") {
return (
<ExpandingDrawer
accessible={props.accessible === "yes"}
screenReaderCaption={props.screenReaderCaption}
screenReaderHint={props.screenReaderHint}
smallContent={props.smallContent}
largeContent={props.largeContent}
fullscreenContent={props.showFullscreenContent ? props.fullscreenContent : null}
Expand Down
41 changes: 39 additions & 2 deletions packages/pluggableWidgets/bottom-sheet-native/src/BottomSheet.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<caption>Trigger attribute</caption>
<description>Defines if the modal bottom sheet is visible or not. Initially this value should be false. When set to true, the bottom sheet will be shown. When the bottom sheet is hidden, the trigger attribute value is set to false.</description>
<attributeTypes>
<attributeType name="Boolean"/>
<attributeType name="Boolean" />
</attributeTypes>
</property>
<property key="modalRendering" type="enumeration" defaultValue="basic">
Expand Down Expand Up @@ -55,6 +55,25 @@
<enumerationValue key="customStyle">Custom</enumerationValue>
</enumerationValues>
</property>
<property key="modalAccessible" type="enumeration" defaultValue="yes">
<caption>Accessible</caption>
<category>General</category>
<description />
<enumerationValues>
<enumerationValue key="yes">Yes</enumerationValue>
<enumerationValue key="no">No</enumerationValue>
</enumerationValues>
</property>
<property key="modalScreenReaderCaption" type="textTemplate" required="false">
<caption>Screen reader caption</caption>
<category>General</category>
<description />
</property>
<property key="modalScreenReaderHint" type="textTemplate" required="false">
<caption>Screen reader hint</caption>
<category>General</category>
<description />
</property>
</properties>
</property>
<property key="nativeImplementation" type="boolean" defaultValue="true">
Expand Down Expand Up @@ -87,9 +106,27 @@
</property>
</propertyGroup>
<propertyGroup caption="Common">
<systemProperty key="Name"/>
<systemProperty key="Name" />
<systemProperty key="Visibility" />
</propertyGroup>
<propertyGroup caption="Accessibilty">
<property key="accessible" type="enumeration" defaultValue="no">
<caption>Accessible</caption>
<description />
<enumerationValues>
<enumerationValue key="yes">Yes</enumerationValue>
<enumerationValue key="no">No</enumerationValue>
</enumerationValues>
</property>
<property key="screenReaderCaption" type="textTemplate" required="false">
<caption>Screen reader caption</caption>
<description />
</property>
<property key="screenReaderHint" type="textTemplate" required="false">
<caption>Screen reader hint</caption>
<description />
</property>
</propertyGroup>
</propertyGroup>
</properties>
</widget>
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { createElement, ReactElement, ReactNode, useCallback, useEffect, useState } from "react";
import { InteractionManager, LayoutChangeEvent, SafeAreaView, StyleSheet, View } from "react-native";
import Modal, { OnSwipeCompleteParams } from "react-native-modal";
import { EditableValue, ValueStatus } from "mendix";
import { DynamicValue, EditableValue, ValueStatus } from "mendix";
import { BottomSheetStyle, defaultPaddings } from "../ui/Styles";

interface CustomModalSheetProps {
triggerAttribute?: EditableValue<boolean>;
content?: ReactNode;
styles: BottomSheetStyle;
accessible?: boolean;
screenReaderCaption?: DynamicValue<string>;
screenReaderHint?: DynamicValue<string>;
}

export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement => {
Expand Down Expand Up @@ -62,6 +65,10 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>

return (
<Modal
accessible={props.accessible}
accessibilityLabel={props.screenReaderCaption?.value}
accessibilityHint={props.screenReaderHint?.value}
accessibilityState={{ expanded: height > 0 }}
isVisible={currentStatus}
coverScreen
backdropOpacity={0.5}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { BottomSheetStyle } from "../ui/Styles";
import { createElement, ReactNode, useCallback, useState, ReactElement, Children } from "react";
import BottomSheet from "reanimated-bottom-sheet";
import { Dimensions, LayoutChangeEvent, SafeAreaView, StyleSheet, View } from "react-native";
import BottomSheet from "reanimated-bottom-sheet";
import { DynamicValue } from "mendix";
import { BottomSheetStyle } from "../ui/Styles";

interface ExpandingDrawerProps {
smallContent?: ReactNode;
Expand All @@ -10,6 +11,9 @@ interface ExpandingDrawerProps {
onOpen?: () => void;
onClose?: () => void;
styles: BottomSheetStyle;
accessible?: boolean;
screenReaderCaption?: DynamicValue<string>;
screenReaderHint?: DynamicValue<string>;
}

export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
Expand Down Expand Up @@ -56,6 +60,10 @@ export const ExpandingDrawer = (props: ExpandingDrawerProps): ReactElement => {
pointerEvents="box-none"
>
<View
accessible={props.accessible}
accessibilityLabel={props.screenReaderCaption?.value}
accessibilityHint={props.screenReaderHint?.value}
accessibilityState={{ expanded: isOpen }}
onLayout={onLayoutHandlerHeader}
style={!isSmallContentValid ? { height: 20 } : {}}
pointerEvents="box-none"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { createElement, ReactElement, useCallback, useEffect, useRef, useState }
import ActionSheet, { ActionSheetCustom } from "react-native-actionsheet";
import { Platform, Text } from "react-native";
import { EditableValue, ValueStatus } from "mendix";
import { executeAction } from "@mendix/piw-utils-internal";
import { ItemsBasicType } from "../../typings/BottomSheetProps";
import { ModalItemContainerStyle, BottomSheetStyle, defaultMargins } from "../ui/Styles";
import { executeAction } from "@mendix/piw-utils-internal";

interface NativeBottomSheetProps {
name: string;
Expand Down Expand Up @@ -47,7 +47,14 @@ export const NativeBottomSheet = (props: NativeBottomSheetProps): ReactElement =

if (Platform.OS === "android" || !props.useNative) {
const options = props.itemsBasic.map((item, index) => (
<Text key={`${props.name}_item_${index}`} style={props.styles.modalItems[item.styleClass]}>
<Text
accessible={item.modalAccessible === "yes"}
accessibilityLabel={item.modalScreenReaderCaption?.value || item.caption}
accessibilityHint={item.modalScreenReaderHint?.value}
accessibilityRole="button"
key={`${props.name}_item_${index}`}
style={props.styles.modalItems[item.styleClass]}
>
{item.caption}
</Text>
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,34 @@
* @author Mendix UI Content Team
*/
import { ComponentType, CSSProperties, ReactNode } from "react";
import { ActionValue, EditableValue } from "mendix";
import { ActionValue, DynamicValue, EditableValue } from "mendix";

export type TypeEnum = "modal" | "expanding";

export type ModalRenderingEnum = "basic" | "custom";

export type StyleClassEnum = "defaultStyle" | "primaryStyle" | "dangerStyle" | "customStyle";

export type ModalAccessibleEnum = "yes" | "no";

export interface ItemsBasicType {
caption: string;
action?: ActionValue;
styleClass: StyleClassEnum;
modalAccessible: ModalAccessibleEnum;
modalScreenReaderCaption?: DynamicValue<string>;
modalScreenReaderHint?: DynamicValue<string>;
}

export type AccessibleEnum = "yes" | "no";

export interface ItemsBasicPreviewType {
caption: string;
action: {} | null;
styleClass: StyleClassEnum;
modalAccessible: ModalAccessibleEnum;
modalScreenReaderCaption: string;
modalScreenReaderHint: string;
}

export interface BottomSheetProps<Style> {
Expand All @@ -38,6 +48,9 @@ export interface BottomSheetProps<Style> {
fullscreenContent?: ReactNode;
onOpen?: ActionValue;
onClose?: ActionValue;
accessible: AccessibleEnum;
screenReaderCaption?: DynamicValue<string>;
screenReaderHint?: DynamicValue<string>;
}

export interface BottomSheetPreviewProps {
Expand All @@ -56,4 +69,7 @@ export interface BottomSheetPreviewProps {
fullscreenContent: { widgetCount: number; renderer: ComponentType<{ caption?: string }> };
onOpen: {} | null;
onClose: {} | null;
accessible: AccessibleEnum;
screenReaderCaption: string;
screenReaderHint: string;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { RowLayoutProps, StructurePreviewProps } from "@mendix/piw-utils-internal";
import { hidePropertyIn, Properties } from "@mendix/pluggable-widgets-tools";

import paginationSVG from "./assets/pagination.svg";

Expand Down Expand Up @@ -56,3 +57,12 @@ export function getPreview(values: CarouselPreviewProps, isDarkMode: boolean): S
]
};
}

export function getProperties(values: CarouselPreviewProps, defaultProperties: Properties): Properties {
if (values.accessible === "no") {
hidePropertyIn(defaultProperties, values, "screenReaderCaption");
hidePropertyIn(defaultProperties, values, "screenReaderHint");
}

return defaultProperties;
}
3 changes: 3 additions & 0 deletions packages/pluggableWidgets/carousel-native/src/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ export const Carousel = (props: CarouselProps<CarouselStyle>): ReactElement => {
<Fragment>
<NativeCarousel
testID={`${props.name}$carousel`}
accessible={props.accessible === "yes"}
accessibilityLabel={props.screenReaderCaption?.value}
accessibilityHint={props.screenReaderHint?.value}
activeSlideAlignment={props.activeSlideAlignment}
layout="default"
firstItem={0}
Expand Down
54 changes: 35 additions & 19 deletions packages/pluggableWidgets/carousel-native/src/Carousel.xml
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<widget id="com.mendix.widget.native.carousel.Carousel" pluginWidget="true" needsEntityContext="true" offlineCapable="true"
supportedPlatform="Native"
xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../node_modules/mendix/custom_widget.xsd">
<widget id="com.mendix.widget.native.carousel.Carousel" pluginWidget="true" needsEntityContext="true" offlineCapable="true" supportedPlatform="Native" xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../node_modules/mendix/custom_widget.xsd">
<name>Carousel</name>
<description/>
<description />
<studioProCategory>Display</studioProCategory>
<studioCategory>Display</studioCategory>
<properties>
<propertyGroup caption="General">
<propertyGroup caption="Data source">
<property key="contentSource" type="datasource" isList="true">
<caption>Source</caption>
<description/>
<description />
</property>
<property key="content" type="widgets" dataSource="contentSource">
<caption>Content</caption>
<description/>
<description />
</property>
</propertyGroup>
<propertyGroup caption="Display">
Expand All @@ -41,19 +38,38 @@
</enumerationValues>
</property>
</propertyGroup>
<!-- Library has a bug with loops-->
<!-- https://github.com/archriss/react-native-snap-carousel/issues/653 - -->
<!-- https://github.com/archriss/react-native-snap-carousel/issues/608-->
<!-- Also not working properly with Mobx-->
<!-- <propertyGroup caption="Behavior">-->
<!-- <property key="loop" type="boolean" defaultValue="false">-->
<!-- <caption>Loop</caption>-->
<!-- <description>After the last item the carousel continues to the first item.</description>-->
<!-- </property>-->
<!-- </propertyGroup>-->
<!-- Library has a bug with loops-->
<!-- https://github.com/archriss/react-native-snap-carousel/issues/653 - -->
<!-- https://github.com/archriss/react-native-snap-carousel/issues/608-->
<!-- Also not working properly with Mobx-->
<!-- <propertyGroup caption="Behavior">-->
<!-- <property key="loop" type="boolean" defaultValue="false">-->
<!-- <caption>Loop</caption>-->
<!-- <description>After the last item the carousel continues to the first item.</description>-->
<!-- </property>-->
<!-- </propertyGroup>-->
<propertyGroup caption="Common">
<systemProperty key="Name"/>
<systemProperty key="Visibility"/>
<systemProperty key="Name" />
<systemProperty key="Visibility" />
</propertyGroup>

<propertyGroup caption="Accessibilty">
<property key="accessible" type="enumeration" defaultValue="no">
<caption>Accessible</caption>
<description />
<enumerationValues>
<enumerationValue key="yes">Yes</enumerationValue>
<enumerationValue key="no">No</enumerationValue>
</enumerationValues>
</property>
<property key="screenReaderCaption" type="textTemplate" required="false">
<caption>Screen reader caption</caption>
<description />
</property>
<property key="screenReaderHint" type="textTemplate" required="false">
<caption>Screen reader hint</caption>
<description />
</property>
</propertyGroup>
</propertyGroup>
</properties>
Expand Down
Loading

0 comments on commit 3109960

Please sign in to comment.