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

React dependency #245

Open
brucou opened this issue Nov 5, 2019 · 6 comments
Open

React dependency #245

brucou opened this issue Nov 5, 2019 · 6 comments

Comments

@brucou
Copy link

brucou commented Nov 5, 2019

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
Copy link
Owner

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
Copy link
Author

brucou commented Nov 6, 2019

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
Copy link
Owner

kettanaito commented Nov 6, 2019

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

Rendering

const Composition: React.FC<CompositionProps> = ({

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.

const MediaQuery: React.FC<MediaQueryProps> = (props) => {

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.

const Only: React.FC<OnlyProps> = ({

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

const Placeholder: React.FC<GenericProps> = ({ children, ...restProps }) => {

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

const Box: React.FC<BoxProps> = styled.div<BoxProps>`

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.

export default function applyStyles(pristineProps: Props): string {

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
Copy link
Author

brucou commented Nov 8, 2019

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

@kettanaito
Copy link
Owner

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
Copy link
Author

brucou commented Dec 26, 2019 via email

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

No branches or pull requests

2 participants