split icon indicating copy to clipboard operation
split copied to clipboard

Use a React component for gutter

Open drazik opened this issue 4 years ago • 6 comments

Hello,

When reading the react-split docs, I found that the gutter prop is a function that should return an html element (https://github.com/nathancahill/split/tree/master/packages/react-split#gutter). I was wondering if there is a way to make it work with a React component. My use case is that I will need to show an icon in the gutter, and a tooltip when the mouse is hovering this icon. Since I have all the components ready to show this icon and tooltip, it would be great that I can use them in a Gutter component that I would give as the gutter prop of the Split component.

If this is not possible to do this right now, do you think it would be good for the library ? I can help doing the changes.

Thanks !

drazik avatar Aug 05 '20 15:08 drazik

Great idea. I'd love to support that.

nathancahill avatar Mar 28 '21 17:03 nathancahill

This would be really cool. @drazik do you have any thought about how much work it could be?

colmanhumphrey avatar Nov 09 '21 16:11 colmanhumphrey

I didn't look into it finally, sorry.

drazik avatar Nov 09 '21 17:11 drazik

fwiw, I have had some success with:

<Split
     gutter={() => {
        const gutterWrapper = document.createElement("div");
        const MyComponent = (
          <div
            style={{background: "red", height: "100%"}}
            onClick={() => console.log("clicked")}
            etc...
          >
             Gutter contents or more components...
          </div>
        );
        ReactDOM.render(MyComponent, gutterWrapper);
        return gutterWrapper;
      }}
>

But note that in this usage, communications between components is one way (upwards from the gutter to the container). You can pass in "onDoSomething" props to the gutter component that it can use to send signal to the component containing the Split but you can't pass mutable state from the container into the gutter component and get it to re-render the gutter on change. Right now, it seems that react-split caches the gutter on mount and does not re-render it afterwards, although there may be some trick to it that I am missing since there is a notion of certain props forcing re-creation of the split object.

Might be doable with a context. I haven't explored that too much.

adamsussman avatar Feb 19 '22 08:02 adamsussman

I struggled with this on a piece of legacy code I have been working on.

The work around I found was to use createPortal from react-dom. I also had to return a null html element if the dom rendered before the gutter was set or I was getting a react error (there is an explanation for this in the createPortal docs).

I mocked up the general idea of the code that ended up working for me:

const InnerGutterElement = ({ clickEvent }) => {
  const handleClick = () => {
    clickEvent();
  };

  return (
      <div className={`gutter-element}`} onClick={() => handleClick()}></div>
  );
};

const PanelComponent = () => {
  const [gutterElement, setGutter] = useState(false);

  return (
    <div>
      <Split
        gutter = (_, direction) => {
          const gutter = document.createElement('div');
          gutter.className = `gutter gutter-${direction}`;

           //sets gutter component to be used by createPortal when gutter is initialized
          setGutter(gutter);

         return gutter;
       };
      >
     {gutterElement ? createPortal(<InnerGutterElemen clickEvent={clickEvent}/>, gutterElement) : null}
    </div>
  )
}

kalkrueger avatar Jul 26 '23 21:07 kalkrueger

It's possible to use Portals to have custom gutter component:

export const CustomGutterSplit = () => {
  const gutterContainer = useRef<HTMLElement>(document.createElement("div"));
  return (
    <>
      <Split
        gutter={() => gutterContainer.current}
      >
        <Container1 />
        <Container2 />
      </Split>
      {createPortal(<div>my custom gutter</div>, gutterContainer.current)}
    </>
  );
};

lehovec avatar Dec 06 '23 14:12 lehovec