Open source @drobinetm/countries-flags

Theming

Styling examples

This page shows the main ways to style the component. Use classNames for slot-level classes, styles for inline styles, or keep the bundled stylesheet and override CSS variables.

Start with your framework or library

Start with the section for your framework, then use the references later on this page.

Example: Angular with Angular Material

The component does not become a Material form field, but you can make it match Material spacing and surfaces.

import { Component } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { MatCardModule } from '@angular/material/card'
import { CountriesFlagsComponent } from '@drobinetm/angular-countries-flags'

@Component({
  standalone: true,
  imports: [FormsModule, MatCardModule, CountriesFlagsComponent],
  template: `
    <mat-card appearance="outlined">
      <mat-card-content>
        <drm-countries-flags
          [(ngModel)]="selectedCode"
          [unstyled]="true"
          [classNames]="{
            trigger: 'mat-mdc-button-base w-full d-flex align-items-center justify-content-between px-3 py-3 rounded-4 border',
            triggerContent: 'd-flex align-items-center gap-2 text-truncate',
            placeholder: 'mat-body-medium text-medium-emphasis',
            list: 'mt-2 rounded-4 border bg-surface p-1 mat-elevation-z8',
            option: 'd-flex align-items-center gap-2 rounded-3 px-3 py-2',
            optionSelected: 'bg-primary text-white'
          }"
          [styles]="{ flag: { borderRadius: "9999px" } }"
        ></drm-countries-flags>
      </mat-card-content>
    </mat-card>
  `,
})
export class DemoComponent {
  selectedCode: string | null = null
}
Copied

Example: React with Tailwind or shadcn/ui

In React, Tailwind and shadcn/ui fit well because the component lets you pass classes to each slot.

import { CountriesFlags } from '@drobinetm/react-countries-flags'

<CountriesFlags
  value={code}
  onChange={(event) => setCode(event.code)}
  unstyled
  classNames={{
    root: 'w-full',
    trigger: 'flex h-11 w-full items-center justify-between rounded-xl border border-slate-300 bg-white px-3 shadow-sm dark:border-slate-700 dark:bg-slate-950',
    triggerContent: 'flex min-w-0 items-center gap-2',
    placeholder: 'text-slate-400 dark:text-slate-500',
    label: 'truncate',
    list: 'mt-2 max-h-64 overflow-auto rounded-xl border border-slate-200 bg-white p-1 shadow-2xl dark:border-slate-800 dark:bg-slate-950',
    option: 'flex cursor-pointer items-center gap-2 rounded-lg px-3 py-2 text-sm',
    optionActive: 'bg-slate-100 dark:bg-slate-900',
    optionSelected: 'bg-sky-600 text-white',
  }}
  styles={{
    flag: { borderRadius: '9999px' },
  }}
/>
Copied

Example: Vue with Vuetify

Use Vuetify utility classes on the exposed slots to align spacing, elevation, and colors.

<CountriesFlags
  v-model="selectedCode"
  :unstyled="true"
  :class-names="{
    root: 'w-100',
    trigger: 'd-flex align-center justify-space-between w-100 px-4 py-3 rounded-lg border',
    triggerContent: 'd-flex align-center ga-2 min-w-0',
    placeholder: 'text-medium-emphasis',
    list: 'mt-2 pa-2 rounded-lg border bg-surface elevation-8',
    option: 'd-flex align-center ga-2 rounded-lg px-3 py-2',
    optionActive: 'bg-grey-lighten-4',
    optionSelected: 'bg-primary text-white',
  }"
  :styles="{
    flag: { borderRadius: '9999px' },
  }"
/>
Copied

Inline styles

Use inline styles when your theme is computed at runtime or comes from JavaScript tokens. The same object shape is used in React, Vue, and Angular.

styles={{
  root: { width: '100%', minWidth: 280 },
  trigger: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    width: '100%',
    minHeight: 44,
    padding: '0 14px',
    border: '1px solid #d4d4d8',
    borderRadius: 16,
    backgroundColor: '#ffffff',
    color: '#111827',
  },
  triggerContent: { display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 },
  placeholder: { color: '#6b7280' },
  list: {
    marginTop: 8,
    padding: 6,
    listStyle: 'none',
    border: '1px solid #e5e7eb',
    borderRadius: 16,
    backgroundColor: '#ffffff',
    boxShadow: '0 24px 48px rgba(15, 23, 42, 0.18)',
  },
  option: { display: 'flex', alignItems: 'center', gap: 8, padding: '10px 12px', borderRadius: 12 },
  optionActive: { backgroundColor: '#f3f4f6' },
  optionSelected: { backgroundColor: '#2563eb', color: '#ffffff' },
  flag: { borderRadius: '9999px' },
}}
Copied

Compatibility matrix

Use this matrix to compare which design systems make sense for each framework package.

SystemAngularReactVueRecommended API
Tailwind CSSYesYesYesunstyled + classNames
BootstrapYesYesYesunstyled + classNames
Inline stylesYesYesYesunstyled + styles
shadcn/uiNoYesNounstyled + classNames
Angular MaterialYesNoNounstyled + host layout classes
VuetifyNoNoYesunstyled + classNames

Available slots

All framework packages expose the same slot names. In most cases, only the syntax changes between frameworks.

type CountriesFlagsClassNames = {
  root?: string
  trigger?: string
  triggerContent?: string
  placeholder?: string
  label?: string
  chevron?: string
  backdrop?: string
  list?: string
  empty?: string
  option?: string
  optionSelected?: string
  optionActive?: string
  flag?: string
  optionName?: string
}
Copied

CSS variables

If you want to keep the default layout and just change colors or radii, CSS variables are the simplest option.

.drm-cf {
  --drm-cf-bg: #ffffff;
  --drm-cf-border: #d4d4d8;
  --drm-cf-border-hover: #93c5fd;
  --drm-cf-focus: #2563eb;
  --drm-cf-radius: 16px;
  --drm-cf-text: #111827;
  --drm-cf-placeholder: #6b7280;
  --drm-cf-dropdown-bg: #ffffff;
  --drm-cf-accent: #2563eb;
}
Copied

Slot mapping reference

Use this table when translating a design system into component slots.

SlotWhat it stylesTypical design-system mapping
rootOuter wrapperWidth, layout, spacing container
triggerClosed field buttonField chrome, border, padding, radius
triggerContentInner trigger rowHorizontal alignment and spacing
placeholderEmpty-state textMuted text color
labelSelected country labelText truncation and typography
chevronOpen/close iconIcon color and transitions
listDropdown panelSurface, border, shadow, radius
optionEvery option rowSpacing, cursor, typography
optionActiveHovered or active rowHover background
optionSelectedSelected rowBrand background and foreground
flagFlag iconRounded shape or fixed size
optionNameCountry text in listTypography and truncation