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

Utility class mapping #33

Closed
shawnbot opened this issue May 23, 2018 · 4 comments
Closed

Utility class mapping #33

shawnbot opened this issue May 23, 2018 · 4 comments
Assignees

Comments

@shawnbot
Copy link
Contributor

I've been using the Primer mapping from system-classnames in #32, but after looking into Text and Heading components I think we should consider more granular mappings for each, e.g.

import createMapper from 'system-classnames'

const breakpoints = [null, 'sm', 'md', 'lg', 'xl']
// one day? import {breakpoints} from 'primer-primitives'

const createPrimerMapper = props => createMapper({
  breakpoints,
  props,
  getter: ({breakpoint, prop, value}) => breakpoint
    ? [prop, breakpoint, value].join('-')
    : [prop, value].join('-')
})

const textMap = createPrimerMapper(['h', 'f', 'lh', 'text'])
const boxMap = createPrimerMapper([
  'bg', 'text', 'border', 'rounded', 'box-shadow',
  'position', 'top', 'right', 'bottom', 'left',
  'v-align', 'overflow', /* 'float', */
  'width', 'height', 'min-width' // these might need to be handled separately
])

export default createPrimerMapper
export {textMap, boxMap}

Then Box, Text, and Heading would each use them like:

const Box = props => <div {...boxMap(props)} />
const Text = props => <span {...textMap(props)} />
const Heading = props => <h1 {...textMap(props)} />
Heading.h2 = props => <h2 {...textMap(props)} />
// etc.

Does this seem like the right way to go about it?

@shawnbot
Copy link
Contributor Author

shawnbot commented May 23, 2018

I feel like we could also use a shorthand for those component definitions that looks something like this, which would give us the withComponent() class method:

function createPrimerComponent(Element, mapProps) {
  const Component = props => <Element {...mapProps(props)} />
  Component.withComponent = other => createPrimerComponent(other,  mapProps)
  return Component
}

const Box = createPrimerComponent('div', boxMap)
const Text = createPrimerComponent('span', textMap)
const Heading = Text.withComponent('h1')
Heading.h1 = Heading
Heading.h2 = Heading.withComponent('h2')
// etc.

@emplums
Copy link

emplums commented May 23, 2018

We chatted about this IRL this morning and decided that as a first step we'll just include all the Primer utilities in the utility map, and then later on improve the mapping to split utilities into different groups and possibly restrict certain utilities from being used on certain components ❇️

@shawnbot
Copy link
Contributor Author

shawnbot commented May 23, 2018

One thing I suggested was using decorators to return modified versions of components, e.g.

import {whitelist} from './utils/decorators'

@whitelist('id', 'hidden', 'aria-*')
export default class Component {
  render() {
    // the whitelist() decorator would modify the props by moving id, hidden,
    // and aria-* props into a "whitelisted" object prop
    const {x, whitelisted, children} = this.props
    return (
      <div className={`util-${x}`} {...whitelisted}>
        {children}
      </div>
    )
  }
}

For functional components it would look something like this:

import {whitelist} from './utils/decorators'

const Component = ({x, whitelisted, children}) => (
  <div className={`util-${x}`} {...whitelisted}>
    {children}
  </div>
)

export default whitelist('id', 'hidden', 'aria-*')(Component)

One benefit of this approach is that the decorator function could return a component class with propTypes that include the whitelisted keys.

@shawnbot
Copy link
Contributor Author

shawnbot commented Jun 7, 2018

It seems like we're not ready for this level of unification across all components, so I'm going to close this as OBE for now.

@shawnbot shawnbot closed this as completed Jun 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants