How can I display a Persona component in a CommandBar in React Fabric-UI? - reactjs

I am trying to display a Persona component on the far right of my CommandBar component, which I use as a header for my application.
Here's a code snippet
const getFarItems = () => {
return [
{
key: 'profile',
text: <Persona text="Kat Larrson" />,
onClick: () => console.log('Sort')
}
]
}
const FabricHeader: React.SFC<props> = () => {
return (
<div>
<CommandBar
items={getItems()}
farItems={getFarItems()}
ariaLabel={'Use left and right arrow keys to navigate between commands'}
/>
</div>
);
}
This throws a type error because the text prop expects a string and not a component. Any help would be appreciated!

Under the ICommandBarItemProps there is a property called commandBarButtonAs that the docs state:
Method to override the render of the individual command bar button.
Note, is not used when rendered in overflow
And its default component is CommandBarButton which is basically a Button
Basically there are two ways to do this.
Keep using Button, and apply your own renderer. Basically the IButtonProps you can add onRenderChildren which would allow you to add any Component such as Persona to render. This example would show you how it is done https://codepen.io/micahgodbolt/pen/qMoYQo
const farItems = [{
// Set to null if you have submenus that want to hide the down arrow.
onRenderMenuIcon: () => null,
// Any renderer
onRenderChildren: () => ,
key: 'persona',
name: 'Persona',
iconOnly: true,
}]
Or add your own crazy component not dependent on CommandBarButton but that means you need to handle everything like focus, accessibility yourself. This example would show you how it is done https://codepen.io/mohamedhmansour/pen/GPNKwM
const farItems = [
{
key: 'persona',
name: 'Persona',
commandBarButtonAs: PersonaCommandBarComponent
}
];
function PersonaCommandBarComponent() {
return (
);
}

Related

AntD Tree: need help! can't pass react element as icon OR title for antd tree

I'm using the AntD tree and I have a react element that I want to pass as either an icon or a title because it has custom styling. Due to it being IP I can't share too much code, but my question is:
how can I pass a react element (see below i.e. generic name) as either a title or icon and have antD tree render it?
i.e. this is what I want to pass as a prop to the icon or title
import React from 'react';
const genericName = (props) => {
// code uses props to get some infor for Color
// cant share code due to proprietary reasons
// but it is not needed for this question
const colorHTML = getColor(Color);
return (
<div>
<div className={`colors from`}>${colorHTML}</div>
{pin}
</div>
);
};
export default genericName;
in my console you can see node.icon is a typeof react.element. I want to target that and just pass the prop into antD tree as either title or icon
i.e.
return (
<Tree
icon={node.icon}
/>
)
I've searched and similar answers were given before antD forbid the use of children and strictly allows treeData. All examples I see only use strings in titles/icons, but since antD documentation is very limited, I need to know if my use case is possible. Right now, for the life of me I can't understand why it doesn't populate.
Thank you in advance.
It should definitely work to put a JSX component as title within treeData. Take a look at this snippet, I added a Icon here in one of the titles:
import React from 'react'
import { RightCircleOutlined } from '#ant-design/icons'
type Props = {}
import { Tree } from 'antd';
import type { DataNode, TreeProps } from 'antd/es/tree';
const treeData: DataNode[] = [
{
title: <span>{<RightCircleOutlined />} parent</span>, //icon added here
key: '0-0',
children: [
{
title: 'parent 1-0',
key: '0-0-0',
disabled: true,
children: [
{
title: 'leaf',
key: '0-0-0-0',
disableCheckbox: true,
},
{
title: 'leaf',
key: '0-0-0-1',
},
],
},
{
title: 'parent 1-1',
key: '0-0-1',
children: [{ title: <span style={{ color: '#1890ff' }}>sss</span>, key: '0-0-1-0' }],
},
],
},
];
const Demo: React.FC = () => {
const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
console.log('selected', selectedKeys, info);
};
const onCheck: TreeProps['onCheck'] = (checkedKeys, info) => {
console.log('onCheck', checkedKeys, info);
};
return (
<Tree
checkable
defaultExpandedKeys={['0-0-0', '0-0-1']}
defaultSelectedKeys={['0-0-0', '0-0-1']}
defaultCheckedKeys={['0-0-0', '0-0-1']}
onSelect={onSelect}
onCheck={onCheck}
treeData={treeData}
/>
);
};
export default Demo;

Pass Data To A Custom Component

I am trying to study this tab feature using ReactJs and seems to be working: Tab in ReactJs
I was wondering if I can pass a data type to the components as follows: Three components for tabs
const TabOne = (data) => {
return (
<p>
{data.map((val: any) => (
val.id
))}
</p>
)
}
In the same time, tried to do the same:
const tabs = [
{
label: 'Opened', // Tab Title - String
Component: TabOne(data) // Tab Body - JSX.Element
},
{
label: 'Closed',
Component: TabTwo
}
]
Or even this one, a silly one:
<Tabs tabs = {tabs(data)} />
Finally got this - Type 'Element' provides no match for the signature '(): Element'. Is there any way I can make use of the above?
N.B: My plan is to show two versions of data in each tab depending upon condition.

React unit test to find the element in the component

