2
votes

I have a need to style a MaterialUI.List component wrapped in MakeSelectable(). I'd like to do this via the MUIThemeProvider using a custom theme, but can also use the inline styles override if necessary. The problem is, it appears I cannot override any of the listItem styles unless I modify values on the palette property of my theme, which affects all material-ui components.

Here is my theme file:

import * as colors from 'material-ui/styles/colors';
import vstColors from './vst-colors.js.es6';
import spacing from 'material-ui/styles/spacing';
import zIndex from 'material-ui/styles/zIndex';
import { fade } from 'material-ui/utils/colorManipulator';
let { tints } = vstColors;
const BLMTheme = {
    spacing: spacing,
    zIndex: zIndex,
    fontFamily: 'Roboto, sans-serif',
    palette: {
        primary1Color: colors.blue800,
        primary2Color: colors.lightBlue800,
        primary3Color: colors.lightBlack,
        accent1Color: colors.orange200,
        accent2Color: colors.grey100,
        accent3Color: colors.grey500,
        textColor: colors.white,
        alternateTextColor: colors.white,
        canvasColor: colors.white,
        borderColor: colors.grey300,
        disabledColor: fade(colors.darkBlack, 0.3),
        pickerHeaderColor: colors.cyan500
    },
    tabs: {
        backgroundColor: colors.grey300,
        selectedTextColor: colors.grey50,
        textColor: colors.grey700
    }
};

export default BLMTheme;

Here is my SelectableList component

import BooklistItemsAPI from '../../api/booklistItemsAPI.js.es6';
import BooklistHelper from '../../helpers/booklistHelper.js.es6';
import vstColors from '../../helpers/vst-colors.js.es6';
import constants from '../../helpers/constants.js.es6';
import Time from 'react-time';
import { default as NewBooklistDialog } from '../booklists/addEdit/NewBooklistDialog.es6.jsx';

/** Redux Store Actions */
import { setBooklistDetailAlert } from '../../stores/actions/alertActions.js.es6';
import { setBooklistDetailPager } from '../../stores/actions/pagerActions.js.es6';
import {
    setBooklistItems,
    toggleSelectAllState,
    setNavigationIndex,
    setFilter,
    deleteFilter
} from '../../stores/actions/booklistActions.js.es6';

let SelectableList = MaterialUI.MakeSelectable(MaterialUI.List);
let { count, status, resource } = constants;
let { colors, tints } = vstColors;

function wrapState(ListComponent){

    class SelectableList extends React.Component {
        constructor(props){
            super(props);
            this.state = {};
            this._onSelect = this._onSelect.bind(this);
        }

        componentWillMount(){
            this.setState({
                selectedIndex: this.props.defaultValue
            });
        }

        _onSelect(e, index){
            let { counts, filters, pager, batchActions } = this.props;
            let _status = e.currentTarget.dataset.status || null,
                _itemCount = BooklistHelper.getCountsByStatus(counts, _status);

            this.setState({
                selectedIndex: index
            });

            batchActions(
                [
                    setBooklistDetailAlert(true, 'Loading Titles...'),
                    setFilter('page', 1),
                    setBooklistDetailPager(1, pager.size, _itemCount),
                    setNavigationIndex(index),
                    (() => {
                        return (_status === null) ?
                            deleteFilter('status') : setFilter('status', _status);
                    })()
                ]
            );

            setTimeout(()=>{
                BooklistItemsAPI
                    .getBooklistItems(BLM.currentContext.booklistId, filters)
                    .then(response => {
                        batchActions(
                            [
                                setBooklistItems(response),
                                toggleSelectAllState(),
                                setBooklistDetailAlert(false, '')
                            ]
                        );
                    });
            }, 50);
        }

        render(){
            let { children } = this.props;
            return (
                <ListComponent
                    value={ this.state.selectedIndex }
                    onChange={ this._onSelect }>
                    { children }
                </ListComponent>
            );
        }
    }

    return SelectableList;
}

export const StatefulList = wrapState(SelectableList);

