Skip to content
This repository has been archived by the owner on Jan 20, 2022. It is now read-only.

[RFC] Styles Customization #103

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

kuzhelov
Copy link
Collaborator

@kuzhelov kuzhelov commented Jul 17, 2018

Goals

  • introduce styles customization system that is flexible enough to tune components' styles
  • plain JS objects should be used
  • provided solution should introduce ways to modularize, extend and reuse styles

Component's anatomy

Each component (except from primitive ones) should advertise its anatomy - which parts this component consist of. This is a key prerequisite that, apart from other things, will allow us to target specific subcomponents of the component. 

As an example, lets consider an anatomy that could be provided by <Search /> component:

Applying styles

The following ways currently proposed for component's styles customization. 

Rules

Rules are functions that map component's props and variables to style objects - the objects that represents mapping from css property names to their corresponding values.

  • each component has default rules object
    • this object must have root property that would return rule function for the component itself
  • there may be additional properties introduced to 'rules' object, with the names matching corresponding anatomy parts
    • in that case those will be applied to corresponding subcomponents
const rules = { root: () => ..., input: () => ...,  }
  • each component can accept rules property - this one will have cascading effect on top of default ones (will be merged into them)
<Search rules={{ root: () => ..., input: () => ... }} />

Variables

Represent parameters of rules functions. These parameters should always have names that reflect clear relationship with component's semantics (so that their effect will be intuitive to the client).

The following principles are driving 'variables' part:

  • each component has default variables set
  • variables is a flat object - there shouldn't be any nested objects provided there
  • variables object contains all the variables of component, as well as prefixed variables for all its anatomy subcomponents - as properties
const searchVars = { border: ..., color: ..., *input... : ...., *icon... : ...., *actionBtn.... : .... } 
  • if user needs to customize subcomponent of the component, the following steps should be made
    • consult the name of the part this subcomponent corresponds to (for the sake of example, let it be input part)
    • use the variables corresponding component exposes (lets suppose that user would like to target padding variable of the subcomponent)
    • in that case inputPadding variable should be provided to main component
  • each component can accept variables property. All the variables that are passed there will override the ones that are introduced by default or by theme
<Search variables={{ border: ..., inputPadding: .. }} />

CSS properties

  • this one should be used as a last resort option - it is about providing css property values via styles attribute of the rendered HTML element
  • allows to fine-tune component's look in case if some of the aspects are not exposed in its variables 
    however, if we will find ourselves always relying on CSS properties tweaking during components development, it would mean that provided styling system is not flexible enough to meet our needs, so we will need to reconsider our approach

Example

<Search 
      variables={{ color: 'red', inputPadding: 10 }}  
      rules={{  input: (props, variables) => { ... return <custom_styles_for_input> }  }} />

Concerns

While there are clearly some concerns that could be raised by this solution (for example, the one that is highlighted as bold italic - this fact could cause bloat in number of variables required, because each component of higher order will sum up all the variables of its subcomponents, as well as add few of individual ones).

Still, currently it is about the following points being met:

  • prove that this logic is able to meet style customization needs - in other words, it should prove to be flexible
  • prove that this system allows to introduce reusable and extendable styles as plain JS objects
    in case if there would be any problems with the implementation approach tat is currently taken - it would be relatively easy to address them. The most critical problems for us will be the ones that are about flaws in the taken approach (its semantics) - all others are solvable. At this point the most simplest approach to implementation is intentionally taken - to prove the concept.

@codecov
Copy link

codecov bot commented Jul 17, 2018

Codecov Report

Merging #103 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #103   +/-   ##
=======================================
  Coverage   69.94%   69.94%           
=======================================
  Files          73       73           
  Lines        1191     1191           
  Branches      223      223           
=======================================
  Hits          833      833           
  Misses        353      353           
  Partials        5        5

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6573d45...eec996e. Read the comment docs.

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

Successfully merging this pull request may close these issues.

1 participant