5 to 12 times better rendering performance (depending on the context)
Change to MIT License
Core code readability/maintainability --> Enable core contributor team growth
Vue integration and extenability --> Modern JS workflow and increased flexibility
Better IDE support --> Removed registry logic enables traceability
Easier API for component development
Improved naming schemas
Reworked docs
License change
We decided to switch back to the MIT License in order to emphasize that we want to create an Open Source project without any commercial restrictions. We will create a blog post about that soon!
Breaking changes
Trailblazer Cell dependency removed
We did a complete Ruby core rewrite and removed the internal dependencies from cells, haml and trailblazer-cells. We're now using pure Ruby for Matestack's HTML rendering and component based UI structuring. We removed the dependency as we realized that we're just using a small subset of Trailblazer's cell feature and are better off when implementing our own business logic. Thank you Trailblazer for bringing us so far!
We only used Trailblazer's cell API internally. If you just used the documented API of Matestack, you only need to follow the below migration steps:
Rails controller
Application helper
classApplicationController<ActionController::Base# old# include Matestack::Ui::Core::ApplicationHelper# newincludeMatestack::Ui::Core::Helperend
or if you want to yield in some method other than response:
classSomeApp<Matestack::Ui::Appdefresponse(&block) main do# old# yield_page# newsome_partial(&block)endenddefsome_partial(&block) div doyieldifblock_given?endend
Include your registry in components, pages, and apps directly instead of including it in your controller.
or
Create base classes for apps, pages and components inherting from Matestack's base classes including the registry(ies) and let your apps, pages and components inherit from them. As this is just a plain Ruby module, you need to include it in all contexts you want to use the alias method (unlike the registry prior to 2.0.0).
It's a good idea to create your own
ApplicationPage
ApplicationComponent
ApplicationVueJsComponent
and ApplicationApp
as base classes for your pages, components and apps. There, you include your component registry module(s) only once and have access to the alias methods in all child classes.
# Example base class strategy usageclassApplicationPage<Matestack::Ui::PageincludeComponents::RegistryendclassApplicationComponent<Matestack::Ui::ComponentincludeComponents::RegistryendclassApplicationVueJsComponent<Matestack::Ui::VueJsComponentincludeComponents::RegistryendclassApplicationApp<Matestack::Ui::AppincludeComponents::Registryend
Slots
classComponents::SomeComponent<Matestack::Ui::Component# old# optional :slots# new# Do not define any slots as optional or requireddefresponse# old# slot slots[:some_slot]# new slot :some_slotendend
classComponents::SomeComponent<Matestack::Ui::VueJsComponent vue_name "some-component" required :bar# old# all options are implicitly injected and used as vue props# or specific vue props through setup method# def setup# @component_config[:baz] = "baz"# end# newdefvue_props {}.tapdo|props| props[:foo] = options[:foo] props[:bar] = context.bar props[:baz] ="baz"endendend
renamed form to matestack_form as form is now rendering the HTML form
matestack_form renders the Vue.js driven form as prior to 2.0.0
defresponse# old# form form_config do# new matestack_form form_config do form_input key::name,type::text,label:'Name'# ... button "submit",type::submitendend
Submit
form_submit component removed, use something like button 'submit', type: :submit instead
get Vue.js form loading state via simple loading instead of loading()
defresponse matestack_form form_config do form_input key::name,type::text,label:'Name'# ...# old# form_submit do# button text: "submit"# end# new button "submit",type::submit# and optionally: button "submit",type::submit,"v-if":"!loading" button "loading...",type::submit,disabled:true,"v-if":"loading"endend
Custom form components
Base class
Example for Form Input, adapt all other custom components accordingly:
# old# class Components::MyFormInput < Matestack::Ui::Core::Form::Input::Base# newclassComponents::MyFormInput<Matestack::Ui::VueJs::Components::Form::Input# old# vue_js_component_name "my-form-input"# new vue_name "my-form-input"# old# def prepare# # optionally add some data here, which will be accessible within your Vue.js component# @component_config[:foo] = "bar"# end# newdefvue_props {foo:"bar" }enddefresponse# exactly one root element is required since this is a Vue.js component template div do label text:"my form input" input input_attributes.merge(class:"flatpickr") render_errorsendendend
Collection component
Helper
classSomePage<Matestack::Ui::Page# old# include Matestack::Ui::VueJs::Components::Collection::Helper# newincludeMatestack::Ui::VueJs::Components::Collection::Helperend
Filter
It's now possible to use ALL form child components within a collection_filter
classSomePage<Matestack::Ui::Page# old# include Matestack::Ui::VueJs::Components::Collection::Helper# newincludeMatestack::Ui::VueJs::Components::Collection::Helperdefresponse collection_filter @collection.configdo# old# collection_filter_input key: :foo, type: :text, label: 'Text'# collection_filter_select key: :buz, options: [1,2,3], label: 'Dropdown'# new form_input key::foo,type::text,label:'Text' form_checkbox key::bar,label:'True/False' form_checkbox key::baz,options: [1,2,3],label:'Multi select via checkboxes' form_select key::buz,options: [1,2,3],label:'Dropdown'#...# old# collection_filter_submit do# button text: 'Submit'# end# new button 'Submit',type:"submit"# same collection_filter_reset do button 'Reset'endendendend
Onclick
changed from rendering a div as root element to a a tag in order to have an inline root element being consistent with transition and action
this possibly breaks the appearance of your UI as we're switching from a block to an inline root element
You can keep the block style by simply applying following styles to your application:
.matestack-onclick-component-root{display:block;}
Link
link is now calling the HTML link tag instead of rendering an a tag
use a href: ... or a path: ... instead
Isolate
isolate component doesn't raise 'not authorized' anymore. When isolate is not authorized no content is returned. Only a warning is logged to the console
Rails view
rails_view is replaced by rails_render. Use rails_render partial: '/some_partial', locals: { foo: 1 }; rails_render file: '/some_view', locals: { foo: 1 } to render a partial or a file or anything you want. Use the same as you would use rails render
Component argument
Pass in text arguments like header 'Your headline', color: :blue
Access it now with self.text or context.text instead of @argument
Minor HTML rendering changes
In general: content blocks take precedence over text or :text option
area coords will no longer be automatically joined -> html option does exactly what is expected, no magic
italic and icon are now called with the corresponding html tag i
a has no more option :path which can take a symbol and renders it with rails url helper. Use :href/:path with or without rails url helper instead
unescaped renamed to unescape as it fits the naming conventions more. For example rails html_escape not html_escaped. unescaped is deprecated now
video has no more magic creation of source tag or automatically fetch asset path to keep dsl as close to html as possible
removed alias pg for paragraph
transition can no longer handle symbols as path. Use rails path helper instead
Matestack::Ui::DynamicActionviewComponent, Matestack::Ui::Core::Actionview::Dynamic and static removed -> is not needed