Skip to content

Chapter 1: User Interface Components#

Welcome to the loaders.gl-showcases tutorial! In this first chapter, we'll start by exploring the fundamental building blocks of the application's visual interface: User Interface Components.

What are User Interface Components?#

Think of building a complex structure, like a house or a large machine. You don't start by shaping every single piece of wood or metal from scratch. Instead, you use pre-made, standard parts – bricks, pipes, screws, buttons. These are reusable building blocks.

In the world of software interfaces, User Interface (UI) Components are exactly that: the reusable building blocks for creating the visual parts of the application that you interact with. As the concept description says:

These are the reusable building blocks for creating the visual parts of the application that you interact with. This includes panels, buttons, switches, checkboxes, and other form elements. They are like standard Lego bricks of different shapes and colors that are used repeatedly to build all the various control panels and dialog boxes in the application's interface.

Using UI components makes building the application's interface much faster and easier. You create a button component once, define how it looks and behaves, and then you can use it anywhere you need a button, without writing the same code over and over. This also helps make the application look and feel consistent.

Our First Look: An Action Button#

Let's consider a simple but very common UI component: a button that performs an action. In the loaders.gl-showcases application, you'll see buttons used for various purposes, like confirming a choice in a dialog or triggering a process.

Imagine you have a panel where you need a button labeled "Save Settings". This button should look a certain way and do something specific when clicked. Instead of coding the visual appearance and click behavior directly inside the panel's code, we use a pre-built ActionButton component.

How to Use a UI Component (The ActionButton)#

Using a UI component is like placing a Lego brick. You tell the application which component you want, where you want it, and what specific job it should do (like what text it should show or what should happen when clicked).

Let's look at a simplified example of how you might use the ActionButton component in another part of the application's code:

import React from 'react';
import { ActionButton } from '../components/action-button/action-button'; // Import the component

// Assume this is some part of your application's interface
function SettingsPanel() {

  const handleSaveClick = () => {
    console.log("Settings saved!");
    // Code to actually save settings goes here...
  };

  return (
    <div>
      {/* ... other panel content ... */}
      <ActionButton onClick={handleSaveClick}>
        Save Settings {/* This text will appear on the button */}
      </ActionButton>
    </div>
  );
}

In this example:

  1. We import the ActionButton component so we can use it.
  2. Inside our fictional SettingsPanel component, we define a function called handleSaveClick. This function contains the code we want to run when the button is clicked.
  3. We use the <ActionButton> tag, just like a standard HTML tag, but this is our custom UI component.
  4. We pass information to the ActionButton using something called props.
    • onClick={handleSaveClick}: This prop tells the ActionButton what function to call when it is clicked. We pass our handleSaveClick function here.
    • Save Settings: The text placed between the opening and closing <ActionButton> tags becomes the children of the component. For a button, the component is designed to display its children as the button's label.

When this code runs, the ActionButton component will render a button on the screen with the text "Save Settings". When a user clicks this button, the handleSaveClick function will be executed, and you would see "Settings saved!" printed in the developer console.

This shows the core idea: the component (ActionButton) handles how the button looks and detects the click, while the code using the component (SettingsPanel) decides what happens when it's clicked by providing the onClick function.

Under the Hood: How Components Work#

How does the ActionButton component do its job? Let's take a peek at the code structure without getting lost in every detail. You can find the ActionButton code in the file src/components/action-button/action-button.tsx.

At its core, a React component (which is what's used here) is essentially a function that takes inputs (the props) and returns what should be displayed on the screen (often written using a syntax called JSX, which looks like HTML).

export const ActionButton = ({
  variant = ActionButtonVariant.primary,
  onClick, // This is the function passed in by the user
  children, // This is the text/content inside the <ActionButton> tags
  type = "button",
}: ActionButtonProps) => {

  // ... code to choose the button style based on 'variant' ...

  // Return the visual representation (using styled-components for styling)
  return ButtonComponent ? <ButtonComponent type={type} onClick={onClick}>{children}</ButtonComponent> : null;
};

This simplified snippet shows the ActionButton function. It receives the onClick function and children (the button text) as props. Inside, there's logic to handle different button styles (variant), but the key part is that it renders an actual HTML <button> element. It attaches the onClick function it received to the HTML button's onClick event handler. The children prop is placed inside the button element, making it the button's label.

When you click the button on the screen, the browser detects the click on the HTML <button>. Since the ActionButton component attached the onClick prop (which was handleSaveClick in our example) to this button, the browser calls that function.

Here’s a simple flow diagram showing this interaction:

sequenceDiagram
    Participant User
    Participant Browser
    Participant ActionButtonComponent
    Participant ParentComponent

    User->Browser: Clicks the button on screen
    Browser->ActionButtonComponent: Detects click, triggers internal click handler
    ActionButtonComponent->ParentComponent: Calls the 'onClick' function provided as a prop
    ParentComponent: Executes the code in the 'onClick' function (e.g., handleSaveClick)

Other components like ToggleSwitch (src/components/toogle-switch/toggle-switch.tsx), CloseButton (src/components/close-button/close-button.tsx), and ModalDialog (src/components/modal-dialog/modal-dialog.tsx) follow a similar pattern: they are functions or classes that take props (like checked, onCancel, title, children) and return visual elements based on those props, often handling user interactions by calling functions provided via props.

The files like src/components/common.tsx contain styled components primarily used for layout and structure (like positioning panels) and common visual elements (like titles or separators), which are also reusable UI building blocks.

By using these components, developers can build complex interfaces by combining smaller, well-defined pieces, much like building different structures with the same set of Lego bricks.

Conclusion#

In this first chapter, we learned that User Interface Components are the reusable building blocks of the application's visual design. We saw how components like ActionButton abstract away the details of how something looks and reacts to basic interactions, allowing the code that uses the component to focus on what should happen when that interaction occurs. This modular approach makes building and maintaining the interface much more manageable.

Now that we have a basic understanding of the UI components, we can move on to see how these components are used to build the application's main feature: the map visualization.

Chapter 2: Map Visualization


Generated by AI Codebase Knowledge Builder. References: 1(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/action-button/action-button.tsx), 2(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/action-icon-button/action-icon-button.tsx), 3(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/close-button/close-button.tsx), 4(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/common.tsx), 5(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/expand-icon/expand-icon.tsx), 6(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/loading-spinner/loading-spinner.tsx), 7(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/modal-dialog/modal-dialog.tsx), 8(https://github.com/visgl/loaders.gl-showcases/blob/3403a56b6839455092211a95c5cd695f20ea6c7e/src/components/toogle-switch/toggle-switch.tsx)