Open ItsJonQ opened 3 years ago
Ohhh boy! Some fun updates. I just prototyped out the initial feature set + component API for <FlatList />
.
It's inspired very heavily on React Native's implementation as well as List
from Swift UI.
Demo:
Live Demo: https://g2-components.xyz/?path=/story/components-flatlist--default
More importantly... check out the code!!!!
const Example = () => {
const [users, setUsers] = useFlatListState(userSchema.make(10));
const addUser = () => setUsers.prepend(userSchema.makeOne());
const deleteUser = (id) => setUsers.delete({ id });
const moveUser = (from, to) => setUsers.move(from, to);
return (
<HStack>
<FlatList
css={{ maxWidth: 400 }}
onMove={(from, to) => moveUser(from, to)}
>
<HStack alignment="edge">
<Button onClick={addUser} variant="primary">
Add User
</Button>
<EditButton />
</HStack>
<FlatListItems>
{users.map((user, index) => {
return (
<FlatListItem
css={{ padding: 12 }}
key={user.id || index}
onDelete={() => deleteUser(user.id)}
>
<HStack alignment="left" spacing={3}>
<Avatar src={user.avatar} />
<Spacer>
<VStack spacing={1}>
<Text size={14} weight="bold">
{user.name}
</Text>
<Text
numberOfLines={2}
size={12}
truncate
variant="muted"
>
{user.description}
</Text>
</VStack>
</Spacer>
</HStack>
</FlatListItem>
);
})}
</FlatListItems>
</FlatList>
</HStack>
);
};
FlatList
can detect if editing is enabled via a prop or the presence of an <EditButton />
onMove
callback enables sortingonDelete
callback enables deletinguseFlatListState
is an enhanced useState
, with convenient + common array methods like add
, delete
, move
, etc...Nicely gelatinous animation, love it!
We use a mover control (up/down arrow) in many places, not just blocks but in the block navigator as well. This is based on the idea that drag and drop is additive to explicit button actions. Do you have any thoughts on how to best handle that?
@jasmussen Haii!! I'm not sure yet! We could offer arrows along side the drag handle.
(Feel free to share design ideas if you have any!)
Or maybe.. we could offer a "mode" where the user can prefer drag handles, mover arrows, or both?
This could be a preference like dark mode, etc...
We could offer arrows along side the drag handle.
It does become a lot, but it also seems necessary. I'd probably just use the two-line drag handle that the block editor uses.
Or maybe.. we could offer a "mode" where the user can prefer drag handles, mover arrows, or both?
If we were to offer a mode, I'd think it was a toggle of the mover control, not drag & drop vs. arrows. For example exactly as shown in this gif, you enter and exit a rearranging "mode".
User options remain a plan B, but even then we'd want to choose a default option, and it would have to be the one that balances the accessibility aspect best.
More ideas on list types + interactions: https://material.io/components/lists#types
I feel that it's important that G2 provides some sort of "FlatList" component (even if it's a basic one).
(Drawing inspiration from the world of native development...)
What's a FlatList?
FlatLists are a feature-rich and high-performant way to render collections of things.
Features
Below are some of the very helpful features that a FlatList component should offer out-of-the-box (speaking purely from a web-based context)
What's it look like?
From a visual UI perspective, FlatLists can resemble many forms. The most familiar example, would be something like this:
The above example is typical of a "Contact List" in contact/messaging-based applications.
Stepping away from mobile....
In Gutenberg, the Block Inserter sidebar can be imagined as a FlatList:
From the G2 storybook, the following would use a FlatList as well:
https://g2-components.xyz/?path=/story/examples-blocks--layout-grid
It's usefulness extends beyond just the Editor UI. 3rd party block authors, plugin authors, and others can use this component as a way to add "native" (editor) support to their data collections.
What's the code going to look like?
I don't think it is necessary to replicate the exact API interfaces from React Native's FlatList. To start, I think it should have some basic props, like...
Also a way to enable programatic sortTo... methods.
We can try to recreate the BlockInserter as a starting test case!