Using Camome to design highly customizable UIs

To ensure an efficient and effective development process, it is crucial for developers to select a UI library or framework that provides a balance of pre-made components and customization choices.

Although many UI libraries and frameworks provide pre-made styles and components, some may not provide enough flexibility for customization due to their rigid styles and patterns. To be able to easily modify the default styles, design decisions, and patterns, customization is necessary. This means being able to adjust the styles and components to fit the unique needs of a project.

In this tutorial, we’ll introduce you to Camome UI, a frontend framework for React and CSS. We will use this flexible framework to demonstrate how to design highly customizable user interfaces.

Jump ahead:

What is Camome UI?

Camome UI is an easy-to-use UI framework for React and CSS that allows users to create website user interfaces. Camome UI is built on top of CSS Modules; this allows users to create various styles of components by leveraging the full power of CSS without using run-time JavaScript. This approach helps improve the performance of the user interface and provides greater flexibility in design options.

Camome UI comes with highly reusable components that are intended to blend in with standard design websites, but they can also be highly customized to suit any style for your site.

Key features of Camome UI

The following principles were kept in mind when developing Camome UI:

Accessibility

When developing components, accessibility is critical. Camome UI states that it may not be perfect at accessibility, but that they are giving serious attention to it.

The aria-labelledby and aria-describedby values are followed by Camome UI input components when using the <Formfield /> component.

The Switch component is built using CSS alone but it is provided keyboard navigation and focus management. By using the <details /> element, Accordion automatically supports opening and closing without client-side JavaScript.

Theming and dark mode

Implementing dark mode with Camome UI is flexible and straightforward because it comes by default.

To enable light and dark themes in your app, you must specify the data-theme attribute:

<!DOCTYPE html>
<html data-theme="<light or dark>">
  <!-- Content -->
</html>

The light and dark themes are then styled as follows in theme.css:

@layer cmm.theme {
  :root[data-theme="light"] {
    --cmm-color-primary-font: var(--cmm-color-primary-7);
    --cmm-color-primary-emphasis: var(--cmm-color-primary-6);
    {...}
  }
  /* And dark theme as well... */
}

It can also be customized as follows in your own CSS file:

:root[data-theme="dark"] .your-class {
  /* Your styles for dark theme... */
}

It can also be customized independently.

Light bundle size

Keeping JavaScript usage to a minimum on your pages is crucial for a fast user experience. A Camome UI component like Button costs 1.42KB when imported from @camome/core/Button (including CSS), and an additional 4KB from the global CSS.

Integration and easy ejection

Camome UI is framework agnostic. It offers guides for integrating with some frontend frameworks including Astro, Next.js, and, Vite.

Camome UI can also be used as a CSS framework similar to Bootstrap, despite being primarily designed as a React library, by importing bundled CSS. Other frameworks, such as Vue or Svelte, can be easily supported by simply binding class names. It also allows Integration with headless UI libraries such as Headless UI, React Aria, Radix Primitives, and Reach UI for building complex UIs such as Menu, Dialog, and Tab:

<head>
  <link
    href="https://unpkg.com/@camome/[email protected]/dist/theme.css"
    rel="stylesheet"
  />
  <link
    href="https://unpkg.com/@camome/[email protected]/dist/components.css"
    rel="stylesheet"
  />
</head>
<body>
  <button class="Button Button--primary Button--soft">Click me</button>
</body>

Camome UI is also entirely composed of React components, CSS Modules, and theme.css, making it simple to inject into your codebase.

CSS first and no JavaScript runtime

No JavaScript runtime means that JavaScript codes are not executed in both the browser’s runtime environment and the Node runtime environment. This is done because no event handlers or useEffect are used and instead, CSS Modules are used for styling and can also be used as a pure CSS framework.

Style override

Camome UI offers CSS Cascade Layers to ensure that your customized CSS styles always prevail due to one disadvantage of CSS Modules: the difficulty of overriding styles.

With Camome UI, you don’t need to always include !important to your styles or worry about the order or specificity when overriding styles because all styles outside the @layer block override the styles enclosed within the @layer block.

Camome UI design system

Before we dive into using Camome UI to design user interfaces, let’s look at the Camome design system. The Camome UI design system is divided into sections covering Color palette, Typography, and Misc.

Color palette

The color palette for the Camome UI design system is a collection of colors used to create user interfaces that are aesthetically pleasing and enjoyable to use while promoting consistency. The color palette is broken down into three categories: Shade, Semantic, and Template. Shade is the most primitive.

