or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

component-api.mdfunctional-api.mdindex.mdmenu-bar.mdthemes.md
tile.json

themes.mddocs/

0

# Themes and Styling

1

2

Vue3 Context Menu provides a comprehensive theming system with built-in themes and extensive customization options. The library includes multiple pre-designed themes with light and dark variants, plus support for custom themes through CSS variables and class overrides.

3

4

## Capabilities

5

6

### Built-in Themes

7

8

The library includes several built-in themes designed to match different design systems and operating system styles.

9

10

```typescript { .api }

11

type ThemeNames =

12

| 'default'

13

| 'default dark'

14

| 'flat'

15

| 'flat dark'

16

| 'win10'

17

| 'win10 dark'

18

| 'mac'

19

| 'mac dark';

20

```

21

22

**Theme Usage:**

23

24

```typescript

25

// Functional API

26

ContextMenu.showContextMenu({

27

x: e.x,

28

y: e.y,

29

theme: 'win10 dark',

30

items: [...]

31

});

32

33

// Component API

34

const menuOptions = {

35

theme: 'mac',

36

x: 100,

37

y: 100

38

};

39

```

40

41

```vue

42

<template>

43

<context-menu :options="menuOptions" v-model:show="show">

44

<!-- menu items -->

45

</context-menu>

46

</template>

47

48

<script setup>

49

const menuOptions = {

50

theme: 'flat dark',

51

x: 0,

52

y: 0

53

};

54

</script>

55

```

56

57

### Theme Descriptions

58

59

#### Default Theme

60

Clean, modern appearance suitable for most applications.

61

62

- **'default'**: Light variant with subtle shadows and rounded corners

63

- **'default dark'**: Dark variant with light text on dark backgrounds

64

65

#### Flat Theme

66

Minimalist design with flat elements and subtle borders.

67

68

- **'flat'**: Light flat design with minimal shadows

69

- **'flat dark'**: Dark flat design with high contrast

70

71

#### Windows 10 Theme

72

Matches Windows 10 context menu styling.

73

74

- **'win10'**: Light Windows 10 style with system-like appearance

75

- **'win10 dark'**: Dark Windows 10 style matching dark mode

76

77

#### macOS Theme

78

Follows macOS design guidelines and visual style.

79

80

- **'mac'**: Light macOS style with system-like rounded corners

81

- **'mac dark'**: Dark macOS style matching macOS dark mode

82

83

### Theme Examples

84

85

```vue

86

<template>

87

<div class="theme-showcase">

88

<!-- Default theme -->

89

<button @click="showDefaultMenu">Default Theme</button>

90

91

<!-- Windows 10 theme -->

92

<button @click="showWin10Menu">Windows 10 Theme</button>

93

94

<!-- macOS theme -->

95

<button @click="showMacMenu">macOS Theme</button>

96

97

<!-- Flat theme -->

98

<button @click="showFlatMenu">Flat Theme</button>

99

</div>

100

</template>

101

102

<script setup>

103

import ContextMenu from '@imengyu/vue3-context-menu';

104

105

function showDefaultMenu(e) {

106

ContextMenu.showContextMenu({

107

x: e.clientX,

108

y: e.clientY,

109

theme: 'default',

110

items: getThemeMenuItems()

111

});

112

}

113

114

function showWin10Menu(e) {

115

ContextMenu.showContextMenu({

116

x: e.clientX,

117

y: e.clientY,

118

theme: 'win10',

119

items: getThemeMenuItems()

120

});

121

}

122

123

function showMacMenu(e) {

124

ContextMenu.showContextMenu({

125

x: e.clientX,

126

y: e.clientY,

127

theme: 'mac',

128

items: getThemeMenuItems()

129

});

130

}

131

132

function showFlatMenu(e) {

133

ContextMenu.showContextMenu({

134

x: e.clientX,

135

y: e.clientY,

136

theme: 'flat',

137

items: getThemeMenuItems()

138

});

139

}

140

141

function getThemeMenuItems() {

142

return [

143

{ label: 'New File', icon: 'file-icon' },

144

{ label: 'Open File', icon: 'folder-icon' },

145

{ divided: true, label: 'Settings', icon: 'settings-icon' }

146

];

147

}

148

</script>

149

```

150

151

## Custom Themes

152

153

### Creating Custom Themes

154

155

Create custom themes by defining CSS classes and overriding CSS variables.

156

157

