Search UI demo annotated source

Back to index

        

The searchbar sample project demonstrates StyledComponent and communicating small view state between components in a hierarchy. More complex or shared state should be stored in Records, and views should listen to events on the view state Records.

5

Bootstrap the required globals from Torus, since we're not bundling

7for (const exportedName in Torus) {
8    window[exportedName] = Torus[exportedName];
9}
10

Input component for the searchbar!

12class SearchInput extends StyledComponent {
13
14    init({setValue}) {
15        this.setValue = setValue;
16        this.boundOnInput = this.onInput.bind(this);
17    }
18

Here's how the input component should look, in CSS

20    styles() {
21        return {
22            'height': '100%',
23            'width': '100%',
24

We can nest styles, like SCSS

26            'input': {
27                'height': '100%',
28                'width': '100%',
29                'line-height': '40px',
30                'box-sizing': 'border-box',
31                '-webkit-appearance': 'textfield',
32                'border': 0,
33                'padding': '8px 16px',
34                'font-size': '16px',
35                'outline': 'none',
36                'transform': 'opacity .2s',
37
38                '&:focus': {
39                    'background': '#f7f7f7',
40                },
41            },
42        };
43    }
44
45    onInput(evt) {
46        this.setValue(evt.target.value);
47    }
48
49    compose() {
50        return jdom`<div>
51            <input type="search" placeholder="Search for something..." oninput="${this.boundOnInput}" autofocus/>
52        </div>`;
53    }
54
55}
56

Component for the button that says "Search" making this a separate component might be overkill, but it's here for demonstration purposes.

60class SearchButton extends StyledComponent {
61
62    init({searchCallback}) {
63        this.searchCallback = searchCallback;
64    }
65
66    styles() {
67        return {
68            'font-size': '16px',
69            'background': '#5073f1',
70            'color': '#fff',
71            'padding': '8px 16px',
72            'margin': '0',
73            'cursor': 'pointer',
74            'transition': 'opacity .2s',
75            'border': '0',
76
77            '&:hover': {
78                'opacity': '.85',
79            },
80        };
81    }
82
83    compose() {

When the user clicks the search button, we just call the callback passed in from our parent component.

86        return jdom`<button onclick="${this.searchCallback}">Search</button>`;
87    }
88}
89

Component for our app's whole screen.

91class App extends StyledComponent {
92
93    init() {
94        this.value = '';
95

Create both our input and button components

97        this.input = new SearchInput({
98            setValue: str => this.value = str,
99        });
100        this.button = new SearchButton({
101            searchCallback: () => this.search(),
102        });
103    }
104
105    styles() {
106        return {
107            'font-family': "'Helvetica', 'Ubuntu', sans-serif",
108            'position': 'absolute',
109            'top': '36%',
110            'left': '50%',
111            'transform': 'translate(-50%, -50%)',
112
113            'h1': {
114                'font-size': '88px',
115                'color': '#333',
116                'margin': '36px 0',
117                'text-align': 'center',
118            },
119
120            '.bar': {
121                'height': '40px',
122                'max-width': '520px',
123                'width': '100%',
124                'display': 'flex',
125                'flex-direction': 'row',
126                'font-size': '16px',
127                'border-radius': '8px',
128                'box-shadow': '0 2px 6px rgba(0, 0, 0, 0.3)',
129                'overflow': 'hidden',
130                'margin': '0 auto',
131            },
132        }
133    }
134
135    search() {

For this demo, when you search, instead of bringing you useful information, we'll just pop up an alert with what you searched for.

139        window.alert('You searched for: ' + this.value);
140    }
141
142    compose() {
143        return jdom`<div>
144            <h1>Torus Search</h1>
145            <div class="bar">
146                ${this.input.node}
147                ${this.button.node}
148            </div>
149        </div>`;
150    }
151
152}
153

Create an instance of the app and mount it to the page DOM.

155const app = new App();
156document.body.appendChild(app.node);
157document.body.style.background = '#f7f7f7';
158