Semantic can be used generally anywhere; for example, font.base is used to add white or gray to your fonts using font.onEmphasis:

h1 {
  color: var(--cmm-color-font-base);
}

Templates are used for specific UI patterns. For example, a button has several templates that may be changed using the variant property’s solid, soft, or outline options:

button:hover {
  background: var(--cmm-primary-solid-bgHover);
}

Typography

Typography includes the styles for setting font family, font size, and font weight:

<style>
 h1{
  font-family: var(--cmm-font-family-base) // font family
  font-size: var(--cmm-font-size-sm) // font size
  font-weight: var(--cmm-font-weight-bold) // font weight
  }
</style>

<body>
  <h1>Hello World!</h1>
</body>

Misc

Misc includes the styles for setting shadows and radius:

<style>
 button{
  border-radiue: var(--cmm-radius-2xl);
  box-shadow: var(--cmm-shadow-xl);
  }
</style>

<body>
  <button>Click Here</button>
</body>

Exploring Camome UI components

Camome UI components are pre-built elements that look the same no matter where they are placed on the webpage. They adhere to patterns that are only effective when the proper class names and modifiers are used.


More great articles from LogRocket:


Buttons

To add a Camome UI button component, you just need to specify the Button class to the button element:

<button class="Button">Button</button>

This will create a default Camome UI button. We can extend the button with additional classes to specify its color scheme, type, state, and variations.

The class names Button--solid, Button--outline, Button--ghost, and Button--soft can be used to identify the button variations. Class names are Button--primary, Button--neutral, Button--success, and Button--danger.

You specify the different states of your button, such as loading or disabled, by specifying role="status" and disabled="true" respectively:

// Loading state
<button class="Button Button--solid Button--primary Button--md">
  <span class="Button__startDecorator">
    <div role="status" class="Spinner Spinner--sm">
      <svg>...</svg>
      <span class="visually-hidden">Loading...</span>
    </div>
  </span>
  Saving...
</button>

// disabled
<button class="Button" disabled="true">
  Solid
</button>

We can also provide Button--sm, Button--md or Button--large to change the button’s size:

<button class="Button Button--sm">Small</button>

KBD

The <kbd> tag denotes text representing a keyboard button or shortcut. This tag can also be used for voice input or any other text input device.

The text content is displayed by default in a monospace font. To create the UI of a keyboard button, your code should look similar to this:

<div>
  <kbd class="Kbd">⌘</kbd>
  <span>+</span>
  <kbd class="Kbd">K</kbd>
</div>

For example, you can add styles to increase the font size; simply set the font-size property to change size:

<div style="font-size: var(--cmm-font-size-lg);">
  <kbd class="Kbd">Ctrl</kbd>
  +
  <kbd class="Kbd">Alt</kbd>
  +
  <kbd class="Kbd">Delete</kbd>
</div>

Message and alert

The Camome UI Message component is used to highlight important information. The Message component can be added by specifying the Message class name. This will automatically produce a message. By adding the Message-info, Message-warn, Message-error, or Message-success classes, we can give the message different variations:

<div class="Message Message-info">
  <span class="Message__icon">
    <svg>...</svg>
  </span>
  <div class="Message__title" id=":R0:">This is a title</div>
  <div class="Message__content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.
  </div>
</div>

Alert is similar to Message; all you need is to specify the role="alert" attribute:

<div role="alert" class="Message Message--info">
  <span class="Message__icon">
    <svg>...</svg>
  </span>
  <div class="Message__content">This is an alert message</div>
</div>

Tooltip

Tooltips show the user additional information about a page element or feature. Use the class name Tooltip__target and the role="tooltip" attribute to target the element, and the data-placement attribute to specify the position of the tooltip:

<div class="Tooltip__target">
  <button class="Button Button--solid Button--primary Button--sm">Top</button>
  <div role="tooltip" class="Tooltip__content" data-placement="top">
    This is a tooltip
  </div>
</div>

Getting started with Camome UI

Camome UI can be added to your project in different ways with different frameworks. It can be added to your project using npm, yarn, or pnpm. After that, you will also need to configure plugins or loaders for webpack or Rollup if you are using Next.js, Astro, or Vite because Camome UI is written in JavaScript and CSS Modules in Sass as they cannot be directly imported from JavaScript.

Look at the integration guide to learn how to set it up with your preferred frontend framework.