```css

158

/* Custom theme definition */

159

.mx-context-menu.my-custom-theme {

160

--mx-menu-backgroud: #2d3748;

161

--mx-menu-border-color: #4a5568;

162

--mx-menu-shadow-color: rgba(0, 0, 0, 0.3);

163

--mx-menu-hover-backgroud: #4a5568;

164

--mx-menu-text-color: #e2e8f0;

165

--mx-menu-hover-text-color: #ffffff;

166

--mx-menu-disabled-text-color: #718096;

167

--mx-menu-separator-color: #4a5568;

168

--mx-menu-placeholder-width: 24px;

169

170

/* Menu container styling */

171

padding: 6px 0;

172

border-radius: 8px;

173

box-shadow: 0 4px 12px var(--mx-menu-shadow-color);

174

border: 1px solid var(--mx-menu-border-color);

175

background: var(--mx-menu-backgroud);

176

177

/* Menu item styling */

178

.mx-context-menu-item {

179

padding: 8px 16px;

180

margin: 2px 4px;

181

border-radius: 4px;

182

color: var(--mx-menu-text-color);

183

184

&:hover:not(.disabled) {

185

background: var(--mx-menu-hover-backgroud);

186

color: var(--mx-menu-hover-text-color);

187

}

188

189

&.disabled {

190

color: var(--mx-menu-disabled-text-color);

191

opacity: 0.6;

192

}

193

}

194

195

/* Separator styling */

196

.mx-context-menu-separator {

197

border-color: var(--mx-menu-separator-color);

198

margin: 4px 8px;

199

}

200

}

201

```

202

203

**Usage of Custom Theme:**

204

205

```typescript

206

ContextMenu.showContextMenu({

207

x: e.x,

208

y: e.y,

209

theme: 'my-custom-theme',

210

items: [...]

211

});

212

```

213

214

### CSS Variables Reference

215

216

All available CSS variables for theme customization:

217

218

```css { .api }

219

.mx-context-menu {

220

/* Background colors */

221

--mx-menu-backgroud: #ffffff;

222

--mx-menu-hover-backgroud: #f0f0f0;

223

--mx-menu-active-backgroud: #e0e0e0;

224

225

/* Text colors */

226

--mx-menu-text-color: #333333;

227

--mx-menu-hover-text-color: #333333;

228

--mx-menu-disabled-text-color: #999999;

229

230

/* Border and shadow */

231

--mx-menu-border-color: #e0e0e0;

232

--mx-menu-shadow-color: rgba(0, 0, 0, 0.15);

233

234

/* Separator */

235

--mx-menu-separator-color: #e0e0e0;

236

237

/* Layout */

238

--mx-menu-placeholder-width: 20px;

239

--mx-menu-padding: 4px 0;

240

--mx-menu-item-padding: 6px 12px;

241

--mx-menu-border-radius: 4px;

242

243

/* Icons */

244

--mx-menu-icon-size: 16px;

245

--mx-menu-check-size: 14px;

246

--mx-menu-arrow-size: 12px;

247

248

/* Transitions */

249

--mx-menu-transition-duration: 0.15s;

250

}

251

```

252

253

### Advanced Custom Theme Example

254

255

```css

256

/* Futuristic theme with gradients and animations */

257

.mx-context-menu.futuristic-theme {

258

--mx-menu-backgroud: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

259

--mx-menu-hover-backgroud: rgba(255, 255, 255, 0.1);

260

--mx-menu-text-color: #ffffff;

261

--mx-menu-shadow-color: rgba(102, 126, 234, 0.3);

262

--mx-menu-border-color: rgba(255, 255, 255, 0.2);

263

264

padding: 8px 0;

265

border-radius: 12px;

266

backdrop-filter: blur(10px);

267

border: 1px solid var(--mx-menu-border-color);

268

box-shadow:

269

0 8px 32px var(--mx-menu-shadow-color),

270

inset 0 1px 0 rgba(255, 255, 255, 0.1);

271

272

.mx-context-menu-item {

273

padding: 10px 16px;

274

margin: 2px 6px;

275

border-radius: 6px;

276

transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);

277

position: relative;

278

overflow: hidden;

279

280

&::before {

281

content: '';

282

position: absolute;

283

top: 0;

284

left: -100%;

285

width: 100%;

286

height: 100%;

287

background: linear-gradient(

288

90deg,

289

transparent,

290

rgba(255, 255, 255, 0.1),

291

transparent

292

);

293

transition: left 0.5s;

294

}

295

296

&:hover:not(.disabled) {

297

background: var(--mx-menu-hover-backgroud);

298

transform: translateX(4px);

299

300

&::before {

301

left: 100%;

302

}

303

}

304

305

.label {

306

font-weight: 500;

307

text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);

308

}

309

}

310

}

311

```

312

313

## Dynamic Theme Switching

314

315

### Theme Switching Implementation

316

317

