grapp-dev / stacks

A set of components for building layouts in React Native. Powered by React Native Unistyles.
https://stacks.grapp.dev
MIT License
982 stars 24 forks source link

Inline and Stack + horizontal won't let their children grow #16

Closed jsamr closed 3 years ago

jsamr commented 3 years ago

Description

Children of Stack (+ horizontal prop) and Inline components with a flexGrow: 1 style won't grow horizontally.

Minimal, Reproducible Example

import * as React from 'react';
import {Text, View} from 'react-native';
import {Stack, Inline, StacksProvider} from '@mobily/stacks';

function HorizontalStackSample() {
  return (
    <Stack space={0} horizontal style={{flexGrow: 0, backgroundColor: 'gray'}}>
      <View style={{width: 40, height: 100, backgroundColor: 'red'}} />
      <View style={{flexGrow: 1, height: 100, backgroundColor: 'purple'}} />
    </Stack>
  );
}

function InlineSample() {
  return (
    <Inline space={0} style={{flexGrow: 0, backgroundColor: 'gray'}}>
      <View style={{width: 40, height: 100, backgroundColor: 'red'}} />
      <View style={{flexGrow: 1, height: 100, backgroundColor: 'purple'}} />
    </Inline>
  );
}

function HorizontalViewSample() {
  return (
    <View style={{flexGrow: 0, backgroundColor: 'black', flexDirection: 'row'}}>
      <View style={{width: 40, height: 100, backgroundColor: 'red'}} />
      <View style={{flexGrow: 1, height: 100, backgroundColor: 'purple'}} />
    </View>
  );
}

export default function App() {
  return (
    <StacksProvider spacing={5}>
      <Text>
        Horizontal Stack, expected to display a red box of width 40, and a
        purple box spanning the remaining horizontal space.
      </Text>
      <HorizontalStackSample />
      <Text>
        Inline, expected to display a red box of width 40, and a purple box
        spanning the remaining horizontal space.
      </Text>
      <InlineSample />
      <Text>
        Horizontal View, expected to display a red box of width 40, and a purple
        box spanning the remaining horizontal space.
      </Text>
      <HorizontalViewSample />
    </StacksProvider>
  );
}

image

Test conditions

PS: Your project is awesome!

mobily commented 3 years ago

Children of Stack (+ horizontal prop) and Inline components with a flexGrow: 1 style won't grow horizontally.

@jsamr 👋 , flexGrow will not work in this case, since all inner elements are wrapped into View components (see: Stack and Inline) and you can't control them, you may want to use either a combination of Columns and Column: https://codesandbox.io/s/issue-16-1-lej4n?file=/src/App.js

or simply with Box (if you don't need spacing between inner elements): https://codesandbox.io/s/issue-16-2-teqv5?file=/src/App.js (however, it looks the same as HorizontalViewSample)

PS: Your project is awesome!

thank you, I really appreciate that! ❤️

jsamr commented 3 years ago

@mobily An other approach would be to use cloneElement and just add the generated styles to the style prop... what do you think?

jsamr commented 3 years ago

Something like this:

// Does it act like React.Children.map?
Belt.Array.mapWithIndexU(children, (index, child) => {
  // test child is an element first
  if (typeof child === "string") {
    throw new Error("...");
  }
  return React.cloneElement(
    child,
    {
      ...child.props,
      style: [
        child.props.style,
        Style.arrayOption([
          width,
          resolveAlignItemsX(align),
          debugStyle,
          isLast(index) ? None : Some(marginFn(space)),
        ]),
      ],
    }
  );
});
mobily commented 3 years ago

@jsamr the initial implementation of Stacks components was based on cloneElement but unfortunately, it had performance issues (for instance in conjunction with React Native SVG elements) and I'd rather avoid using cloneElement (also, in ReScript cloneElement is useful only for interoping with JS modules, and it isn't recommended to use in ReScript components body)

anyway, the horizontal prop is still sort of "experimental", and I believe, there is room for improvements :)

jsamr commented 3 years ago

@mobily OK, thanks for this clarification :-) I guess it's a pitfal worth mentioning in the docs! Keep up with the good work :rocket: