Skip to content

Latest commit

 

History

History
114 lines (90 loc) · 3.12 KB

component-api.md

File metadata and controls

114 lines (90 loc) · 3.12 KB

This document is constructed in the form of Q&A, search for your case on the list or add your case in the format of question and answer otherwise.

Glossary

compound component - a react pattern that assumes building the desired component from the predefined blocks, which are usually available as static props on the main component. Blocks may share the state implicitly and communicate in the background

facade - a pattern that assumes one react component available for the consumer with access to the internal props

content props - props that provide content for the component

universal component - a component that suppports both compound and regular way of usage

Principles

  • Prefer HTML native components' API for Picasso components over designing new APIs when possible

Practical cases

Q: Should I choose a compound component or facade pattern for my NewComponent?

A: Check how many content props you have. For 2+ content props create a universal component, for 1 content prop use facade.

Example:

// Universal

const ModalTitle = ({ children }) => (
  <div style={{ borderBottom: "1px solid gray", padding: "15px 0" }}>
    {children}
  </div>
);
const ModalContent = ({ children }) => (
  <div style={{ margin: "30px 0" }}>{children}</div>
);
const ModalActions = ({ children }) => (
  <div style={{ borderTop: "1px solid gray", padding: "15px 0" }}>
    {children}
  </div>
);
const ModalRoot = ({ children }) => (
  <div style={{ background: "white", padding: "30px" }}>{children}</div>
);

const Modal = ({ title, content, actions, children }) => {
  return (
    <ModalRoot>
      {children ?? (
        <>
          <ModalTitle>{title}</ModalTitle>
          <ModalContent>{content}</ModalContent>
          <ModalActions>{actions}</ModalActions>
        </>
      )}
    </ModalRoot>
  );
};

Modal.Title = ModalTitle;
Modal.Content = ModalContent;
Modal.Actions = ModalActions;

export default function App() {
  return (
    <div className="App">
      {/* Facade */}
      <Modal
        title="hello"
        content="content"
        actions={
          <>
            <button>Save</button>
            <button>Cancel</button>
          </>
        }
      />

      {/* Compound */}
      <Modal>
        <Modal.Title>Title</Modal.Title>
        <Modal.Content>Content</Modal.Content>
        <Modal.Actions>Actions</Modal.Actions>
      </Modal>
    </div>
  );

Q: What if my component should have a different size?

A: Use a size prop with an enum of limited values.

Example:

size?: SizeType<'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large'>

Q: How should I name my prop?

A: Use native equivalent if possible. Otherwise, check the codebase for the property with similar functionality.

Example:

<Button disabled>Disabled</Button>

Q: Should I use boolean or enum for my prop?

A: Imagine or investigate how many different values of this prop is possible to have.

Example:

<Alert danger /> // boolean. renders red box
<Alert warning /> // boolean. renders yellow box

<Alert warning danger /> // bad. which color should win?
<Alert variant='danger' /> // good