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

A way to easily use hierarchical accoutrement maps in Herman #345

Open
johncrim opened this issue Jan 3, 2020 · 7 comments
Open

A way to easily use hierarchical accoutrement maps in Herman #345

johncrim opened this issue Jan 3, 2020 · 7 comments
Assignees

Comments

@johncrim
Copy link

johncrim commented Jan 3, 2020

Given an accoutrement map like the following:

@use 'accoutrement' as a;

$colors: (
  'white': #f8f8f8,
  'warm-offwhite': hsl(28, 25, 93),
  'contrast-dark': #444,
  'contrast-light': #f8f8f8cc,
  'page': (
    'background': '#white'
  ),
  'header': (
    'background': '#white',
  ),
  'footer': (
    'background': hsl(240,67%,94%) ('shade': 80%),
  )
);
@include a.add-colors($colors); 

If I add these colors to the herman map, using:

@use 'herman';

/// @group colors
/// @colors site-colors
@include herman.herman-add('colors', 'site-colors', $colors);

The values in the root of the map are displayed correctly, but the submaps, and references, aren't. This problem isn't specific to displaying colors in herman - it would also be great to resolve and display hierarchical sizes, fonts, etc in herman.

If there were an accoutrement function that "flattened" the above map to:

$colors: (
  'white': #f8f8f8,
  'warm-offwhite': hsl(28, 25, 93),
  'contrast-dark': #444,
  'contrast-light': #f8f8f8cc,
  'page->background': #f8f8f8,
  'header->background': #f8f8f8,
  'footer->background': hsl(240,67%,94%) ('shade': 80%)
);

And then the color swatch rendering combined all keys with the same value under a single swatch (it may already do this), accoutrement + herman would be a nicer combination IMO.

The workaround is to manually map the hierarchical values to a new map that's added only to herman.

It would also be great to be able to flatten sub-maps for display in herman. Eg if I have:

$sizes: (
  'sm': (
    'icon-size': 24px,
    'page-margin': 1rem,
    'header-height': 3rem,
    'footer-height': '#sm->header-height',
    'vertical-spacing': 1.5rem,
    'horizontal-spacing': 2rem
  ),
  'lg': (
    'icon-size': 32px,
    'page-margin': 3rem,
    'header-height': 4rem,
    'footer-height': 5rem,
    'vertical-spacing': 2rem,
    'horizontal-spacing': 3rem
  ),
  'image': (
    'border-radius': 8px
  ),
  'text-column-width': 70ch,
  'page-min-width': 300px,
  'page-max-width': 1230px
);
@include a.add-sizes($sizes);

It would be nice to be able to display only the values within a specific submap (eg #sm) within herman.

@johncrim
Copy link
Author

johncrim commented Jan 4, 2020

It turns out, this function was easier to write than I thought it would be. Here's what I came up with:

@use 'accoutrement' as a;

/// @group util
/// Resolves all the values in $map starting with $root.
/// Needed to turn accoutrement maps into something that Herman can display
/// (Herman can only display flat maps with simple values.)
@function flatten-accoutrement-map($map, $root: '') {
  $enumMap: null;
  @if ($root == '') {
    $enumMap: $map;
  }
  @else {
    $enumMap: a.get-token($map, $root)
  }

  @if (type-of($enumMap) != 'map') {
    @return ( $root: $enumMap );
  }
  @else {
    $result: ();
    @each $key, $value in $enumMap {
      $flattened-key: '#{$root}->#{$key}';
      @if ($root == '') {
        $flattened-key: $key;
      }
      @if (type-of($value) == 'map') {
        $result: map.merge($result, flatten-accoutrement-map($map, $flattened-key));
      }
      @else {
        $result: map.merge($result, ($flattened-key: $value));
      }
    }
    @return $result;
  }
}

And it can be used like this to display the contents of hierarchical accoutrement maps in Herman:

@use 'herman';

/// @group colors
/// @colors site-colors
@include herman.herman-add('colors', 'site-colors', flatten-accoutrement-map(site-colors.$colors));

/// Site sizes for screens below desktop
/// @group site-sizes
/// @sizes site-sm-sizes {ruler}
@include herman.herman-add('sizes', 'site-sm-sizes', flatten-accoutrement-map(a.$sizes, 'sm'));

/// Site sizes for desktop+
/// @group site-sizes
/// @sizes site-lg-sizes {ruler}
@include herman.herman-add('sizes', 'site-lg-sizes', flatten-accoutrement-map(a.$sizes, 'lg'));

Herman does already display multiple map keys with the same value together (yay!).

I'll leave this here in case it's useful to others. It would be awesome IMO if this were added to accoutrement or herman.

@mirisuzanne
Copy link
Member

Hi @johncrim - sorry I missed this. Accoutrement does have a map-flattening function, but it's currently private: _a_flat-source(). Maybe in the next release we can make it part of the public API.

@johncrim
Copy link
Author

That would be great. I don't have other use-cases (that I can think of right now) for flattening maps, but I'm sure they exist.

My main point though, is that since accoutrement supports hierarchical maps, and the hierarchical nature is super useful, it would be nice if they worked in Herman.

@mirisuzanne
Copy link
Member

I agree. I'm also working on a spec for Sass to provide better native nested-map support. That would simplify things in both places.

Should Herman support go beyond flattening maps, though? Do we want ways to render nested data? I'd be open to proposals (and then PRs) along those lines.

@johncrim
Copy link
Author

johncrim commented May 2, 2020

I certainly agree that native nested map support would be ideal. Flattening it to view it in a table is a workaround.

Extending Herman is outside my comfort zone for the time being. (I'm still trying to set aside some time to implement a couple Accoutrement issues that I raised.)

@mirisuzanne
Copy link
Member

Before implementation, we'd need to determine how we access & render nested maps - what's the API / syntax for that. Open to ideas.

@mirisuzanne
Copy link
Member

I don't think we want to build the Accoutrement parser into Herman. Any token-parsing should happen before maps are passed to Herman. That leaves the question of displaying nested maps. @sondra @stacyk is that something you'd be interested in looking at from a UX perspective?

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