score:0

we went for overriding behaviour. in some cases you want to add your class in some others you want to override them, but i don't think we can't have both at the same time.

score:0

similar to one of the other solutions, but more robust to work with additional classes. we can use object.values(classes).join(' ') to join all the classes passed to to the textinput component.

note that i also had to give the class a different key. classes={{root: classes.input}} became classes={{input: classes.input}}.

const { component } = react;
const { render } = reactdom;
const injectsheet = reactjss.default;

// textinput.jsx
const textinput = (() => {
  const styles = {
    root: {
      border: '1px solid #ccc',
      borderradius: 3,
    }
  };
  const textinput = ({ classes, ...rest }) => (
      <input classname={object.values(classes).join(' ')} type="text" {...rest} />
  );
  return injectsheet(styles)(textinput);
})();

// inputfield.jsx
const inputfield = (() => {
  const styles = {
    root: {
      display: 'inline-flex',
    },
    label: {
      marginright: 5,
      width: 40,
    },
    input: {
      width: 80,
    },
  };
  const inputfield = ({ classes, id, label }) => (<span classname={classes.root}>
      <label classname={classes.label} htmlfor={id}>{label}</label>
      <textinput classes={{input: classes.input}} id={id} />
    </span>
  );
  return injectsheet(styles)(inputfield);
})();


// demonstration
class app extends component {
  render() {
    return (
      <dl>
        <dt>without wrapper:</dt>
        <dd><textinput /></dd>
        <dt>with wrapper:</dt>
        <dd><inputfield id="f" label="foo"/></dd>
        <dt>what i want:</dt>
        <dd><inputfield classes={{input: 'generated-by-textinput-root generated-by-inputfield-input'}} id="b" label="foo"/></dd>
      </dl>
    );
  }
}

render(<app />, document.getelementbyid('root'));
.generated-by-textinput-root {
  border: 1px solid #ccc;
  border-radius: 3px;
}

.generated-by-inputfield-input {
  width: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jss/9.8.7/jss.min.js"></script>
<script src="https://unpkg.com/react-jss@8.6.1/dist/react-jss.min.js"></script>
<div id="root"></div>

score:0

i have created an issue to investigate if we can/should add the merging behavior to react-jss https://github.com/cssinjs/jss/issues/933

score:1

here is an alternative way to approach the problem. instead of trying to pass a class from the parent to be merged in with the child's classes, influence the child using the parent's styles (e.g. '& > input': { width: 80 }).

const { component } = react;
const { render } = reactdom;
const injectsheet = reactjss.default;

// textinput.jsx
const textinput = (() => {
  const styles = {
    root: {
      border: '1px solid #ccc',
      borderradius: 3,
    }
  };
  const textinput = ({ classes, ...rest }) => (
    <input classname={classes.root} type="text" {...rest} />
  );
  return injectsheet(styles)(textinput);
})();

// inputfield.jsx
const inputfield = (() => {
  const styles = {
    root: {
      display: 'inline-flex',
      '& > input': {
        width: 80
      }
    },
    label: {
      marginright: 5,
      width: 40,
    }
  };
  const inputfield = ({ classes, id, label }) => (
    <span classname={classes.root}>
      <label classname={classes.label} htmlfor={id}>{label}</label>
      <textinput id={id} />
    </span>
  );
  return injectsheet(styles)(inputfield);
})();


// demonstration
class app extends component {
  render() {
    return (
      <dl>
        <dt>without wrapper:</dt>
        <dd><textinput /></dd>
        <dt>with wrapper:</dt>
        <dd><inputfield id="f" label="foo"/></dd>
      </dl>
    );
  }
}

render(<app />, document.getelementbyid('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jss/9.8.7/jss.min.js"></script>
<script src="https://unpkg.com/react-jss@8.6.1/dist/react-jss.min.js"></script>
<div id="root"></div>

score:2

i think you want something along the lines of the following:

...
const textinput = ({ classes, classesfromparent, ...rest }) => (
    <input classname={classes.root + ' ' + classesfromparent.root} type="text" {...rest} />
);
...
const inputfield = ({ classes, id, label }) => (
    <span classname={classes.root}>
      <label classname={classes.label} htmlfor={id}>{label}</label>
      <textinput classesfromparent={{root: classes.input}} id={id} />
    </span>
);

Related Query

More Query from same tag