Troubleshoot EmviUI React Tailwind: Styling, Variants & Build Errors

Author: Pablo Mayoral Published: 11/11/2026 Updated: 11/11/2026
Category: Product design →

Find the failing layer before changing a shared component’s visual recipe.

Troubleshoot EmviUI React Tailwind: Styling, Variants & Build Errors
Quick Answer

To troubleshoot EmviUI styling conflicts, missing component variants or build errors in React and Tailwind, first identify the resource you imported. Then isolate the failing layer: build, rendered component, generated CSS or cascade. Check one component on a minimal route and verify the correction in a production build.

To troubleshoot EmviUI styling conflicts, missing component variants or build errors in React and Tailwind, first identify the resource you imported. Then isolate the failing layer: build, rendered component, generated CSS or cascade. Check one component on a minimal route and verify the correction in a production build.

EmviUI’s button page describes editable Figma patterns. A Figma variant is a design reference; it does not establish a React prop API or install CSS. This guide follows a fictional Fieldnote toolbar implemented from that reference. Its recipes and diagnostic cases are proposed application code, not an official EmviUI SDK.

Locate the failing component layer

Record the exact symptom before changing styles. If the build fails, start with its first actionable error. If the component is absent, inspect rendering. If it exists but looks wrong, inspect its rules. The button anatomy below helps separate arrangement, internal space and surface decisions once you reach the CSS layer.

Button anatomy separating arrangement, internal spacing and surface utilities
Example recipe: give each utility a clear visual responsibility.

Create a temporary review route containing one button and its surrounding toolbar. Keep the same imports and stylesheet entry as the failing screen. Compare the affected role with one working role. Record the route, installed Tailwind version, expected appearance and observed result. Change one cause at a time so the result remains explainable.

If the minimal route works, add the original surrounding layout back in stages. A wrapper that changes width or a page stylesheet that overrides the surface can then be identified directly. Do not recreate the entire production screen before learning which addition makes the symptom return. Keep the reproduction until the fix has been checked in the real route.

Map component choices to complete classes

Keep finite component choices in a lookup table of complete utility strings. Tailwind’s source-detection documentation describes why class-name fragments assembled at runtime can be missed. In our example, the role “primary” selects a complete background-and-text recipe; it does not supply the middle of a generated class name.

Primary and secondary roles select complete recipes with a shared focus and padding layer
Finite roles select full strings. The example falls back to secondary.

Let the component own its internal appearance. A caller chooses primary or secondary, while the component owns padding, focus styling and the approved role recipes. If a page needs extra space around the button, put that spacing on the surrounding toolbar. This makes a later change to the shared button easier to reason about.

Provide a fallback for an unexpected role. A runtime API response can still contain a value outside the intended vocabulary, even if the local TypeScript caller is well typed. In this example, an unknown role uses the secondary recipe. Document that decision so a new backend value does not silently become a brand-new visual state.

Avoid exposing an unrestricted color name simply because it makes the first example shorter. A role such as destructive carries a reviewable meaning; a shade such as red-600 only describes a paint choice. The recommended API lets the team revise the paint without changing every caller. Keep business permission checks outside this styling map.

const roles = {
  primary: "bg-slate-900 text-white enabled:hover:bg-slate-800",
  secondary: "bg-white text-slate-900 border border-slate-300"
};

export function SaveButton({ role = "primary", disabled = false, children }) {
  const recipe = Object.hasOwn(roles, role) ? roles[role] : roles.secondary;
  return (
    <button type="button" disabled={disabled}
      className={[
        "inline-flex items-center justify-center gap-2 rounded-xl px-4 py-2",
        "font-medium focus-visible:outline-2 focus-visible:outline-offset-2",
        "focus-visible:outline-blue-600 disabled:opacity-50",
        recipe
      ].join(" ")}>
      {children}
    </button>
  );
}

Separate missing markup from dynamic values

When a variant seems missing, inspect whether React rendered it at all. The React conditional-rendering guide shows how branches can include or omit JSX. Check the prop value at the component boundary, the selected branch and the resulting element before diagnosing its colors.

