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

WP/Components with G2 Adapters #75

Open
ItsJonQ opened this issue Nov 3, 2020 · 9 comments
Open

WP/Components with G2 Adapters #75

ItsJonQ opened this issue Nov 3, 2020 · 9 comments

Comments

@ItsJonQ
Copy link
Owner

ItsJonQ commented Nov 3, 2020

Going with out Context System based integration strategy, we need to create a series of "adapters" to bridge the props/markup between the current WordPress components UI and the G2 components UI.

Using the Typography Design Tools as the potential G2 launch candidate/vehicle.. I've identified a list of components we need to pay attention to.

Note: (...) indicates sub-components

☀️ Required G2 Components

  • Animated (...)
  • ArrowIndicator
  • Button
  • Card (...)
  • Collapsible
  • ControlGroup
  • ControlLabel
  • Divider
  • Dropdown (...)
  • Elevation
  • Flex (...)
  • Grid
  • Heading
  • HStack
  • Icon
  • ListGroup (...)
  • Menu (...)
  • Panel
  • Scrollable
  • Select
  • Separator
  • Spinner
  • Subheading
  • Surface
  • Text
  • TextInput
  • Truncate
  • UnitInput
  • View
  • VStack

🌔 Existing WP Component equivalents

  • Animated (...)
  • Button
  • Card (...)
  • ControlGroup
  • Dropdown (...)
  • Flex (...)
  • Icon
  • Panel
  • Select
  • Separator
  • Spinner
  • Text
  • TextInput
  • UnitInput

