Giter Club home page Giter Club logo

festival's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

festival's Issues

on style cascading

Can you guess what's the color of this without looking at browser:

<div className="bg-red bg-blue" />

It depends on CSS's definition order, which is not guaranteed by Tailwind (and that's a good thing).

What should be done is to be sure one type of attribute can only be set at most once. In other words, use JS or whatever to ensure there is only one "bg-foo" at the final result

JS Modules for components

When designing and using React components, we usually need to export and import more than just the component itself. For example, we may want to import the interface of a prop (e.g., button's color) or its implementations/options (e.g., the "primary" color for a button).

This page describes our expectations, several approaches, and what we believe is the optimal solution to export and import React components as JS modules (for now).

Expectations

We should choose an approach that:

  • Increase the discoverability of a component (e.g., what props are there and what are their options).
  • Increase the ease for a new engineer to understand the approach (i.e., it's not too far/strange from the outside world).
  • Decrease naming conflicts when importing props with same name from several components (e.g., button's color and tag's color).

Approaches

Although there are only 2 types of export in JavaScript (default and named), there are many ways (in term of syntax) to export and import from a module. Here we only discuss the most prominent ones:

A. All are named without prefix

// Button.ts
export interface Color { light: string; dark: string; }
export const Colors: { [key: string]: Color } = { /* ... */}
export const Component = ({ color: Color }) => (/* ... */);
// Foo.tsx
import * as Button from "@dvkndn/core/button";
import * as Tag from "@dvkndn/core/tag";
<Button.Component color={Button.Colors.Primary} />

B. All are named with prefix

// Button.ts
export interface ButtonColor { light: string; dark: string; }
export const ButtonColors: { [key: string]: Color } = { /* ... */ };
export const Button = ({ color: Color }) => (/* ... */);
// Foo.tsx
import { Button, ButtonColors } from "@dvkndn/core/button";
import { Tag, TagColors } from "@dvkndn/core/tag";
<Button color={ButtonColors.Primary} />

C. Component is default, others are named without prefix

// Button.ts
export interface Color { light: string; dark: string; }
export const Colors: { [key: string]: Color } = { /* ... */ };
export default ({ color: Color }) => (/* ... */);
// C1. Alias import
// Foo.tsx
import Button, { Colors as ButtonColors } from "@dvkndn/core/button";
import Tag, { Colors as TagColors } from "@dvkndn/core/tag";
<Button color={ButtonColors.Primary} />
// C2. Namespace import
// Foo.tsx
import Button, * as button from "@dvkndn/core/button";
import Tag, * as tag from "@dvkndn/core/button";
<Button color={button.Colors.Primary} />

Current solution

  • Speaking of discoverability, A is better than B and C:
    • In A, users can see all exports at every occurrence of Button
    • In B and C1, the exports can only be suggested at the import statement. The "auto import" of some editors may not be able to help here (to discover ButtonColors).
    • in C2, exports may be found at occurrences of button but this is obviously not as good as A
  • Speaking of learning curve, C is the most common approach.
    • A and B are less common because in most systems the API of components are quite simple and only export the component itself.
    • However, these are all standard methods and any engineer should be able to understand how they work in no time.
  • Speaking of naming in importing, both A and B are better than C:
    • A is good because of the enforcement of namespace imports, having a nice, concise import statements.
    • B is good because all definitions are globally unique in the first place, thus make the import easier, but could easily lead to long, repetitive import statements (e.g., import { FooA, FooB, ..., FooX }).
    • C is not really good as users must always do extra work to avoid naming conflicts, either via alias or via namespace (more work comparing to A).

Therefore, for now, we prefer the approach A.

References

on variables sharing

Don't use @apply. They are unnecessarily complicated and can be solved easier with native solution: CSS variables. For example:

:root {
  --color-red: #123456
}

to use in tailwinds:

red: "var(--color-red)",

to use outside of tailwind:

body {
  color: var(--color-red);
}

Accessing ref of consumers

Some components need to have a reference to a DOM element created by their consumers. For example, a Popover component needs to know its target's DOM element's position to render the content next to it:

w

We are going to consider 3 approaches:

1. Ref is handled by the consumers

<Popover content={<Content />}>
  {(ref) => (
    <Button ref={ref}>Click me</Button>
  )}
</Popover>

Result:

<button>Click me</button>

Pros:

  • Declarative.
  • Maintain the DOM order.

Cons:

  • Not so much convenience.
  • Target component must handle a ref props.

2. Wrap target with an element ex: span

and then ref to that span element

<Popover content={<Content />}>
  <Button ref={ref}>Click me</Button>
</Popover>

Result:

<span>
  <button>Click me</button>
</span>

Pros:

  • Convenience

Cons:

  • DOM order is not changed. Might lead to unexpected results.

3. Find a the DOM that created from target's React Component

<Popover content={<Content />}>
  <Button ref={ref}>Click me</Button>
</Popover>
<button>Click me</button>

Pros:

  • Convenience.
  • DOM structure is not changed.

Cons:

  • Target element must be ref-able (a valid DOM).

How: Using ReactDOM.findElement().

Thought

On the Popover case, I think Solution #3 is should fit the most, since it maintain the DOM order also the convenience for library user.

on components accepting className

This is a valid usage, but can you guess what will be the background color of the Button:

<Button className="bg-success-4" type="danger" />

In general, inheriting class names, although common, is not a good practice. It allows consumers of Button to change Button's internal attributes (background, font size) while the author of Button would have no idea about this.

This is a burden, since the author may be limited in improving the Button, since they don't know what are all of the cases that may break.

In practice:

  • If the styles are external (e.g. margin) then they should be set to a wrapper
  • If the styles are internal (e.g. color) then they should be set by Button itself, customized via props

on tailwinds (and others)

Web Styling (Draft)

  • CSS
    • Convention: SMACSS, BEM, OOCSS
    • Framework: Bootstrap, Foundation, Bulma, Tachyons
    • Generator: Tailwinds
    • Shadow DOM
  • CSS-in-JS
    • Run-time: Styled Components, Emotion
    • No run-time: Linaria, Astroturf
  • CSS preprocessing
    • SASS, Less
    • PostCSS
    • CSS Modules, CSS Blocks, Stylable
    • Vue's single file components

document.tags.H1.fontSize = "20pt";

IDO dream

  • Modular
  • Dynamic
  • Performant
  • CSS capatibilities
  • Tooling
  • Customisation

CSS is not designed to be a programming language

https://jxnblk.com/blog/why-you-should-learn-css-in-js/
https://mxstbr.com/thoughts/css-in-js/
https://noti.st/brucelawson/5O0d81#sQH4abT
https://csswizardry.com/2014/10/the-specificity-graph/
https://css-tricks.com/the-fragmented-but-evolving-state-of-css-in-js/
https://css-tricks.com/bridging-the-gap-between-css-and-javascript-css-modules-postcss-and-the-future-of-css/
https://css-tricks.com/the-differing-perspectives-on-css-in-js/
https://css-tricks.com/the-many-ways-to-include-css-in-javascript-applications/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.