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

Add Position components #202

Merged
merged 25 commits into from
Aug 15, 2018
Merged

Add Position components #202

merged 25 commits into from
Aug 15, 2018

Conversation

shawnbot
Copy link
Contributor

@shawnbot shawnbot commented Aug 8, 2018

This introduces first-class components for positioning:

  • Position is the "base" component, and provides position, top, right, bottom, and left props.
  • Absolute is an implementation of Position that always sets position="absolute"
  • Relative is an implementation of Position that always sets position="relative"
  • Fixed is an implementation of Position that always sets position="fixed"
  • Sticky is an implementation of Position that always sets position="sticky"

There are tests for Absolute, Relative, Fixed, and Sticky that ensure each always gets styled as position: <value>, even when provided a different position prop. I've deleted position from both defaultProps and propTypes for each of these because they always get that value, and it can't be changed.

💥 ⚠️ This PR also renames the CaretBox component to PointerBox, which now (unconditionally) gets position: relative. This means that to absolutely position a PointerBox, for example, you would need to wrap it in <Absolute>.

Here's an example of a dropdown (select menu?) implemented with these components. You can paste the following example into the sandbox to see how it works:

<Relative>
  <Details>
    <Button is="summary">Yo</Button>
    <Absolute left={0} top="100%" mt={1}>
      <PointerBox caret="top-left" p={3} boxShadow="medium">
        Hi there
      </PointerBox>
    </Absolute>
  </Details>
</Relative>

(You can add open mb={64} to the <Details> above if you want to see what it looks like open — without having to click it each time — and not overlapping the live editor.)

@emplums emplums mentioned this pull request Aug 8, 2018
12 tasks
@shawnbot shawnbot changed the base branch from release-1.0.0-beta to master August 8, 2018 21:41
@shawnbot
Copy link
Contributor Author

shawnbot commented Aug 8, 2018

We chatted about this in Slack today and agreed that CaretBox should wrap its children in a <Position> rather than using is:

<Position position={position}>
  <Box {...boxProps}>
    {children}
    <Caret {...caretProps} />
  </Box>
</Position>

There are a couple of problems with this.

  1. When the Box doesn't have relative positioning, the caret is positioned outside of its border-box rather than inside:

    image

  2. When you add a maxWidth or otherwise size the Box, the relative positioning of the caret is off:

    image

  3. We have to programmatically pass margin props to the Position and padding props to the Box, which gets ugly quickly.

My proposed fix for this is not to render a <Box> (soon to be <BorderBox>) in the CaretBox component at all, but just to spread Box.defaultProps into Caret.defaultProps so that it gets box styling by default:

function CaretBox(props) {
  const {bg, border, borderColor} = props
  const {caret, children, ...boxProps} = props
  const caretProps = {bg, borderWidth: border, borderColor}
  return (
    <Position {...boxProps}>
      {children}
      <CaretBox {...caretProps} />
    </Position>
  )
}

CaretBox.defaultProps = {
  ...Position.defaultProps,
  ...Box.defaultProps,
  position: 'relative'
}

@shawnbot shawnbot changed the title Add Position components [WIP] Add Position components Aug 8, 2018
@broccolini
Copy link
Member

My proposed fix for this is not to render a (soon to be ) in the CaretBox component at all, but just to spread Box.defaultProps into Caret.defaultProps so that it gets box styling by default

This seems reasonable to me. Could you add an example of what the public api would look like with a common use-case example?


One thing that we talked about in the past is "caret" is the wrong name for this, caret is the name of the triangle icon usually shown in dropdowns etc. This can be a follow-up pr but we should rename this to "PointerBox" or something.

@shawnbot shawnbot changed the base branch from master to release-2.0.0-beta August 14, 2018 23:23
@shawnbot
Copy link
Contributor Author

Thanks, @broccolini! In e53aa08 I merged @emplums Block → + Box → BorderBox work and updated CaretBox accordingly. I like the name PointerBox better than CaretBox, and can update that in another commit.

@shawnbot shawnbot changed the title [WIP] Add Position components Add Position components Aug 14, 2018
@shawnbot
Copy link
Contributor Author

Okay, this is ready for review! 🤞

Copy link
Member

@jonrohan jonrohan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I expected the <Position component would look like. I think it looks good. 💯

@shawnbot
Copy link
Contributor Author

TODO: don't make PointerBox render a Position; instead, have it always be position: relative.

@shawnbot shawnbot merged commit ae87f4d into release-2.0.0-beta Aug 15, 2018
@shawnbot shawnbot deleted the position-components branch August 15, 2018 22:43
This was referenced Aug 15, 2018
@shawnbot shawnbot mentioned this pull request Aug 24, 2018
8 tasks
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

Successfully merging this pull request may close these issues.

3 participants