FlyingDR / scss-snippets

Collection of helpful SCSS mixins and functions to use into various projects
1 stars 2 forks source link

Responsive configurations for reusable blocks #15

Open FlyingDR opened 7 years ago

FlyingDR commented 7 years ago

Currently responsive configuration is solid, it prevents convenient use of reusable blocks.

It is necessary to implement ability to define responsive configuration for separate block and then include it into main configuration.

For example it can look like this (rc here and below is an acronym for responsive configuration.):

// Define responsive configuration for the block
@include rc-block(block-id, (
  config-id1: ( /* parameters */),
  config-id2: ( /* parameters */),
 // ... some more ...
  config-idN: ( /* parameters */),
));

rc-block mixin should register given configuration map under given id into responsive module so it will be possible to refer it later by id when including into main configuration

// Include block configuration into main configuration
@include r-config(config-id, (
  // ... some configuration ...
  key: rс-block(block-id),
  // ... 
));

rс-block inclusion function may be called at any level of configuration, however it should only be allowed to include blocks into default responsive configurations. Attempts to include blocks into non-default configurations should result into error.

It may be good idea to allow passing $ids-map mapping table from block's configuration ids into application's configuration ids because they, obviously, may differ. This mapping table can be detected by comparing map's keys with block's configuration keys and values with application's configuration values.

To allow further flexibility - it is necessary to provide a way to extend block configuration. Something like this:

// Extend given configuration map with provided configuration
// 
// @param string|map $block Either Id of registered configuration block or block configuration map
// @param map $override     Map with information to merge over configuration block
// @return map              Extended configuration map 
@function rc-extend($block, $override)

It will also require implementation of functions:

// Get configuration of registered configuration block
//
// @param string $block  Id of registered configuration block
// @return map|null 
@function rc-get-block($block)
// Remap given configuration block to new configuration ids
// 
// @param string|map $block      Either Id of registered configuration block or block configuration map
// @param map $ids-map           Mapping table from block's configuration ids into new ids
// @param boolean $skip-unmapped true to skip block's configurations that are missed into map, false to throw error in this case 
// @return map                   Remapped configuration
// @throws error in a case if unknown source id or if there is unmapped configuration and $skip-unmapped: true
@function rc-remap($block, $ids-map, $skip-unmapped: true)
FlyingDR commented 7 years ago

This proposal may conflict with #13 and #14 because it will require either moving block's responsive configuration into separate file (doubling files amount) with intensive imports or will require allowing modifications after call to r-init().

FlyingDR commented 7 years ago

Another possible solution is to treat rc-block() function call during configuration definition as a promise. In this case rc-block() will just define position into responsive configuration will be inserted. Then, later, rc-block() mixin will define actual configuration that will be processed and merged into main responsive configuration.

This approach will allow definition of overall configuration structure while allowing its actual construction block by block as needed.

It is open question how to track calls to not-yet-resolved block promises.

FlyingDR commented 7 years ago

Some more thoughts on this topic:

Block configuration definition can be implemented as a function instead of mixin and will return path within responsive configuration. This path can be then passed to r-with() for further usage.

In this case block configuration embedding function should look like this:

// Include external responsive configuration block into main responsive configuration
// 
// @param string|map $block Either Id of registered configuration block or block configuration map
// @param function $transformer    Configuration block transformation function
// @return string
@function rc-include($block-id, $transformer: null)

$transformer parameter is optional name of the function to call to perform configuration transformations that are required to apply to block configuration in order to use it into main configuration. Examples of such transformations are:

Transformation function should receive receive block responsive configuration as argument and return information that should be embedded into main responsive configuration.

It will be also necessary to provide implementations of some standard transformations, such as ones, listed above.

When block configuration will be actually registered - library should call transformation function (if there is any), embed resulted block into main configuration and return path to this configuration, so it will look something like this:

$config-path: rc-block(block-id, (
  // ... some block configuration ...
));

// ... later in code ...

@include r-with($config-path) {
  // Block responsive configuration can be used
}
FlyingDR commented 5 years ago

Another possibility is to allow passing responsive configurations as maps for r-with() and allow passing maps directly to r-each(). There is separate issue #23 for last point.