Nested inside of Joystick's /ui
folder, by default, you will find three different folders:
ui/layouts
ui/pages
ui/components
Each of these folders represents a type of component that's used in your UI. Though all components in a Joystick app are defined using the same joystick.component()
method, their purpose dictates where they live within your project structure.
Layouts
Layout components in a Joystick app are intended to be global components that render always-visible UI (e.g., a navigation bar and a footer) along with the current page. While they're typically used exclusively for rendering a page within a consistent "frame," they can be as simple or as advanced as your app requires.
ui/layouts/app/index.js
import joystick from "@joystick.js/ui";
const App = joystick.component({
render: ({ props, component }) => {
return `
<div>
${component(props.page, props)}
</div>
`;
},
});
export default App;
Above, we have the default App
layout component created for you when you run joystick create <app-name>
via the CLI. Here, we use the component()
render method, anticipating a props.page
value representing the current page being rendered into the layout. We also pass the props passed to the layout down to the page the layout is rendering.
Behind the scenes, that props.page
value is automatically set by Joystick when using the res.render()
method inside of one of your routes:
index.server.js
import joystick from "@joystick.js/node";
joystick.app({
routes: {
"/": (req = {}, res = {}) => {
res.render("ui/pages/index/index.js", {
layout: "ui/layouts/app/index.js",
});
},
},
});
Above, because we've passed the layout
option to res.render()
, when this route is visited by a user, Joystick will automatically render that layout component (ui/layouts/app/index.js
) and pass the component defined at ui/pages/index/index.js
to it as props.page
.
Inside of the layout component then, we take this prop and pass it to the component()
render method because we expect it to contain an instance of a page component that we want to render into our layout.
Pages
A page component in a Joystick app represents a single page or "screen" in your UI. A profile page, a dashboard, a settings page, etc. A page can contain anything you'd like: static content, interactive elements—whatever. A page can be completely self-contained, or, import other components to render into itself.
Like we showcased above, a page is rendered via the res.render()
method from one of your routes (passed as the first argument to that method):
index.server.js
import joystick from "@joystick.js/node";
joystick.app({
routes: {
"/": (req = {}, res = {}) => {
res.render("ui/pages/index/index.js", {
layout: "ui/layouts/app/index.js",
});
},
},
});
A page can be rendered by itself, or—as the example shows above—within a layout.
Components
Any component that isn't a layout or page in a Joystick app is just considered a generic component. These are typically standalone components that are composed into your layouts, pages, or other components (e.g., a navbar component that's rendered inside of your layout component). Similar to pages, these can contain any UI or functionality you wish.