Quill: combining snow theme with bubble theme

Created on 5 Mar 2018  路  3Comments  路  Source: quilljs/quill

Hi,
is there a theme that combines both snow and bubble themes ?
or a way to show the toolbar and the when the user select a text the tooltip toolbar shows up like in bubble theme ?

Thanks !

Most helpful comment

@ahmadyousefdev @jhchen themes are mutually exclusive only in css/styles part. If we talking about behavior/js part then with small tuning you can combine for example styles from snow theme and behavior from bubble theme.

That's how I've implemented this combination in React-component:

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';

import Quill from 'quill';
import 'quill/dist/quill.snow.css'; // adding css styles for `snow` theme

import debounce from 'lodash/debounce';

import styles from './style.scss';

class QuillEditor extends PureComponent {
  static propTypes = {
    html: PropTypes.string
  };

  constructor (props) {
    super(props);
    this.editor = React.createRef();
    this.config = {
      theme: 'snow',
      modules: {/* modules config */} };
  }

  componentDidMount () {
    this.attachQuill();
  }

  attachQuill () {
    this.quill = new Quill(this.editor?.current, this.config);
    this.toolbar = this.quill.getModule('toolbar');
    this.toolbar.container.style.visibility = 'hidden';

    this.quill.on('selection-change', this.onSelectionChange);
    this.setDefaultContent();
  }

  setDefaultContent = () => {
    const quote = this.quill.clipboard.convert(this.props.html || '<p> </p>');
    this.quill.setContents(quote, Quill.sources.SILENT);
    this.quill.setSelection(this.quill.getLength(), 0, Quill.sources.SILENT);
  };

  onSelectionChange = range => {
    const toolbarElement = this.toolbar.container;

    if (range) {
      if (range.length === 0) {
        this.hideInactiveToolbar();
      } else {
        const { top, left } = this.quill.getBounds(range);
        const shift = 49;
        toolbarElement.style.visibility = 'visible';
        toolbarElement.style.position = 'absolute';
        toolbarElement.style.top = `${top - shift}px`; // TODO need additional calculation for edge cases
        toolbarElement.style.left = `${left}px`;
      }
    } else {
      this.hideInactiveToolbar();
    }
  };

  hideInactiveToolbar () {
    const element = this.toolbar?.container;
    const isToolbarFocused =
      element &&
      (element.contains(document.activeElement) ||
        element === document.activeElement);
    if (!isToolbarFocused) {
      element.style.visibility = 'hidden';
    }
  }

  render () {
    return (
      <div className={ styles.editor }>
        <div role="application" ref={ this.editor } className={ styles.quill } />
      </div>
    );
  }
}

export default QuillEditor;

Screen Shot 2020-04-23 at 3 32 45 PM

All 3 comments

Maybe you can add your own theme and rebuild the source code. or here is an example Final Polish using Quill API

Officially supported themes are currently mutually exclusive.

@ahmadyousefdev @jhchen themes are mutually exclusive only in css/styles part. If we talking about behavior/js part then with small tuning you can combine for example styles from snow theme and behavior from bubble theme.

That's how I've implemented this combination in React-component:

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';

import Quill from 'quill';
import 'quill/dist/quill.snow.css'; // adding css styles for `snow` theme

import debounce from 'lodash/debounce';

import styles from './style.scss';

class QuillEditor extends PureComponent {
  static propTypes = {
    html: PropTypes.string
  };

  constructor (props) {
    super(props);
    this.editor = React.createRef();
    this.config = {
      theme: 'snow',
      modules: {/* modules config */} };
  }

  componentDidMount () {
    this.attachQuill();
  }

  attachQuill () {
    this.quill = new Quill(this.editor?.current, this.config);
    this.toolbar = this.quill.getModule('toolbar');
    this.toolbar.container.style.visibility = 'hidden';

    this.quill.on('selection-change', this.onSelectionChange);
    this.setDefaultContent();
  }

  setDefaultContent = () => {
    const quote = this.quill.clipboard.convert(this.props.html || '<p> </p>');
    this.quill.setContents(quote, Quill.sources.SILENT);
    this.quill.setSelection(this.quill.getLength(), 0, Quill.sources.SILENT);
  };

  onSelectionChange = range => {
    const toolbarElement = this.toolbar.container;

    if (range) {
      if (range.length === 0) {
        this.hideInactiveToolbar();
      } else {
        const { top, left } = this.quill.getBounds(range);
        const shift = 49;
        toolbarElement.style.visibility = 'visible';
        toolbarElement.style.position = 'absolute';
        toolbarElement.style.top = `${top - shift}px`; // TODO need additional calculation for edge cases
        toolbarElement.style.left = `${left}px`;
      }
    } else {
      this.hideInactiveToolbar();
    }
  };

  hideInactiveToolbar () {
    const element = this.toolbar?.container;
    const isToolbarFocused =
      element &&
      (element.contains(document.activeElement) ||
        element === document.activeElement);
    if (!isToolbarFocused) {
      element.style.visibility = 'hidden';
    }
  }

  render () {
    return (
      <div className={ styles.editor }>
        <div role="application" ref={ this.editor } className={ styles.quill } />
      </div>
    );
  }
}

export default QuillEditor;

Screen Shot 2020-04-23 at 3 32 45 PM

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rsdrsd picture rsdrsd  路  3Comments

splacentino picture splacentino  路  3Comments

markstewie picture markstewie  路  3Comments

aletorrado picture aletorrado  路  3Comments

emanuelbsilva picture emanuelbsilva  路  3Comments