```vue

318

<template>

319

<div>

320

<div class="theme-controls">

321

<select v-model="currentTheme" @change="updateTheme">

322

<option value="default">Default Light</option>

323

<option value="default dark">Default Dark</option>

324

<option value="win10">Windows 10</option>

325

<option value="win10 dark">Windows 10 Dark</option>

326

<option value="mac">macOS</option>

327

<option value="mac dark">macOS Dark</option>

328

<option value="flat">Flat</option>

329

<option value="flat dark">Flat Dark</option>

330

</select>

331

</div>

332

333

<div @contextmenu="showThemedMenu">

334

Right-click to see themed menu

335

</div>

336

</div>

337

</template>

338

339

<script setup>

340

import { ref } from 'vue';

341

import ContextMenu from '@imengyu/vue3-context-menu';

342

343

const currentTheme = ref('default');

344

345

function showThemedMenu(e) {

346

e.preventDefault();

347

348

ContextMenu.showContextMenu({

349

x: e.clientX,

350

y: e.clientY,

351

theme: currentTheme.value,

352

items: [

353

{ label: 'New', icon: 'new-icon' },

354

{ label: 'Open', icon: 'open-icon' },

355

{ label: 'Save', icon: 'save-icon', shortcut: 'Ctrl+S' },

356

{ divided: true, label: 'Settings', icon: 'settings-icon' }

357

]

358

});

359

}

360

361

function updateTheme() {

362

// Theme will be applied to next menu

363

console.log(`Theme changed to: ${currentTheme.value}`);

364

}

365

</script>

366

```

367

368

### System Theme Detection

369

370

```vue

371

<template>

372

<div @contextmenu="showSystemThemedMenu">

373

Right-click for system-matched theme

374

</div>

375

</template>

376

377

<script setup>

378

import { ref, onMounted } from 'vue';

379

import ContextMenu from '@imengyu/vue3-context-menu';

380

381

const systemTheme = ref('default');

382

383

function detectSystemTheme() {

384

if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {

385

systemTheme.value = 'default dark';

386

} else {

387

systemTheme.value = 'default';

388

}

389

}

390

391

function showSystemThemedMenu(e) {

392

e.preventDefault();

393

394

ContextMenu.showContextMenu({

395

x: e.clientX,

396

y: e.clientY,

397

theme: systemTheme.value,

398

items: getMenuItems()

399

});

400

}

401

402

onMounted(() => {

403

detectSystemTheme();

404

405

// Listen for system theme changes

406

const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

407

mediaQuery.addEventListener('change', detectSystemTheme);

408

});

409

</script>

410

```

411

412

## Icon Integration

413

414

### Icon Font Classes

415

416

Configure global icon font classes for consistent icon display:

417

418

```typescript { .api }

419

interface IconConfiguration {

420

/** Global icon font class name */

421

iconFontClass?: string;

422

/** Reserve icon width for items without icons */

423

preserveIconWidth?: boolean;

424

}

425

```

426

427

**Usage Examples:**

428

429

```typescript

430

// Global icon font configuration

431

ContextMenu.showContextMenu({

432

x: e.x,

433

y: e.y,

434

iconFontClass: 'fa', // Font Awesome

435

preserveIconWidth: true,

436

items: [

437

{ label: 'New', icon: 'fa-file' },

438

{ label: 'Open', icon: 'fa-folder-open' },

439

{ label: 'Save', icon: 'fa-save' }

440

]

441

});

442

443

// Per-item icon font class

444

ContextMenu.showContextMenu({

445

x: e.x,

446

y: e.y,

447

items: [

448

{

449

label: 'Custom Icon',

450

icon: 'custom-icon',

451

iconFontClass: 'material-icons'

452

}

453

]

454

});

455

```

456

457

### SVG Icons

458

459

Support for SVG symbols and custom SVG icons:

460

461

```typescript

462

// SVG symbol icons

463

ContextMenu.showContextMenu({

464

x: e.x,

465

y: e.y,

466

items: [

467

{

468

label: 'Home',

469

svgIcon: '#icon-home',

470

svgProps: {

471

width: 16,

472

height: 16,

473

fill: 'currentColor'

474

}

475

}

476

]

477

});

478

```

479

480

### Custom Icon Components

481

482

```vue

483

<template>

484

<context-menu>

485

<context-menu-item label="Custom Icon">

486

<template #icon>

487

<svg class="custom-icon" viewBox="0 0 24 24">

488

<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>

489

</svg>

490

</template>

491

</context-menu-item>

492

</context-menu>

493

</template>

494

495

<style scoped>

496

.custom-icon {

497

width: 16px;

498

height: 16px;

499

fill: currentColor;

500

}

501

</style>

502

```