Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/spacejack/mithril-modal

Modal example for Mithril.js
https://github.com/spacejack/mithril-modal

mithriljs

Last synced: about 7 hours ago
JSON representation

Modal example for Mithril.js

Awesome Lists containing this project

README

        

# Mithril Modal Examples

There are lots of ways to implement modal-style popups in a [Mithril.js](https://mithril.js.org/) app. These are a few example techniques.

## Imperative Style

Probably the most straightforward to implement and often the easiest to use. This takes the approach of conditionally rendering a single Modal component at the top level of the DOM, at the very end of the top level nodes. This placement in the DOM ensures it will render over everything else.

Visibility of the modal is controlled by a simple `isOpen` flag, which is changed by calling the `openModal` and `closeModal` functions. The `openModal` function also accepts some paramters for content that should be rendered in the Modal.

[Flems demo](https://flems.io/#0=N4IgzgpgNhDGAuEAmIBcICGAHLA6AVmCADQgBmAljEagNqgB2GAthGiLgBbzNQkiwA9g0Qj2IAL7FGLNumaCkGKASKkhIiGPQB6AFR6AOgwAC8AJ5ZkEMgAJgwY4fjwK8GKlth4AJwoMAcyd4DVF4AH5PDAZzYIAjAFcXYTBI+wokT28-QIBuW0QAD3gs338AiVoAXWCfZB8MAHc0uMFBGGjg4VgoClgAa3CACgzSnICASk8AN0EM4wkJWwB5LFcU4z0dJwZ9PVszSwh7VfWGMCWt4xh4W0E1ihTbAF57V3cITwByAFlFZS+EmuEFuFDAqy0L1sZGUkB2e2Mtn2JiwGAazBODxSS3u8DAiKuDAghSwgh8tzICQYCEeDDuVgYfyUUFsQ1xYAm9mCOh0tgAIhAIFhbEIsOYCpxjmAEjhesh6XjgmCIXTXr4EhAuljzlDgLh9eygQxnLjaWBcIlkjrXuyLUl4E9wgrzZaHedcMxsEM4i8AHysvX6uISCaczzVbm8gBK9Satji4qQNgwCSgtyp1DAIuUMB8XhlWDqYEgSCVdjZ2vNdSQDUaL1eDFTLIAPs2FWbcNXa-W1T4NZzHMb4M5mJ3Y40hhNgkajcY9rYAMI5rNduMJ2xJmGp9MMTPZqAwJC2RpuTi2AAGMKgkHPSO2RJJZIpVJpwhFUEEkCZylZq7rvf7Lkh2VBkoSvOEhx5WwYxrNdE2TbdbAzCBi33XN8xwIsSzLX9xwHYIRzHWCJynIcZx2YlSXJaEXzOWwFGZABJcEGUnIDnDqeAEh8OkQK0BZ4QMWxvxZIRmFJIkRDvYwNG8YT-hZV5BxNBg4hsMkIDqBRpmOIZgCQQRmBDdjh3gKCABU-ACAJNNsTgMmOaIKE9M5iGPDA3GhMlbE8h1oX8MFOAI+ADNHHoMGLAAZMF4FwDAkCQIYvnspMvlI5wOJBbi6SJOsAAUfEMsEICGPNnn9ZTTOcUK4oSgBRHSRGi7wtE0pKnJc2ktCQL43J8dLTJDadiB2ZxpgoCASJMzKuJ4+iko9BTeuCkcFoY5QAFpWkKZahwy0zmCSzgAGZdv286HUrXB3hgFbTImEa9qqy6znNUItFuAAyT75q+RbmQ296RDO579tNFJcCB4cnv2h67tWv71qgLb7RSEGLpNK7XQhz0sG9P14eew6vmxhh0dB57KoximLCsb5SfJ6n9qQMEMDiQ9PAAQj4hhHqZinul6AY2KpinqZ5sDYU1GGxee8H3UFvp+lsb72whxXhbiXAMgG-n9tnWX9b5w3TK1opob1+BdYp63Ybu62BvI40Hyo25NxTNN5OZYxJGkEAmFYdhsDwQh+Ch9hnNdr3lDc4B7i0ES3KR5iVSWMhCoxP6dCR1Qvh2WTbgAQRwXVgnGybPDY8rbFoYLibinBGZ4I6AEZetsX4FP5CAFDS439uJrB26+BcheVtSPzrPz47pDB6KWuGZcHpuEYZ-uKdF6nac+Du18JsHqTHkX9+eqCVVsOekePU8JTBEVhDCfVcBPsGGREvSX+em6d6+AAJaAPzRygJzFessobfHMvZLMd9og+XEppDArgdLz2ZLYYkLAsAwFwKA6mpMwDhk-hdYAowO6CH6O3c23xljkKkIQymJCviwGiLAaAFDiQlA7kuakrCDaW2cFUdelsNb9BGEgfCMtLYWUlCgn8PRPwoQvkkQyiC+g5nFI0SUs94yo14lmHoStkB0P2rJdoEBcAfgCElUeBijxX1Jj5TIHdbAAGoHG2xNrwjx7iLqeJ8YI56Xxz4iTzhIq2-iHbryggAdWOI0aItw-JYCSLfLMV9EESmOJdWwMAdIskEHYeA0i+TLB+G5DAZBEA+GClBHMdxCm2UKoIeAG0cnQFsAwRQCiwCCB8rcOoDAkw+CzIIHSeYICjPMIU8oaDrxmOqbySBxxzwzxEreSk1I6JMLpGpJCJYL4xA0ZpY4-gMkXxwG5S08zTlXxPAeC+UA4nmCzDs4idJJR1GPJo+kWhn5PWTixLQbFVaHREgNGoDBZwMFHAoKk8AhgGVgAkVgIgLSKHMG5YuWBSK+xkIHdAkNixhwfh9dgrQkDikqp6HwAR-CeAAAy5GCKiBK5R6WMqHGQB+G0YTMCoOYLI0QwAbUgH4Mg7LnCcpEMKigAAvHeLcABsWBCjsshQ3YUlVmUs0CJ4AATD3VVOwTD9AgOYdOsgswwiTBtE5lV06GXsPcDAsA3D8tsAyg2fk46ohdRYTwLdchO2MMa015rWCWvihADaghkl2ozo6n1rr-WBuCF6p1vq3UeoEs7f6P5NWfjcLSTwlBCjIHFckLAbLggwAqVWocJ4kCFP9XSulABSctkoKABG4M2tt5a4jOv6AEQqVIkCA3aGSTw1KB1DF1QAVjncQedi7l3EDpbgAA7HOiY5aWZgEwRgN1ZAYAquCPgBI3gKBkHMOOzQIhPAsM0D4ctygu0MBtYgZg+CRQfU0uW3wgrC3CE8Om117rcBzrAC+hgzkVHAehJGm1dJ12QcNQwXNKgUrHEqh1ODDBi2IZjbcFDUHs3GAw1tQQhQTLmw2q+gI+Gf1PvLVq1lth9UYgACw91sMdHj3HmD9sHcOmNAzx0fh8J4AAxAAMTk-2qjwrODxUEI0elEGeMoZ4xx2wUmACcBmFM+EGdJhcZnbAt2VV4doGQ0PkaRresIJkqU0vfa0ZIzB-UGrI+hhzeDtFWmc2iVz9KLPeYhT7CQAiQC9AYP0Gg9B-ayHYLywpfg+CkG4nwdA3B4BYHwTyKkWAh2Q0MtnU86WTAt1wNVhV5W0tUFUPwbe7AwCwD8GsSQVQJBAA)

See the `imperative` directory in this repo for sources.

### Caveats

While you can open a modal from anywhere in your app, this approach requires that you render the Modal component itself in a root-level component. This implementation can only render one modal at a time (though it could be developed further to handle a stack of modals.)

## Declarative (Portal) Style

This technique uses a portal-like technique to append a DOM node to the end of the document body and temporarily mounts a separate vnode tree there. When the modal is removed, that DOM node and vnode tree are cleaned up.

This allows you to declaratively render a modal component nested anywhere within your vdom.

[Flems demo](https://flems.io/#0=N4IgtglgJlA2CmIBcBWAzAOgOwCYA0IAZhAgM7IDaoAdgIZiJIgYAWALmLCAQMYD21NvEHIQIAL54a9RiACyfKLVgYAVuV4ChIpv2qk2AAgVLYhgLyHCAV2o82EAQAoAlIeAAdaocMIjUPjAvDzY-Qx4WEigAJ2Fg70MAekTDAGEtWghqeGjwwIAHAWEjAHd4QzA+WyM2PkNaQ2i+PjYAWgQAN3gzABEAeTlDakV4Lx89A2NFZXTBTOzcy09qEJCOiHgSpENXCwA+cMjYGLiVtnF4n1i2a2jvZZ8fAR5Y2iEnDrcHx-Gjk+9LB0MBEorEVgkfslDABBfL5YRQeoVaZmPRseY5Qy1LEscoIwx8QiGABGigAnmMfoYAmALNS+DxrAxBMDXkIAKIIZlsJwAcigEA6vJclMhKQAKrjkaZwrBaKRSIYWPKkYRaFB4K0svVqBAwG9HOCqfSwMC5QqAHIyOm8yqmXmix4BRncjCkqBkjC0OEI1J-Jw0kUQx5QhTVJGkeD5WjRN7lABq-UGbFi5VxsUdPlNlWqAcCeCmplm6KyOSDP0kjoExPghD4sWs+SU70+7kzh1BwjpQJBxzBjsrwertfrOXglS62w+ww1bnMB2+YphMCRPHNipKEDYLCs6s1VSM8AAHludXqDQJ2zSzfLSAAZCAGL0wPmRDXC9vXW7ebIlQwABSaSBIycRYF3bHxr3VKB2S6QQHwMYQcj5WhdX1BwimoKBeQLaJyypcR8J8QcfgEWIJ3gXZFxDFIengAwmjJHFyjtZQTSxVMMEMABVUgsgAcwqDAc0EQxN23dsoWoaxYDMFMIH4-ickVVCmNY1E-jBRpxz4Do2JYZoAGtSAwdtsyqQQ8zAAtpNkoinQZJlijdckMHI3T4D9KIrPskjHnWTYqIuBJguC7gQEjBB7ENcgmAANiQHAcAkKQQDoBhRDUDQQDRYpRAmIxYXyOkbDsDDqCoykwlIAyShMNjLDVWBI0ubSbjuNtgwCrYdjnA4wD5L04RwszXwARhwwxeXq3odOFPBRt5fJJt5VJYAgHhDJJbo+D-bE+HhbwGnU+bFuWhbgx+AbeWJaw2FqagRsuqlqONHw2DJeFthuu6Hqet6qWedbNqomrdpmukU2seBgoB4iLrhqa+kOwtlAdZ6fBcC7VjYHGoVgrttyqfid23R9pTY8nskQxFxMibwqlyIrDA6GlsdxjmQihU9N1k+ofRjAlvFqYrCUMeAumiMkyeoQTukjAtvUOjUoGCTmOahbFtzxLCCSJZ0nNE91PQgwwwbqlFDAAMitionBmhG4eu4SUVaXLBH+xG7d5Fg0BWgAJbpYDqGaAEJToxqlroFIVHa973bvugRPfjnxXtTj6vqmxO-rj1OnjsYHDNB2qIca5RI1h-PDD8-PVuDyNUdgdH8-sgG26pDvMfbez8NC+JzNzA3XWNgsiqDcLIvgaKBFikAxoADiQAAGFLpAyphgQVcL3bYURjc6rMY34rJtmXgBuSloxgASz8vhI60EVo1UgWAyW2UhUNIVpI2iCBCHvj4R+bQ+IAC94DbDGnFfIR577BS8ENYq3xr4ClltsHA444HxAAAKGXgGSQgsYGCKjVBqLU9xKSEMCO4A6tAeBbnfoYC+VdsTAFofQj6kDz793BLg-BhCZAkL3K0A8h8rBARodGDhjCxrcMpKw9hDC748IQepMRhQ+LlW2MQI88AoCAKxAdO+VVaxsGMQkTcUBtyQOXsvAApAY3ECl2A2PsQY4kdDDL8SaLYKAbs+DB2iNsaI-EPFOBwCgFAeAIlRJiXgZe2AUAuAMQKUg+Q5SMMIAgWBlJVDWAMP-Mk-jBDFG2DwYoOQDHKAUtQLUQgwCkDKRU6IBiUxfy3IabYiiPpMIwCgUgVS0IXmoNo4R2oEn9KwdQF2phWDQHKN8VC54tG7jIaIiZAyvDwOmepYp2gjDfCEEeNo1T+IjPCM0gxKDb6GAwbSAALOOQwaAnmPLAO4zx3iLJ+P4IE7YABiAAYsC9xfAjw-2VAEHqEynkwtpHcww-yACcKLQXRA1EExFqRsWGDGjAs2AToBwMnt0ae5U55jXuUgMaEgAC6BB1rUGMpQdeshIDbj-lwAgtwuBMHYGwfIjTki2HyF44EgREjspYJy7BY0MByripKrc0qSBZXCpnWQpAXgQHyHvcQtLxBAA)

See the `declarative` directory in this repo for sources.

### Caveats

The "portal" approach may have trouble if you're rendering the body tag itself with Mithril, and if the top-level dom nodes within the body are changing while the modal exists. Otherwise, it should safely co-exist with the rest of your Mithril DOM/VDOM.

## Declarative composed from re-usable parts

We might want to create a less opinionated, more re-usable declarative `Overlay` component that relies on this portal-like behaviour. Then render a `Modal` component (or anything else) within that. Here is a [Flems demo](https://flems.io/#0=N4IgtglgJlA2CmIBcBWAzAOgOwCYA0IAxgPYB2AzsQskVbAIYAO58UIBAZhAucgNqhS9MIiQgMACwAuYWO1qkp8RTRABfPIOGiQAeQBu8AE4MAnhgBWvAiUXKpNAPQAqZwB1SAFQkRyAAgNjMz8SMEYyez9GI2J9aHh-ej8OAFdYWABackIjeGUQ2OM-eAQRRQwPAEkpP18-MGIUuyg-KWI-JJZGeiN6JT8ANUcAEV0AWVbc+A7GRmUoVlb2qQlpgCNiKHMPAGEfWChc0j9yFNnYCEW2gMMTelMO3L8jhdyWiEVln38pKYqvVY3IL3AphCKKEL0Y5raakBJKFpQ0wAd1WT2REBWHz8pkaRhmjAA5OQPHF4Mi-GsUjUMelKdMXsYru0oL5GMFCkY2oxirdTFjSABzYqwFj-ZyODweWzkGqBO4PAC8ySahCkEDIAAoAJR+YBSqQIGpQYhgA1GkL7Q7KKWkNxSGVy25mHZkKT0D5FZX6u1Se1k5FIPw6vyKgB8lu41rtvrUtvtuSkKSMxx99vtZBy8D68E1+l1ab9RcIVqOob8+gwJajRwN6akjkcfgAgrN5h0CooPXD8dcVtN28QOJTNqY60WTWByybCCkylIq7kcwBRUr2TWE1n6Qna8f2ydVhjkcgAOW05cJnLMhL3Uhnc-sGA2WwwTDmpCgeyjmsnu+OfgAgDGz8MZGghTp4G6Xp+gGUYJl+PI-DReBbzADAGiaKQf1NPAgQVV0u09Iw-3rDRxzIGEOGIXIzigHM8wLW9qwOMtlUrZjo3HMjfQzUhKOopkGkMENC3rYDmxgDtCCPfwMRWZJ6AWDJGhqeAAA9MQ6UgIDAPoNRjet91NQ96GPAAZXwF0UqANx8BYd1vRNk2OOEKQABRiSAWE1fFwz1W8jLQ6zl0MRQLNlZRjA3KEdL08EoEJXDiNvNQSKLbj6zIXIhNzRieKLYDhnhGIHn7PwrxBSdJjyDA-AAVXID5hTQjCITkiRb2A0g0lgSYIEFQVjESUgHgaOjeo4ststieheokYhiAAa3If5DJkdCwKwydcO69I0vre95yfUcMGmwwvwObCwH2qQMqLAMRLjWMPDUeQWAQNV9N4MQcDQJAABYAAYMl+pAADZ1E0EAhBEGhQPGyxrAUJQVDEFx3ABOp4dm0FwjhCEUhYH5AXlYJQjxyJrmiWJ4g6DxUjpbIpmOEhbi0lpGSMRI-FZWbiEFDILkW6YMSgQaaUxHxjhWPoPGRD0pH8Kje0BQmimuaSIEIRaOypKQ2lIWrmxAzYcY+WUoUIaZCChDwYT8OEIsREbUSZPx2uxXFkwJYkK0uCkoRaWlevtznWA8Mglh5IdeWMfkpeFEoxVtZc1LmNVFj6X5EieUzkjoYhkXIJBbQ+JQjA4egrZbfWuf8-91UNeAgzQi7OP-WwUakFuMDb2t-z1g3i71aAg1lIwmtwpQ1O7k5fiatQ+AAXQ8ACyB2WBiG80e54noVtSDfRiGgF7bWbGoEFMmoIkpakDZOea0hae3qbiBYWmIfsjAxFhWmQuXuAh1hO0eWpV2jSS3tMMqY1ZriklDGR0JtxrllSKQT6Wp8z1wAhaTW2tWCVCgKvPwRCnIpiwYBB6wAs5cyDMARuCBcKd3sLhQeZByC4XXpvFgahUrkMArUYcmpcHCygAQvwABCZUu1YB5X4fw4CAB1WEeQWjXFmpvCkZVSYgnJuCVSal4Czn6JiEk-45F+GAupTSMVdLqjILVAAQoY+gatag1DqEkDi5VhxYn8Lo-GUg8BEPMcBTSwcHaf2SBAdEqxpbfFxno2o-gzqsH+OYoCTZKgUCUIpXCyJlHMmePAHKbiolcxqPxJ4viEkBOCXI4CgpiAJA6KA1aRYxJNgUbE3Wd9I51GEawPJ0xTSaS0c6HRpoKaKDqfIpsHBPJ-yxqbCaky9G+zhDPP25IikfmMHknwJZ3aAJmYBYC88BpFG0aYX2FF4DK0EoUJCC1FppPSaQlyPUTlPXMe8+omorlBLMXIn06TAJZWKYUESJyQmdIVvnFWwzxnXOSRC-QOMbFxWluAyZRp4CvNBRkvw3h8j5LKcM72UF7C+xtukNYVdFr7K1hII56RoX1KbNEBIc56BrFgA8FJiz-DYxWWCAJ+KCUeRGWKXIlBYDCW1BgfspBNQhj8iCgl-DOGQKERcPBoioB-g1fwtCbxejIh1Gy-hqVLV+G+ek7ioKwAbg2uNRKNqnWEgkGgRKrRMQIG1ICjVHqXWzQyEwxQPrw1SADe651MDMisIoG6oFoLE0rV0owTUaxQxhhtcajcibk1GuBXm9JUhTBzCDISQtgbi1yNZOQHlCAoBBgGfqiRUieq1rrWCtBurFpQpTT2kI-b8EtGVGsDAJ8h3FrtT2h1w7J3Tz9DO9JhqjXrtBZuuR26AK6jkXUu1T0npvRKIYuxFAaAAEYcBIEBpDLQsMxCI3kFGmgiDWw8mVKg9ByrZF+AtOQeayJhUoNmiwW0AFfnqoAgGIMqqIzBrfEWuRHqJBXp9YSUDRUGg7m7YBD1RJcKEg3lrHWMINFLHKu+Ds8a8MnMIyh8xHqa02pgwS8tla-DVt6aQJjBLMz9sHT2oDhdQPKl+CkFCq6rU2oXaCwkugaPCpvKumNq7gIhXyCsRogpmXVPjUkh28JFge2OHiFsswKzbTZaEiWdI3zZnxJHbk3jY5GHjk1EULBcKOd2S0WzTY+yAkHMOQ6kRnzbFXaJkDyy-AADJ4t-OFbhdj5j6HN24wACRKJvJBs1xH8fMVGqtpHtZ-3WLx+klGNZcLxUVuRaagwCB3oSCBLAfXLtK3Vwkagl74fMVq7eBq+EEpi+JhSoppMarnXI61Q7t3ruPbaFqm1sKziOpF3Cn6-wPuhtoGgVZjyvrdPYGgkXyG6SMIKD4QZAYAG4iHdBgE1O7j3-xUUUBkSukA+VjyhOQLIxgIAcHewBT7UgsgQAAF6ZavWDRgal3tPQ8K+Kz6rnusiFEGHAxTke2gAALC1MPM7QStFLwAyNidV8zTR6mIN0QgmJTBvbtdcYADOq7M6DFe+7y2YxE-gCT3oIhydKRUuQ2nU4OeM+534XnbP2gy65+W1np8YwYAqg8DHW9MT6SDFwAxUAwdRze0QhAHBZ4PaIaLFYPPAaAwAKQm9WP1aQ9uncm7pdrQUMQmhQDDVQaiQZrt0s1DgFAKA8AR6jzHvAgNsAoG1Cbht7J7gG4QEjohFhCbqg4KYQPdhFCtvsMYE3s1+qkCp0oMAw8rZ2CMOX7Stj9cKSUtiBPKByD48NlryQtN1UYovQbinylqR+E7939XqPDPquXRkCvgpSAl4bybzHr2-C46nP9Ypfg0C7532AL39LfdgQDyQTeRggwAGIABi9+vfEDUlkCQilC53YwCgXfnfd9b78NfgATiAMfyMFeBvx2AgPl0RxOCoGgB7xn2WQyDTUux6Buyr25B5zxwAnVxDQTV438ETRQOu1uwnwn0-zx3V1PQ+gvW+hADQBQCQCvXUH6xAAuFIGWn4EfR0EgBWAnjkAIGTDkDEGkCkGYCQEbCaEYEWkFCrFNEcB4IkD4IJyvQwBULBnkMlj4JfQIE4x0CZggEYAcD6zUCAA) that uses this technique.

See the `declarative-composed` directory in this repo for sources.

*Note that the examples use ES6 and modern CSS. Sources would need to be compiled to ES5 and include style prefixes for older browsers.*