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

Virtual viewports #1

Open
bpierre opened this issue Mar 7, 2020 · 1 comment
Open

Virtual viewports #1

bpierre opened this issue Mar 7, 2020 · 1 comment

Comments

@bpierre
Copy link
Contributor

bpierre commented Mar 7, 2020

It could be useful to have the possibility to declare viewport contexts, or virtual viewports. It would make it possible for components to react to either the global viewport or a local one.

For example, let’s imagine an app with two panels: a menu and a main screen.

Some components in the main screen would always use to the global viewport G, like a popover or a modal, so they can position themselves over the menu panel. But some others, like layout breakpoints in the main screen, would need to know the dimensions of their local viewport L, which is the right panel.

A way to do this could be to declare it all in ViewportProvider:

// App.js

const MENU_PANEL_WIDTH = 300

function App() {
  return (
    <ViewportProvider
      viewports={{
        // Local viewports could be declared as callbacks
        // that would receive the main viewport dimensions.
        main: ([ width, height ]) => [ width - MENU_PANEL_WIDTH, height ],
      }}
    >
      <PanelsLayout
        menu={/* … */}
        main={
          <MyLocalComponent />
        }
      />
    </ViewportProvider>
  )
}
// MyLocalComponent.js

function MyLocalComponent() {
  const viewport = useViewport()
  const mainPanelViewport = useViewport('main')

  // …
}

Another way would be to nest the ViewportProvider components. That might be useful to prevent having to move all the information at the level of the single ViewportProvider element. At this point, I think it would make sense to also rename the component Viewport (as in “declares a viewport”).

// App.js

function App() {
  return (
    <Viewport>
      <PanelsLayout
        menu={/* … */}
        main={
          <MyLocalComponent />
        }
      />
    </Viewport>
  )
}
// PanelsLayout.js

const MENU_PANEL_WIDTH = 300

function PanelsLayout({ menu, main }) {
  return (
    <div style={{ display: 'flex', width: '100%' }}>
      <div style={{ flexShrink: '0', width: `${MENU_PANEL_WIDTH}px` }}>
        {menu}
      </div>
      <div style={{ flexGrow: '1' }}>
        <Viewport
          name="main"
          size={([ width, height ]) => [ width - MENU_PANEL_WIDTH, height ]}
        >
          {main}
        </Viewport>
      </div>
    </div>
  )
}
// MyLocalComponent.js

function MyLocalComponent() {
  const viewport = useViewport()
  const mainPanelViewport = useViewport('main')

  // …
}

Finally, it might also be useful to declare the coordinates of these viewport. Rather than an array with two entries, we could accept an object containing the x and y coordinates. These would get returned by the useViewport() function as x and y, and be 0 for the global viewport.

Note: this feature would let us deprecate the useLayout() hook in aragonUI to use useViewport() directly.

@Evalir @sohkai let me know what you think!

@sohkai
Copy link

sohkai commented Mar 21, 2020

Another way would be to nest the ViewportProvider components.

I like this a lot! I think it makes total sense; at one point in the tree, you declare: "all children should use my dimensions as their viewport reference", which is very similar to the overall box model.

Because modals and etc. can still escape via portals or generic libraries working on the general viewport, I don't even think we need to have an "escape" mechanism.

Finally, it might also be useful to declare the coordinates of these viewport.

You wouldn't set these, but the component would read and update these based on its parent container's dimensions, right? So the intent wouldn't be to allow a component to declare "x: 30, y:100 is where the viewport starts"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants