Skip to content

Commit d5fc9ef

Browse files
committed
added and refactored guides
1 parent 4fa1836 commit d5fc9ef

File tree

3 files changed

+280
-11
lines changed

3 files changed

+280
-11
lines changed

guides/hello_world.md renamed to guides/10_hello_world.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
# Hello World Guide
2-
31
## Getting from zero to one, quickly
42

53
*Prerequisite:* We assume you have read and followed the [installation guide](/docs/install), either in a new or existing Rails application.
64

75
### Creating your first Matestack app
86

7+
*A matestack `app` is something like a classic Rails `layout`. It will wrap `pages`.*
8+
99
Within your `app/matestack/` folder, create a folder called `apps` and there,
1010
we will start by adding a file called `my_app.rb`!
1111
Put the following code inside it:
1212

13+
`app/matestack/apps/my_app.rb`
14+
1315
```ruby
1416
class Apps::MyApp < Matestack::Ui::App
1517

@@ -27,15 +29,19 @@ class Apps::MyApp < Matestack::Ui::App
2729
end
2830
```
2931

30-
Great! Now we have our first Matestack app inside our Rails application. It can have many pages, and adding a first one is our next step!
32+
Great! Now we have our first matestack app inside our Rails application. It can wrap many pages, and adding a first one is our next step!
3133

32-
### Creating your first Matestack page
34+
### Creating your first matestack page
35+
36+
*A matestack `page` is something like a classic Rails `view`. It will be wrapped by an `app`.*
3337

3438
Now, within `app/matestack/`, create another folder called `pages/`, and put a folder for our app in it (`my_app`).
3539
In `app/matestack/pages/my_app/`, create a file called `my_example_page.rb` for our first view.
3640

3741
Notice how we describe our User Interface with elements that resemble `HTML tags` - but we can also write Ruby just the way we want to!
3842

43+
`app/matestack/pages/my_app/my_example_page.rb`
44+
3945
```ruby
4046
class Pages::MyApp::MyExamplePage < Matestack::Ui::Page
4147

@@ -54,7 +60,7 @@ class Pages::MyApp::MyExamplePage < Matestack::Ui::Page
5460
end
5561
```
5662

57-
After creating this example page for our example Matestack app, we're nearly finished. But as you may have guessed, we've yet to prepare the routes and the controller!
63+
After creating this example page for our example matestack app, we're nearly finished. But as you may have guessed, we've yet to prepare the routes and the controller!
5864

5965
### Setting up router and controller
6066

@@ -63,7 +69,7 @@ This is straightforward and just works *the Rails way*.
6369
Inside `config/routes.rb`, add a route for the example page:
6470

6571
```ruby
66-
scope :my_app do
72+
Rails.application.routes.draw do
6773
get 'my_example_page', to: 'my_app#my_example_page'
6874
end
6975
```
@@ -74,19 +80,18 @@ In `app/controllers/`, create a file called `my_app_controller.rb` and define ou
7480
class MyAppController < ApplicationController
7581

7682
# if it is not already included in the ApplicationController
77-
# add the Matestack ApplicationHelper here by
78-
# uncommenting the line below
79-
# include Matestack::Ui::Core::ApplicationHelper
83+
include Matestack::Ui::Core::ApplicationHelper
8084

8185
def my_example_page
8286
responder_for(Pages::MyApp::MyExamplePage)
8387
end
88+
8489
end
8590
```
8691

8792
### Test it
8893

89-
All we got left to do is to start Rails by entering `rails server` in the console and then head to [localhost:3000/my_app/my_example_page](http://localhost:3000/my_app/my_example_page) in our favorite browser!
94+
All we got left to do is to start Rails by entering `rails server` in the console and then head to [localhost:3000/my_example_page](http://localhost:3000/my_example_page) in our favorite browser!
9095

9196
### Summary
9297

guides/20_page_transitions.md

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
A Single Page Application (SPA) usually is loaded once and handles all user
2+
interactions dynamically by calling backend APIs. This gives the user the
3+
ofted desired "app-feeling". Rails View Layer only offers the static request/response
4+
mode to render content. matestack fixes that without adding the complexity a
5+
SPA written in JavaScript usually brings with it. matestacks app instance simply
6+
performs dynamic transitions between pages. You only have to follow the basic
7+
structure to get this running:
8+
9+
## 1. Setup your matestack pages
10+
11+
First of all we need at least two matestack pages:
12+
13+
Your routes:
14+
15+
config/routes.rb
16+
17+
```ruby
18+
Rails.application.routes.draw do
19+
get '/page1', to:'my_app#first_page', as: 'first_page'
20+
get '/page2', to:'my_app#second_page', as: 'second_page'
21+
end
22+
```
23+
24+
Your controller actions:
25+
26+
`app/controllers/my_app_controller.rb`
27+
28+
```ruby
29+
class MyAppController < ApplicationController
30+
31+
include Matestack::Ui::Core::ApplicationHelper
32+
33+
def first_page
34+
responder_for(Pages::MyApp::MyExamplePage)
35+
end
36+
37+
def second_page
38+
responder_for(Pages::MyApp::MySecondExamplePage)
39+
end
40+
41+
end
42+
```
43+
44+
*Note: As you see, controller action names don't have to match the page class name.*
45+
46+
Now we define our matestack pages:
47+
48+
`app/matestack/pages/my_app/my_example_page.rb`
49+
50+
```ruby
51+
class Pages::MyApp::MyExamplePage < Matestack::Ui::Page
52+
53+
def response
54+
components {
55+
div do
56+
span do
57+
plain "This is Page 1!"
58+
end
59+
end
60+
}
61+
end
62+
63+
end
64+
```
65+
66+
and
67+
68+
`app/matestack/pages/my_app/my_second_example_page.rb`
69+
70+
```ruby
71+
class Pages::MyApp::MySecondExamplePage < Matestack::Ui::Page
72+
73+
def response
74+
components {
75+
div do
76+
span do
77+
plain "This is Page 2!"
78+
end
79+
end
80+
}
81+
end
82+
83+
end
84+
```
85+
86+
*Note: the page class name has to match your file name and the apps name has to match the namespace of your matestack page*
87+
88+
- Pages::**MyApp**::MyExamplePage --> `app/matestack/pages/my_app/my_example_page.rb`
89+
- Pages::**MyApp**::MySecondExamplePage `app/matestack/pages/my_app/my_second_example_page.rb`
90+
91+
## 2. Add transition links to your app
92+
93+
Now we have to add transition links to your matestack app.
94+
95+
`app/matestack/apps/my_app.rb`
96+
97+
```ruby
98+
class Apps::MyApp < Matestack::Ui::App
99+
100+
def response
101+
components {
102+
header do
103+
heading size: 1, text: "My App"
104+
end
105+
106+
nav do
107+
108+
# perform a dynamic transition to a different page
109+
# the links get the class "active" when their path is active
110+
transition path: :first_page_path, text: "First Page", class: "nav-link"
111+
112+
# or with a button for example
113+
transition path: :second_page_path, class: "nav-link" do
114+
button do
115+
plain "Second Page"
116+
end
117+
end
118+
119+
end
120+
121+
main do
122+
page_content
123+
end
124+
}
125+
end
126+
127+
end
128+
```
129+
130+
Clicking on the transition links will perform dynamic transition and change the
131+
page_content without a full page reload.
132+
133+
You can see this in action when navigating through this guides. The links on the
134+
sidebar of these docs are transition components.
135+
136+
## Recap
137+
138+
We've implemented a dynamic SPA with a few lines of Ruby. No JavaScript was required.
139+
On the next section, we will learn how to add some custom UI Sugar in order to perform
140+
a smooth page transition!
141+
142+
### Handle Page Transition Events
143+
144+
On the previous section we learned, how to implement dynamic page transitions in pure
145+
Ruby. matestack wants to cover the basic dynamic behavior of your Web-App with
146+
minimum complexity. You should be able to add custom UI Goodies on top of this
147+
solid structure though. To give you maximum flexibility, you can use classic JavaScript
148+
and a Vue.js EventBus for that.
149+
150+
We now want to add a nice loading transition when the user navigates between pages.
151+
152+
matestack emits vue.js events on specific UI interactions. If you receive these events,
153+
you can do all kinds of DOM-Manipulations. **Let's see, how
154+
page transition effects as on this documentation app are implemented, for example.**
155+
156+
(We're using Material Design Light, you could use whatever you want)
157+
158+
`app/matestack/apps/my_app.rb`
159+
160+
```ruby
161+
class Apps::MyApp < Matestack::Ui::App
162+
163+
def response
164+
components {
165+
#...
166+
main do
167+
div class: "loading" do
168+
div id: "spinner", class: "mdl-spinner mdl-js-spinner is-active"
169+
end
170+
div id: "page_content" do
171+
page_content
172+
end
173+
partial :alert_bar #optional
174+
end
175+
#...
176+
}
177+
end
178+
179+
#optional
180+
def alert_bar
181+
partial {
182+
div id: "alert_bar", class: "mdl-js-snackbar mdl-snackbar mdl-snackbar--alert" do
183+
div class: "mdl-snackbar__text"
184+
div class: "mdl-snackbar__action"
185+
end
186+
}
187+
end
188+
189+
end
190+
```
191+
192+
Now let's add some custom JavaScript behavior (just pick what you want to use on your project and adapt to your DOM):
193+
194+
**Note 1: All the DOM Manipulations below may depend on your custom DOM structure/CSS Framework**
195+
196+
**Note 2: In v0.7.3 we aditionally will offer a component handling most of these effects, making it easier to apply a nice page transition to your component with less JS**
197+
198+
`app/assets/javascripts/application.js`
199+
200+
```javascript
201+
//Transition Start - DOM Manipulation (depends on your DOM/CSS Framework!)
202+
MatestackUiCore.matestackEventHub.$on('page_loading', function(url){
203+
//hide old content
204+
document.querySelector('#page_content').style.opacity = 0;
205+
setTimeout(function () {
206+
//show loading spinner
207+
document.querySelector('#spinner').style.display = "inline-block";
208+
}, 300);
209+
});
210+
211+
//Transition End - DOM Manipulation (depends on your DOM/CSS Framework!)
212+
MatestackUiCore.matestackEventHub.$on('page_loaded', function(url){
213+
setTimeout(function () {
214+
//hide loading spinner
215+
document.querySelector('#spinner').style.display = "none";
216+
//show new content
217+
document.querySelector('#page_content').style.opacity = 1;
218+
}, 500);
219+
});
220+
221+
//Transition End Scroll Top (depends on your DOM/CSS Framework!)
222+
MatestackUiCore.matestackEventHub.$on('page_loaded', function(url){
223+
//scroll top in order to display new content at top position
224+
document.getElementsByTagName("main")[0].scrollTop = 0
225+
})
226+
227+
//Transition End Material Snackbar API Call (depends on your DOM/CSS Framework!)
228+
MatestackUiCore.matestackEventHub.$on('page_loaded', function(url){
229+
setTimeout(function () {
230+
var noticebarContainer = document.querySelector('#notice_bar');
231+
var data = {message: 'loaded: ' + url, timeout: 1500};
232+
noticebarContainer.MaterialSnackbar.showSnackbar(data)
233+
}, 500);
234+
})
235+
236+
//Transition Error DOM Manipulation and Material Snackbar API Call (depends on your DOM/CSS Framework!)
237+
MatestackUiCore.matestackEventHub.$on('page_loading_error', function(error){
238+
setTimeout(function () {
239+
//hide loading spinner
240+
document.querySelector('#spinner').style.display = "none";
241+
//show old content again
242+
document.querySelector('#page_content').style.opacity = 1;
243+
//call Material Snackbar API
244+
var alertbarContainer = document.querySelector('#alert_bar');
245+
var data = {message: 'error loading: ' + error.config.url, timeout: 3000};
246+
alertbarContainer.MaterialSnackbar.showSnackbar(data)
247+
}, 500);
248+
})
249+
250+
251+
```
252+
253+
and a some CSS:
254+
255+
`app/assets/stylesheets/application.css`
256+
257+
```css
258+
#page_content{
259+
transition:opacity 0.2s linear;
260+
}
261+
#spinner {
262+
display: none; //init hide
263+
}
264+
```

guides/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Table of Contents
22

3-
1. [Hello World](/guides/hello_world.md)
3+
1. [Hello World](/guides/10_hello_world.md)

0 commit comments

Comments
 (0)