{"id":39,"date":"2022-07-28T17:24:27","date_gmt":"2022-07-28T21:24:27","guid":{"rendered":"https:\/\/kimsal.com\/blog\/?p=39"},"modified":"2022-07-28T17:24:27","modified_gmt":"2022-07-28T21:24:27","slug":"vuejs-wrapping-ui-toolkits","status":"publish","type":"post","link":"https:\/\/kimsal.com\/blog\/2022\/07\/28\/vuejs-wrapping-ui-toolkits\/","title":{"rendered":"VueJS wrapping UI toolkits"},"content":{"rendered":"\n<p>There are a number of UI toolkits in the JS (and specifically VueJS) space.  BootstrapVue, Vuetify, VueStrap, Ionic, Quasar, ElementUI and more.  I wrote a post some time ago (which may get recovered at some point!) about some of these, and indicated I&#8217;d be diving in to one or more at some point, and&#8230; I have.<\/p>\n\n\n\n<p>Through a long and winding set of events, I&#8217;ve found myself working with <a href=\"https:\/\/quasar.dev\">Quasar<\/a>\/Vue3 over the last 7 months.  This is a relatively big change from <a href=\"https:\/\/bootstrap-vue.org\">BootstrapVue<\/a> which I&#8217;d used on multiple projects since pre-covid times.<\/p>\n\n\n\n<p>As a side note, I&#8217;m generally a fan of these, because there&#8217;s typically a lot of work that&#8217;s already gone in to providing defaults &#8211; default settings, theme\/styling, documentation, accessibility concerns, testing, and many other things I may not have thought about up front.  I&#8217;ve worked with folks that are very against this approach, and prefer to do everything &#8216;by hand&#8217;, but I&#8217;ve also found a lot tends to be missed, especially with respect to accessibility, documentation and testing, and often for little upside (yes, you can control the UI 100% to your liking but&#8230; I also happen to like the defaults and options available in the bootstrap world, for example).<br><br>Moving in to Quasar has been &#8230; interesting.  I&#8217;m not a fan of material design styling, which is their default design language.  I think changing *from* it to something else may be too big a lift for the project, and they actually may not care to, although there do seem to be some rumblings from folks in the forums about supporting alternate design languages.  We&#8217;ll see where that goes.<\/p>\n\n\n\n<p>What I&#8217;ve recently started doing is wrapping the framework components in my own super-components.  This allows for some ability to do more uniform customizations of, say, input tags.  <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;q-input\n  dense\n  stacked-label\n  clearable\n  v-model=\"user.email\"\n\/><\/pre>\n\n\n\n<p><br>This use of Quasar&#8217;s q-input component is common, useful but also gets verbose.  You may want the same set of attributes on dozens of inputs on a screen.  Wrapping in a common custom input component can save a lot of repetition.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ src\/components\/My\/Input.vue\n&lt;template>\n  &lt;div class=\"my-input\">\n    &lt;q-input \n      dense\n      stacked-label\n      dark\n      clearable\n      v-bind=\"$attrs\"\n    >\n      &lt;slot>&lt;\/slot>\n    &lt;\/q-input>\n  &lt;\/div>\n&lt;\/template>\n\n&lt;script>\nexport default {\n  name: \"MyInput\",\n};\n&lt;\/script>\n<\/pre>\n\n\n\n<p>Using this in a project&#8230;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ src\/components\/UserInfo.vue\n\n&lt;template>\n  &lt;q-page>\n    &lt;q-row>\n      &lt;my-input\n        autofocus\n        v-model=\"user.name\"\n        label=\"Name\"\n      \/>\n    &lt;\/q-row>\n    &lt;q-row>\n      &lt;my-input\n        v-model=\"user.email\"\n        label=\"Email\"\n      \/>\n    &lt;\/q-row>\n    &lt;q-row>\n      &lt;my-input\n        v-model=\"phone\"\n        label=\"Phone\"\n      \/>\n    &lt;\/q-row>\n  &lt;\/div>\n&lt;\/template>\n\n&lt;script>\nimport MyInput from \"src\/components\/My\/Input.vue\";\nexport default {\n   components: [MyInput], \n   ....\n   ....\n};\n&lt;\/script><\/pre>\n\n\n\n<p>Each input now gets &#8216;dense&#8217;, &#8216;stacked-label&#8217; and &#8216;clearable&#8217; attributes set to on without the repetition.  (FWIW, this is typed from memory &#8211; hopefully no major errors in there!).<\/p>\n\n\n\n<p>There may potentially be some benefit if the desire to switch to a new UI toolkit arises, but I suspect that&#8217;s probably way too hard of a lift (but I&#8217;ve only just considered this a potential benefit this morning!)<br><br>I&#8217;ve seen this done in other places in the past &#8211; this is not claiming the approach is new by any means.  I&#8217;ve just recently started to incorporate this approach to recent projects.  I&#8217;ll keep you posted if this proves troublesome later on down the road.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are a number of UI toolkits in the JS (and specifically VueJS) space. BootstrapVue, Vuetify, VueStrap, Ionic, Quasar, ElementUI and more. I wrote a post some time ago (which may get recovered at some point!) about some of these, and indicated I&#8217;d be diving in to one or more at some point, and&#8230; I&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-39","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/posts\/39","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/comments?post=39"}],"version-history":[{"count":0,"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/posts\/39\/revisions"}],"wp:attachment":[{"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/media?parent=39"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/categories?post=39"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kimsal.com\/blog\/wp-json\/wp\/v2\/tags?post=39"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}