Coder Social home page Coder Social logo

aesthetic-suite / framework Goto Github PK

View Code? Open in Web Editor NEW
203.0 6.0 5.0 6.97 MB

๐ŸŽจ Aesthetic is an end-to-end multi-platform styling framework that offers a strict design system, robust atomic CSS-in-JS engine, a structural style sheet specification (SSS), a low-runtime solution, and much more!

Home Page: https://aestheticsuite.dev

License: MIT License

JavaScript 4.11% CSS 0.01% HTML 1.69% TypeScript 86.78% EJS 7.41%
react css css-in-js design-system web android ios atomic-css low-runtime

framework's People

Contributors

alphy11 avatar dependabot[bot] avatar ifndefdeadmau5 avatar milesj avatar

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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

framework's Issues

Migration guide

Some points.

  • theme prop may be optional now, assuming previous types weren't optional.
  • advanced selectors must be moved to @selectors.
// Before
{
  ':first-child': {},
  '::-moz-focus-inner': {}
  ':not([disabled]):hover': {},
}

// After
{
  ':first-child': {},

  '@selectors': {
    '::-moz-focus-inner': {}
    ':not([disabled]):hover': {},
  },
}
  • @keyframes is no longer definable within a component.
// Before
{
  '@keyframes': {
    fade: {
      from: {},
      to: {},
    },
  },

  element: {
    animationName: 'fade',
  },
}

// After
{
  element: {
    animationName: {
      name: 'fade',
      from: {},
      to: {},
    },
  },
}
  • @font-face is no longer definable within a component.
// Before
// Before
{
  '@font-face': {
    Roboto: {
      src: 'url()',
    },
  },

  element: {
    fontFamily: 'Roboto',
  },
}

// After
{
  element: {
    fontFamily: {
      src: 'url()',
      fontFamily: 'Roboto',
    },
  },
}

RFC: The future, a design system framework

History & Present

Aesthetic was built around the time that CSS-in-JS solutions were rising in popularity. It was
designed to bridge the gap between current CSS-in-JS libraries and React components, and was not
meant to be yet another CSS-in-JS library. As such, Aesthetic offers the adapter pattern where
CSS-in-JS libraries are plug-and-play, while not handling the CSS itself.

Besides the above mentioned, Aesthetic aimed to solve the following problems that plagued libraries
and applications.

  1. CSS-in-JS libraries require different syntax for defining styles. This could be problematic when
    switching libraries (for performance or other reasons), as the syntax differs, and would require
    a potential massive migration (and ejection if a failure). To mitigate this, Aesthetic implements
    a "unified syntax", where the same syntax works
    for all adapters.
  2. The other issue that a unified syntax solves is third-party library adoption. If library A styles
    their components with Aphrodite, and library B styles theirs with Fela, then we have 2 differing
    and conflicting libraries. This would increase bundle size, reduce interoperability, and more. If
    both A and B libraries were instead written in Aesthetic, then the underlying adapter (Aphrodite
    or Fela) can be swapped out without breaking compatibility or increasing bundle sizes.

Outstanding issues

For the most part, Aesthetic works and serves its purpose pretty well. However, it's not perfect,
and could use a rewrite to solve the following issues.

Themes are too dynamic

There is no set structure for theme objects, and as such, they cannot be typed safely, nor can they
be trusted when interoping with third-party libraries. For example:

// Registered in an application
aesthetic.registerTheme('app-light', {
  colors: {
    white: '#fff',
  },
  unit: 8,
});

// Registered in a library
aesthetic.registerTheme('3rd-party-dark', {
  color: {
    black: ['#000'],
  },
  spacing: 4,
});

In the above example, an application and a third-party library may register a theme, completely
independent of each other, with differing structures (unit vs spacing, etc). When used in
parallel, components will break when themes change, as the following styles would only work under
one theme, not both.

useStyles(theme => ({
  padding: theme.unit * 2,
}));

This actually breaks interoperability and the 2nd adoption problem above. This was a massive
oversight on my end when designing the theme layer.

Global styles are complicated to manage

Global styles are primarily applied to html, body, and a, for global inheritance of colors,
spacing, and font sizing. This works flawlessly until one of the following occurs:

  • Rendering parallel themes using the React ThemeProvider component. When this happens, the global
    styles in the next theme to compile will overwrite the previous theme. I'm not sure there's a way
    to solve this correctly.
  • Dynamically change themes for the entire page, usually through a toggle switch or dropdown. When
    this happens, we can easily purge/delete all existing styles in the document. However, in
    practice, this is only true if the CSS-in-JS adapter that is currently configured supports it,
    which most do not (will require upstream patches).

Component styles are hard to customize

Take the following style sheet for a Button, where it has a primary background with a 1px border
(dark blue), and a base text color (white). Seems straight forward right?

useStyles(({ color }) => ({
  button: {
    border: `1px solid ${color.primary[4]}`,
    backgroundColor: color.primary[3],
    color: color.base,
  },
}));

Not really. It's actually very restrictive, isolating, and hard to customize. The above works well
for the theme it was initially designed for, in this instance, a "light" theme. But what happens
when we change it to a dark theme?

  1. First, the indices are reversed, so 0 is darkest and 10 is lightest. Depending on the
    component, this will look great, or it will look terrible, and there's no way to change it based
    on theme
    , since the CSS/syntax is hard-coded in the component.
  2. The base color may change from white to black in the dark theme, so now we run into
    accessibility concerns. Is black text viable on a colored button? Usually not. This is similar to
    the issue previously mentioned, where we can't change the color property on a theme-by-theme
    basis.
  3. What if the dark theme wants 2px borders? Or no borders? Or rounded corners? Again, we have no
    way of handling that.
  4. So on and so forth.

Future

