Common Components - Bng* UI Elements
Reusable Vue components and directives for building BeamNG UI.
Reusable Vue components and directives for building BeamNG UI.
Overview
BeamNG provides a comprehensive component library:
- Bng Components* - Buttons, inputs, icons, cards, lists, etc.
- Directives - Blur, tooltip, navigation, focus control
- Layouts - Screen structures and containers
- Utility Components - Drawers, overflow containers, etc.
Importing Components
// From base components
import {
BngButton,
BngIcon,
BngInput,
BngCard,
BngSlider,
BngSwitch,
BngDropdown,
BngBinding,
ACCENTS,
icons
} from '@/common/components/base'
// From utility components
import { Drawer } from '@/common/components/utility'
// Directives
import {
vBngBlur,
vBngTooltip,
vBngOnUiNav,
vBngScopedNav,
vBngDisabled
} from '@/common/directives'Button (BngButton)
Full-featured button with accents, icons, and controller support.
Basic Usage
<BngButton @click="handleClick">
Click Me
</BngButton>With Icon
<BngButton :icon="icons.save" @click="save">
Save
</BngButton>Accents
<script setup>
import { BngButton, ACCENTS } from '@/common/components/base'
</script>
<template>
<BngButton :accent="ACCENTS.primary">Primary</BngButton>
<BngButton :accent="ACCENTS.secondary">Secondary</BngButton>
<BngButton :accent="ACCENTS.outlined">Outlined</BngButton>
<BngButton :accent="ACCENTS.ghost">Ghost</BngButton>
<BngButton :accent="ACCENTS.attention">Attention</BngButton>
</template>Available Accents
ACCENTS = {
primary, // Orange filled
secondary, // Gray filled
outlined, // Bordered, transparent
ghost, // Minimal, text only
attention, // Red/warning
confirm // Green/success
}Props
| Prop | Type | Description |
|---|---|---|
accent | ACCENTS | Button style |
icon | icons | Icon to display |
disabled | Boolean | Disable button |
bngNoNav | Boolean | Exclude from controller nav |
Icon (BngIcon)
Display icons from the icon set.
Basic Usage
<BngIcon type="save" />
<BngIcon :type="icons.engine" />With Custom Size
<BngIcon type="car" style="--bng-icon-size: 2em" />As External Image
<BngIcon :externalImage="'/path/to/image.png'" />Props
| Prop | Type | Description |
|---|---|---|
type | String/icons | Icon name |
externalImage | String | External image path |
fallbackType | String | Fallback if type not found |
Using icons Object
import { icons } from '@/common/components/base'
// Access icons by name
icons.save
icons.engine
icons.car
icons.arrowLargeLeft
icons.sprayCanInput (BngInput)
Text input field.
Basic Usage
<BngInput v-model="searchText" placeholder="Search..." />With Label
<BngInput
v-model="name"
label="Vehicle Name"
:maxlength="50"
/>Props
| Prop | Type | Description |
|---|---|---|
modelValue | String | v-model binding |
placeholder | String | Placeholder text |
label | String | Input label |
disabled | Boolean | Disable input |
maxlength | Number | Max characters |
type | String | Input type (text, password, etc.) |
Slider (BngSlider)
Range slider input.
<BngSlider
v-model="volume"
:min="0"
:max="100"
:step="1"
label="Volume"
/>Props
| Prop | Type | Description |
|---|---|---|
modelValue | Number | v-model binding |
min | Number | Minimum value |
max | Number | Maximum value |
step | Number | Step increment |
label | String | Slider label |
Switch (BngSwitch)
Toggle switch.
<BngSwitch v-model="enabled" label="Enable Feature" />Label Alignment
import { LABEL_ALIGNMENTS } from '@/common/components/base'
<BngSwitch
v-model="enabled"
label="Enable"
:labelAlignment="LABEL_ALIGNMENTS.left"
/>Dropdown (BngDropdown)
Selection dropdown.
<BngDropdown
v-model="selectedOption"
:items="options"
placeholder="Select..."
/>
<script setup>
const options = [
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' },
{ label: 'Option 3', value: 'opt3' }
]
</script>Card (BngCard)
Container card with optional heading.
<BngCard>
<template #heading>
<BngCardHeading>Card Title</BngCardHeading>
</template>
<div class="card-content">
Content goes here
</div>
</BngCard>Screen Heading (BngScreenHeading)
Page title component.
<BngScreenHeading>
<template #title>{{ $t('ui.myModule.title') }}</template>
<template #subtitle>{{ vehicleName }}</template>
</BngScreenHeading>Binding (BngBinding)
Display controller button bindings.
<!-- Show binding for "back" action -->
<BngBinding ui-event="back" />
<!-- Controller only (hide on keyboard) -->
<BngBinding ui-event="confirm" controller />
<!-- Show even if unassigned -->
<BngBinding ui-event="action_4" show-unassigned />Props
| Prop | Type | Description |
|---|---|---|
ui-event | String | Action name (back, confirm, menu, etc.) |
controller | Boolean | Only show for controllers |
show-unassigned | Boolean | Show even if no binding |
action | String | Alternative to ui-event |
List (BngList)
Scrollable list with various layouts.
<BngList
:items="items"
:layout="LIST_LAYOUTS.grid"
@itemClick="onItemClick"
>
<template #item="{ item }">
<div class="list-item">{{ item.name }}</div>
</template>
</BngList>Layouts
import { LIST_LAYOUTS } from '@/common/components/base'
LIST_LAYOUTS = {
list, // Vertical list
grid, // Grid layout
carousel // Horizontal scroll
}Progress Bar (BngProgressBar)
Progress indicator.
<BngProgressBar
:value="progress"
:max="100"
:showLabel="true"
/>Directives
v-bng-blur
Apply blur effect to element.
<div v-bng-blur>
This content has a blur background
</div>
<!-- Conditional blur -->
<div v-bng-blur="isBlurred">...</div>v-bng-tooltip
Show tooltip on hover.
<BngButton v-bng-tooltip="'Click to save'">Save</BngButton>
<!-- With position -->
<BngButton v-bng-tooltip:top="'Tooltip above'">Hover me</BngButton>
<BngButton v-bng-tooltip:bottom="'Tooltip below'">Hover me</BngButton>v-bng-disabled
Disable element and prevent interaction.
<BngButton v-bng-disabled="!isReady">Submit</BngButton>v-bng-on-ui-nav
Handle controller navigation events.
<div
v-bng-on-ui-nav:back="goBack"
v-bng-on-ui-nav:confirm="submit"
v-bng-on-ui-nav:menu="openMenu"
>
<!-- Content -->
</div>v-bng-scoped-nav
Create navigation scope for controller.
<div
v-bng-scoped-nav="{
activateOnMount: true,
bubbleWhitelistEvents: ['menu']
}"
@deactivate="onExit"
>
<BngButton :bng-scoped-nav-autofocus="true">
First focused button
</BngButton>
<BngButton>Another button</BngButton>
</div>v-bng-focus-if
Conditionally focus element.
<BngInput v-bng-focus-if="shouldFocus" />v-bng-frustum-mover
Move element when frustum camera changes.
<div v-bng-frustum-mover:left="true">
Moves with camera
</div>Utility Components
Drawer
Expandable drawer panel.
<Drawer v-model="isExpanded" position="left">
<template #header>
<BngButton @click="isExpanded = !isExpanded">
Toggle Drawer
</BngButton>
</template>
<template #expanded-content>
<div class="drawer-content">
Drawer content here
</div>
</template>
</Drawer>BngOverflowContainer
Handle content overflow with scroll indicators.
<BngOverflowContainer>
<div class="long-content">
<!-- Lots of content -->
</div>
</BngOverflowContainer>Common Component Patterns
Button Group
<div class="button-group">
<BngButton
v-for="option in options"
:key="option.id"
:accent="selectedId === option.id ? ACCENTS.primary : ACCENTS.outlined"
@click="selectedId = option.id"
>
{{ option.label }}
</BngButton>
</div>Form Layout
<div class="form">
<div class="form-row">
<BngInput v-model="form.name" label="Name" />
</div>
<div class="form-row">
<BngDropdown v-model="form.type" :items="typeOptions" />
</div>
<div class="form-row">
<BngSlider v-model="form.value" :min="0" :max="100" label="Value" />
</div>
<div class="form-actions">
<BngButton :accent="ACCENTS.primary" @click="submit">Save</BngButton>
<BngButton :accent="ACCENTS.secondary" @click="cancel">Cancel</BngButton>
</div>
</div>Icon Button
<BngButton
:icon="icons.settings"
:accent="ACCENTS.ghost"
v-bng-tooltip:top="'Settings'"
/>Conditional Icon
<BngIcon
:type="isComplete ? icons.checkmark : icons.clock"
:class="{ 'icon-success': isComplete }"
/>Styling Components
CSS Variables
// Common CSS variables available
.my-component {
color: var(--bng-off-white);
background: rgba(var(--bng-off-black-rgb), 0.5);
border-radius: var(--bng-corners-1);
font-family: var(--fnt-defs);
}Theming Icons
.my-icon {
--bng-icon-size: 2em;
--bng-icon-color: var(--bng-orange);
}See Also
- UI Apps - Using components in HUD apps
- Vue Modules - Using components in screens
- Services - Popup and translation services