Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
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
- Host: GitHub
- URL: https://github.com/spacejack/mithril-modal
- Owner: spacejack
- License: mit
- Created: 2018-06-23T16:14:09.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2019-03-07T19:12:28.000Z (over 5 years ago)
- Last Synced: 2024-08-01T22:41:43.103Z (3 months ago)
- Topics: mithriljs
- Language: JavaScript
- Size: 23.4 KB
- Stars: 16
- Watchers: 3
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: license.txt
Awesome Lists containing this project
- awesome-mithril - Modal component example
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.*