Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/fluent-tester/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"@fluentui-react-native/spinner": "^0.6.0",
"@fluentui-react-native/stack": ">=0.8.2 <1.0.0",
"@fluentui-react-native/switch": "^0.10.0",
"@fluentui-react-native/tablist": "0.1.0",
"@fluentui-react-native/text": ">=0.21.0 <1.0.0",
"@fluentui-react-native/theme": ">=0.9.0 <1.0.0",
"@fluentui-react-native/theme-tokens": "^0.25.0",
Expand Down
36 changes: 36 additions & 0 deletions apps/fluent-tester/src/TestComponents/TabList/TabListTest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';

import { TabList, Tab } from '@fluentui-react-native/tablist';

import type { PlatformStatus, TestSection } from '../Test';
import { Test } from '../Test';

const TabListMainTest: React.FunctionComponent = () => {
return (
<TabList>
<Tab key="hello">Tab 1</Tab>
<Tab key="world">Tab 2</Tab>
</TabList>
);
};

const sections: TestSection[] = [
{
name: 'Main Test',
component: TabListMainTest,
},
];

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

const description = 'With Tabs, users can navigate to another view.';

return <Test name="TabsV1 Test" description={description} sections={sections} status={status} />;
};
7 changes: 7 additions & 0 deletions apps/fluent-tester/src/testPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { SpinnerTest } from './TestComponents/Spinner';
import { StrokeWidthTest } from './TestComponents/StrokeWidth';
import { SvgTest, RNSVGIconsTest } from './TestComponents/Svg';
import { SwitchTest } from './TestComponents/Switch';
import { TabListTest } from './TestComponents/TabList/TabListTest';
import { TabsLegacyTest } from './TestComponents/TabsLegacy';
import { TabsV1Test } from './TestComponents/TabsV1';
import { TextLegacyTest } from './TestComponents/TextLegacy';
Expand Down Expand Up @@ -286,6 +287,12 @@ export const tests: TestDescription[] = [
testPageButton: Constants.HOMEPAGE_SWITCH_BUTTON,
platforms: ['android', 'ios', 'macos', 'win32', 'windows'],
},
{
name: 'TabList',
component: TabListTest,
testPageButton: '',
platforms: ['win32', 'windows'],
},
{
name: 'Tabs Legacy',
component: TabsLegacyTest,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Define initial tablist package",
"packageName": "@fluentui-react-native/tablist",
"email": "winlarry@microsoft.com",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Add TabList test page on win32",
"packageName": "@fluentui-react-native/tester",
"email": "winlarry@microsoft.com",
"dependentChangeType": "patch"
}
3 changes: 3 additions & 0 deletions packages/experimental/TabList/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: ['@fluentui-react-native/eslint-config-rules'],
};
Empty file.
Empty file.
1 change: 1 addition & 0 deletions packages/experimental/TabList/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@fluentui-react-native/scripts/babel.config');
3 changes: 3 additions & 0 deletions packages/experimental/TabList/just.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { preset } = require('@fluentui-react-native/scripts');

preset();
70 changes: 70 additions & 0 deletions packages/experimental/TabList/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"name": "@fluentui-react-native/tablist",
"version": "0.1.0",
"description": "A cross-platform TabList component using the Fluent Design System",
"main": "src/index.ts",
"module": "src/index.ts",
"typings": "lib/index.d.ts",
"onPublish": {
"main": "lib-commonjs/index.js",
"module": "lib/index.js"
},
"scripts": {
"build": "fluentui-scripts build",
"clean": "fluentui-scripts clean",
"depcheck": "fluentui-scripts depcheck",
"just": "fluentui-scripts",
"lint": "fluentui-scripts eslint",
"test": "fluentui-scripts jest",
"update-snapshots": "fluentui-scripts jest -u",
"prettier": "fluentui-scripts prettier",
"prettier-fix": "fluentui-scripts prettier --fix true"
},
"repository": {
"type": "git",
"url": "https://github.com/microsoft/fluentui-react-native.git",
"directory": "packages/experimental/TabList"
},
"dependencies": {
"@fluentui-react-native/framework": "0.10.0",
"@fluentui-react-native/interactive-hooks": ">=0.23.0 <1.0.0",
"@fluentui-react-native/focus-zone": ">=0.12.0 <1.0.0",
"@fluentui-react-native/text": ">=0.20.0 <1.0.0",
"@fluentui-react-native/tokens": ">=0.21.0 <1.0.0",
"@fluentui-react-native/use-styling": ">=0.10.0 <1.0.0",
"@fluentui-react-native/icon": "0.18.0",
"@fluentui-react-native/adapters": "0.11.0",
"tslib": "^2.3.1"
},
"devDependencies": {
"@fluentui-react-native/eslint-config-rules": "^0.1.1",
"@fluentui-react-native/scripts": "^0.1.1",
"@fluentui-react-native/test-tools": ">=0.1.1 <1.0.0",
"@office-iss/react-native-win32": "^0.71.0",
"react": "18.2.0",
"react-native": "^0.71.0"
},
"peerDependencies": {
"react": "18.2.0",
"react-native": "^0.71.0"
},
"author": "",
"license": "MIT",
"rnx-kit": {
"kitType": "library",
"alignDeps": {
"presets": [
"microsoft/react-native"
],
"requirements": [
"react-native@0.71"
],
"capabilities": [
"core",
"core-android",
"core-ios",
"react"
]
}
}
}
18 changes: 18 additions & 0 deletions packages/experimental/TabList/src/Tab.styling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { UseStylingOptions } from '@fluentui-react-native/framework';
import { buildProps } from '@fluentui-react-native/framework';

