Skip to content

SubComponent

esr360 edited this page Feb 29, 2020 · 12 revisions

SubComponents are an extension of Components

SubComponents differ from Components in the way they are treated. Normally when you nest a Component inside another Component, it will still be treated as a Component of the parent Module. If you want the nested Component to be treated as a Component of the parent Component, you should use <SubComponent>.

This is typically not recommended; if you find yourself using <SubComponent> often, consider whether your Modules are granular enough.

It should be noted that:

<Module name='header'>
  <Component name='navigation'>
    <SubComponent name='item'>Nav Item</SubComponent>
  </Component>
</Module>

Is equivalent to:

<Module name='header'>
  <Component name='navigation'>
    <Component subComponent={true} name='item'>Nav Item</Component>
  </Component>
</Module>

Passing Styles To Sub-Components

Passing sub-component styles is similar to passing Component styles - they should be contained within an object whose key is named after the sub-component's name prop, and the object should exist within the main Component's object.

The name prop for the main <Module> element is optional (learn more)

const styles = {
  navigation: {
    item: {
      // ... some styles
    }
  }
}

const Header = (props) => (
  <Module name='header' styles={styles} {...props}>
    <Component name='navigation'>
      <SubComponent name='item'>Nav Item</SubComponent>
    </Component>
  </Module>
);

All Lucid styling-concepts work with sub-components:

const styles = {
  navigation: ({ state }) => ({
    clear: state.inline && 'both',

    item: ({ state, context }) => ({
      fontWeight: 'bold',

      ...(context.navigation.inline && {
        float: 'left',
        paddingLeft: state.isFirstChild ? 0 : '1em'
      })
    })
  })
}

const Header = (props) => (
  <Module name='header' styles={styles} {...props}>
    <Component name='navigation' inline={props.inlineNav}>
      <SubComponent name='item'>Nav Item</SubComponent>
    </Component>
  </Module>
);

...or you could avoid using context by passing the navigation options down to the item element:

const styles = {
  navigation: (navigation) => ({
    clear: navigation.state.inline && 'both',

    item: ({ state }) => ({
      fontWeight: 'bold',

      ...(navigation.state.inline && {
        float: 'left',
        paddingLeft: state.isFirstChild ? 0 : '1em'
      })
    })
  })
}

...either way, it would be used like so:

<Header inlineNav />