使 Vuetify (3) 选择下拉菜单在卡片/对话框表面上脱颖而出

问题描述 投票:0回答:3

我有一个 VDialog,其中包含一个 VCard,而 VCard 又包含一个 VSelect。当我打开 VSelect 时,很难看到选项的下拉列表,因为它的颜色与 VCard 相同。两者似乎都有

background: rgb(var(--v-theme-surface));
唯一让下拉菜单脱颖而出的是阴影,但在黑暗主题中,你几乎看不到它。

如果 VSelect(或 VMenu、VCombobox)位于 VDialog 或 VCard 内,建议更改其背景的方法是什么?

我知道 Vuetify 3 有一种方法可以更改全局配置(包括嵌套选项,例如 VCard 内的 VSelect),但我无法使其工作。

我还尝试使用 CSS 变量,更改

--v-theme-surface
CSS 属性的值,但看起来下拉列表已移到父容器之外并靠近 html
<body>
,因此我无法定位它。

有没有办法将 CSS 类“发送”到子下拉菜单中,以便我可以这样定位它?

非常感谢。

vuetify.js vuetifyjs3
3个回答
1
投票

我不知道如何直接通过 Vuetify 更改嵌套组件的样式,但是使用

:menu-props
属性,您可以将配置对象传递给底层
v-menu
组件。
:content-class
属性的内容将被设置为覆盖内容节点上的类:

<v-select
  ...
  :menu-props="{
    contentClass: 'lighter-surface',
  }"
>

有了这个,您现在可以定义 CSS 规则来调整背景颜色变量:

.lighter-surface > .v-theme--dark{
  --v-theme-surface: var(--v-theme-on-surface-variant); /* or something like 55,55,55; */
}

const { createApp } = Vue;
const { createVuetify } = Vuetify
const vuetify = createVuetify({theme: {defaultTheme: 'dark'}})
const app = {}
createApp(app).use(vuetify).mount('#app')
.lighter-surface > .v-theme--dark{
  --v-theme-surface: var(--v-theme-on-surface-variant);
}
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" />
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
  <v-app>
    <v-main>
      <v-card class="ma-4">
        <v-card-title>Selection Card</v-card-title>
        <v-card-text>
          <v-select
            :items="['option 1', 'option 2', 'option 3']"
            label="Select"
            :menu-props="{
              contentClass: 'lighter-surface',
            }"
          ></v-select>
          <div style="height: 200px;">
          </div>
        </v-card-text>
      </v-card>
    </v-main>
  </v-app>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>

如果您不想更改全局样式,可以尝试使用

v-menu
 属性将 v-card
 附加到 
:attach
,然后就可以使用本地样式。但不确定是否值得。


或者你可以通过添加自己的主题来解决:

const vuetify = createVuetify({
  theme: {
    defaultTheme: 'dark',
    themes: {
      darkOnSurface: { // <--- name of the theme
        dark: true, // <--- extend dark theme
        colors: {
          surface: 'blue', // <--- override color variant from dark theme
        }
      }
    }
  }
})

然后在

v-menu
中设置该主题:

<v-select
  ...
  :menu-props="{
    theme: 'darkOnSurface',
  }"
></v-select>

优点是你可以在所有 Vuetify 组件上使用它。

const {
  createApp
} = Vue;
const {
  createVuetify
} = Vuetify
const vuetify = createVuetify({
  theme: {
    defaultTheme: 'dark',
    themes: {
      darkOnSurface: {
        dark: true,
        colors: {
          surface: 'blue',
        }
      }
    }
  }
})
const app = {}
createApp(app).use(vuetify).mount('#app')
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" />
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<div id="app">
  <v-app>
    <v-main>
      <v-card class="ma-4">
        <v-card-title>Selection Card</v-card-title>
        <v-card-text>
          <v-select
            :items="['option 1', 'option 2', 'option 3']"
            label="Select"
            :menu-props="{
              theme: 'darkOnSurface',
            }"
          ></v-select>
          <div style="height: 200px;">
          </div>
        </v-card-text>
      </v-card>
    </v-main>
  </v-app>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>


0
投票

谢谢你!我做了一些测试,你的三种方法效果很好。这是我对它们的看法。

一、模板:

<v-card id="my-card" style="padding: 1rem; height: 17rem;">
    <v-select label="By Props" :menu-props="{contentClass: 'lighter-surface' }" />
    <v-select label="By Theme" theme="onSurface" />
    <v-select label="By Attach" :menu-props="{attach: '#my-card' }" />
</v-card>

CSS:

// For the 'By Props' method
.lighter-surface [class*=' v-theme--'] {
  --v-theme-surface: var(--v-theme-inner-surface);
  --v-theme-on-surface: var(--v-theme-on-inner-surface);
}
// For the 'By Attach' method
.v-card [class*=' v-theme--'] {
  --v-theme-surface: var(--v-theme-inner-surface);
  --v-theme-on-surface: var(--v-theme-on-inner-surface);
}

Vuetify.ts

const defaultDark: ThemeDefinition = {
  dark: true,
  colors: {
    background: '#1D1716',
    surface: '#322929',
    'inner-surface': '#BDBDBD', // For the By Props & Attach method
    primary: '#793C86',
  },
}
const onSurface: ThemeDefinition = {
  dark: true,
  colors: { surface: '#BDBDBD' }, // For the By Theme method
}
createVuetify({
    theme: {
      defaultTheme: 'defaultDark',
      themes: { defaultDark, onSurface },
    },
  })

就个人而言,我更喜欢“通过道具”方法。

“通过附加”方法会导致功能发生变化,例如如果掉落物溢出容器,则会被切断。

“按主题”方法要求始终有两个维护的主题。我更喜欢每个主题都包含整个应用程序中使用的所有颜色。

遗憾的是,没有办法自动检测 VCard 中是否使用了 VMenu,而无需使用菜单属性明确标记它。但是,嘿,这效果非常好!


0
投票

您可以使用上下文默认值来执行此操作:https://vuetifyjs.com/en/features/global-configuration/

createVuetify({
  theme: {
    themes: {
      light: {
        colors: { 'inner-surface': '#f00' },
      },
    },
  },
  defaults: {
    VCard: {
      VSelect: {
        VList: { bgColor: 'inner-surface' },
      },
    },
  },
})
© www.soinside.com 2019 - 2024. All rights reserved.