import { tabName } from './Tab.types';
import type { TabSlotProps, TabTokens, TabProps } from './Tab.types';
import { tabStates, defaultTabTokens } from './TabTokens';

export const stylingSettings: UseStylingOptions<TabProps, TabSlotProps, TabTokens> = {
tokens: [defaultTabTokens, tabName],
states: tabStates,
slotProps: {
root: buildProps(() => ({}), []),
content: buildProps(() => ({}), []),
icon: buildProps(() => ({}), []),
stack: buildProps(() => ({}), []),
indicator: buildProps(() => ({}), []),
},
};
38 changes: 38 additions & 0 deletions packages/experimental/TabList/src/Tab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/** @jsxRuntime classic */
/** @jsx withSlots */
import { Pressable, View } from 'react-native';

import type { UseSlots } from '@fluentui-react-native/framework';
import { compose, withSlots } from '@fluentui-react-native/framework';
import { Icon } from '@fluentui-react-native/icon';
import { TextV1 as Text } from '@fluentui-react-native/text';

import { stylingSettings } from './Tab.styling';
import type { TabType, TabProps } from './Tab.types';
import { tabName } from './Tab.types';
import { useTab } from './useTab';

export const Tab = compose<TabType>({
displayName: tabName,
...stylingSettings,
slots: {
root: Pressable,
stack: View,
icon: Icon,
indicator: View,
content: Text,
},
useRender: (userProps: TabProps, useSlots: UseSlots<TabType>) => {
const tabsItem = useTab(userProps);

// Grab the styled slots.
const Slots = useSlots(userProps, (layer) => tabsItem.state[layer] || userProps[layer]);

// Return the handler to finish render.
return () => {
return <Slots.root></Slots.root>;
};
},
});

export default Tab;
142 changes: 142 additions & 0 deletions packages/experimental/TabList/src/Tab.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import type * as React from 'react';
import type { ViewStyle, ColorValue } from 'react-native';

import type { IViewProps } from '@fluentui-react-native/adapters';
import type { IconPropsV1 as IconProps } from '@fluentui-react-native/icon';
import type { IFocusable, PressableState, PressablePropsExtended } from '@fluentui-react-native/interactive-hooks';
import type { TextProps } from '@fluentui-react-native/text';
import type { FontTokens, IBorderTokens } from '@fluentui-react-native/tokens';

export const tabName = 'Tab';

export interface TabTokens extends FontTokens, IBorderTokens {
/**
* The indicator color.
*/
indicatorColor?: string;

/**
* The opacity of the Tab.
*/
tabsItemOpacity?: number;

/**
* The indicator marginHorizontal value.
*/
indicatorMarginHorizontal?: number;

/**
* The icon color.
*/
iconColor?: string;

/**
* The amount of padding between the border and the headerText.
*/
headerTextPadding?: number | string;

/**
* The amount of padding between the border and the headerText when the TabsItem has focus.
*/
headerTextPaddingFocused?: number | string;
/**
* Background color for the button
*/
backgroundColor?: ColorValue;

/**
* Foreground color for the text and/or icon of the button
*/
color?: ColorValue;

/**
* The amount of padding between the border and the contents.
*/
contentPadding?: number | string;

/**
* The amount of padding between the border and the contents when the Button has focus.
*/
contentPaddingFocused?: number | string;

/**
* The icon color when hovering over the Button.
*/
iconColorHovered?: ColorValue;

/**
* The icon color when the Button is being pressed.
*/
iconColorPressed?: ColorValue;

/**
* The size of the icon.
*/
iconSize?: number | string;

/**
* The weight of the lines used when drawing the icon.
*/
iconWeight?: number;

width?: ViewStyle['width'];
minHeight?: ViewStyle['minHeight'];
minWidth?: ViewStyle['minWidth'];

/**
* States that can be applied to a button
*/
hovered?: TabTokens;
focused?: TabTokens;
pressed?: TabTokens;
disabled?: TabTokens;
selected?: TabTokens;
}

export interface TabProps extends Omit<PressablePropsExtended, 'onPress'> {
/**
* A unique key-identifier for each option
*/
key: string;

/**
* Whether or not the tab is selectable
*/
disabled?: boolean;

/**
* Source URL or name of the icon to show on the Button.
*/
icon?: IconProps;

/**
* A RefObject to access the IButton interface. Use this to access the public methods and properties of the component.
*/
componentRef?: React.RefObject<IFocusable>;

testID?: string;
}

export interface TabState extends PressableState {
selected?: boolean;
}

export interface TabInfo {
props: TabProps & React.ComponentPropsWithRef<any>;
state: TabState;
}

export interface TabSlotProps {
root: React.PropsWithRef<PressablePropsExtended>;
icon: IconProps;
stack: IViewProps;
indicator: IViewProps;
content: TextProps;
}

export interface TabType {
props: TabProps;
tokens: TabTokens;
slotProps: TabSlotProps;
state: TabState;
}
14 changes: 14 additions & 0 deletions packages/experimental/TabList/src/TabList.styling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { UseStylingOptions } from '@fluentui-react-native/framework';
import { buildProps } from '@fluentui-react-native/framework';

import { tabListName } from './TabList.types';
import type { TabListTokens, TabListSlotProps, TabListProps } from './TabList.types';
import { defaultTabListTokens } from './TabListTokens';

export const stylingSettings: UseStylingOptions<TabListProps, TabListSlotProps, TabListTokens> = {
tokens: [defaultTabListTokens, tabListName],
slotProps: {
root: buildProps(() => ({}), []),
stack: buildProps(() => ({}), []),
},
};
Loading