const BooklistDetail_NavPanel = class BooklistDetail_NavPanel extends React.Component {
    constructor(props){
        super(props);
    }

    render(){
        let { booklist, counts, company } = this.props;
        let _listItemStyles = {
            color: tints.CLOUD_1,
            backgroundColor: tints.CLOUD_6
        };

        return (
            <section className="blm-booklist-nav__container">
                <header className="blm-booklist-nav__header">
                    <div className="row">
                        <div className="col-md-12 text-center">
                            <h5 className="vst-color--sangria">
                                { ((company && company.name) || '') }
                            </h5>
                            <h1>
                                { booklist.name }
                            </h1>
                            <p className="blm-booklist-nav__last-updated">
                                last updated&nbsp;
                                <Time value={ booklist.updated_at } format="MM/DD/YY" />
                            </p>
                        </div>
                    </div>
                    <div className="btn-group-xs text-center blm-booklist-nav__header-links">
                        <NewBooklistDialog create={ false }
                                           title={ "Add Items to: " + booklist.name }
                                           buttonStyle="link"
                                           buttonSize="small"
                                           { ...this.props }
                        />
                        <a title={ "Export " + booklist.name } href={ "/booklists/" + booklist.id + "/export"} className="btn btn-link blm-booklist__icon-link">
                            <i className="blm-icon--circle-export" />
                        </a>
                    </div>
                </header>
                <section className="blm-booklist-nav__selectable-list-container">
                    <StatefulList className="blm-booklist-nav__selectable-list" defaultValue={1} { ...this.props }>
                        <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_TOTAL"
                                             className="blm-booklist-nav__selectable-list__item"
                                             primaryText={'All Books (' + counts['TOTAL'] + ')'}
                                             value={1}
                                             style={_listItemStyles}
                        />
                        <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_NEEDSATTENTION"
                                             className="blm-booklist-nav__selectable-list__item"
                                             primaryText={'Needs Attention (' + counts[status.NEEDS_ATTENTION] + ')'}
                                             value={2}
                                             data-status={ status.NEEDS_ATTENTION }
                                             initiallyOpen={true}
                                             autoGenerateNestedIndicator={false}
                                             nestedItems={[
                                            <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_ADDRIGHTS"
                                                                 className="blm-booklist-nav__selectable-list__item"
                                                                 value={3}
                                                                 primaryText={ 'Adopt (' + counts[status.ADD_RIGHTS] + ')'}
                                                                 data-status={ status.ADD_RIGHTS } />,
                                            <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_REQUESTRIGHTS"
                                                                 className="blm-booklist-nav__selectable-list__item"
                                                                 value={4}
                                                                 primaryText={ 'Request Rights (' + counts[status.REQUEST_RIGHTS] + ')'}
                                                                 data-status={ status.REQUEST_RIGHTS } />,
                                            <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_UNAVAILABLE"
                                                                 className="blm-booklist-nav__selectable-list__item"
                                                                 value={5}
                                                                 primaryText={ 'Unavailable (' + counts[status.UNAVAILABLE] + ')'}
                                                                 data-status={ status.UNAVAILABLE } />,
                                            <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_FULFILLMENT"
                                                                 className="blm-booklist-nav__selectable-list__item"
                                                                 value={6}
                                                                 primaryText={ 'Fulfillment (' + counts[status.FULFILLMENT] + ')'}
                                                                 data-status={ status.FULFILLMENT } />
                                         ]}
                        />
                        <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_AVAILABLE"
                                             className="blm-booklist-nav__selectable-list__item"
                                             primaryText={'Available (' + counts[status.AVAILABLE] + ')'}
                                             value={7}
                                             data-status={ status.AVAILABLE } />
                        <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_REQUESTED"
                                             className="blm-booklist-nav__selectable-list__item"
                                             primaryText={'Submitted Requests (' + counts[status.REQUESTED] + ')'}
                                             value={8}
                                             data-status={ status.REQUESTED } />
                        <MaterialUI.ListItem data-blm-id="blmNavPanelStatus_DENIED"
                                             className="blm-booklist-nav__selectable-list__item"
                                             primaryText={'Denied Requests (' + counts[status.DENIED] + ')'}
                                             value={9}
                                             data-status={ status.DENIED } />
                    </StatefulList>
                </section>
            </section>
        );
    }
};

BLM.components.BooklistDetail_NavPanel = BooklistDetail_NavPanel;
export default BooklistDetail_NavPanel;

I've tried adding (just as a test)

listItem: {
    textColor: '#ffffff',
    backgroundColor: '#505050'
}

to my BLMTheme, but that has no impact. If I use the inline:

style={{ color: '#ffffff', backgroundColor: '#505050' }}

the text color gets set correctly, but the backgroundColor does not. In all of material-ui's documentation on theming and customizing, and even looking at the source code for listItem on github, it is not readily apparent just which styles can be passed, either via the BLMTheme or the inline { style } attribute, and have them applied to the listItem.

So, the question is...how in the hell do you style this component, and style it independently of other selectable list components in the app?

EDIT

I should note that I am aware I can do this using !imporant in the .sass files to override the inline styles. However, this doesn't allow me, for example, to change the styles for the :selected state of the listItem. What I'm really looking for is a map of what properties from the muiTheme correspond to the default textColor, backgroundColor, hoverColor, selectedColor, etc of the ListItem component. There is no documentation on the material-ui.com website that provides this information.

2
Maybe your solution is to use separated MuiThemeProvider for each ListItem? I don't like it, but the other way may couse to write your own components after a long digging in the source codeOleg Pro

2 Answers

1
votes

I realize you may have already come to a solution for this but..

Basically, each material-ui component has a key that you can use to override the styles of said component in the programmatic method you are looking for. In your case, it would be

list: { //custom style overrides here }

You can read more here

And more specifically Showing component override keys

As for a map to it all I'm sorry to say I don't know of one but if you just read the source code for the component you are trying to override, you will see what you need to put in the style override.

You can view the components here:

https://github.com/callemall/material-ui/tree/master/src

0
votes
listItem: {
    textColor: '#ffffff !important',
    backgroundColor: '#505050 !important'
}

this should fix the problem I think