If we want to bring the G2 Typography tools experience (in it's entirety), we'll need to ensure the above listed components (under 🌔) are 💯 adapted.

@ItsJonQ
Copy link
Owner Author

ItsJonQ commented Nov 5, 2020

Had a wonderful chat with @griffbrad today!

One of the things we talked about was this ContextSystem x Adapter strategy.
Brad had pointed out that these mechanics are similar to that of "feature flagging".

I thought that was a wonderful way to look at it.

Yes! Indeed. ContextSystem x Adapters enables use to "feature flag" our way to safely integrating G2 in Gutenberg 🎉

@ItsJonQ
Copy link
Owner Author

ItsJonQ commented Nov 6, 2020

📂 File/Code convention idea

Let's use the Button component as an example. Within Gutenberg, in the button/ component directory, we can add a next.js file:

/button
  |- index.js
  \- next.js

All of the logic and G2 Component "rigging" can happen in that file.

For example:

// components/src/button/next.js
import { withNextComponent as withNext } from '@wordpress/ui.context';
import { Button } from '@wordpress/ui.components';

function adapter(props) { ... }

export function withNextComponent(current) {
  // current - Current WP Button
  // Button - The G2 Component Button
  // 'WPComponentsButton' - Namespace to register into the Context System
  // adapter - Adapter to bridge the props between current Button -> G2 Button

  return withNext(current, Button, 'WPComponentsButton', adapter);
}

Finally, in the current Button index.js file, we just need to import this withNextComponent HOC and export the wrapped component.

import { withNextComponent } from './next';

function Button (props) { ... }

export default withNextComponent(Button);

With this technique, there's a clear division between:

  1. Existing Button code
  2. Bridge code (between old/new button)
  3. New Button code (lives in the G2 Components package)

@ItsJonQ
Copy link
Owner Author

ItsJonQ commented Nov 12, 2020

Chatted with @griffbrad today! In addition to the technical implementation, @griffbrad had suggested the idea having guides for developers. Developers who have existing 3rd party block code, and devs who want to build something brand new.

I don't think we necessarily need to write a details walkthrough/guide, at least not in the beginning. However, I think we should have a good solid sense of what the migration path would be like for both core and 3rd party devs.


Expanding a bit on the Context/HOC strategy above.

It seems like the current plan is to add the G2 packages into Gutenberg as separate packages (e.g. @wordpress/ui.components ... maybe).

This would certainly make it clearer which parts of the system you're working in (e.g. @wordpress/data).

The question is, should we globally export and expose the G2 component code?
So that @wordpress/ui.components/Button exports to window.wp.ui-components.Button.

I would say no.

I propose that G2 Components is surfaced throughout the project, as well as globally (window), via @wordpress/components.

There will be a (long) period where we'll have 2 component codebases.

Overtime, as we've completely migrated over to G2 Components, we'll be able to move the @wordpress/ui.components code into @wordpress/components, and move the current code into (maybe) into legacy.js files - similar to how G2 code exists in next.js files in the current integration proposal (above).

In short, G2 Components should ultimately become @wordpress/components.
We're just working out the details on how to do it :)

And these details should define and influence how we approach best practices and developer guidelines/tutorials.

@youknowriad
Copy link

It seems like the current plan is to add the G2 packages into Gutenberg as separate packages (e.g. @wordpress/ui.components ... maybe).

Why a separate package? I'd personally prefer a folder in the same package instead. This ensures it's organized properly and at the same time only exposed internally and not externally (through wp.*)

button example

In the Button example above, I believe it means we keep both components working right? How does one consumer switches? Also can't we instead remove the legacy component and have a "prop adapter" instead (rewriting props, triggering deprecations for deprecated props) but still use the G2 components for both usage?

@ItsJonQ
Copy link
Owner Author

ItsJonQ commented Nov 14, 2020

Why a separate package?

At the moment, G2 Components has about 8 primary packages (about 6 if you exclude packages that are basically dependency aliases):

  • animations (aka. framer-motion)
  • a11y (can be dropped for reakit)
  • components
  • context
  • create-styles
  • gestures (aka. react-use-gesture)
  • styles
  • substate
  • utils

I'd personally prefer a folder in the same package instead.

Just double checking. Is your suggestion for all of these packages to be moved directly into @wordpress/components?


For context, these packages do very different things (not unlike how many of the current @wordpress/* packages are split/organized).

It's also valuable to be able to use/share styles from certain G2 packages (like utils, state or styles) in code beyond the components package. Based on my experience with (current) Gutenberg and more recent experience with G2 Components, I'm very certain things that fall into the "Design Tools" category will benefit greatly from this shared code.

(e.g. Performant state management/syncing, unit parsing/serializing)


In the Button example above, I believe it means we keep both components working right?

Correct!


How does one consumer switches?

With this strategy, there are two primary ways to render the new Button.

Inline version prop:

<Button version="next">...</Button>

Or, with a ContextSystemProvider:

<ContextSystemProvider value={{ WPComponentsButton: { version: 'next' }}>
  ...
  <Button />
  ...
</ContextSystemProvider>

(Note: We can change the version prop to anything we want. That's just the prop I've chosen for my initial tests)


Also can't we instead remove the legacy component

Unfortunately not, mostly for style conflict reasons.

For example, the Button. It's being used in many (many) places, some of which have custom styling (e.g. Toolbar).

Replacing the current Button with the G2 Components Button won't break (JS) component rendering (assuming all props are adapted), but it would break CSS styling rendering.

Having the feature-flag like control of the ContextSystemProvider allows us to incrementally upgrade things while (hopefully) reducing unexpected side-effects (again, mostly from CSS related conflicts).

That being said, I'm 100% open to alternative strategies. This incremental context-based "chunking" migration strategy was something I've used in the past (with great success).


Hope this helps! Really appreciate your thoughts @youknowriad ! ❤️

@ItsJonQ ItsJonQ changed the title WP/Components to G2 Adapters WP/Components with G2 Adapters Nov 14, 2020
@youknowriad
Copy link

Just double checking. Is your suggestion for all of these packages to be moved directly into @wordpress/components?

I see, I think it seems there's value in these packages being separate (maybe not all, we'll have to see). The important thing though is that they stay as "bundled modules" (like @wordpress/icons and @wordpress/interface right now) to avoid having them leak as public APIs in WordPress.

for the components one (I guess the highest level one), I think we should avoid the temporary package and just use a folder in @wordpress/components to start with.

Inline version prop:

👌 I wonder if we should mark this prop as unstable, since it's only useful during the migration.

Unfortunately not, mostly for style conflict reasons.

So you're saying, once we migrate all buttons usage in our codebase, we can remove the old implementation. that seems reasonable.

@ItsJonQ
Copy link
Owner Author

ItsJonQ commented Nov 14, 2020

📁 Modules

The important thing though is that they stay as "bundled modules" (like @wordpress/icons and @wordpress/interface right now) to avoid having them leak as public APIs in WordPress

Wonderful! icons and interface are the ones that come to mind for how I'd imagine these G2 packages working - especially icons as those bits of code can be accessed in many other parts of the Gutenberg codebase.

💫 Combined Component Package

for the components one (I guess the highest level one), I think we should avoid the temporary package and just use a folder in @wordpress/components to start with

I'm open to that. Although, I think there's value in separating the newer G2 Components code in same way. If all of it goes into @wordpress/components, I feel like they should live in a directory labelled __next (or something similar).

Perhaps like this:

src/
├── button/
│	├── __next/
│	└── index.js
├── card/
│	├── __next/
│	├── (other files)
│	└── index.js
├── hstack/
│	└── index.js
└── etc...

I feel like the structure above can make code easier to find (since the G2 code is scoped locally to it's named directory), while encapsulating and signifying the "next" version of code that's being worked on.

In this above example, I've included HStack (one of the new layout-based primitive components), specifically because it currently doesn't exist within @wordpress/components.

For cases like this, I think it would be okay organize the files without using a __next/ directory.

⚛️ Version Prop

👌 I wonder if we should mark this prop as unstable, since it's only useful during the migration.

I'm happy with that :). I think using __unstableVersion (or something similar) is a good signifier that stuff is being updated.

🧹 Cleaning up the Old Implementation

So you're saying, once we migrate all buttons usage in our codebase, we can remove the old implementation.

That's my hope 🙏 . That these G2 Components eventually become @wordpress/components.
Since we can migrate things incrementally, that means that we can also remove the old implementation incrementally as well - rather than waiting for the day were we remove all of the old code in one-shot (which, we can do if that's a better strategy).

Once all of the previous implementation is removed, all that remains of it are the (now) legacy component APIs.

At that point, we can decide if we want to deprecate these component APIs in favour of newer ones that make sense to the ecosystem.

@ItsJonQ ItsJonQ added this to the Prep: Gutenberg Migration milestone Nov 16, 2020
@ItsJonQ
Copy link
Owner Author

ItsJonQ commented Nov 16, 2020

cc'ing @saramarcondes

@ItsJonQ
Copy link
Owner Author

ItsJonQ commented Nov 17, 2020

Related:
#123

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

No branches or pull requests

2 participants