custom chevron on selects with 16px right inset

Native <select> chevrons render at varying offsets across browsers.
Replaced them with `appearance-none` + an absolute-positioned
chevron-down Icon at right-4 (16px) so the gap between the chevron
and the right border is consistent. Applied to RegisterPage's
salutation select and ShippingStep's shipping/billing country selects.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-05-03 18:56:24 +01:00
parent 0bf8a32d97
commit 4ed021280a
10 changed files with 58 additions and 32 deletions

File diff suppressed because one or more lines are too long

1
dist/assets/RegisterPage-dPnfxt-C.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/assets/ShippingStep-BGY1kvmS.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/assets/index-CLf26bWJ.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/index.html vendored
View File

@@ -12,14 +12,14 @@
href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,200;0,9..144,400;0,9..144,600;0,9..144,700;1,9..144,200;1,9..144,400;1,9..144,600&family=DM+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400&display=swap"
rel="stylesheet"
/>
<script type="module" crossorigin src="/assets/index-BEH7XedS.js"></script>
<script type="module" crossorigin src="/assets/index-DSgweLra.js"></script>
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-BOai-rQB.js">
<link rel="modulepreload" crossorigin href="/assets/preload-helper-DzyYoeor.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-core.esm-bundler-DTXUv7Wx.js">
<link rel="modulepreload" crossorigin href="/assets/runtime-dom.esm-bundler-Bg1uJ-W7.js">
<link rel="modulepreload" crossorigin href="/assets/pinia-D94NEbtV.js">
<link rel="modulepreload" crossorigin href="/assets/vue-router-Cyqru1db.js">
<link rel="stylesheet" crossorigin href="/assets/index-BhtMpj4L.css">
<link rel="stylesheet" crossorigin href="/assets/index-CLf26bWJ.css">
</head>
<body>
<div id="app"></div>

View File

@@ -11,6 +11,7 @@ import Navbar from '@/design-system/components/Navbar.vue'
import Footer from '@/design-system/components/Footer.vue'
import Input from '@/design-system/components/Input.vue'
import Button from '@/design-system/components/Button.vue'
import Icon from '@/design-system/components/Icon.vue'
import { products, register } from '@/api/index.js'
import { useCartStore } from '@/stores/cart.js'
import { useI18n } from '@/i18n/index.js'
@@ -125,15 +126,23 @@ onBeforeUnmount(() => {
<label class="text-[11px] font-bold uppercase tracking-eyebrow text-muted">
{{ t('checkout.field.salutation') }}
</label>
<select
v-model="salutation"
class="w-full rounded-sm border border-line bg-paper px-4 py-3 text-[15px] text-ink transition-colors duration-base focus:outline-none focus:border-brand"
>
<option value="">{{ t('checkout.field.salutation.placeholder') }}</option>
<option value="frau">{{ t('checkout.field.salutation.frau') }}</option>
<option value="herr">{{ t('checkout.field.salutation.herr') }}</option>
<option value="divers">{{ t('checkout.field.salutation.divers') }}</option>
</select>
<div class="relative">
<select
v-model="salutation"
class="appearance-none w-full rounded-sm border border-line bg-paper pl-4 pr-10 py-3 text-[15px] text-ink transition-colors duration-base focus:outline-none focus:border-brand"
>
<option value="">{{ t('checkout.field.salutation.placeholder') }}</option>
<option value="frau">{{ t('checkout.field.salutation.frau') }}</option>
<option value="herr">{{ t('checkout.field.salutation.herr') }}</option>
<option value="divers">{{ t('checkout.field.salutation.divers') }}</option>
</select>
<Icon
name="chevron-down"
:size="18"
:stroke-width="2"
class="absolute right-4 top-1/2 -translate-y-1/2 text-muted pointer-events-none"
/>
</div>
</div>
<div class="grid gap-5 md:grid-cols-2">

View File

@@ -8,6 +8,7 @@ import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import Input from '@/design-system/components/Input.vue'
import Button from '@/design-system/components/Button.vue'
import Icon from '@/design-system/components/Icon.vue'
import { useCheckoutStore } from '@/stores/checkout.js'
import { useI18n } from '@/i18n/index.js'
@@ -77,14 +78,22 @@ function onSubmit() {
<label class="text-[11px] font-bold uppercase tracking-eyebrow text-muted">
{{ t('checkout.field.country') }}<span class="text-danger"> *</span>
</label>
<select
:value="checkout.shippingAddress.country"
required
class="w-full rounded-sm border border-line bg-paper px-4 py-3 text-[15px] text-ink transition-colors duration-base focus:outline-none focus:border-brand"
@change="checkout.updateShipping({ country: $event.target.value })"
>
<option v-for="c in countries" :key="c.code" :value="c.code">{{ c.label }}</option>
</select>
<div class="relative">
<select
:value="checkout.shippingAddress.country"
required
class="appearance-none w-full rounded-sm border border-line bg-paper pl-4 pr-10 py-3 text-[15px] text-ink transition-colors duration-base focus:outline-none focus:border-brand"
@change="checkout.updateShipping({ country: $event.target.value })"
>
<option v-for="c in countries" :key="c.code" :value="c.code">{{ c.label }}</option>
</select>
<Icon
name="chevron-down"
:size="18"
:stroke-width="2"
class="absolute right-4 top-1/2 -translate-y-1/2 text-muted pointer-events-none"
/>
</div>
</div>
<Input
:model-value="checkout.shippingAddress.phone"
@@ -142,14 +151,22 @@ function onSubmit() {
<label class="text-[11px] font-bold uppercase tracking-eyebrow text-muted">
{{ t('checkout.field.country') }}<span class="text-danger"> *</span>
</label>
<select
:value="checkout.billingAddress.country"
required
class="w-full rounded-sm border border-line bg-paper px-4 py-3 text-[15px] text-ink transition-colors duration-base focus:outline-none focus:border-brand"
@change="checkout.updateBilling({ country: $event.target.value })"
>
<option v-for="c in countries" :key="c.code" :value="c.code">{{ c.label }}</option>
</select>
<div class="relative">
<select
:value="checkout.billingAddress.country"
required
class="appearance-none w-full rounded-sm border border-line bg-paper pl-4 pr-10 py-3 text-[15px] text-ink transition-colors duration-base focus:outline-none focus:border-brand"
@change="checkout.updateBilling({ country: $event.target.value })"
>
<option v-for="c in countries" :key="c.code" :value="c.code">{{ c.label }}</option>
</select>
<Icon
name="chevron-down"
:size="18"
:stroke-width="2"
class="absolute right-4 top-1/2 -translate-y-1/2 text-muted pointer-events-none"
/>
</div>
</div>
<Input
:model-value="checkout.billingAddress.phone"