Skip to content

Commit

Permalink
Add Expander native component (WinUI 2.6) (#756)
Browse files Browse the repository at this point in the history
### Platforms Impacted
- [ ] iOS
- [ ] macOS
- [ ] win32 (Office)
- [x] windows
- [ ] android

### Description of changes

Adding a native windows Expander control (WinUI 2.6) to FURN. 
- packages/experimental/Expander/windows: Contains native module code for the Expander control
- packages/experimental/Expander/src: Contains code to compose the native view into a component

Notable design choices:
- packages/experimental/Expander/windows/ReactNativeExpander/ExpanderView.idl: ExpanderView inherits from a ContentPresenter, and the Expander control is displayed from within the ContentPresenter control. This is because we are unable to inherit from the Expander control directly.

Future work:
- Resolve layout issues between Yoga and XAML layout systems within the RNW framework. Conflicting layout systems caused the following issues and work arounds in the Expander implementation:
   - Expander requires a fixed collapsed and expanded height
   - height must be exposed as props to allow the proper collapsed/expanded height changes. If the user tries to use the height prop, it is overridden. Can potentially fix this using token states to update the Expander height.
   - Expander does not account for height changes caused by window resizing
   - User cannot interact with non-native components within the header. In this scenario, the Expander will expand instead.
- Remove implicit ordering of Expander header and content. The user should be able to specify which child element is the header and which is the content. 

### Verification

Tested on a [React Native for Windows v0.64.x tester app](https://github.com/amdingler/expander-tester). Expander was tested for light mode, dark mode, and keyboard accessibility.

**Basic Expander**

https://user-images.githubusercontent.com/47195059/127239274-c1378b17-2429-410e-9afd-d769772e7c35.mp4


**Full Expander Functionality**

https://user-images.githubusercontent.com/47195059/127241306-3870077d-9a22-4f2c-85e7-3cdc2d329d5c.mp4


**Dark Mode**

<img width="300" alt="Dark_Mode_Expander" src="https://user-images.githubusercontent.com/47195059/127238400-8e6f61a5-3a82-4883-943e-c88a0cae8dfd.PNG">

### Pull request checklist

This PR has considered (when applicable):
- [ ] Automated Tests
- [x] Documentation and examples
- [x] Keyboard Accessibility
- [ ] Voiceover
- [ ] Internationalization and Right-to-left Layouts
  • Loading branch information
amdingler committed Aug 13, 2021
1 parent cbe7dd8 commit 364c4b6
Show file tree
Hide file tree
Showing 37 changed files with 1,974 additions and 0 deletions.
1 change: 1 addition & 0 deletions apps/fluent-tester/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@fluentui-react-native/experimental-button": "0.8.9",
"@fluentui-react-native/experimental-native-button": ">=0.7.10 <1.0.0",
"@fluentui-react-native/experimental-native-date-picker": ">=0.3.3 <1.0.0",
"@fluentui-react-native/experimental-expander": "0.1.0",
"@fluentui-react-native/experimental-shimmer": "0.5.4",
"@fluentui-react-native/experimental-text": ">=0.6.9 <1.0.0",
"@fluentui-react-native/framework": ">=0.5.28 <1.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import * as React from 'react';
import { Expander } from '@fluentui-react-native/experimental-expander';
import { Text } from '@fluentui/react-native';
import { Stack } from '@fluentui-react-native/stack';
import { stackStyle, commonTestStyles as commonStyles } from '../Common/styles';
import { Test, TestSection, PlatformStatus } from '../Test';
import { EXPANDER_TESTPAGE } from './consts';
import { View, Switch } from 'react-native';

const expanderTest: React.FunctionComponent = () => {
/** This test page has not yet been tested and does not currently build because
* the react-native-test-app does not yet support WinUI 2.6
* Filed issue in react-native-test-app: https://github.com/microsoft/react-native-test-app/issues/444
*/
const CustomizedExpander = Expander.customize({
headerBackground: '#9c9c9c',
headerForeground: '#ffffff',
contentBackground:'#c3c3c3',
chevronBackground: '#ff7f7f',
chevronForeground: '#ffffff',
chevronPointerOverBackground: '#b5ffb2',
chevronPointerOverForeground: '#bfbdbd',
chevronPressedBackground: '#ffb2f4',
chevronPressedForeground: '#912a2a',
headerForegroundPointerOver: '#27f238',
headerForegroundPressed: '#f227eb',
headerBorderBrush: '#f22727',
headerBorderPointerOverBrush: '#27f238',
headerBorderPressedBrush: '#f227eb',
contentBorderBrush: '#f227eb',
headerBorderThickness: 2,
chevronBorderBrush: '#f22727',
chevronBorderPointerOverBrush: '#27f238',
chevronBorderPressedBrush: '#f227eb',
chevronBorderThickness: 2
});

const [switchValue, setSwitchValue] = React.useState(false);
const [expanderText, setExpanderText] = React.useState('Initial state');
const onExpanding = () => {
setExpanderText('Expanding event changed title');
}
const onCollapsing = () => {
setExpanderText('Collapsing event changed title');
}

return (
<Stack style={stackStyle}>
<Text>expanded=true, expandDirection=up, and event functionality</Text>
<Expander collapsedHeight={50} expandedHeight={100} expanded={true} expandDirection='up'
onCollapsing={onExpanding}
onExpanding={onCollapsing}>
<Text>{expanderText}</Text>
<Text>Text in the content</Text>
</Expander>
<Text>enabled = false</Text>
<Expander collapsedHeight={50} expandedHeight={100} enabled={false}>
<Text>User cannot interact with this control</Text>
<Text>Content that you should not see</Text>
</Expander>
<Text>Multiple components in header and content</Text>
<Expander collapsedHeight={64} expandedHeight={150}>
<View style={{flexDirection: 'row', width: 200, height: 62}}>
<View style={{alignSelf:'center'}}>
<Text>Line one</Text>
<Text>Line two</Text>
</View>
<Switch style={{marginLeft:'auto', marginTop:12}}
value={switchValue}
onValueChange={setSwitchValue} />
</View>
<View>
<Text>First line of text</Text>
<Text>Second line of text</Text>
</View>
</Expander>
<Text>Customized Expander</Text>
<CustomizedExpander collapsedHeight={50} expandedHeight={100}>
<Text>Text in the header</Text>
<Text>Text in the content</Text>
</CustomizedExpander>
</Stack>
);
};

const basicExpander: React.FunctionComponent = () => {
return (
<Stack style={stackStyle}>
<View style={commonStyles.root}>
<Expander collapsedHeight={50} expandedHeight={100}>
<Text>Text in the header</Text>
<Text>Text in the content</Text>
</Expander>
</View>
</Stack>
);
};

const expanderSections: TestSection[] = [
{
name: 'BaseExpander',
testID: EXPANDER_TESTPAGE,
component: basicExpander,
},
{
name: 'Expander',
testID: EXPANDER_TESTPAGE,
component: expanderTest,
},
];

export const ExpanderTest: React.FunctionComponent = () => {
const status: PlatformStatus = {
win32Status: 'Backlog',
uwpStatus: 'Beta',
iosStatus: 'Backlog',
macosStatus: 'Backlog',
androidStatus: 'Backlog',
};

const description =
'Expander is a content control that displays components in the header and content. The control has an expanded and collapsed size. Expander is a native control implemented with WinUI 2.6 Expander.';

return <Test name='Expander Test' description={description} sections={expanderSections} status={status}></Test>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const HOMEPAGE_EXPANDER_BUTTON = 'Homepage_Expander_Button';
export const EXPANDER_TESTPAGE = 'Expander_TestPage';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './ExpanderTest';
export * from './consts';
6 changes: 6 additions & 0 deletions apps/fluent-tester/src/FluentTester/testPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ContextualMenuTest, HOMEPAGE_CONTEXTUALMENU_BUTTON } from './TestCompon
import { ActivityIndicatorTest, HOMEPAGE_ACTIVITYINDICATOR_BUTTON } from './TestComponents/ActivityIndicator';
import { MenuButtonTest, HOMEPAGE_MENU_BUTTON } from './TestComponents/MenuButton';
import { HOMEPAGE_TOKEN_BUTTON, TokenTest } from './TestComponents/Tokens';
import { ExpanderTest, HOMEPAGE_EXPANDER_BUTTON } from './TestComponents/Expander';

export const tests: TestDescription[] = [
{
Expand Down Expand Up @@ -133,4 +134,9 @@ export const tests: TestDescription[] = [
component: TokenTest,
testPage: HOMEPAGE_TOKEN_BUTTON,
},
{
name: 'Expander Test',
component: ExpanderTest,
testPage: HOMEPAGE_EXPANDER_BUTTON,
},
];
6 changes: 6 additions & 0 deletions apps/fluent-tester/src/FluentTester/testPages.windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { HOMEPAGE_SEPARATOR_BUTTON, SeparatorTest } from './TestComponents/Separ
import { HOMEPAGE_TEXT_BUTTON, TextTest } from './TestComponents/Text';
import { HOMEPAGE_THEME_BUTTON, ThemeTest } from './TestComponents/Theme';
import { HOMEPAGE_TOKEN_BUTTON, TokenTest } from './TestComponents/Tokens';
import { ExpanderTest, HOMEPAGE_EXPANDER_BUTTON } from './TestComponents/Expander';

export const tests = [
{
Expand Down Expand Up @@ -66,4 +67,9 @@ export const tests = [
component: TokenTest,
testPage: HOMEPAGE_TOKEN_BUTTON,
},
{
name: 'Expander Test',
component: ExpanderTest,
testPage: HOMEPAGE_EXPANDER_BUTTON,
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Add native Expander component",
"packageName": "@fluentui-react-native/experimental-expander",
"email": "amdingler694@gmail.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Add Expander component test",
"packageName": "@fluentui-react-native/tester",
"email": "amdingler694@gmail.com",
"dependentChangeType": "patch"
}
4 changes: 4 additions & 0 deletions packages/experimental/Expander/CHANGELOG.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@fluentui-react-native/experimental-expander",
"entries": []
}
5 changes: 5 additions & 0 deletions packages/experimental/Expander/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Change Log - @fluentui-react-native/experimental-native-button

This log was last generated on Thu, 11 Mar 2021 19:48:16 GMT and should not be manually modified.

<!-- Start content -->

0 comments on commit 364c4b6

Please sign in to comment.