Skip to content

The core functionality of notion's dynamic components with drag & drop

Notifications You must be signed in to change notification settings

llGaetanll/notion-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

notion-core

This project aims to re-create the concept of dynamically editable components seen on notion.so.

Motivation

The idea of the end user being able to freely manipulate website elements is really powerful. Having an opensource project like this means that developers can create their own custom components, or incorporate this functionality in part of their react websites.

How does it work?

It's actually really easy!

Each dynamic component has 2 modes: display, and edit. To create a new dynamic component, simply create a component for each these modes and pass it in to the DynamicComponent component. You can also chose to pass in props to each mode component.

Below is the actual code for the TextField component.

// This component is displayed when the component is in `display` mode
const TextDisplayComponent = ({ text, setComponentMode, ...props }) => {
  const classes = useStyles();

  // when the user hovers over the element
  // switch to edit mode
  const handleEdit = () =>
    setComponentMode("edit");

  return (
    <Typography 
      onMouseEnter={handleEdit} 
      className={classes.display} 
      {...props}
    >
      {text}
    </Typography>
  );
}

// This component is displayed when the component is in `edit` mode
const TextEditComponent = ({ text = '', setText, setComponentMode, ...props }) => {
  const ref = useRef();
  const classes = useStyles();
  
  // focus the input ref
  useEffect(() => {
    ref.current.focus();
  })

  const handleEdit = event => setText(event.target.value);

  return (
    <MuiInputBase
      className={classes.edit}
      onChange={handleEdit}
      value={text}
      inputRef={ref}
      {...props}
    />
  );
}

// This is the final exported component
const TextField = ({ text, setText, displayProps, editProps }) =>
  <DynamicComponent 

    displayComponent={<TextDisplayComponent />}
    editComponent={<TextEditComponent />}

    displayProps={{
      text,
      ...displayProps
    }}
    editProps={{
      text,
      setText,
      ...editProps
    }}

    // default mode of the component
    mode="display" 
  />

export default TextField;

Now using this code in your app is easy as pie

const App = () => {
  // keep track of state for the text component
  // as your app grows you might think of using redux or apollo...
  const [text, setText] = useState('hello world');

  return (
    <div style={{height: '100%', width: 400, margin: '0 auto'}}>
        <TextField text={text} setText={setText} />
    </div>
  );
}

With the functionality implemented in the TextField component defined above, the component should become editable when hovered.

PRs are welcome!

If you want to help me out on this project, feel free! Any help or suggestion is greatly appreciated.

Contributing

If you would like to help contribute to the project, see the Dynamic Components Project and contribute a component! Alternatively you could contribute an idea for one.

About

The core functionality of notion's dynamic components with drag & drop

Topics

Resources

Stars

Watchers

Forks