I would love to resolve all the issues mentioned previously, most of which are easily solved with a
type-safe and structure-safe theme layer. However, while brainstorming the possibilities, I thought
to myself, "Why not take a step back and expand the scope of the project?". What does this mean
exactly? Well, in the current state of the web development world, companies are pushing hard and
forward with design systems, such as: Airbnb Lunar/DLS, Google Material, GitHub Primer, SalesForce
Lightning, Mozilla Photon, Shopify Polaris, IBM Carbon, so on and so forth.

Every company is building their design system from scratch, with different technologies, duplicated
across many platforms. What if there was a technological solution to this problem? This is where
Aesthetic comes in. What if Aesthetic was re-purposed to be a "design system framework", where a
design system's fundamentals are configured (fonts, spacing, borders, shadows, breakpoints,
interactions, etc), are compiled to multiple target platforms or technologies (CSS, Sass, Less,
JS/TS, iOS, Android, React Native, etc), and is ultimately robust and easy enough to be used by any
company.

How it works

I've been researching existing design systems for commonalities
(Google doc),
as a means to build a foundation for this framework. After a bit of research, and minor technical
prototyping, I believe the initial step forward would be to use YAML for configuring a design
system, while adhering to the following fundamentals.

  • Modular scale will be used for all
    scaling based algorithms. Can be configured per setting, with name or integer based values.
  • Colors may be unique per design system (and maybe theme too), but is inaccessible to consumers.
    Consumers will need to use palettes, which are pre-defined colors + states for common UI elements.
  • Multiple design systems can be used in parallel (e.g., version 2019 vs version 2020). This is
    possible since the "theme template" for the consumer will be identical regardless of design system
    and theme parameters.

An example of that YAML file is as follows, with descriptive comments.

# Whether the design system focuses on mobile or desktop first.
# This settings will control various features, like breakpoints.
# Accepts "mobile-first" or "desktop-first".
strategy: mobile-first

# List of 3-5 breakpoints for responsive and adaptive support. If not provided,
# will default to the following 5 values.
breakpoints:
  - 0
  - 600
  - 960
  - 1280
  - 1920

# Spacing related settings.
spacing:
  # The algorithm used for spacing and page density calculations. Accepts the following:
  #   vertical-rhythm - Calculates font size + line height for spacing.
  #   unit - Uses an explicit pixel unit value for spacing.
  type: vertical-rhythm

  # Explicit spacing unit (in pixels).
  unit: 8

# Text and font related settings.
typography:
  # Font family for the entire system. If not provided, defaults to the OS font.
  fontFamily: 'Roboto'

  # Root font size (in pixels).
  fontSize: 16

  # Factor to increase (mobile-first) or decrease (desktop-first) root font size each breakpoint.
  fontScale: 1.1

  # Factor to increase font size for each text heading.
  headingScale: 1.25

  # Root line height.
  lineHeight: 1.5

# Border related settings.
border:
  # Rounded corner radius (in pixels).
  radius: 3

  # Factor to increase radius each size.
  radiusScale: 1

  # Width of the border.
  width: 1

  # Factor to increase width each size.
  widthScale: 1

# Shadow and depth related settings.
shadow:
  # Depth Y offset (in pixels).
  depth: 2

  # Factor to increase depth each size.
  depthScale: 1

  # Blur radius (in pixels).
  blur: 2

  # Factor to increase blur each size.
  blurScale: 1.25

  # Spread radius (in pixels).
  spread: 0

  # Factor to increase spread each size.
  spreadScale: 0

# List of all color names that each theme must implement.
colors:
  - red
  - blue
  - green
  - ...

# Mapping of themes and their colors.
themes:
  # A light theme with a custom name.
  foo:
    # Base color scheme for this theme. Accepts "light" or "dark".
    # Used in `prefers-color-scheme` browser detection.
    scheme: light

    # Mapping of all colors in the theme, with a range of 10 hexcodes per color,
    # with 400 being the base default color, and the bounds going from light to dark,
    # or dark to light if scheme is "dark".
    colors:
      red:
        00: '#FE8484' # Lightest
        10: '#FE8484'
        20: '#FE8484'
        30: '#FE8484'
        40: '#FE8484' # Base
        50: '#FE8484'
        60: '#FE8484'
        70: '#FE8484'
        80: '#FE8484'
        90: '#FE8484' # Darkest

    # Mapping of pre-defined palettes (UI states) to colors and their shades (from above).
    # Consumers will reference these values, instead of colors directly.
    palettes:
      # Priority (properties in order of specificity)
      # TODO - THESE ONLY APPLY TO BACKGROUNDS... WHAT ABOUT FOREGROUND/TEXT?
      primary:
        base: purple.40
        focused: purple.50
        selected: purple.50
        hovered: purple.60
        disabled: gray.40
        failed: red.40
      secondary: # ...
      tertiary: # ...
      neutral: # ...
      # States
      muted: # ...
      danger: # ...
      warning: # ...
      success: # ...
      info: # ...
      # Layout
      text: # ...
      box: # ...
      boxBorder: # ...
      input: # ...
      inputBorder: # ...
      shadow: '#000'

  # A dark theme with a custom name.
  bar:
    scheme: dark
    colors:
      red:
        00: '#FE8484' # Darkest
        10: '#FE8484'
        20: '#FE8484'
        30: '#FE8484'
        40: '#FE8484' # Base
        50: '#FE8484'
        60: '#FE8484'
        70: '#FE8484'
        80: '#FE8484'
        90: '#FE8484' # Lightest

Furthermore, the design system will embrace the following:

  • ems and rems for all font sizing.
  • Accessible colors and font sizes (AAA, AA Large, etc).
  • Responsive and adaptive aware by default.
  • prefers-color-scheme for automatic theme selection.

References

Global font familys of the same name should be allowed