For Fieldnote, an empty toolbar is different from a visible button with the wrong surface. If the element is absent, confirm the permission and loading branches. If it exists, inspect its complete class string and role fallback. A correct Figma variant name does not guarantee that the application uses the same spelling or even the same API.

Keep true runtime values separate from class names. For a project accent, use a stable utility reading a validated CSS custom property, as described in Tailwind’s custom-style documentation. The marker below is decorative; it does not replace a visible project title. Test a missing value and a stored invalid value as well as two valid accents.

<span class="inline-block size-3 rounded-full bg-[var(--project-accent)]"
      style="--project-accent: #2563eb" aria-hidden="true"></span>

Check the source boundary before adding CSS

When a dependency or shared package supplies the markup, confirm that its source is included in the stylesheet’s detection boundary. In Tailwind v4, an explicit @source path can register an otherwise ignored library. Keep the path relative to the stylesheet and register the smallest relevant directory. The version matters when borrowing configuration examples.

Application entry, stylesheet and UI source connected by import and source paths
Check real repository paths; an import and a detection boundary do different jobs.

Draw a simple ownership map before editing configuration: the application entry imports the stylesheet, the stylesheet detects the UI source, and the UI source contains the intended utility strings. Put actual repository paths beside these three responsibilities. A broken arrow identifies a better next investigation than adding another background class to a page.

If the entire page is unstyled, verify the stylesheet import and network response first. If one role is missing while shared padding works, inspect that role’s recipe and the file containing it. If a package works in a local playground but not the consuming application, compare the package path and build entry in those two environments.

A narrow safelist can be appropriate for a small, intentional vocabulary supplied outside scanned source; v4 provides @source inline(). Write down the owner and reason for each exception. Avoid hiding a broken component contract behind a broad range of generated colors. For initial application wiring, use the separate React and Vite setup guide.

Inspect the winning rule and its condition

A generated utility can exist without being the rule that controls the element. The utility-class documentation explains how conflicting classes are resolved. Inspect the browser’s computed style and the conditions around the rule. When utilities compete under equivalent conditions, their order in the generated stylesheet matters; moving a token to the end of the HTML class attribute is not a reliable override strategy.

Real EmviUI toast specimens showing light and filled color treatments with status and close icons
EmviUI visual specimens: compare intended surfaces with computed CSS; the image does not prove announcement behavior.
Inspection of a present CSS rule, matching condition and winning declaration
Separate missing rules, inactive conditions and competing declarations.

Start with one property, such as background-color. Find the value the browser currently uses, identify the selector that supplied it, and see whether the intended selector is absent, crossed out or conditional. Only then change the source. A missing rule, a competing rule and an inactive media query are three different failures.

State variants such as enabled:hover: and focus-visible: describe conditions; they do not create application behavior. Tailwind’s state documentation explains the selectors behind these variants. In the sample button, disabled is an actual HTML attribute. Merely adding disabled:opacity-50 without setting that attribute would not disable the control.

For width-dependent styling, unprefixed utilities form the baseline and breakpoint variants apply from their threshold upward, as described in the responsive-design documentation. Review the toolbar just below and above its chosen transition. Read the project’s configured breakpoints rather than assuming another repository’s numbers. For longer labels and zoom cases, continue with readable type and reflow checks.

Review the button states with EmviUI

The EmviUI button component page offers editable Figma button patterns for comparing action treatments. The real EmviUI specimen below shows filled, outlined and lighter treatments in several colors. Use it to choose a small visual vocabulary for the toolbar, then record which state each implementation must demonstrate.

EmviUI button specimen with filled, outlined and light treatments in several colors
Real EmviUI visual specimen. Choose role treatments here; verify semantics and behavior in the browser.

For this exercise, select one primary treatment and one secondary treatment. In Figma, place the same “Save project” label into both and compare the hierarchy beside a project title. Mark the intended default, hover and unavailable appearances in your own review sheet. The image supplies visual examples; it does not prove which HTML attributes or CSS rules implement them.

In the browser, add a visible focus treatment and reach the action with Tab. WCAG’s Focus Visible explanation describes why keyboard users need to see which control has focus. Keep that review separate from hovering with a mouse. A darker background during hover does not tell a keyboard user where they are.