According to their docs, Camome UI is not yet stable — Breaking changes may be introduced without increment of significant version number. When you update @camome/*, see changelogs to make sure your code is not affected by breaking changes.

For this tutorial, we will be using the CDN version. Create an index.html file within a new folder camome-project and add the CDN link to the head tag element. Your code should look like the one below:

<!DOCTYPE html>
<html lang="en" data-theme="light">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    // camome UI CDN link
    <link href="https://unpkg.com/@camome/[email protected]/dist/theme.css" rel="stylesheet" />
  <link href="https://unpkg.com/@camome/[email protected]/dist/components.css" rel="stylesheet" />
    <title>Camome UI Landing page</title>
  </head>
  <body></body>

The data-theme attribute is what Camome used to define light and dark modes.

Building a user interface using Camome UI

Here, we will put all that we’ve learned so far into building a landing page. We’ll implement a couple of Camome UI components and design systems. We will create a basic homepage that includes Camome UI components and the pre-existing styles that Camome UI provides by default for both light and dark modes.

Subsequently, we will modify the user interface to integrate our individualized styles and design preferences. Here’s what our finished project will look like:

Using Camome to design highly customizable UI

Using Camome to design highly customizable UI by miracle

Creating our Navbar

Open the camome-project/index.html file we previously prepared to begin creating our home page. Following that, we’ll make a nav element to house our navigation link and toggle button:

<nav>
  <div class="Tab__group">
    <div class="Tab__list" role="tablist" aria-orientation="horizontal">
      <div class="tab">
        <a href="#" class="Tab Tab--active">Home</a>
        <a href="#" class="Tab">FAQ</a>
        <a href="#" class="Tab">Contact Us</a>
      </div>
       <button class="Button Button--solid Button--primary Button--md'>dark</button>
    </div>        
  </div>
</nav>

This code creates a navigation bar for a website. The navigation bar has a group of tabs with links to different pages on the website such as the homepage, FAQ page, and contact page. The active tab, or the one currently selected, is highlighted with a different color.

In addition to the tabs, there is also a button that can be clicked to toggle between light and dark. We will be handling the functionality of the toggle button with JavaScript.

Now let’s add our Hero section:

<header>
  <div class="container">
      <h1>Light weight, accessibleUI framework for React and CSS</h1>
      <p>Camome UI enables you to build various styles of components without run-time JavaScript by fully utilizing the power of CSS.</p>
      <div class="Tooltip__target">
        <button class="Button Button--solid Button--primary Button--lg">
          Hover me
        </button>
        <div role="tooltip" class="Tooltip__content" data-placement="bottom">
          Camome UI is a React component library and a CSS framework.
        </div>
      </div>
  </div>
      <form>
        <div class="FormField FormField--fill">
            <label class="FormFieldLabel">
              First name
            </label>
            <input
              class="TextInput TextInput--md TextInput--fill"
              type="text"
              placeholder="John"
              name="firstName"
            />
          </div>
          <div class="FormField FormField--fill">
            <label class="FormFieldLabel">
              Email
            </label>
            <input 
              class="TextInput TextInput--md TextInput--fill" 
              type="email" 
              placeholder="example.com" 
              name="email" 
            />
          </div>
        <div class="FormField FormField--fill">
          <label class="FormFieldLabel">
            Job title
          </label>
          <select class="Select Select--md Select--fill" name="jobTitle">
            <option value="developer">Developer</option>
            <option value="designer">Designer</option>
            <option value="other">Other</option>
          </select>
        </div>
        <button class="Button Button--solid Button--primary Button--md" type="submit">
          Submit
        </button>
      </form>
</header>

The markup code is used to create a header section for a website. The header includes a title and description and a button that, when hovered over, displays a tooltip. Additionally, there is a form included that allows users to input their name, email, and job title with a submit button.

With this, let’s add styles to our site to make it look good. We will style our app using the Camome design system. This will give us more power to easily customize our styles. Create a new camome-project/styles.css file, link the CSS file to the HTML file, and add the code below:

body {
  max-width: 1080px;
  width: 100%;
  height: 100vh;
  margin: 0 auto;
  padding: 2rem 1rem;
}
nav {
  display: flex;
  margin-bottom: 5rem;
}
nav .tab {
  display: flex;
}
nav .Tab__list {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 5rem;
}
.container{
  flex: 0 0 40%;
  max-width: 40%;
}
header h1 {
  font-size: var(--cmm-font-size-2xl);
}
header p {
  margin: 2rem 0
}
form {
  flex: 0 0 60%;
  max-width: 60%;
  display: grid;
  gap: 1.5rem;
  color: var(--cmm-color-neutral-0);
  background: var(--cmm-color-neutral-7);
  padding: 1rem;
  border-radius: var(--cmm-radius-lg);
}
select, input{
  color: var(--cmm-color-neutral-7);
}

Styling using Camome UI is usually variable and starts with the prefix -cmm-. For example, var(--cmm-font-size-2xl) will increase the font size by 24px.

Customizing our user interface with Camome UI

To add and customize the dark mode user interface, we will adjust the background-image of the webpage’s body and background-color of the hover button. Additionally, we will modify the background-color of the form, input, and select elements. These instances can serve as helpful references for making additional modifications to the pre-existing styles within Camome UI.

Inside the styles.css file, add the code below:

[data-theme="dark"] body{
  background: url("https://media.giphy.com/media/aRZ4vTsHnyW6A/giphy.gif");
}
[data-theme="dark"] .container button {
  background: linear-gradient(
    to right,
    hsl(240deg 60% 40%) 0%,
    hsl(300deg 80% 40%) 100%
  );
}

[data-theme="dark"] form{
  background: linear-gradient(
    to right,
    hsl(240deg 60% 40%) 0%,
    hsl(300deg 80% 40%) 100%
  );
}

[data-theme="dark"] select, input{
  color: var(--cmm-color-neutral-7);
  background: var(--cmm-color-neutral-0);
}

The UI for the light mode will not change once we have successfully added these custom styles to our CSS file. But, we’ve customized our dark mode, which will make it look different.

Now, handling click events in JavaScript will be the last step. First, add an id attribute with a toggle value to the navigation button. That way, when we click on it, we will be able to switch between dark and light modes:

<button class="Button Button--solid Button--primary Button--md' id='toggle'>dark</button>

To handle the switch between the light and dark mode user interface, add the following code to the index.js file:

const toggle = document.getElementById("toggle");
const html = document.documentElement;

toggle.addEventListener("click", () => {
  if (html.getAttribute("data-theme") === "light") {
    html.setAttribute("data-theme", "dark");
    document.getElementById('toggle').innerHTML = 'light'
  } else {
    html.setAttribute("data-theme", "light");
    document.getElementById('toggle').innerHTML = 'dark'
  }
});

Camome UI vs. Tailwind CSS

Camome UI is a React component framework that provides the same styling benefits as Tailwind CSS but handles all of the details for you. This library contains meticulously constructed components, allowing you to concentrate on accessibility, component composition, keyboard navigation, style overrides, and other important tasks.

When using various applications, it is often difficult to modify styles to meet specific design needs for a particular situation. In the case of Tailwind CSS, users may need to determine the most effective method to override certain classNames or create their own CSS. Conversely, with Camome UI, overrides are simple because their styles are based on CSS modules, and can be easily adjusted.

Tailwind CSS supports dark mode for all of its components through the use of a dark variant. On the other hand, Camome UI components can be used in both light and dark modes, and you can also create custom light and dark mode experiences for your entire application.

Tailwind CSS requires the user to manage semantic HTML structure, adhere to WAI-ARIA requirements, enable keyboard navigation, and so on. On the other hand, Camome UI offers the ease of use of Tailwind as well as all of these other advantages pre-packaged.

Being a utility-first approach, Tailwind CSS usually uses many classes in HTML. The size of your HTML file may consequently grow larger during download. As a larger HTML file could take longer to download and render in the browser, it can also affect how quickly the page loads. On the other hand, the Camome UI component costs 1.42KB (including CSS), and an extra 4KB of global CSS is required.

Conclusion

In this guide, we looked at the Camome UI framework and its features, as well as explored the components and design system. We displayed some examples and guided you through the process of incorporating Camome UI into your webpage development. We also demonstrated how to substitute predefined styles with our unique styles. Although we concentrated on overriding dark mode styles, you can apply the information acquired from this guide to override light mode styles as well as overriding components.

In general, styling with Camome starts with the prefix -cmm- and customizing for either light or dark mode starts with [data-theme="<dark or light>"]. There are many styles that can be modified for both modes, allowing for a multitude of customization options for your web pages.

Good luck using Camome UI in your next project!

LogRocket: Full visibility into your production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time,
try LogRocket.


LogRocket
combines session replay, product analytics, and error tracking – empowering software teams to create the ideal web and mobile product experience. What does that mean for you?

Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay problems as if they happened in your own browser to quickly understand what went wrong.

No more noisy alerting. Smart error tracking lets you triage and categorize issues, then learns from this. Get notified of impactful user issues, not false positives. Less alerts, way more useful signal.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps —
.

Is your frontend hogging your users’ CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .


Source link