This pattern currently fails:

export default {
  CircularBook: {
    fontFamily: 'Circular',
    fontStyle: 'normal',
    fontWeight: 'normal',
    src:
      'url("fonts/Circular_Air-Book.woff2") format("woff2"), url("fonts/Circular_Air-Book.woff") format("woff")',
  },
  CircularBookItalic: {
    fontFamily: 'Circular',
    fontStyle: 'italic',
    fontWeight: 'normal',
    src:
      'url("fonts/Circular_Air-Book_Italic.woff2") format("woff2"), url("fonts/Circular_Air-Book_Italic.woff") format("woff")',
  },
};

Since fontFamily is identical, it throws "TypeError: Font face "Circular" has already been defined.". We should combine font family + property name for uniqueness.

Problem on Uglify for production build

First of all, thank you for this awesome package. It's really cool package.

I use HOC for 4 my components, it's work as expected in development mode.
When I build project in production mode - 2 components receive the classNames object for property from another component.

If I disable webpack.optimize.UglifyJsPlugin from the production build - it also works as expected.

Link to my rep: https://github.com/AndreyShpilevoy/DemUiBoilerplate/tree/master/DEM_MVC_UI
I trying to create Bootstrap-like grid on jss with theme support.

2.0 issues

  • Don't pass firstMount to component.
  • Keyframes/fontFaces throw "already exists" errors. Since we moved to transform on render instead of mount, this is far more problematic.
  • createStyleSheet doesn't work when extending parent styles with Aphrodite, since the stylesheet isn't a plain object.

Performance issues

Describe the bug

Our performance is average but could be better. Most of the time is spent in the SSS parsing -> style rendering layer. Things we can maybe do to improve it:

  • At the moment, we wait for the entire parser to finish and return a "block" object, which is multiple iterations on the original object. We then pass it to the renderer, which then loops it again. Perhaps we can avoid this by rendering declarations immediately on the events the parser fires.
  • Finding the style tags in the document over and over is too slow. Let's cache and provide a reference.
  • Subsequent renders are slow (how?). They should be almost instant since the initial styles are rendered and cached. Something is a miss here.
  • processRule/renderRule taking the most time in the renderer.
  • renderComponentStyles also taking a lot of time. Perhaps we can cache this harder.
  • toTokens/toVariables needs to be improved. Find another way to generate these variables?

Screenshots

Screen Shot 2020-09-16 at 12 51 52 PM

Environment

Platform: Web

System:
    OS: macOS 10.15.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 638.70 MB / 32.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.18.2 - ~/.nvm/versions/node/v12.18.2/bin/node
    Yarn: 1.22.4 - ~/.nvm/versions/node/v12.18.2/bin/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v12.18.2/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.7, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 23, 28, 29
      Build Tools: 28.0.3, 29.0.2, 29.0.3
      System Images: android-29 | Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom
  Browsers:
    Chrome: 85.0.4183.102
    Safari: 13.1.2
  npmPackages:
    @aesthetic/react: ^0.2.2 => 0.2.2 
    @anansi/eslint-plugin: ^0.9.6 => 0.9.6 
    @anansi/webpack-config: ^1.0.5 => 1.0.5 
    @babel/core: ^7.10.2 => 7.10.2 
    @babel/preset-react: ^7.10.1 => 7.10.1 
    @babel/preset-typescript: ^7.10.1 => 7.10.1 
    @babel/runtime: ^7.10.2 => 7.10.2 
    @callstack/react-theme-provider: ^2.1.0 => 2.1.0 
    @emotion/babel-preset-css-prop: ^10.0.27 => 10.0.27 
    @emotion/core: ^10.0.28 => 10.0.28 
    @emotion/styled: ^10.0.27 => 10.0.27 
    @hot-loader/react-dom: ^16.0.0 => 16.13.0+4.12.20 
    @reach/router: ^1.3.3 => 1.3.3 
    @types/mathjs: ^6.0.5 => 6.0.5 
    @types/node-sass: ^4.11.1 => 4.11.1 
    @types/reach__router: ^1.3.5 => 1.3.5 
    @types/react: ^16.9.36 => 16.9.36 
    @types/react-dom: ^16.9.8 => 16.9.8 
    @types/styled-components: ^5.1.0 => 5.1.0 
    @types/styled-jsx: ^2.2.8 => 2.2.8 
    aphrodite: ^2.4.0 => 2.4.0 
    classnames: ^2.2.6 => 2.2.6 
    cli-table: ^0.3.1 => 0.3.1 
    colors: ^1.4.0 => 1.4.0 
    css-loader: ^3.6.0 => 3.6.0 
    eslint: ^7.2.0 => 7.2.0 
    file-loader: ^6.0.0 => 6.0.0 
    linaria: ^2.0.0-alpha.5 => 2.0.0-alpha.5 
    mathjs: ^7.0.2 => 7.0.2 
    mini-css-extract-plugin: ^0.9.0 => 0.9.0 
    node-sass: ^4.14.1 => 4.14.1 
    patch-package: ^6.2.2 => 6.2.2 
    postinstall-postinstall: ^2.1.0 => 2.1.0 
    react: ^16.13.1 => 16.13.1 
    react-benchmark: ^2.1.1 => 2.1.1 
    react-dom: ^16.13.1 => 16.13.1 
    react-refresh: ^0.8.0 => 0.8.3 
    scheduler: ^0.19.1 => 0.19.1 
    serve: ^11.3.2 => 11.3.2 
    styled-components: ^5.1.1 => 5.1.1 
    styled-jsx: ^3.3.0 => 3.3.0 
    thread-loader: ^2.1.3 => 2.1.3 
    ts-loader: ^7.0.5 => 7.0.5 
    typescript: ^3.9.5 => 3.9.5 
    webpack: ^4.36.0 => 4.43.0 
    webpack-cli: ^3.3.11 => 3.3.11 
    webpack-dev-server: ^3.4.0 => 3.11.0 
    yargs: ^15.3.1 => 15.3.1 