any help is appreciated. I was bit stuck with writing unit test in react. I need to check if action button and link button exists in the component.
here is my code for component. It is rendering child component and passing button as render props
export interface CloseableNotificationBannerProps {
title?: string;
message: string;
variant: "default" ;
icon: "info";
actionButton?: React.ReactNode;
showLinkButton: boolean;
}
export const CloseableNotificationBanner: React.FC<CloseableNotificationBannerProps> =
({
title,
message,
variant,
icon,
actionButton,
showLinkButton
}) => {
const [show, setShow] = useState(false); // extract into props to deafult it
const handleClick = () => setShow(prevState => !prevState);
return (
show ?
<BasicNotificationBanner
title={title}
message={message}
variant={variant}
icon={icon}
actionButton={actionButton}
closeButton={showLinkButton && <LinkButton
variant="transparent"
color="neutrals.dn40"
onClick={handleClick}>×</LinkButton>}
/> : null
);
};
For now It is able to mount the component successfully but unable to find action button and link button. Below is my unit test:
// Given
const content = {
message: chance.string(),
icon: chance.pickone(["info", "check_circle", "warning"]),
variant: chance.pickone(["default", "information", "success", "error", "warning"]),
actionButton: <Button>button</Button>,
showLinkButton: true
};
// When
const actual = mount(<CloseableNotificationBanner content={content}/>);
const button = actual.find(Button);
// Then
expect(actual.exists()).toBeTruthy();
expect(button.exists()).toBeTruthy();
output shows that
Error: expect(received).toBeTruthy()
Received: false
for button. Please help. I have tried wit both shallow and render
The right way to do this is to use the
toBeInTheDocument() function.
Like this:
expect(actual).toBeInTheDocument();
expect(button).toBeInTheDocument();
So, you need find particular button by its id or by its class name like
expect(actual.find('#actionButton').length).toBe(1); // if it has actionButton id
expect(actual.find('.button-class').at(0).length).toBe(1); // if its has many buttons and all have button-class and its on first position
expect(actual.find('button').length).toBe(2); // 2, if you have only two buttons
solved it using expect(actual.children().props().actionButton).toEqual(content.actionButton);

How to show JSDoc based prop tooltips in VSCode for React functional component prop?

I have a React functional component:
interface ISpecialButton {
text: string;
}
const SpecialButton: FC<ISpecialButton > = ({
/* Prop description */
text
} = {
//code
});
And would like a developer who uses it in a JSX template to see "Prop description" when he hovers over text prop when adding the SpecialButton to a template. I have tried various ways to do it with JSDoc, but none of these work. What is the correct way to use JSDoc for a React functional component so that VSCode shows tooltips?
The interface is the one that should be documented so every other place it's going to show the docs when hovering over it. Something like this:
interface ISpecialButton {
/**
* Prop description
*/
text: string;
}
const SpecialButton: React.FC<ISpecialButton> = ({
text
}) => {
return <>{ text }</>;
};
const Template: React.FC = () => {
return <>
<SpecialButton text='' />
</>
}

How to Manipulate Dropdown placeholder, onFocus?

Am new to ReactJS. I need to make the "placeholder" which is set to "State" initially to Empty/Null when onClicked or onFocus and then when it's not focused on, it goes back to "State" again. Can someone help me with this, am very new to react so any help will be appreciated.
import React from "react";
import { render } from "react-dom";
import { Container, Button, Modal, Dropdown } from "semantic-ui-react";
const stateOptions = [
{ key: "AL", value: "AL", text: "Alabama" },
{ key: "NY", value: "NY", text: "New York" }
];
const App = () => (
<Dropdown
placeholder="State"
fluid
multiple
search
selection
options={stateOptions}
/>
);
render(<App />, document.getElementById("root"));
From React's perspective, placeholder is a state that needs to be changed according to user's actions (onClick, onBlur)
So create a state to hold placeholder value that need to change.
There are two ways (since v16.8.0 with the introduction of React Hooks).
Using Class Component
class DropDown extends React.Component {
defaultPlaceholderState = "State";
state = { placeholder: this.defaultPlaceholderState };
clearPlaceholder = () => this.setState({ placeholder: "" });
resetPlaceholder = () =>
this.setState({ placeholder: this.defaultPlaceholderState });
render() {
return (
<Dropdown
onClick={this.clearPlaceholder}
onFocus={this.clearPlaceholder}
onBlur={this.resetPlaceholder}
placeholder={this.state.placeholder}
fluid
multiple
search
selection
options={stateOptions}
/>
);
}
}
In the code above, placeholder declared as a state with default value set to this.defaultPlaceholderState.
When a user clicks on the dropdown, onClick clears the placeholder value by setting it to an empty string. Same for onFocus when the Dropdown is on focus.
When a user clicks outside (onBlur), resetPlaceHolder sets the placeholder value to the default this.defaultPlaceholderState.
Using Function Component with useState hook
React v16.8.0 introduces Hooks, which enables Function Components (not a Functional Component, as it refers to Functional Programming) to hold states.
You can use React.useState hook to hold placeholder value.
const DropDownUsingHook = () => {
const defaultPlaceholderState = "State";
const [placeholder, setPlaceholder] = React.useState(defaultPlaceholderState);
const clearPlaceholder = () => setPlaceholder("");
const resetPlaceholder = () => setPlaceholder(defaultPlaceholderState);
return (
<Dropdown
onClick={clearPlaceholder}
onFocus={clearPlaceholder}
onBlur={resetPlaceholder}
placeholder={placeholder}
fluid
multiple
search
selection
options={stateOptions}
/>
);
};
⚠ Note: Unlike the Class version, clearPlaceholder, resetPlaceholder methods and placeholder state don't use this. prefix.
The implementation is similar but you use useState hook to declare the state and the setter (setPlaceholder).
Refer to the Hooks documentation, Using State Hook for more info.
You can play around with the working code on CodeSandbox.

Resources