Next.js

This library requires React 19+

There are four steps to installation:

  1. Install the npm packages
  2. Import the CSS
  3. Configure fonts
  4. Configure theme provider

This guide assumes you're using Next.js with the app router.

1. Install the npm packages

npm i @qualcomm-ui/react @qualcomm-ui/react-core @qualcomm-ui/core @qualcomm-ui/qds-core @qualcomm-ui/dom @qualcomm-ui/utils @tanstack/react-virtual lucide-react

2. Import the CSS

In your app/globals.css file, import the QUI styles.

@import "@qualcomm-ui/qds-core/styles/components.css";
@import "@qualcomm-ui/qds-core/themes/qualcomm-dark.css";
@import "@qualcomm-ui/qds-core/themes/qualcomm-light.css";

:root {
  --type-font-family-secondary: var(--font-roboto-flex), sans-serif;
  --type-font-family-tertiary: var(--font-roboto-mono), monospace;
}

Learn more about the available brands in the theme documentation.

3. Configure fonts

QUI components are designed with the Roboto Flex and Roboto Mono font families.

In Next.js, configure fonts using next/font/google and set up the theme provider in your root layout:

import type {Metadata} from "next"
import {Roboto_Flex, Roboto_Mono} from "next/font/google"
import "./globals.css"
import {type ReactNode} from "react"

const sansFont = Roboto_Flex({
  variable: "--font-roboto-flex",
  weight: ["400", "500", "600"],
  subsets: ["latin"],
})

const monoFont = Roboto_Mono({
  variable: "--font-roboto-mono",
  subsets: ["latin"],
})

export const metadata: Metadata = {
  title: "Your App Title",
  description: "Your app description",
}

export default function RootLayout({
  children,
}: Readonly<{
  children: ReactNode
}>) {
  return (
    <html lang="en">
      <body className={`${sansFont.variable} ${monoFont.variable}`}>
        {children}
      </body>
    </html>
  )
}

4. Configure the theme provider

QUI styles support both light and dark modes. This step configures theme storage using cookies so the user's preferred theme is remembered and rendered without flash on page load.

Create the ThemeProvider

First, create a ThemeProvider component at app/components/theme-provider.tsx:

"use client"

import {
  createContext,
  type ReactNode,
  useCallback,
  useContext,
  useState,
} from "react"

import type {QdsTheme} from "@qualcomm-ui/qds-core/theme"

type ThemeContextValue = {
  setTheme: (theme: QdsTheme) => void
  theme: QdsTheme
  toggleTheme: () => void
}

const ThemeContext = createContext<ThemeContextValue | null>(null)

export function useTheme(): ThemeContextValue {
  const context = useContext(ThemeContext)
  if (!context) {
    throw new Error("useTheme must be used within a ThemeProvider")
  }
  return context
}

type ThemeProviderProps = {
  children: ReactNode
  defaultTheme: QdsTheme
}

export function ThemeProvider({
  children,
  defaultTheme,
}: ThemeProviderProps): ReactNode {
  const [theme, setThemeState] = useState<QdsTheme>(defaultTheme)

  const setTheme = useCallback((newTheme: QdsTheme) => {
    document.cookie = `app-qds-theme=${newTheme}; path=/; max-age=31536000`
    document.documentElement.setAttribute("data-theme", newTheme)
    setThemeState(newTheme)
  }, [])

  const toggleTheme = useCallback(() => {
    setTheme(theme === "dark" ? "light" : "dark")
  }, [theme, setTheme])

  return (
    <ThemeContext.Provider value={{setTheme, theme, toggleTheme}}>
      {children}
    </ThemeContext.Provider>
  )
}

Update the root layout

Update your app/layout.tsx to read the theme cookie server-side and pass it to the provider:

// previous imports and setup...
import {cookies} from "next/headers"
import type {QdsTheme} from "@qualcomm-ui/qds-core/theme"
import {ThemeProvider} from "./components/theme-provider"

export default async function RootLayout({
  children,
}: Readonly<{
  children: ReactNode
}>) {
  const cookieStore = await cookies()
  const themeCookie = cookieStore.get("theme")
  const theme: QdsTheme = themeCookie?.value === "light" ? "light" : "dark"

  return (
    <html
      lang="en"
      data-brand="qualcomm"
      data-theme={theme}
      style={{colorScheme: theme}}
    >
      <body className={`${sansFont.variable} ${monoFont.variable}`}>
        <ThemeProvider defaultTheme={theme}>{children}</ThemeProvider>
      </body>
    </html>
  )
}

Key configuration details:

  • cookies() reads the theme preference server-side to prevent flash of wrong theme
  • data-theme={theme} on <html> ensures correct theme on first render
  • data-brand="qualcomm" sets the brand (change to "snapdragon" or "dragonwing" for other brands)

Your application is now ready to import and use our components. An example application with this configuration is available in our templates repository.

Next Steps

  • Learn more about theming in our theming documentation.
  • Use the navigation menu on the left to view component documentation and examples.

Using the theme

Import the useTheme hook from your theme provider to access and toggle the theme:

import {useTheme} from "./components/theme-provider"

function ThemeToggle() {
  const {theme, toggleTheme} = useTheme()

  return <button onClick={toggleTheme}>Current theme: {theme}</button>
}

Customize the default theme

The default theme is "dark" when no cookie is set. To change this, modify the fallback in your layout:

const theme: QdsTheme = themeCookie?.value === "dark" ? "dark" : "light"

To set a different brand, change the data-brand attribute on the <html> element:

<html lang="en" data-brand="snapdragon" data-theme={theme} style={{colorScheme: theme}}>

Troubleshooting

Styles aren't loading

If @qualcomm-ui/react components are appearing without styles, check the following:

If styles still aren't appearing, inspect the DOM of your application in your browser's dev tools. Your application's <html> element should have at least two attributes:

  • data-brand: the QDS brand (either qualcomm, snapdragon, or dragonwing)
  • data-theme: the QDS theme (either light or dark)

Your <html> element should look something like this:

<html
  data-brand="qualcomm"
  data-theme="light"
  style="color-scheme: light"
></html>

Note that you need to import the corresponding CSS for the brand you've selected:

@import "@qualcomm-ui/qds-core/themes/qualcomm-dark.css";
@import "@qualcomm-ui/qds-core/themes/qualcomm-light.css";

Component Styles

Always import component styles, regardless of the chosen brand.

@import "@qualcomm-ui/qds-core/styles/components.css";

Migrating from legacy QUI

NextGen is independent of the legacy @qui/react package. Both can be installed and used in the same project without conflicts.

/* this is fine */
@import "@qui/styles/dist/all.min.css";
@import "@qui/base/dist/all.min.css";

@import "@qualcomm-ui/qds-core/styles/components.css";
@import "@qualcomm-ui/qds-core/themes/qualcomm-dark.css";
@import "@qualcomm-ui/qds-core/themes/qualcomm-light.css";

NOTE

We're working on a codemod script to automate the migration process. Check back regularly for updates!