Additional context

IE 11+

Reeeeeallly want to try this. Is the IE 11+ support a matter of test coverage (i.e., a soft-requirement) or a hard requirement (i.e., it will not work.)?

Multiple external stylesheet imports.

Jss supports multiple imports via an array of strings, cssinjs/jss#230

    '@import': [
      'react-date-range/dist/styles.css',
      'react-date-range/dist/theme/default.css',
    ],

aesthetic throws error @import value must be string
I can work around this by importing the two files in separate style objects or by combining them in an external css file.

Overwriting styles vs Extending styles

Aesthetic aims to solve the following two ownership scenarios:

  • Owner - You own the component in your application and can easily set styles.
  • Provider -> Consumer - You use a component provided by a third-party library (NPM package) and want to change its styles. (It must being using Aesthetic).

The first scenario is rather easily solved without much hassle. The second scenario is what Aesthetic tries to solve via the static setStyles method on a wrapped component (provided by a styler function).

Now for the comparison. I will use Toolkit components as an example, even though they don't use Aesthetic. Just assume it does use Aesthetic, and defines external classes as its style, like so:

// toolkit/components/Accordion
export default style({
  accordion: 'accordion',
  accordion__collapsible: 'is-collapsible',
  accordion__multiple: 'is-multiple',
}, {
  styleName: 'ToolkitAccordion',
  lockStyling: false,
})(Accordion);

Both approaches need to satisfy the following criteria:

  • Styling pattern can be changed (class names -> style objects, or vice versa).
  • Provided styles can be completely overwritten with custom styles.
  • Provided and custom styles can make use of themes.

Overwriting

Overwriting allows us to change the styles without having to create a new local component. The original styles can be referenced by using style functions.

// bootstrap.js
import Accordion from 'toolkit/components/Accordion';

Accordion.setStyles({
  accordion: { ... },
  accordion__collapsible: { ... },
  accordion__multiple: { ... },
});

// App.js
import Accordion from 'toolkit/components/Accordion';

<Accordion />

Pros

  • No local components or files.

Cons

  • Provided styles can only be overwritten once, which applies to all instances of the third-party component. (Can be worked around using themes).
  • If another third-party library uses Toolkit (for example), overwriting it's styles may break the other package. However, either a) you'd want it to match your new styles, or b) this requires another Aesthetic layer which wouldn't cause collision.

Extending

Extending allows us to change the styles but creates a new local component in the process (another layer of composition).

// components/Accordion.js
import Accordion from 'toolkit/components/Accordion';

export default Accordion.extendStyles({
  accordion: { ... },
  accordion__collapsible: { ... },
  accordion__multiple: { ... },
});

// App.js
import Accordion from '../components/Accordion';

<Accordion />

Pros

  • Provided styles can be completely overwritten multiple times, with each call of extendStyles.

Cons

  • Requires composition, which equates to more local files.

CID return from className generator

The cid generator in src/style.js can generate random strings that start with numbers.
classNames that start with numbers are ignored by the browser so when trying to user version 2.0+ on our prod environment styles get applied or not applied at random depending on whether the generator made a CID starting with a letter.

I tried to submit a pr to change the line to
c${Math.random().toString(32).substr(2)}${instanceID}

to force it to always start with a c. I get permission denied when I try to push my branch though?

Component extension

class Bar extends React.Component {
  getString() {
    return 'Foo';
  }

  render() {
    return <div className={this.props.styles.string}>{this.getString()})</div>
  }
}

export default withStyles({
  string: {
    backgroundColor: 'red',
  },
},
{
  styleName: 'Bar',
  extendable: true,
})(Bar);
export default class Foo extends Bar  {
  getString() {
    return 'Foo';
  }
}

Given then example above I'm attempting to extend a react component to share the render and common methods. However it appears that only the styles can be extended as this results in the equivalent of this.props.styles.string throwing the error,
TypeError: Cannot read property 'string' of undefined when the extended component Foo is ran.

Is there a way to extend the base component but not the styles or is this a bad pattern?

Enzyme + Component tests of something with useStyles

Hi!