Use the disabled state only when the action is actually unavailable, and explain the reason near the action when the context does not make it clear. For Fieldnote, “No changes to save” is more useful than an unexplained faded control. If saving fails, preserve the edited project name and give the person a clear retry path. The visual recipe cannot decide whether the save reached the server.

EmviUI can help the team align the appearance being reviewed. The application still needs its own event handling, validation and browser checks. Keep a short mapping from each selected Figma treatment to the corresponding component role and observed state. For the next interface review, use the practical form and state checklist.

Resolve build errors before visual debugging

A failed build is a different branch of this investigation. Read the first actionable error with its file path, line and command. Check whether the import exists, whether its export matches the usage and whether the command is running from the intended package. Fix that error before changing button colors.

For a Vite application, the production-build documentation describes the build entry and public base path. Run the project’s existing build script and serve its output using the configured preview workflow. If compilation succeeds but the deployed stylesheet returns 404, inspect the emitted URL and hosting path. That is a delivery problem, not evidence that the role recipe was missed.

Keep the exact failing command in the issue record. A missing module needs an import or dependency correction; a malformed CSS declaration needs a syntax correction. Neither is repaired by generating more utility classes. After the build passes, return to the original route and repeat the class and state checks; one resolved error does not prove every visual decision is correct.

Verify the built page with a small acceptance matrix

Finish with the actual production build served through the project’s preview command. Open the page directly, refresh it and repeat the important state changes. Record outcomes against the same component contract used in design review. The matrix below is a proposed acceptance tool, not a claim that every application uses these exact states.

Fieldnote preview alongside four concrete production acceptance checks
Proposed review matrix for the fictional Fieldnote component.

First, load the primary and secondary roles without navigating through another page. Confirm that both have their intended surface and internal spacing. Next, supply an unknown role and confirm the documented fallback. This catches a surprisingly common review gap: only the happy-path role was present in the demonstration.

Then use the keyboard to reach the Save action, disable it through the actual application state, and re-enable it after making an edit. Observe the indicator and the action’s availability. Finally, narrow the viewport and use the longer Spanish label. A successful build still needs a readable interface with a usable action.

Keep evidence brief: build identifier, route, tested role, observed rule and result. If a failure returns, that record tells the next person where to start. A class list is finished when its visual responsibilities, source boundary and state conditions can all be explained from the running page.

CaseExpected evidence
Primary and secondaryComplete recipe and intended surface
Unknown roleDocumented secondary fallback
Keyboard focusVisible indicator on the active control
Disabled actionActual disabled attribute and explanation
Narrow layoutReadable label and usable action
Pablo Mayoral

Senior UX/UI & Web Designer with 10+ years of experience. Creator of EmviUI (10k+ components Figma design system), UImand, and Vitamin Bootstrap. Currently designing digital products at CQMRewards.

Frequently asked questions

How do I troubleshoot an EmviUI component in React and Tailwind? ▼
Identify whether you are using a Figma reference or actual implementation code. Reproduce one component, separate build failures from absent markup and CSS failures, then inspect the rendered role, generated rule and cascade. Verify the correction against a production build.
Can I choose classes conditionally in React? ▼
Yes. Choose between complete strings, such as the primary and secondary recipes in the example. Avoid constructing fragments of a class name; Tailwind detects source text rather than executing the component to discover its final strings.
Does a Figma variant automatically become a React prop? ▼
No automatic mapping is established by a Figma specimen. EmviUI’s button page describes editable Figma patterns. Your implementation must define the prop names, available roles and fallback behavior, then verify the rendered output.
Does the final class in the HTML attribute always win? ▼
No. For competing utilities under equivalent conditions, the order of rules in the stylesheet matters. Inspect the computed property and remove the conflicting decision from the component contract instead of relying on token order.
How should I handle a color that comes from user data? ▼
Use a stable utility referring to a CSS custom property and supply an application-validated value. Keep user data separate from class-name construction. Tailwind supports arbitrary values, but your application must define accepted inputs and fallbacks.
Does adding a focus class make the button accessible? ▼
A visible focus indicator is one part of a usable control. Review it with a keyboard, use appropriate HTML semantics and check the actual action and unavailable state. WCAG’s Focus Visible explanation addresses the indicator; it is not a complete certification of the component.

Related articles