|
2 | 2 |
|
3 | 3 | ## Table of contents
|
4 | 4 |
|
5 |
| -1) Concept |
6 |
| - 1) Apps |
7 |
| - 2) Pages |
8 |
| - 3) Components |
9 |
| -2) Event System |
10 |
| -3) Core Features |
| 5 | +1. Concept |
| 6 | + 1. Apps |
| 7 | + 2. Pages |
| 8 | + 3. Components |
| 9 | +2. Event System |
| 10 | +3. Core Features |
11 | 11 |
|
12 | 12 | ## Concept
|
13 | 13 |
|
14 | 14 | Matestack enables you to write modern user interfaces in pure ruby. Let's take a closer look at how matestacks concept works and what features it offers you. The below graphic shows the conceptual structure of apps, pages and components.
|
15 | 15 |
|
16 | 16 | 
|
17 | 17 |
|
18 |
| -* describe matestack apps, pages, components concept with an image |
19 |
| -* first app -> layout |
20 |
| -* second page -> view |
21 |
| -* third component -> partial |
| 18 | +Apps are similiar to layouts in Rails. Apps wrap pages with provided content, like a top navigation or a sidebar as displayed in the above image. You will always have at least one app in your Rails application, but you can have as much as you want. For example you could have a public app, which wraps your landing, contact, about pages with a top navigation and a private app, which wraps management pages with a sidebar and different top navigation. |
| 19 | + |
| 20 | +As we already mentioned pages it is time to explain them. Pages are similiar to Rails views. A controller action usually renders a view, with matestack a controller action usually renders a page. |
| 21 | + |
| 22 | +Lastly there are components. Components can be compared to Rails partials. They can be used to structure content and define reusable ui parts. In the above image components are represented with a green background. There is one component containing a text block which is reused three times on the page and another component containing a button, which could be reused on other pages. So with components you can create reusable content blocks to structure your ui and keep it dry. |
| 23 | +Components can not only be used inside pages, but also in apps and other components. |
| 24 | + |
| 25 | + |
| 26 | +Apps, pages and components will live in a `matestack` folder inside your `app` directory. Apps, pages and components can be created as you like, but we recommend to namespace apps and pages. Imagine we have an online shop with a shop app and a management app. The corresponding folder structure should look like this: |
| 27 | + |
| 28 | +```sh |
| 29 | +app/matestack/ |
| 30 | +| |
| 31 | +└───shop/ |
| 32 | +│ │ app.rb |
| 33 | +│ └───pages/ |
| 34 | +│ │ │ home.rb |
| 35 | +| |
| 36 | +└───management/ |
| 37 | +│ │ app.rb |
| 38 | +│ └───pages/ |
| 39 | +│ │ │ dashboard.rb |
| 40 | +``` |
| 41 | + |
| 42 | + |
| 43 | +Having taken a look at the overall concept of matestacks apps, pages and components and how they work together, we can take a deeper look at each one of them. |
| 44 | + |
22 | 45 |
|
23 | 46 | ### Apps
|
24 | 47 |
|
25 |
| -* describe an app in more details |
26 |
| - |
27 |
| -* advantages of apps combined with pages |
28 |
| -* describe why we need a layout usually per app |
29 |
| -* where to put and how to namespace your apps |
| 48 | +As mentioned above apps wrap pages with provided content. But what advantages to we get from using an app with pages? |
| 49 | + |
| 50 | +Apps can transition between pages corresponding to the same app. What does transition between pages mean? It means that an app can switch between pages without reloading the apps content. For example your navigation will not be reloaded, but only the page content, improving the user experience. With pure Rails views and layouts the browser would do a full reload of the website. With matestack only the content that should change is requested, rendered and replaced asynchronously without a full reload, providing a more app like or single page application like feeling. |
| 51 | + |
| 52 | +**Creating an app** |
| 53 | + |
| 54 | +Creating an app is easy. Let's create the shop app from the example at the beginning. As mentioned we recommend namespacing your apps and store pages, which in this case means we create our shop app under the namespace shop. Create a file `app/matestack/shop/app.rb` which will contain our app code. |
| 55 | + |
| 56 | +```ruby |
| 57 | + class Shop::App < Matestack::Ui::App |
| 58 | + |
| 59 | + def response |
| 60 | + heading text: 'Matestack Shop' |
| 61 | + yield_page |
| 62 | + end |
| 63 | + |
| 64 | + end |
| 65 | +``` |
| 66 | + |
| 67 | +Apps need to inherit from `Matestack::Ui::App` and implement a `response` method. The `response` method contains the output which will be rendered. In our case it would add an "h1" saying "Matestack Shop" above the pages. The `yield_page` method determines where inside the app the page would be rendered. `yield_page` enables the app to transition between pages. |
| 68 | + |
| 69 | +How the call of `heading text: "Matestack Shop"` works will be explained later in this guide. |
| 70 | + |
| 71 | +As you might have read in the [installation](/docs/guides/000-installation/) guide you need to have a rails layout containing a html element with "matestack-ui" as class name. This is required because matestack uses vue.js and we mount to this class name. Because we do not yet support writing "html, head, meta" and other tags that are used outside the body in matestack you need at least one layout file. But we recommend using one layout file for each app. |
| 72 | + |
| 73 | +**Accessing data in pages** |
| 74 | +TODO |
30 | 75 |
|
31 | 76 | ### Pages
|
32 | 77 |
|
33 |
| -* describe a page in more details |
34 |
| - |
35 |
| -* what offers a page |
36 |
| -* pages without an app and with an app |
37 |
| -* transitions of pages when wrapped in app |
38 |
| -* where to put pages and how to namespace them |
| 78 | +Pages come close to rails views, but give you the ability to transition between them without full website reloads when used with an app. |
| 79 | + |
| 80 | +**Creating a page** |
| 81 | + |
| 82 | +Let's create the home page from the online shop example. Therefore we create a file `app/matestack/shop/pages/home.rb`. |
| 83 | + |
| 84 | +```ruby |
| 85 | +class Shop::Pages::Home < Matestack::Ui::Page |
| 86 | + |
| 87 | + def response |
| 88 | + heading size: 2, text: 'A few products you may like' |
| 89 | + Products.limit(5).each do |product| |
| 90 | + paragraph text: product.name |
| 91 | + small text: product.price |
| 92 | + end |
| 93 | + end |
| 94 | + |
| 95 | +end |
| 96 | +``` |
| 97 | + |
| 98 | +Pages need to inherit from `Matestack::Ui::Page` and like apps implement a `response` method. Within the `response` method we implement our UI which will be rendered when we call `render Shop::Pages::Home`. Our home page will render a "h2" saying "A few products you may like" followed by five sets of "p" and "small" tags containing the product name and price. With matestack you write pure ruby instead of html and therefore can leverage all of rubys and rails features. |
| 99 | + |
| 100 | +Again, how the `heading`, `paragraph` and `small` calls work will be explained later in this guide. |
| 101 | + |
| 102 | +**Advanced page** |
| 103 | + |
| 104 | +Let's create another page, where we will give you an example what you could do because you're writing uis in pure ruby. |
| 105 | + |
| 106 | +`app/matestack/shop/pages/products/index.rb` |
| 107 | + |
| 108 | +```ruby |
| 109 | +class Shop::Pages::Products::Index < Matestack::Ui::Page |
| 110 | + |
| 111 | + def response |
| 112 | + banner do |
| 113 | + heading text: 'New in the matestack shop' |
| 114 | + end |
| 115 | + banner do |
| 116 | + heading text: 'Sale' |
| 117 | + paragrap text: 'Now until tommorow' |
| 118 | + end |
| 119 | + Products.all.each do |product| |
| 120 | + product_teaser product.name, product.price |
| 121 | + end |
| 122 | + end |
| 123 | + |
| 124 | + private |
| 125 | + |
| 126 | + def banner(&block) |
| 127 | + div class: 'banner' do |
| 128 | + yield |
| 129 | + end |
| 130 | + end |
| 131 | + |
| 132 | + def product_teaser(name, price) |
| 133 | + paragraph text: name, |
| 134 | + small text: prive |
| 135 | + end |
| 136 | + |
| 137 | +end |
| 138 | +``` |
| 139 | + |
| 140 | +The possibilities are endless. Our `banner` method takes in a block and sourrounds it with a "div". This could be useful if you have complex repeating markup which is only relevant on this page and has different content inside. Our `product_teaser(name, price)` methods renders a "p" and "small" tag with the given name and price. But to be clear, we would recommend creating a component for product teaser. You will learn more about components in a second. There is much more you can do. For example you can inherit from your own page. |
| 141 | + |
| 142 | +**Accessing data in pages** |
| 143 | +TODO |
39 | 144 |
|
40 | 145 | ### Components
|
41 | 146 |
|
42 |
| -* describe components in more detail |
43 |
| - |
44 |
| -* core components -> implemented in order to write uis in pure ruby |
45 |
| -* different types of components |
46 |
| - * components |
47 |
| - * vue.js components |
48 |
| - * short description of what they are and a few examples (in greater detail in core features) |
49 |
| -* how to use core components in order to create apps, pages, own components |
50 |
| -* what are own components good for |
51 |
| -* how to create and use a component |
52 |
| -* where to put components and how to namespace them |
| 147 | +We talked shortly about components and even adviced to create a component for the product teaser, but before doing this we will take a closer look at what components are. |
| 148 | + |
| 149 | +Components are reusable UI parts. They can represent simple parts like a button with specific classes or more complex parts like a product teaser or whatever you think should be a reusable part of your UI. Components are used through method calls which are defined throug a component registry. More on that later. |
| 150 | + |
| 151 | +**Core Components** |
| 152 | + |
| 153 | +Above we used methods like `heading`, `paragraph`, `small` and `div`. These are all what we call core components provided trough a core component registry which is automatically loaded. They are components representing the corresponding html tag. For example calling `div` would result after rendering in `<div></div>`. Matestack a wide set of w3c's specified html tags for you, so you could write UIs in pure ruby. All available components are listed in our [components api](/docs/api/100-components/). |
| 154 | + |
| 155 | +There are two different types of core components. Simple components and so called vue.js components. `div` for example is a simple component, it renders a "div" tag either emtpy or containing the content given by a block. `toggle` on the other hand is a vue.js component, because it comes with a corresponding vue.js component to enable dynamic behavior on the client side. `toggle` for example can show or hide content depending on events, enabling you to write such dynamic behavior without writing anything else than ruby. |
| 156 | + |
| 157 | +**Using core components** |
| 158 | + |
| 159 | +Like already mentioned core components are automatically available in apps, pages and components, which means you can right ahead write your UI with apps, pages and components in pure ruby. Just use them like in the examples above. Core components always take a hash as parameter which can contain all corresponding w3c specified html attributes in order to set them. |
| 160 | + |
| 161 | +```ruby |
| 162 | +def response |
| 163 | + div id: 'product-1', class: 'product-teaser', data: { foo: 'bar' } |
| 164 | + paragraph text: 'I am a p tag', class: 'highlight' |
| 165 | + span text: 'I am a span', style: 'color: red;' |
| 166 | +end |
| 167 | +``` |
| 168 | + |
| 169 | +Most simple core components are callable like their tag name. For example `div` and `span` but some differ from their tag name. `paragraph` for example would overwrite the short version of `puts` `p` and therefore was named differently. Take a look at the component list in the [components api](/docs/api/000-base/). |
| 170 | + |
| 171 | +**Creating own components** |
| 172 | + |
| 173 | +Components can be used to structure the UI in smaller parts, which may be reusable. Creating a component is as easy as creating apps and pages. Create a file called `teaser.rb` inside `app/matestack/components/products/teaser.rb`. We put our component inside a components folder inside the matestack folder because we may want to reuse this component in both our apps (shop, management). If we knew we will use this component only in our shop, we could have placed it inside our shop folder inside a components folder. |
| 174 | + |
| 175 | +```ruby |
| 176 | +class Components::Products::Teaser < Matestack::Ui::Component |
| 177 | + |
| 178 | + def response |
| 179 | + paragraph 'Product name placeholder' |
| 180 | + small 'Product price placeholder' |
| 181 | + end |
| 182 | + |
| 183 | +end |
| 184 | +``` |
| 185 | + |
| 186 | +Components need to inherit from `Matestack::Ui::Component` and implement a `response` method. If this component gets called somewhere in a page or app the response method will define the content that gets rendered. |
| 187 | + |
| 188 | +**Accessing data in components** |
| 189 | +TODO |
| 190 | + |
53 | 191 |
|
54 | 192 | ## Event System
|
55 | 193 |
|
|
0 commit comments