akveo / react-native-ui-kitten

:boom: React Native UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/react-native-ui-kitten/
MIT License
10.34k stars 956 forks source link

πŸ“ [Sticky] UI Kitten 5.0 Discussion & Roadmap #896

Closed artyorsh closed 4 years ago

artyorsh commented 4 years ago

This is a communication-open issue indicating version 5.0 roadmap. Yes, we're going to skip future 4.x releases since it will introduce some breaking changes πŸ’£

Our plan is:

Features

For now, we realize that background-basic-color-1 looks like a magic string. And that's why we should describe all theme variables exported from Eva and describe how and where they're used and where not.

Bug Fixes

Refactoring

We're going to add support of passing Component classes as well as Functional components to component props. A good example for this is a title property of TopNavigation component which more likely can include an Image.

This should close the following issues: #564 #737 #777 #810 #863

Currently, we're investigating this feature and looking for a good architecture solution. If you have any suggestions, feel free to mention them in the discussion.

Migration


⚠️

We're not going to include more feature requests in 5.0. In this discussion, we accept proposals regarding the features described above.

Please open a new issue if you have a feature request or questions regarding the current API in order to help us keep this conversation clean.

artyorsh commented 4 years ago

TopNavigation syntax proposal

Idea

We should be able to pass any component to title property. Also, leftControl and rightControls properties can be replaced with this suggestion to resolve same problem.

What does it resolve

This will help use resolve #777 and potentially #863. Also, as for maintainers, this will let us remove several properties like titleStyle or descriptionStyle because it will be handled by developers.

Examples

  1. TopNavigation with title and image
const Title = (evaProps) => (
  <React.Fragment>
    <Image source={require('./logo.png')}
    <Text style={...evaProps, ...myCustomStyle} {...someOtherCustomProps}>Title</Text>
  <React.Fragment/>
);

const Header = () => (
  <TopNavigation title={evaProps => <Title {...evaProps}/>} />
);

// Even better with inline syntax
//  <TopNavigation title={Title} /> 
  1. TopNavigation actions
const BackIcon = (evaProps) => (
  <Icon {..evaProps} name='arrow-ios-back' />
);

// Why not to use a `ghost` Button instead of TopNavigationAction?

const BackButton = (evaProps) => (
  <Button {...evaProps} appearance='ghost' accessoryLeft={BackIcon}>BACK</Button>
);

const Header = () => (
  <TopNavigation accessoryLeft={evaProps => <BackButton {...evaProps} />} />
);

// Even better with inline syntax
// <TopNavigation accessoryLeft={BackButton} />
artyorsh commented 4 years ago

Replaceicon properties with something more generic

Idea

We can replace icon properties of all components with something more generic, e.g accessoryLeft and accessoryRight so that these properties can accept any component.

What does it resolves

This will help us resolve #564 and #737.

Examlples

  1. This should render a Button with Icon, like it works currently. Also, we can use accessoryLeft to render icon at the left (currently can be achieved with flexDirection: 'row-reverse')
const StarIcon = (evaProps) => (
  <Icon {...evaProps} name='star' />
);

const IconButton = () => (
  <Button accessoryRight={StarIcon} />
);
  1. This should render a Button with any other component, e.g Spinner.
const Loader = (evaProps) => (
  <Spinner {...evaProps ...customStyle} {...customProps} />
);

const LoadingButton = () => (
  <Button accessoryRight={evaProps => <Loader {...evaProps}/>} />
);

// Even better with inline syntax 
// <Button accessoryRight={Loader} />
  1. This should render an Input with left and right icons
const ClearIcon = (evaProps) => (
  <Icon {...evaProps ...customStyle} {...customProps} name='clear' />
);

const SearchIcon = (evaProps) => (
  <Icon {...evaProps ...customStyle} {...customProps} name='search' />
);

const SearchInput = () => (
  <Input 
    accessoryLeft={evaProps => <SearchIcon {...evaProps} />}
    accessoryRight={evaProps => <ClearIcon {...evaProps}/>}
   />
);

// Even better with inline syntax
// <Input accessoryLeft={SearchIcon} accessoryRight={ClearIcon} />
artyorsh commented 4 years ago

Potentially affected components

Resuming the ideas above, the following components can be potentially affected, but not bring breaking changes.

With the new syntax, the properties described for each component below should be able to accept Class components, Functional components, and meaningful primitives like strings or numbers (depending on property meaning).

artyorsh commented 4 years ago

New syntax example

v4 Input

You can render only a Text inside label property.

