Search UI demo annotated source
Back to indexThe 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