Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Recommended way to create styles on-the-fly? #52

Closed
brandondurham opened this issue Feb 23, 2016 · 13 comments
Closed

Recommended way to create styles on-the-fly? #52

brandondurham opened this issue Feb 23, 2016 · 13 comments

Comments

@brandondurham
Copy link

In a previous project similar to Draft.js I used JSS to create a dynamic stylesheet that I could manage classes and styles in real-time. Primarily for things like changing text color to a user-selected color, or changing font-size to something the user selects. This allowed for a lot of flexibility, but also meant that the styles didn’t have to be created up front. They were created on-the-fly, as the user selected them.

Is there a recommended way to create classes and/or styles (mostly inline) on-the-fly and applying to the selection?

@hellendag
Copy link

Take a look at the "Color" editor example. This example should give you an idea of how inline styles can be named and defined via the customStyleMap prop. In the "Color" example, the styles are treated as mutually exclusive (since it's font color) but inline styles do not have to be mutually exclusive in this way.

For instance, we could include something like this within the customStyleMap with color values in it:

small: {
  fontSize: '8px',
},
medium: {
  fontSize: '12px',
},
large: {
  fontSize: '16px',
},

Then, by using RichUtil, you could add these styles to ranges as needed. Characters could then have styles like OrderedSet(['small', 'red']) or OrderedSet(['large', 'blue']).

At render time, these style values will be merged. In this way, you can define distinct inline styles and let React (more specifically, DraftEditorLeaf) worry about merging the values together.

Does this help?

@brandondurham
Copy link
Author

I think I’ve got that part figured out thus far, and it’s working wonderfully. My question is more about the CSS property values themselves, and whether or not they can be dynamic.

Here’s the thing: I’m working with many hundreds of font styles (~700) that each require their own CSS properties (font-family, font-style and font-weight). I could create the styles for every possible font file that may be loaded up front, but that would clearly be a lot more data for the user to load than is really necessary.

So, I’m wondering if there is a way to make the value of the CSS property dynamic, and only set when requested by the user?

For instance, say I have a select menu with 100 different fonts in it that the user can choose from. To avoid preloading 100 fonts worth of CSS classes/properties, I’d like to only create and apply them when requested. So when selecting “Fancy Font Number 5” in the menu I need to:

  • Create the CSS class and properties (font-family, font-style and font-weight);
  • Load the font file with a Webpack require; and
  • Apply the CSS class to the selection.

Can I add styles to the customStyleMap object after the Editor is already mounted?

For what it’s worth, I’ve been working on a proprietary tool very much like Draft.js for the last 6 months or so using Rangy, Scribe and JSS. This is what I currently do when the user selects a font to load:

loadFont = () => {
    const {
        selectedFamily,
        selectedStyle,
        sheet
    } = this.props;

    // Stop here if user hasn’t selected a style yet
    if (!selectedFamily || selectedFamily === null || selectedStyle === null) return false;

    // Create the CSS based on the product data
    const fontStyles = {
        'font-family': selectedStyle.value,
        'font-style': selectedStyle.style,
        'font-weight': selectedStyle.weight
    };

    // Create CSS class
    const className = fontClassName(selectedFamily.label, selectedStyle.id);

    // Add the CSS to the JSS sheet
    const theRule = sheet.addRule(`.${className}`, fontStyles, { named: false });

    global.scribe.transactionManager.run(() => {
        // Create the CSS class and inline styles based on the font
        // parameters passed in from the JSON
        theRangyClass = rangy.createClassApplier(className, {
            applyToEditableOnly: true,
            tagNames: ['p'],
            useExistingElements: true
        });

        // Apply the class and styles to the selected text
        theRangyClass.applyToSelection();
    });

    // Load the font CSS and associated file
    require(`font/css/${selectedStyle.value}.css`);

    // Return the JSS generated className
    return theRule.className;
};

@hellendag
Copy link

Can I add styles to the customStyleMap object after the Editor is already mounted?

You can define a new customStyleMap to pass in as the prop, though that won't currently trigger a re-render of the entire editor if the ContentState hasn't changed along with it.

What we could do is make customStyleMap an immutable Map (which we probably should have done anyway), then allow a full re-render if it changes so that the newly defined styles can be picked up. That way, when you want to load your fonts, once they are available you could create a new customStyleMap and pass it through.

@brandondurham
Copy link
Author

That sounds nice.

@kalaxiya
Copy link

What we could do is make customStyleMap an immutable Map (which we probably should have done anyway), then allow a full re-render if it changes so that the newly defined styles can be picked up. That way, when you want to load your fonts, once they are available you could create a new customStyleMap and pass it through.

so it means I could also show a color picker to select a wathever color ?

@tylercraft
Copy link
Contributor

PR landed and fixed the issue, so closing this out.

@davidchang
Copy link
Contributor

@Linzerui super super late response, but yes - it seems like you could achieve dynamic styles by updating the customStyleMap and referencing the class name you use in customStyleMap

@gdad-s-river
Copy link

gdad-s-river commented Nov 11, 2017

@Linzerui were you able to implement the colour picker ?

@betancourtl
Copy link

It's possible to create a color picker. Here is an example https://webdeveloperpr.github.io/draft-js-color-picker/

@betancourtl
Copy link

You can also create custom styles with this package https://www.npmjs.com/package/draft-js-custom-styles

@gdad-s-river
Copy link

@webdeveloperpr, I already stumbled upon both of these, and used it (http://bit.ly/poetry-editor) (and spent a lot of time understanding it, because I'm new to draft-js), needless to stay star-ed 'em! Kudos to you! 💛.

@rybkowskigrzegorz
Copy link

@webdeveloperpr hi, did you use your package to make this color-picker ? I'm trying to figure it out :| Do you have code for draft-js-color-picker example?

@betancourtl
Copy link

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

9 participants