<Input 
  label='Movies'
  labelStyle={{ color: 'red' }}
/>

v5 Input

You can render anything inside label property, but labelStyle will be deprecated.

<Input label='Movies' /> // Let Eva handle stylings

// OR let me customize it

const Label = (props) => (
  <Text {...props} style={[props.style, { color: 'red' }]}>Movies</Text>
);

<Input label={Label} />
focux commented 4 years ago

I can't wait for the V5. Also, can we add a prop to the Icon component to change his color?

Edit. I just saw that there's an undocumented property called fill to do that. Anyways, thank you for your work and I'm really excited about this new version.

artyorsh commented 4 years ago

@focux there is no need to do this. An Icon accepts fill to change it's color in case you use it with @ui-kitten/eva-icons package (which renders svg and accepts svg props). You may also make it render Image and pass tintColor within style property, like it is described in the guide.

artyorsh commented 4 years ago

Combine styled and withStyles injected properties into one

We can combine properties injected by styled and withStyles function into one, called eva. This may help us control passing ...restProps to the root components and avoid Invalid prop *** warnings. Should resolve #669 and #884.

withStyles Example

const MyComponent = ({ eva, ...props }) => (
  <View {...props} style={[eva.themedStyle.container, props.style]} />
);

export const MyStyledComponent = withStyles(MyComponent, theme ({
  container: { backgroundColor: theme['background-basic-color-1'] },
}));

styled Example

const MyComponent = ({ eva, ...props }) => {

  const onPressIn = () => {
    eva.dispatch([Interaction.ACTIVE]);
  };

  return (
    <TouchableOpacity {...props} onPressIn={onPressIn} />
  );
};

export const MyStyledComponent = styled(MyComponent);
artyorsh commented 4 years ago

Select syntax

const MySelect = () => (
  <Select selectedIndex={selectedIndex} onSelect={setSelectedIndex}>      
    <SelectGroup title='Group 1'>     
      <SelectItem title='Option 1.1'/>
      <SelectItem title='Option 1.2'/>
    </SelectGroup>                    
    <SelectGroup title='Group 2'>     
      <SelectItem title='Option 2.1'/>
      <SelectItem title='Option 2.2'/>
    </SelectGroup>                    
  </Select>                           
);

Same would be available for Drawer and Menu components

sudomann commented 4 years ago

In my opinion your Button component should conform to react-native's Button such that the text is passed through the title prop and not as a child.

artyorsh commented 4 years ago

Upcoming changes can be found in PR Changelog

sudomann commented 4 years ago

Oh what about making input icons have a visual response when pressed?

artyorsh commented 4 years ago

@sudomann we can't handle this because there are multiple icon types, e.g react-native-vector-icons, that for any reason come with it's own press handler. However, in v5, you will be able to put any component there, e.g ghost button.

AdamChrist commented 4 years ago

Support import individual components on demand.

When we create a new project by npx react-native init MyApp --template @ui-kitten/template-js . By using react-native-startup-time, you can see that the app startup time is about 2000 ms. If you create an app through npx react native init, the startup time is about 500ms. (android)

The reason is that when we import ApplicationProvider, we actually import all the modules, hoping to optimize the way of importing modules in order to optimize the APP startup time.

artyorsh commented 4 years ago

@AdamChrist

The reason is that when we import ApplicationProvider, we actually import all the modules, hoping to optimize the way of importing modules in order to optimize the APP startup time.

This is not the reason of increased startup time. Check this guide

rdewolff commented 4 years ago

Thanks for all the great works and detailed changelog.

Is there a ETA for the 5.0.0 version ? Even a rough estimation. Is it more likely to come in 2-3, 2-3 months or 2-3 years? :)

rdewolff commented 4 years ago

ping ?

artyorsh commented 4 years ago

@rdewolff v5 stable will come during the next two weeks. I plan to close several known issues before the version update (you can track it in #1055). This version will not include new components unfortunately.

rdewolff commented 4 years ago

Thanks for the update! Looking forward!

gatoasang94 commented 4 years ago

Time Picker please :(

fortezhuo commented 4 years ago

AutoComplete is great component. But I think Autocomplete can be extended for :

  1. Support multiple value using tags / Chips
  2. Support adhoc value, so user can input external value if not exist

Other components like Table, Accordion, etc like https://www.akveo.com/ngx-admin/pages/dashboard will be great if can be provided.

lukeramsden commented 4 years ago

List and ListItem aren't typed properly like FlatList is, would be nice to have that fixed before V5 is pushed.