Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Button: Getting anchor native props if href prop is specified #9456

Merged
merged 6 commits into from
Jun 18, 2019
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@uifabric/experiments",
"comment": "Button: Getting anchor native props if href prop is specified.",
"type": "patch"
}
],
"packageName": "@uifabric/experiments",
"email": "[email protected]"
}
68 changes: 54 additions & 14 deletions packages/experiments/src/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Button', () => {
it('renders a disabled default Button with content correctly', () => {
const component = renderer.create(<Button disabled content="Disabled default button" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a primary Button with content correctly', () => {
Expand All @@ -32,7 +32,7 @@ describe('Button', () => {
it('renders a default Button with content and an icon correctly', () => {
const component = renderer.create(<Button icon="Upload" content="Button with string icon" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a primary Button with custom content and icon right-aligned correctly', () => {
Expand All @@ -43,60 +43,100 @@ describe('Button', () => {
</Button>
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a default circular Button with an icon correctly', () => {
const component = renderer.create(<Button icon="PeopleAdd" circular />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a disabled default circular Button with an icon correctly', () => {
const component = renderer.create(<Button icon="Phone" circular disabled />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a primary circular Button with an icon correctly', () => {
const component = renderer.create(<Button icon="FontSize" circular primary />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a disabled primary circular Button with an icon correctly', () => {
const component = renderer.create(<Button icon="Attach" circular primary disabled />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a default Button as an anchor correctly', () => {
const component = renderer.create(
<Button content="Button as an anchor: Go to Bing" href="http://bing.com" target="_blank" title="Let us bing!" />
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

it('renders a primary Button as an anchor correctly', () => {
const component = renderer.create(
<Button primary content="Button as an anchor: Go to Bing" href="http://bing.com" target="_blank" title="Let us bing!" />
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

it('renders a Button inside a CommandBar correctly', () => {
const component = renderer.create(<CommandBar items={[{ key: '0', text: 'Button 1', iconProps: { iconName: 'Upload' } }]} />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a default checked Button correctly', () => {
const component = renderer.create(<Button checked content="Button" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a default disabled checked Button correctly', () => {
const component = renderer.create(<Button disabled checked content="Button" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

it('renders a primary checked Button correctly', () => {
const component = renderer.create(<Button primary checked content="Button" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a primary disabled checked Button correctly', () => {
const component = renderer.create(<Button primary disabled checked content="Button" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

it('renders a default circular checked Button correctly', () => {
const component = renderer.create(<Button checked circular icon="Volume3" />);
const component = renderer.create(<Button circular checked icon="Volume3" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a default circular disabled checked Button correctly', () => {
const component = renderer.create(<Button circular disabled checked icon="Volume3" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

it('renders a primary circular checked Button correctly', () => {
const component = renderer.create(<Button primary checked circular icon="Volume3" />);
const component = renderer.create(<Button primary circular checked icon="Volume3" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot;
expect(tree).toMatchSnapshot();
});

it('renders a primary circular disabled checked Button correctly', () => {
const component = renderer.create(<Button primary circular disabled checked icon="Volume3" />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
});
22 changes: 16 additions & 6 deletions packages/experiments/src/components/Button/Button.view.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
/** @jsx withSlots */
import { Stack, Text, KeytipData } from 'office-ui-fabric-react';
import { withSlots, getSlots } from '../../Foundation';
import { getNativeProps, buttonProperties } from '../../Utilities';
import { getNativeProps, anchorProperties, buttonProperties } from '../../Utilities';
import { Icon } from '../../utilities/factoryComponents';

import { IButtonComponent, IButtonProps, IButtonRootElements, IButtonSlots, IButtonViewProps } from './Button.types';

export const ButtonView: IButtonComponent['view'] = props => {
const { icon, content, children, disabled, onClick, allowDisabledFocus, ariaLabel, keytipProps, buttonRef, ...rest } = props;

const { slotType, htmlType, propertiesType } = _deriveRootType(props);

// TODO: 'href' is anchor property... consider getNativeProps by root type
const buttonProps = { ...getNativeProps(rest, buttonProperties) };
const buttonProps = { ...getNativeProps(rest, propertiesType) };
Copy link
Member

@JasonGore JasonGore Jun 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS3.5 is requiring explicit types for getNativeProps calls (due to deficiencies in getNativeProps typing that I've documented there) so you may have to add one here. You can search any other use of getNativeProps for examples.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


const Slots = getSlots<IButtonProps, IButtonSlots>(props, {
root: _deriveRootType(props),
root: slotType,
stack: Stack,
icon: Icon,
content: Text
Expand All @@ -31,7 +33,7 @@ export const ButtonView: IButtonComponent['view'] = props => {

const Button = (keytipAttributes?: any): JSX.Element => (
<Slots.root
type="button" // stack doesn't take in native button props
type={htmlType}
role="button"
onClick={_onClick}
{...buttonProps}
Expand Down Expand Up @@ -59,6 +61,14 @@ export const ButtonView: IButtonComponent['view'] = props => {
);
};

function _deriveRootType(props: IButtonViewProps): IButtonRootElements {
return !!props.href ? 'a' : 'button';
interface IButtonRootType {
slotType: IButtonRootElements;
htmlType: 'link' | 'button';
propertiesType: string[];
}

function _deriveRootType(props: IButtonViewProps): IButtonRootType {
return !!props.href
? { slotType: 'a', htmlType: 'link', propertiesType: anchorProperties }
: { slotType: 'button', htmlType: 'button', propertiesType: buttonProperties };
}
Loading