Embeddable editor
See original GitHub issueA few companies have embedded Maputnik in their website now. All of the current implementations are a number of custom modifications on top of Maputnik. This is neither good for Maputnik or the people embedding the editor.
We lose out because Maputnik doesn’t get updated when we release a new version. Over the years we received a few bug reports about Maputnik being broken, when its nothing to do with the current release of the editor.
Lucky for us the latest of these companies has reached out before proceeding with their custom implementation. I’ve been in contact with them and they are willing to sponsor this development, the company is @fielda (👋 Fielda)
To be open with the community here’s how the work will be split up. I will be breaking apart Maputnik into an npm installable set of react components to make it easy to embed Maputnik in a react application. This will also include adding additional configuration for Maputnik such as changing the styles shown in the ‘open’ modal, changing the sources in the ‘data sources’ modal and removing keys from the export modal. There will also be a private part of the work I’ll do outside of the Maputnik organisation to integrate Maputnik within their application which will mainly involve custom styling.
The initial needs of @fielda will be prioritised for embedding this into their application. However nothing within the Maputnik codebase will be written with only them in mind, and everything written should be generally useful. However saying that, anything that’s not initially a priority for this integration will probably be fleshed out later down the road.
I hope everyone agrees this is a positive thing for Maputnik and adds a feature set useful for many many organisations. Also hopefully it’ll allow folks to build Maputnik into products we haven’t even considered yet.
This is personally the first paid piece of development for Maputnik that I have done, so thanks again to @fielda for supporting this feature.
It’s also worth noting that the current publicly accessible editor will have no noticeable changes to the user.
Implementation
The new embeddable interface for the editor has the following requirements
- Custom arrangement of parts of the editor, mainly for alternate placement/replacement of the toolbar
- Change styling to use CSS variables, to allow for custom colors/spacing
- Move all icons into CSS so they can be modified by CSS variables
- Custom modal component, to match internal modals of host app (TBD this might be complex)
Here is an example implementation (subject to change)
import '@maputnik/editor/css/default.css';
import {Editor, EditorState} from '@maputnik/editor';
class SimpleCustomEditor extends React.Component {
constructor () {
super(props);
this.editor = new EditorState({
style: {
// osmLiberty...
},
settings: {
styles: [
// Default styles in the editors open modal
],
sources: [
{
name: "Foobar transport",
id: "foobar_transport",
data: {
type: "tilejson",
url: "http://example.com/foobar.geojson",
},
},
],
"layer_editor": {
"json_editor": {
"visiblity": "collapsed"
},
},
"keyboard_shortcuts": {
enabled: false,
},
renderers: [
"mapbox-gl",
"openlayers",
],
}
});
this.editor.on("change", newState => {
this.setState({editorState: newState});
});
}
render () {
const {editorState} = this.state;
return (
<Editor
className="maputnik-custom"
editorState={editorState}
/>
);
}
}
A more complex example where we include an imaginary custom toolbar.
import '@maputnik/editor/css/default.css';
import {Map, EditorContent, EditorState} from '@maputnik/editor';
// Because the maputnik toolbar is simple we can easily replace it with a
// totally custom one.
import MaputnikCustomToolbar from './MaputnikCustomToolbar';
class AdvancedCustomEditor extends React.Component {
constructor () {
// Same as before...
}
render () {
const {editorState} = this.state;
return (
<div className="maputnik-custom">
<div className="maputnik-custom__top">
<MaputnikCustomToolbar editorState={editorState} />
</div>
<div className="maputnik-custom__main">
<div className="maputnik-custom__main__left">
<EditorContent editorState={editorState} />
</div>
<div className="maputnik-custom__main__right">
<Map editorState={editorState} />
</div>
</div>
</div>
);
}
}
The CSS variables are to be named via the following conventions. Root level variables which effect the UI in it’s entirety. These have the following convention
/*[1 ]-[2 ]*/
--maputnik-font-size-1: 26px;
/**
* 1. namespace - always 'maputnik'
* 2. name - a name decribing what's being configured
*/
Component level variables have the following convention
/*[1 ]-[2 ]-[3 ]-[4 ]*/
--maputnik-popup-layer-header-border-color: #000;
/**
* 1. namespace - always 'maputnik'
* 2. group - name of component
* 3. sub-group - section of component
* 4. property - the property you want to change, this mostly corrosponds to
* the underlying CSS property although other part of that UI could also use
* these along with CSS filters
*/
Following are some examples from my working copy of the new implementation
.maputnik-custom {
/* Root level */
--maputnik-font-family: sans-serif;
--maputnik-font-size-1: 26px;
--maputnik-font-size-2: 22px;
--maputnik-font-size-3: 20px;
/* Component level */
--maputnik-link-color: #333;
--maputnik-link-hover-color: #a2a2a2;
--maputnik-popup-layer-background-color: white;
--maputnik-popup-layer-color: #000;
--maputnik-popup-layer-header-background-color: #fafafa;
--maputnik-popup-layer-header-color: #000;
--maputnik-popup-layer-header-border-color: #e8e8e8;
/* more... */
}
You’ll also be able to override specific features via .maputnik-<component> {/* rules... */}
however these are more likely to break between versions so should be only used where absolutely necessary.
FAQs
Why CSS modules rather than something else like styled components?
CSS modules are standard web functionality, so will be around for a long time. We also use a bunch of different off the shelf libraries and React components. Standard CSS styling/overrides tend to work best with this approach as they always work regardless of the underlying tech.
Why are we adding support for all the companies to change the look and feel of the editor why not just Maputnik?
Companies want an integrated experience and having companies contributing time/money to Maputnik is good for everyone. It also opens the possibility for things like
- A university creating an intro to cartography online course embedding Maputnik
- Newsrooms could embed Maputnik into the end of a process to create simple maps. In future you could have locked layers and only allow changing of colors with a ‘on brand’ color palette (future work)
I think there is lots of future opportunity here.
Won’t this make future development of Maputnik harder?
The Maputnik editor will use the same React components in the existing editor, so it’ll make a slight difference in that we’ll have to be more careful with styling changes. However having already started some of the styling/theming work and it has forced me to tidy up some of our CSS, which has made it a lot nicer.
Feedback
Please let me know any thoughts in the comments below.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:6 (5 by maintainers)
Top GitHub Comments
Sure @orangemug, please go ahead! 😃
I think we’ve reached a point which many open source projects are reaching when the popularity increases: The questions if it’s possible to turn from the time investing in a hobby project and learning experience into a (part-)time job. As you’ve described, the work for @fielda sounds like a good opportunity that fit’s also well in your current situation. I really appreciate that you’re thinking about ways how the whole project could benefit from this.
@orangemug @pathmapper Thanks a lot for your work on Maputnik! I have started integrating maputnik in Baremaps (A pipeline for creating and styling custom vector tiles) and I face an issue similar to the one described here. At the moment, I forked maputnik in the baremaps organisation, did some modifications, built it, and copied the build directory in my app. I tried without success to install and use maputnik as a npm dependency. Is this something that will be addressed with this issue?