Tryna test a component that uses @airbnb/lunar/lib/hooks/useStyles, and it comes at me with

    Theme "default" does not exist.

      23 |
      24 | export default function Header() {
    > 25 |   const [styles, cx] = useStyles(styleSheet)
...
      at Aesthetic.getTheme (node_modules/aesthetic/lib/index.js:1065:15)
      at Aesthetic.getGlobalSheet (node_modules/aesthetic/lib/index.js:1037:22)
      at ClassNameAdapter.applyGlobalStyles (node_modules/aesthetic/lib/index.js:815:38)
      at ClassNameAdapter.createStyleSheet (node_modules/aesthetic/lib/index.js:839:10)
      at node_modules/aesthetic-react/lib/index.js:172:22
      at useReducer (node_modules/react-dom/cjs/react-dom-server.node.development.js:1194:57)

Is there some test setup that must be done for Enzyme/Jest/whatever to register the default theme?

Example repo: Data-2-the-People/skyfall#49

[Question] Can the `stylename` be part of a component's classnames?

We are using aesthetic with JSS in our project.

Here is an excerpt of our rendered HTML:
<a class="logo-0-1-9"><div class="image-0-1-7"></div></a>

Is it possible to have the stylename included as part of the classname, for example:

<a class="MyComponent__logo-0-1-9"><div class="MyImage__image-0-1-7"></div></a>

ClassNameAdapter needs transform method

the method inside the adapter is currently named transformStyles instead of transform.

this results in an error like this :

Uncaught Error: ClassNameAdapter must define the `transform` method.

3.0 alpha issues

  • Lower @types/react to ^16.0.0.
  • Peer deps are pointing to v2.
  • Fix URLS in package.json.
  • Add docblocks to withStyles interfaces.
  • transformStyles needs to handle false/undefined.
  • getDerivedStateFromProps causing issues for component references.
src/components/ProgressCard/index.tsx:21:30 - error TS2345: Argument of type 'StyledComponent<Theme, Props & WithStylesWrapperProps>' is not assignable to parameter of type 'string | ComponentClass<any, ComponentState> | StatelessComponent<any>'.
  Type 'StyledComponent<Theme, Props & WithStylesWrapperProps>' is not assignable to type 'ComponentClass<any, ComponentState>'.
    Types of property 'getDerivedStateFromProps' are incompatible.
      Type 'GetDerivedStateFromProps<Props & WithStylesWrapperProps, ComponentState> | undefined' is not assignable to type 'GetDerivedStateFromProps<any, ComponentState> | undefined'.
        Type 'GetDerivedStateFromProps<Props & WithStylesWrapperProps, ComponentState>' is not assignable to type 'GetDerivedStateFromProps<any, ComponentState>'.
          Types of parameters 'nextProps' and 'nextProps' are incompatible.
            Type 'Readonly<any>' is not assignable to type 'Readonly<Props & WithStylesWrapperProps>'.
              Property 'percent' is missing in type 'Readonly<any>'.

21     progress: childrenOfType(ProgressBar).isRequired,
  • Return this in applyGlobalStyles.
  • Fela doesn't handle specificity well, as newer classes may still be overridden by previously compiled ones.
  • Add StyleBlock type alias
  • Rename StyledComponent to StyledComponentClass.
  • Throw errors when syntax should use @selectors.
  • Props in withStyles argument are not re-rendering when different/changed.

Double extend a component

Is it possible to override styles from grandparent in a child component?

Example:

  • ComponentB extends ComponentA with extendStyles.
  • ComponentC extends ComponentB with extendStyles.

ComponentC styles can only override styles from componentB and no longer change styles from componentA

Using multiple font faces

When trying to set up multiple '@font-face' it seems to always load the font that is declared last and ignore the first.

Take this example

'@font-face': {
  Roboto: {
    fontStyle: 'normal',
    fontWeight: 'normal',
    srcPaths: ['fonts/Roboto.woff2', 'fonts/Roboto.ttf'],
  },
  Roboto2: {
    fontStyle: 'normal',
    fontWeight: 'normal',
    srcPaths: ['fonts/Roboto2.woff2', 'fonts/Roboto2.ttf'],
  },
}

In the network Tab I would get Roboto2 downloading and being used around the site but not Roboto.
Tried Lots of different implementations after seeing this jss issue

Unsure if its implementation or a limitation at this point?

Vendor pseudos crash in other vendors

Describe the bug

When inserting vendor pseudos into a different vendor, they can crash.

index.js:985 Uncaught DOMException: Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to parse the rule '.m::-moz-focus-inner { border:0; }'.
    at StandardStyleSheet.BaseStyleSheet.injectRule (webpack:///./node_modules/@aesthetic/style/esm/index.js?:985:19)
    at eval (webpack:///./node_modules/@aesthetic/style/esm/index.js?:994:15)
    at Array.forEach (<anonymous>)
    at BaseStyleSheet.flushRules (webpack:///./node_modules/@aesthetic/style/esm/index.js?:993:24)

Steps to reproduce

Insert a pseudo that starts with -moz in Chrome/WebKit.

Expected behavior

Not to crash. We will most likely have to skip over these in unsupported browsers.

Screenshots

Environment

Platform: Web

  System:
    OS: macOS 10.15.5
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 207.37 MB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.18.3 - ~/.nvm/versions/node/v12.18.3/bin/node
    Yarn: 1.22.4 - ~/.nvm/versions/node/v12.18.3/bin/yarn
    npm: 6.14.6 - ~/.nvm/versions/node/v12.18.3/bin/npm
  SDKs:
    iOS SDK:
      Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
  Browsers:
    Chrome: 85.0.4183.83
    Firefox: 79.0
    Safari: 13.1.1
  npmPackages:
    @milesj/build-tools: ^2.11.0 => 2.11.0 
    @rollup/plugin-babel: ^5.2.0 => 5.2.0 
    @rollup/plugin-node-resolve: ^9.0.0 => 9.0.0 
    @types/hoist-non-react-statics: ^3.3.1 => 3.3.1 
    @types/react: ^16.9.49 => 16.9.49 
    @types/react-dom: ^16.9.8 => 16.9.8 
    babel-loader: ^8.1.0 => 8.1.0 
    builtin-modules: ^3.1.0 => 3.1.0 
    conventional-changelog-beemo: ^2.0.0 => 2.0.0 
    eslint-plugin-rut: ^1.1.0 => 1.1.0 
    jest-rut: ^1.0.2 => 1.0.2 
    lerna: ^3.22.1 => 3.22.1 
    react: ^16.13.1 => 16.13.1 
    react-docgen-typescript: ^1.20.4 => 1.20.4 
    react-dom: ^16.13.1 => 16.13.1 
    react-styleguidist: ^11.0.11 => 11.0.11 
    rollup: ^2.26.11 => 2.26.11 
    rollup-plugin-node-externals: ^2.2.0 => 2.2.0 
    rut-dom: ^1.0.2 => 1.0.2 
    webpack: ^4.44.1 => 4.44.1 

Additional context

Problem with 1.1.1 and webpack

I updated from 1.0.1 to 1.1.1.
And after that I receive an error:

Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_1_aesthetic_adapter_jss___default.a is not a constructor
    at eval (eval at 74 (app.js:375), <anonymous>:14:71)
    at Object.74 (app.js:375)
    at __webpack_require__ (vendor.js:692)
    at fn (vendor.js:111)
    at eval (eval at 184 (app.js:15), <anonymous>:5:73)
    at Object.184 (app.js:15)
    at __webpack_require__ (vendor.js:692)
    at fn (vendor.js:111)
    at eval (eval at 295 (app.js:182), <anonymous>:6:80)
    at Object.295 (app.js:182)
    at __webpack_require__ (vendor.js:692)
    at fn (vendor.js:111)
    at eval (eval at 296 (app.js:190), <anonymous>:6:72)
    at Object.296 (app.js:190)
    at __webpack_require__ (vendor.js:692)
    at fn (vendor.js:111)
    at eval (eval at 298 (app.js:206), <anonymous>:5:77)
    at Object.298 (app.js:206)
    at __webpack_require__ (vendor.js:692)
    at fn (vendor.js:111)
    at eval (eval at 269 (app.js:62), <anonymous>:15:66)
    at Object.269 (app.js:62)
    at __webpack_require__ (vendor.js:692)
    at fn (vendor.js:111)
    at Object.675 (app.js:366)
    at __webpack_require__ (vendor.js:692)
    at webpackJsonpCallback (vendor.js:24)
    at app.js:1

It looks like some issue with aesthetic_adapter_jss export.
Can you check it?
Thank you.

HOCs break wrapped component generics

When a component with generics is wrapped with an HOC, the generics are lost and any usage breaks that relied on them.

class Comp<T> extends React.Component {}

export default aesthetic.withStyles()(Comp);

Not sure if this is fixable?

Problem with version 1.1.0

Hi, I have error
ERROR in ./~/aesthetic/index.js Module not found: Error: Can't resolve './lib/Aesthetic' in 'C:\Git\dem-afterlife\src\dem-afterlife-ui\node_modules\aesthetic' @ ./~/aesthetic/index.js 8:18-44 @ multi babel-polyfill aesthetic aesthetic-adapter-jss history jss jss-camel-case jss-default-unit jss-expand jss-extend jss-nested jss-props-sort jss-vendor-prefixer raven-js react react-dom re act-notification-system react-redux react-router react-router-redux redux redux-saga webpack-hot-middleware/client?reload=true

As I see - node_modules\aesthetic is hadn't folder Lib and all necessary files.
Please, can you check it?

How do you access the react props from the styler function?

Typically in a code like:

style((theme) => ({
button: {
fontSize: ${theme.unitSize}${theme.unit},
fontFamily: theme.font,
padding: theme.spacing,
},
}))(Component);

you has access to the theme object, but how can you access the props object that is passed to the HoC ?

Cheers!

JSS adapter with default preset for plugins not working properly

We're trying to setup Aesthetic in our project in combination with the JSS adapter.

But we're running into an issue where the jss plugins provided by 'jss-preset-default' aren't being used.

As an example, the style object used:

paper: {
    maxWidth: 380,
    padding: '24px',
    margin: '0 auto',
    transform: 'translateY(-56px)',
}

results in the following class:

.paper-1372835007 {
    maxWidth: 380;
    padding: 24px;
    margin: 0 auto;
    transform: translateY(-56px);
}

As you can see, the maxWidth rule is not being compiled to max-width (jss-camel-case plugin) as well as it's value, which should become 380px (jss-default-unit plugin).

This is what our styler configuration file looks like currently, is there anything we're missing here?

import Aesthetic, { createStyler } from 'aesthetic';
import JSSAdapter from 'aesthetic-adapter-jss'; // Or your chosen adapter

import { create } from 'jss';
import preset from 'jss-preset-default';

const jss = create().use(preset());
export default createStyler(new Aesthetic(new JSSAdapter(jss)));

Nice job on this library btw, looks very promising!

File size of packages are too large

Describe the bug

Compared to other libs (gzipped):

Aesthetic (w/ React): 11.8kb
Emotion (w/ Stylis): 9.2kb
Aphrodite: 6.4kb
Styled components: 5.6kb
Linaria (w/ ThemeProvider): 3.7kb
Styled JSX: 2.8kb
Linaria: 2.5kb

This will be a hard solve since Aesthetic offers more than others (like design system, vendor prefixing, RTL, themeing, etc). Some of these libraries also don't have a React implementation, since they're ran in the module scope.

However, ways to improve it:

  • Add more __DEV__ checks when applicable.
  • Rewrite the SSS package to not use classes? This can most likely be done with a handful of functions. Would need to figure out events.
  • Remove getters from system classes. This can be done with standard properties.
  • Combine core Sheet classes into 1. We don't need 3.
  • Use method overloading for class name generation of variants. This will avoid many loops.
  • Move RTL/vendor prefixing/other stuff into separate packages. Should be opt-in.

Screenshots

Screen Shot 2020-09-16 at 12 11 00 PM

Environment

Platform: Web

System:
    OS: macOS 10.15.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 638.70 MB / 32.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.18.2 - ~/.nvm/versions/node/v12.18.2/bin/node
    Yarn: 1.22.4 - ~/.nvm/versions/node/v12.18.2/bin/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v12.18.2/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.7, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 23, 28, 29
      Build Tools: 28.0.3, 29.0.2, 29.0.3
      System Images: android-29 | Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom
  Browsers:
    Chrome: 85.0.4183.102
    Safari: 13.1.2
  npmPackages:
    @aesthetic/react: ^0.2.2 => 0.2.2 
    @anansi/eslint-plugin: ^0.9.6 => 0.9.6 
    @anansi/webpack-config: ^1.0.5 => 1.0.5 
    @babel/core: ^7.10.2 => 7.10.2 
    @babel/preset-react: ^7.10.1 => 7.10.1 
    @babel/preset-typescript: ^7.10.1 => 7.10.1 
    @babel/runtime: ^7.10.2 => 7.10.2 
    @callstack/react-theme-provider: ^2.1.0 => 2.1.0 
    @emotion/babel-preset-css-prop: ^10.0.27 => 10.0.27 
    @emotion/core: ^10.0.28 => 10.0.28 
    @emotion/styled: ^10.0.27 => 10.0.27 
    @hot-loader/react-dom: ^16.0.0 => 16.13.0+4.12.20 
    @reach/router: ^1.3.3 => 1.3.3 
    @types/mathjs: ^6.0.5 => 6.0.5 
    @types/node-sass: ^4.11.1 => 4.11.1 
    @types/reach__router: ^1.3.5 => 1.3.5 
    @types/react: ^16.9.36 => 16.9.36 
    @types/react-dom: ^16.9.8 => 16.9.8 
    @types/styled-components: ^5.1.0 => 5.1.0 
    @types/styled-jsx: ^2.2.8 => 2.2.8 
    aphrodite: ^2.4.0 => 2.4.0 
    classnames: ^2.2.6 => 2.2.6 
    cli-table: ^0.3.1 => 0.3.1 
    colors: ^1.4.0 => 1.4.0 
    css-loader: ^3.6.0 => 3.6.0 
    eslint: ^7.2.0 => 7.2.0 
    file-loader: ^6.0.0 => 6.0.0 
    linaria: ^2.0.0-alpha.5 => 2.0.0-alpha.5 
    mathjs: ^7.0.2 => 7.0.2 
    mini-css-extract-plugin: ^0.9.0 => 0.9.0 
    node-sass: ^4.14.1 => 4.14.1 
    patch-package: ^6.2.2 => 6.2.2 
    postinstall-postinstall: ^2.1.0 => 2.1.0 
    react: ^16.13.1 => 16.13.1 
    react-benchmark: ^2.1.1 => 2.1.1 
    react-dom: ^16.13.1 => 16.13.1 
    react-refresh: ^0.8.0 => 0.8.3 
    scheduler: ^0.19.1 => 0.19.1 
    serve: ^11.3.2 => 11.3.2 
    styled-components: ^5.1.1 => 5.1.1 
    styled-jsx: ^3.3.0 => 3.3.0 
    thread-loader: ^2.1.3 => 2.1.3 
    ts-loader: ^7.0.5 => 7.0.5 
    typescript: ^3.9.5 => 3.9.5 
    webpack: ^4.36.0 => 4.43.0 
    webpack-cli: ^3.3.11 => 3.3.11 
    webpack-dev-server: ^3.4.0 => 3.11.0 
    yargs: ^15.3.1 => 15.3.1 

Additional context

Merge media queries during SSR

Right now, it duplicates a lot.

<style
  id="aesthetic-global"
  type="text/css"
  media="screen"
  data-aesthetic-type="global"
  data-aesthetic-hydrate-index="-1"
  data-aesthetic-rule-index="100"
></style>
<style
  id="aesthetic-standard"
  type="text/css"
  media="screen"
  data-aesthetic-type="standard"
  data-aesthetic-hydrate-index="77"
  data-aesthetic-rule-index="100"
>
  .a {
    align-items: center;
  }
  .b {
    border-bottom: 1px solid rgb(235, 235, 235);
  }
  .c {
    display: flex;
  }
  .d {
    justify-content: space-between;
  }
  .e {
    padding-bottom: var(--spacing-md);
  }
  .f {
    padding-left: 5rem;
  }
  .g {
    padding-right: 5rem;
  }
  .h {
    padding-top: var(--spacing-md);
  }
  .i {
    color: rgb(72, 72, 72);
  }
  .j {
    font-size: var(--text-sm-size);
  }
  .k {
    font-weight: 600;
  }
  .l {
    width: 400px;
  }
  .m {
    border: 1px solid rgb(235, 235, 235);
  }
  .n {
    border-radius: var(--border-df-radius);
  }
  .o {
    box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 4px;
  }
  .p {
    font-size: var(--text-df-size);
  }
  .q {
    font-weight: 800;
  }
  .r {
    height: 48px;
  }
  .s {
    padding-left: var(--spacing-md);
  }
  .t {
    width: 460px;
  }
  .u {
    margin: auto;
  }
  .v {
    max-width: 1760px;
  }
  .w {
    font-family: var(--typography-font-text);
  }
  .x {
    word-wrap: break-word;
  }
  .y {
    color: var(--palette-neutral-color-80);
  }
  .z {
    line-height: var(--text-df-line-height);
  }
  .a1 {
    display: inline-block;
  }
  .b1 {
    margin-top: var(--spacing-df);
  }
  .c1 {
    padding: var(--spacing-df);
  }
  .d1 {
    text-decoration: underline;
  }
  .e1 {
    margin-left: NaNpx;
  }
  .f1:hover {
    background-color: var(--palette-tertiary-bg-hovered);
  }
  .g1:hover {
    border-radius: 5px;
  }
  .h1 {
    padding-bottom: var(--spacing-xl);
  }
  .i1 {
    padding-top: var(--spacing-xl);
  }
  .j1 {
    margin-bottom: var(--spacing-md);
  }
  .k1 {
    font-family: var(--typography-font-heading);
  }
  .l1 {
    letter-spacing: var(--heading-l1-letter-spacing);
  }
  .m1 {
    line-height: var(--heading-l1-line-height);
  }
  .n1 {
    font-size: var(--heading-l1-size);
  }
  .o1 {
    margin-bottom: 0;
  }
  .p1 {
    font-weight: normal;
  }
  .q1 {
    font-size: var(--text-lg-size);
  }
  .r1 {
    line-height: var(--text-lg-line-height);
  }
  .s1 {
    margin-top: var(--spacing-sm);
  }
  .t1 {
    border-radius: 12px;
  }
  .u1 {
    box-shadow: rgba(0, 0, 0, 0.15) 0px 2px 8px;
  }
  .v1 {
    flex: 1px;
  }
  .w1 {
    flex-direction: row;
  }
  .x1 {
    height: 84px;
  }
  .y1 {
    margin: 0 8px;
  }
  .c2:first-child {
    margin-left: 0;
  }
  .d2:last-child {
    margin-right: 0;
  }
  .e2 {
    padding: 16px;
  }
  .f2 {
    border-bottom-left-radius: 12px;
  }
  .g2 {
    border-top-left-radius: 12px;
  }
  .k2 {
    flex: 1 1 auto;
  }
  .l2 {
    margin: 0rem 0.5rem;
  }
  .m2 {
    max-width: 50%;
  }
  .n2 {
    padding: var(--spacing-lg);
  }
  .o2 {
    margin-top: 0.75rem;
  }
  .p2 {
    box-sizing: border-box;
  }
  .q2 {
    margin: var(--spacing-df);
  }
  .r2 {
    border-top-right-radius: 12px;
  }
  .s2 {
    height: 483px;
  }
  .t2 {
    line-height: var(--text-sm-line-height);
  }
  .u2 {
    margin-bottom: var(--spacing-df);
  }
  .v2 {
    display: none;
  }
  .w2 {
    width: 100%;
  }
  .x2 {
    border-top: 1px solid rgb(221, 221, 221);
  }
  .g3 {
    margin: 0;
  }
  .h3 {
    padding: 0;
  }
  .i3 {
    display: block;
  }
  .j3 {
    flex-direction: column;
  }
  .k3 {
    margin-bottom: var(--spacing-xl);
  }
  .l3 {
    border-bottom: 1px solid rgb(221, 221, 221);
  }
  .n3 {
    list-style: none;
  }
  .w3:hover {
    text-decoration: underline;
  }
</style>
<style
  id="aesthetic-conditions"
  type="text/css"
  media="screen"
  data-aesthetic-type="conditions"
  data-aesthetic-hydrate-index="22"
  data-aesthetic-rule-index="100"
>
  @media (min-width: 46.5em) {
    .t3 {
      flex-basis: 33.33333333333333%;
    }
  }
  @media (min-width: 70.5em) {
    .v3 {
      padding-top: var(--spacing-md);
    }
  }
  @media (min-width: 70.5em) {
    .u3 {
      padding: 0;
    }
  }
  @media (min-width: 46.5em) {
    .s3 {
      padding-right: var(--spacing-df);
    }
  }
  @media (min-width: 46.5em) {
    .r3 {
      padding-left: var(--spacing-df);
    }
  }
  @media (min-width: 46.5em) {
    .q3 {
      padding-top: var(--spacing-df);
    }
  }
  @media (min-width: 46.5em) {
    .o3 {
      flex-wrap: wrap;
    }
  }
  @media (min-width: 70.5em) {
    .p3 {
      display: block;
    }
  }
  @media (min-width: 46.5em) {
    .m3 {
      border: none;
    }
  }
  @media (min-width: 46.5em) {
    .b3 {
      padding-right: var(--spacing-lg);
    }
  }
  @media (min-width: 70.5em) {
    .f3 {
      padding-right: var(--spacing-xl);
    }
  }
  @media (min-width: 70.5em) {
    .e3 {
      padding-left: var(--spacing-xl);
    }
  }
  @media (min-width: 70.5em) {
    .d3 {
      flex-direction: row;
    }
  }
  @media (min-width: 70.5em) {
    .c3 {
      justify-content: space-around;
    }
  }
  @media (min-width: 46.5em) {
    .a3 {
      padding-left: var(--spacing-lg);
    }
  }
  @media (min-width: 46.5em) {
    .z2 {
      flex-direction: column;
    }
  }
  @media (min-width: 46.5em) {
    .y2 {
      display: flex;
    }
  }
  @media (max-width: 1112px) {
    .j2 {
      height: 200px;
    }
  }
  @media (max-width: 1112px) {
    .i2 {
      border-top-right-radius: 12px;
    }
  }
  @media (max-width: 1112px) {
    .h2 {
      border-bottom-left-radius: 0;
    }
  }
  @media (max-width: 1112px) {
    .b2 {
      width: 290px;
    }
  }
  @media (max-width: 1112px) {
    .a2 {
      height: 250px;
    }
  }
  @media (max-width: 1112px) {
    .z1 {
      flex-direction: column;
    }
  }
</style>

Backslash in pseudo element content.

Using unicode characters for the content of a pseudo element from within a custom font.

In the bellow the \ gets stripped out by jss in both.

 content: '"\e000"',
 content: '"/\e000"',

Leaving me with either

  content: "e000";
  content: "/e000";

Is it possible to escape these, If so what am I missing?

Referencing the component inside the styler wrapper

<Comp
  ref={ref => this.name = ref}
/>

The above used to give access to the functions and methods contained on that component. Now that component is wrapped in a styled component we are ferencing the styler. I've managed to pass refs through and reference specific dom nodes but can't get the original Component.

Pretty sure its accomplishable I just can't figure it out. any solution appreciated

Support for SSR

Any plans supporting SSR? It breaks when rendering/applying the global styles, complaining that document is not defined - obviously ๐Ÿ˜„

Production ready? Or when?

Hi!

Awesome library man!

Can I use it in a production application? Or, like, when will it be ready?

It kinda looks ready but I still see rapid development going on.

Thanks!

Cache function calls

Based on profiling, the following function results can be cached.

  • isSSR
  • canInsertNestedRules

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.