kettanaito / atomic-layout

Build declarative, responsive layouts in React using CSS Grid.
https://redd.gitbook.io/atomic-layout
MIT License
1.13k stars 33 forks source link

React dependency #245

Open brucou opened 5 years ago

brucou commented 5 years ago

What:

Is it possible to remove the react dependency? Meaning are you using features that are specific to React to achieve this (by curiosity which?)? I wonder if this could be packaged in a web component, leveraging the native slot mechanism.

Why:

This would extend the audience of the component to other frameworks but more importantly vanilla-JS.

How:

I don't know about the underlying code for this component. However, the web component standard allows you to get components children as slots. You could use the slot name to indicate placeholding for the Thumbnail, Header, Footer components. Haven't given too much thoughts about that, but what I have in mind is something like this:

<Composition areas={areasMobile} areasMd={areasTablet} gap={20}>
        <slot name='Thumbnail'>
          <Thumbnail src={imageUrl} alt={title} />
        </slot>
        <h3><slot name-'Header' >{title}</slot></h3>
        <slot name='Footer' padding={10} paddingMd={20}>
          <Footer>...</Footer>
        </slot>
  </Composition>

The Stencil compiler may help along the way with some of that work.

kettanaito commented 5 years ago

Hello, @brucou. That's a good question.

I'll try to give a brief overview on this topic. Atomic Layout can be divided into three parts:

  1. Core. Deals with breakpoints calculations.
  2. Rendering. Renders actual elements in the DOM.
  3. Styling. Generates CSS from Responsive props.

I cherish an idea that the first part can live in a separate package, while two remaining would be parametric. I've tried to raise this in #57, yet it's more complicated than it seems. Although the core may be abstracted just fine, the rendering and styling libraries people may want usually have a different API.

I guess the most versatile solution would be to generate different packages for different frameworks (like Vue, Angular, or web components), while leaving the styling part parametric. That being said, this is nowhere in the list of my priorities at the moment. I'd like to get as much feedback on the existing API to improve it, before expanding Atomic Layout to different worlds.

Please, if you have any ideas on how Atomic Layout could work or be distributed in different environment, share them here. Pull requests are always welcome as well. If you decide to tackle this, I will support you with code reviews and share my knowledge on the library.

brucou commented 5 years ago

Thanks for the explanations. That helps.

Alright, I'll first try to figure out the logic. At first sight, I do believe it is possible to abstract out the rendering library. I don't really know about how styling could work, but both Svelte (dynamic styling possible with using css variables) and Stencil (using shadow-DOM when available) have scoped-CSS, and they compile down to standard JS, so that may be an avenue of investigation.

When I'll figure that out, I will have a better perspective on the effort or roadblocks related to an implementation with web components and we can take it from there.

kettanaito commented 5 years ago

Sounds awesome! I'll try to list the places where you can find rendering/styling parts.

Rendering

https://github.com/kettanaito/atomic-layout/blob/5b40cec2ab3d7803bd17a91c891a4e36d06d2184/src/components/Composition.tsx#L24

Composition is a heart and sould of the library's concept. Implementation-wise, it's a container element with display: grid that affects the direct children.

https://github.com/kettanaito/atomic-layout/blob/5b40cec2ab3d7803bd17a91c891a4e36d06d2184/src/components/MediaQuery.tsx#L33

MediaQuery itself is a wrapper that accepts media query description (props like maxWidth, minHeight, etc.) and returns a render prop with the matches argument, to which you can base your render. It uses native window.matchMedia() to resolve the predicate. It's used in the Placeholder component that wraps composition areas that are conditional.

https://github.com/kettanaito/atomic-layout/blob/5b40cec2ab3d7803bd17a91c891a4e36d06d2184/src/components/Only.tsx#L46

Only is a wrapper above given children that can be described as a smarter MediaQuery component. It only renders on match, and it uses the Placeholder component, so the relation between then three is:

Only -> Placeholder -> MediaQuery

https://github.com/kettanaito/atomic-layout/blob/5b40cec2ab3d7803bd17a91c891a4e36d06d2184/src/utils/templates/generateComponents/generateComponents.tsx#L24

A function that generates React components based on the given areas list (component name-template mapping). Since certain areas may be conditional (present only at certain breakpoints), it wraps such area components in the Placeholder component.

Pretty much all components exported by the library are React components. I don't see much parametrization happening here, as each framework/library uses its own API, which is often incompatible with the other one. Components are likely to be explicit per framework, which would also allow framework-specific features, like React Hooks present now.

Styling

https://github.com/kettanaito/atomic-layout/blob/5b40cec2ab3d7803bd17a91c891a4e36d06d2184/src/components/Box.tsx#L12

Box is lies in the core of styling, as most of the components inherit from Box. In practice it's a div (by default) that accepts Responsive props. Those are transformed into actual CSS properties later on in the applyStyles() function.

https://github.com/kettanaito/atomic-layout/blob/5b40cec2ab3d7803bd17a91c891a4e36d06d2184/src/utils/styles/applyStyles/applyStyles.ts#L42

A single place that generates CSS properties based on Responsive props. Resolves prop aliases to actual CSS properties (a single Responsive prop may have multiple corresponding CSS properties), and handles values transformations, as numeric prop values are suffixed with a default unit. Custom units, such as rem, if set, will be appended to numeric prop values instead.


This should give a basic idea. For feature-wise info please refer to the end-to-end tests, which are also usage examples.

brucou commented 5 years ago

Thanks for the additional information! I will let you know when I reach a conclusion,

kettanaito commented 4 years ago

As of 0.12.0 release Atomic Layout is split into two packages:

  1. @atomic-layout/core that contains all the core functionality (breakpoints calculations, styles generation). This _still depends on React).
  2. atomic-layout that contains components/hooks declarations, reusing the core library.

In the future, if we decide to make the library framework-agnostic, it would be a question to properly abstracting React-dependent parts in @atomic-layout/core, and adjusting "rendering" packages (like atomic-layout).

brucou commented 4 years ago

Artem, that's duly noted. I am still busy with writing a clone of the conduit app with my state machine library. But I already had a look with Svelte, and it looks a little bit more complicated than I thought, when it comes to styling. But I'll get back to it in 2020. Happy new year in advance!

Bruno Couriol Twitter: https://twitter.com/bricoi1

On Thu, Dec 26, 2019 at 10:59 AM Artem Zakharchenko < notifications@github.com> wrote:

As of 0.12.0 release Atomic Layout is split into two packages:

  1. @atomic-layout/core that contains all the core functionality (breakpoints calculations, styles generation). This _still depends on React).
  2. atomic-layout that contains components/hooks declarations, reusing the core library.

In the future, if we decide to make the library framework-agnostic, it would be a question to properly abstracting React-dependent parts in @atomic-layout/core, and adjusting "rendering" packages (like atomic-layout).

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kettanaito/atomic-layout/issues/245?email_source=notifications&email_token=AB3QEAJXFKDUK73BEZMHOV3Q2R6AZA5CNFSM4JJHY3T2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHVK5KA#issuecomment-569028264, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB3QEAPDPICCELXS46Y2KMTQ2R6AZANCNFSM4JJHY3TQ .