Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frontend - Styling autocomplete #670

Merged
merged 30 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
90b4c90
Styling autocomplete
Roene-JustBetter Aug 20, 2024
cafc646
Make resize larger | Fix comment
Roene-JustBetter Aug 20, 2024
995f797
Update comment
Roene-JustBetter Aug 20, 2024
d91bd5c
Added v-else and added :key
Roene-JustBetter Aug 26, 2024
f8cf4ae
Merge branch 'master' of github.com:rapidez/core into feature/fronten…
Roene-JustBetter Sep 6, 2024
1040a6b
Merge branch 'master' of github.com:rapidez/core into feature/fronten…
Roene-JustBetter Sep 6, 2024
f875e94
Removed .css for imports
Roene-JustBetter Sep 6, 2024
298e857
Merge branch 'master' of github.com:rapidez/core into feature/fronten…
Roene-JustBetter Oct 1, 2024
4c230d6
Feedback autocomplete
Roene-JustBetter Oct 1, 2024
0b7aa90
Revert wrong changes
Roene-JustBetter Oct 1, 2024
34a28cb
Replaced z-index for correct name
Roene-JustBetter Oct 1, 2024
ed2dffb
Update search autocomplete visual and functional
Roene-JustBetter Oct 9, 2024
d6a4474
Update translations | Dynamic generate height for autocomplete | Remo…
Roene-JustBetter Oct 9, 2024
f9f6936
Change config back to original
Roene-JustBetter Oct 9, 2024
5971e4f
Changed size back to 3 & removed it from categories as it is not need…
Roene-JustBetter Oct 10, 2024
43616f6
Merge branch 'master' of github.com:rapidez/core into feature/fronten…
Roene-JustBetter Dec 5, 2024
e917f23
Update autocomplete with new colors & z-indexes
Roene-JustBetter Dec 5, 2024
6419204
Apply fixes from Prettier
Roene-JustBetter Dec 5, 2024
4ec268b
Revert file
Roene-JustBetter Dec 5, 2024
6be26cc
Added translations
Roene-JustBetter Dec 5, 2024
b1cd21f
Added border in header back
Roene-JustBetter Dec 5, 2024
cbca0f2
Merge branch 'feature/frontend-autocomplete' of github.com:rapidez/co…
Roene-JustBetter Dec 5, 2024
dac772a
Added translation
Roene-JustBetter Dec 5, 2024
d5b8939
Added missing translations
Roene-JustBetter Dec 5, 2024
5794063
Added padding bottom in header for small screens
Roene-JustBetter Dec 5, 2024
63a3e9f
Update resources/views/layouts/partials/header/autocomplete.blade.php
Roene-JustBetter Dec 6, 2024
c29c2ef
Update resources/views/layouts/partials/header/autocomplete.blade.php
Roene-JustBetter Dec 6, 2024
51cf8c7
Update resources/views/layouts/partials/header/autocomplete/no-result…
Roene-JustBetter Dec 6, 2024
922a839
Changed slot-scope
Roene-JustBetter Dec 9, 2024
05f7078
Addec v-bind:
Roene-JustBetter Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions config/rapidez/frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
// ],
],

'debounce' => 100,
'size' => 10,
'debounce' => 500,
'size' => 3,
],

// Link store codes to theme folders
Expand Down
8 changes: 8 additions & 0 deletions lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"Categories": "Categorieën",
"Category": "Categorie",
"Checkout": "Afrekenen",
"Check the spelling of your search term": "De spelling van je zoekterm te controleren",
"City": "Stad",
"Close": "Sluiten",
"Company": "Bedrijf",
Expand All @@ -29,6 +30,7 @@
"Firstname": "Voornaam",
"Forgot your password?": "Wachtwoord vergeten?",
"Go to home": "Naar de homepagina",
"Have you tried:": "Heb je gedacht aan:",
"Home": "Homepagina",
"Housenumber": "Huisnummer",
"Items per page": "Producten per pagina",
Expand All @@ -37,6 +39,7 @@
"Loading": "Aan het laden",
"Login": "Inloggen",
"Logout": "Uitloggen",
"Make your search term less specific": "Je zoekterm minder specifiek maken",
"Maximum image height": "Maximale hoogte",
"Maximum image width": "Maximale breedte",
"Middlename": "Tussenvoegsel",
Expand All @@ -45,6 +48,7 @@
"New address": "Nieuw adres",
"Next": "Volgende",
"No": "Nee",
"No results found for :searchterm": "Geen resultaten voor :searchterm",
"Order placed succesfully": "Bestelling succesvol geplaatst",
"Orders": "Bestellingen",
"page": "pagina",
Expand All @@ -58,6 +62,7 @@
"Prev": "Vorige",
"Privacy Policy": "Privacybeleid",
"products": "producten",
"Products": "Producten",
"Quantity": "Hoeveelheid",
"Related products": "Gerelateerde producten",
"Remove": "Verwijderen",
Expand Down Expand Up @@ -92,6 +97,9 @@
"This website uses cookies": "Deze website maakt gebruik van cookies",
"Total": "Totaal",
"Update": "Update",
"Use other search terms": "Andere zoektermen te gebruiken",
"View all products": "Bekijk alle producten",
"What are you looking for?": "Waar ben je naar op zoek?",
"Want product news and updates?": "Wil je productnieuws en updates?",
"We care about the protection of your data. Read our": "Wij geven om de bescherming van uw gegevens. Lees onze",
"We found other products you might like!": "We hebben andere producten gevonden die je misschien leuk vindt!",
Expand Down
1 change: 1 addition & 0 deletions resources/css/app.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@import 'components/vue-slider';
@import 'components/price-slider';
@import 'components/pagination';
@import 'components/autocomplete';

@tailwind base;
@tailwind components;
Expand Down
17 changes: 17 additions & 0 deletions resources/css/components/autocomplete.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.search-input + div div[groupposition='right'] {
@apply size-6 right-16 cursor-pointer z-50 !-translate-y-1/2 !top-1/2 !absolute;

.cancel-icon {
@apply hidden;
}
}

.search-input + div div[groupposition='right'] div[isclearicon='true']::before {
@apply size-6;
content: '';
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M4.20986 4.38708L4.29286 4.29308C4.46505 4.1209 4.69415 4.01747 4.93718 4.00219C5.18021 3.98691 5.42046 4.06083 5.61286 4.21008L5.70686 4.29308L11.9999 10.5851L18.2929 4.29308C18.3851 4.19757 18.4955 4.12139 18.6175 4.06898C18.7395 4.01657 18.8707 3.98898 19.0035 3.98783C19.1362 3.98668 19.2679 4.01198 19.3908 4.06226C19.5137 4.11254 19.6254 4.18679 19.7193 4.28069C19.8131 4.37458 19.8874 4.48623 19.9377 4.60913C19.988 4.73202 20.0133 4.8637 20.0121 4.99648C20.011 5.12926 19.9834 5.26048 19.931 5.38249C19.8786 5.50449 19.8024 5.61483 19.7069 5.70708L13.4149 12.0001L19.7069 18.2931C19.879 18.4653 19.9825 18.6944 19.9978 18.9374C20.013 19.1804 19.9391 19.4207 19.7899 19.6131L19.7069 19.7071C19.5347 19.8793 19.3056 19.9827 19.0625 19.998C18.8195 20.0133 18.5793 19.9393 18.3869 19.7901L18.2929 19.7071L11.9999 13.4151L5.70686 19.7071C5.51826 19.8892 5.26566 19.99 5.00346 19.9878C4.74126 19.9855 4.49045 19.8803 4.30504 19.6949C4.11963 19.5095 4.01447 19.2587 4.01219 18.9965C4.00991 18.7343 4.1107 18.4817 4.29286 18.2931L10.5849 12.0001L4.29286 5.70708C4.12068 5.53489 4.01725 5.30579 4.00197 5.06276C3.98669 4.81974 4.06061 4.57949 4.20986 4.38708Z' fill='%232E4A56'/%3E%3C/svg%3E");
}

mark {
@apply bg-transparent text-inherit font-bold;
}
11 changes: 11 additions & 0 deletions resources/js/components/Search/Autocomplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export default {
results: {},
resultsCount: 0,
searchAdditionals: () => null,
overlay: false,
searchLoading: false,
}
},

Expand Down Expand Up @@ -103,11 +105,20 @@ export default {
},

methods: {
startLoading() {
this.searchLoading = true
},
stopLoading() {
this.searchLoading = false
},
highlight(hit, field) {
let source = hit._source ?? hit.source
let highlight = hit.highlight ?? source.highlight
return highlight?.[field]?.[0] ?? source?.[field] ?? ''
},
showOverlay(isOpen) {
this.overlay = isOpen
},
},
}
</script>
2 changes: 1 addition & 1 deletion resources/views/checkout/steps/shipping_method.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
v-if="!cart.is_virtual"
>
<fieldset class="flex flex-col gap-3" partial-submit="mutate" v-on:change="window.app.$emit('setShippingAddressesOnCart')">
<label class="flex items-center gap-x-1.5 p-5 border rounded bg-white cursor-pointer text-sm text-neutral" v-for="(method, index) in cart.shipping_addresses[0]?.available_shipping_methods">
<label class="flex items-center gap-x-1.5 p-5 border rounded bg-white cursor-pointer text-sm text" v-for="(method, index) in cart.shipping_addresses[0]?.available_shipping_methods">
<x-rapidez::input.radio.base
name="shipping_method"
v-model="variables.method"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{{-- This is the search icon in the autocomplete --}}
<div {{ $attributes->twMerge('transition-colors duration-300 rounded-lg bg-muted absolute right-1 inset-y-1 w-11 pointer-events-none flex items-center justify-center text z-header-autocomplete-button') }}>
<x-heroicon-o-magnifying-glass class="size-5" />
</div>
4 changes: 4 additions & 0 deletions resources/views/components/autocomplete/title.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{{-- This title is shown in the search autocomplete above the products and categories --}}
<div {{ $attributes->twMerge('text-muted text-xs font-semibold pb-2 px-5') }}>
{{ $slot }}
</div>
4 changes: 2 additions & 2 deletions resources/views/layouts/partials/header.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<header class="relative mb-5 border-b shadow z-header">
<header class="relative mb-5 max-md:pb-4 border-b z-header">
<div class="container flex flex-wrap items-center max-sm:px-3">
<input id="navigation" class="peer hidden" type="checkbox" />
<div class="py-2">
Expand All @@ -16,7 +16,7 @@
</label>
</div>
</div>
<div class="flex h-12 max-w-lg flex-1 items-center">
<div class="flex items-center h-12 max-md:order-last max-md:w-full md:max-w-lg md:flex-1">
@include('rapidez::layouts.partials.header.autocomplete')
</div>
<div class="ml-auto flex items-center justify-end pl-3">
Expand Down
78 changes: 46 additions & 32 deletions resources/views/layouts/partials/header/autocomplete.blade.php
Original file line number Diff line number Diff line change
@@ -1,56 +1,70 @@
@php $inputClasses = 'border !border-default !text-sm !min-h-0 outline-none !h-auto rounded !p-2 !bg-white w-full focus:!border-emphasis' @endphp
@php $inputClasses = 'relative z-header-autocomplete border !font-sans !border-default !text-sm !min-h-0 outline-0 ring-0 !h-auto rounded-xl !pl-5 !pr-24 !py-3.5 !bg-white w-full focus:ring-transparent search-input' @endphp

<label for="autocomplete-input" class="sr-only">@lang('Search')</label>
<input
id="autocomplete-input"
placeholder="@lang('Search')"
class="{{ $inputClasses }}"
v-on:focus="$root.loadAutocomplete = true"
v-if="!$root.loadAutocomplete"
>
<div v-if="!$root.loadAutocomplete" class="relative w-full">
<label for="autocomplete-input" class="sr-only">@lang('Search')</label>
<input
id="autocomplete-input"
placeholder="@lang('What are you looking for?')"
class="{{ $inputClasses }}"
v-on:focus="$root.loadAutocomplete = true"
>
<x-rapidez::autocomplete.magnifying-glass />
</div>

<autocomplete
v-if="$root.loadAutocomplete"
v-else
v-on:mounted="() => window.document.getElementById('autocomplete-input').focus()"
v-bind:additionals="{{ json_encode(config('rapidez.frontend.autocomplete.additionals')) }}"
v-bind:debounce="{{ config('rapidez.frontend.autocomplete.debounce') }}"
v-bind:size="{{ config('rapidez.frontend.autocomplete.size') }}"
class="w-full"
class="relative w-full"
v-cloak
>
<x-rapidez::reactive-base slot-scope="{ results, resultsCount, searchAdditionals, debounce, size, highlight }">
<x-rapidez::reactive-base slot-scope="autocompleteScope">
<div
class="z-header-autocomplete-overlay pointer-events-none fixed inset-0 cursor-pointer bg-black/40 opacity-0 transition duration-500"
:class="autocompleteScope.overlay ? 'pointer-events-auto opacity-100 prevent-scroll' : 'opacity-0 pointer-events-none '"
></div>
<x-rapidez::autocomplete.magnifying-glass v-bind:class="{ 'bg-primary text-white': autocompleteScope.overlay }" />
<data-search
placeholder="@lang('Search')"
placeholder="@lang('What are you looking for?')"
v-on:value-selected="search"
component-id="autocomplete"
:inner-class="{ input: '{{ $inputClasses }}' }"
{{-- These classes are only used when you come from a page with a product listing, --}}
{{-- click on a link that leads to a 404 page and try to use the search there --}}
class="relative [&_*]:!m-0 [&_[isclearicon=]]:!mr-2 [&_.cancel-icon]:!fill-[#595959] [&_[groupposition=right]]:!absolute [&_[groupposition=right]]:!top-2/4 [&_[groupposition=right]]:!right-0 [&_[groupposition=right]]:!-translate-y-2/4"
class="relative [&_*]:!m-0"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested the case local:

  1. Created a link that leads to a 404 page.
  2. Navigated to a page where a product listing is used.
  3. Clicked on the link that leads to a 404 page.
  4. Used the autocomplete to search.
    Tested running yarn dev & yarn prod

:data-field="Object.keys(config.searchable)"
:field-weights="Object.values(config.searchable)"
:show-icon="false"
fuzziness="AUTO"
:debounce="debounce"
:size="size"
v-bind:debounce="autocompleteScope.debounce"
v-on:blur="autocompleteScope.showOverlay(false)"
v-on:focus="autocompleteScope.showOverlay(true)"
v-bind:size="autocompleteScope.size"
:highlight="true"
v-on:value-change="searchAdditionals($event)"
v-on:value-change="autocompleteScope.searchAdditionals"
v-on:key-down="autocompleteScope.startLoading"
v-on:suggestions="autocompleteScope.stopLoading"
>
<div
slot="render"
slot-scope="{ downshiftProps: { isOpen }, data: suggestions }"
>
<div slot="render" slot-scope="dataSearchScope">
<div
class="z-header-autocomplete absolute -inset-x-10 top-full max-h-[600px] overflow-auto rounded-b-xl border bg-white p-2 md:p-5 shadow-xl md:inset-x-0 md:w-full md:-translate-y-px"
v-if="isOpen && (suggestions.length || resultsCount)"
v-if="dataSearchScope.downshiftProps.isOpen && !autocompleteScope.searchLoading && !dataSearchScope.loading && dataSearchScope.value"
class="z-header-autocomplete absolute -inset-x-5 top-14 overflow-x-hidden overflow-y-auto scrollbar-hide pt-4 pb-7 bg-white shadow-xl max-md:h-[calc(100svh-150px)] max-md:max-h-[calc(100svh-150px)] md:top-14 md:max-h-[calc(100svh-150px)] md:rounded-xl md:border md:inset-x-0 md:w-full md:-translate-y-px"
>
<template v-for="(resultsData, resultsType) in results ?? {}" v-if="resultsData?.hits?.length">
@foreach (config('rapidez.frontend.autocomplete.additionals') as $key => $fields)
@includeIf('rapidez::layouts.partials.header.autocomplete.' . $key)
@endforeach
</template>

@include('rapidez::layouts.partials.header.autocomplete.products')
<div v-if="dataSearchScope.data.length || autocompleteScope.resultsCount">
<div class="flex flex-col prose-li:px-5 hover:prose-li:bg-muted">
{{-- The order can be changed with https://tailwindcss.com/docs/order --}}
<template v-for="(resultsData, resultsType) in autocompleteScope.results ?? {}" v-if="resultsData?.hits?.length">
@foreach (config('rapidez.frontend.autocomplete.additionals') as $key => $fields)
@includeIf('rapidez::layouts.partials.header.autocomplete.' . $key)
@endforeach
</template>
@include('rapidez::layouts.partials.header.autocomplete.products')
</div>
@include('rapidez::layouts.partials.header.autocomplete.all-results')
</div>
<div v-else class="p-5">
@include('rapidez::layouts.partials.header.autocomplete.no-results')
</div>
</div>
</div>
</data-search>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="font-sans px-5">
<x-rapidez::button.primary
v-bind:href="'/search?q=' + dataSearchScope.value"
class="relative group flex items-center gap-x-4 w-full text-sm"
>
<span>@lang('View all products')</span>
</x-rapidez::button.primary>
</div>
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<div class="flex gap-5 pb-5 my-2" v-if="resultsType == 'categories'">
<div class="font-bold">
@lang('Categories')
</div>
<ul class="flex flex-col gap-1">
<li v-for="hit in resultsData.hits" class="w-full">
<a :href="hit._source.url" class="w-full hover:text-primary flex gap-1">
<span class="ml-2" v-html="highlight(hit, 'name')"></span>
<div class="border-b pb-2" v-if="resultsType == 'categories'">
<x-rapidez::autocomplete.title>@lang('Categories')</x-rapidez::autocomplete.title>
<ul class="flex flex-col font-sans">
<li v-for="hit in resultsData.hits" :key="hit._source.id" class="flex flex-1 items-center w-full">
<a v-bind:href="hit._source.url" class="relative flex items-center group w-full py-2 text-sm gap-x-4">
<span class="ml-2 line-clamp-2" v-html="autocompleteScope.highlight(hit, 'name')"></span>
</a>
</li>
</ul>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="font-bold text text-lg break-all">
@lang('No results found for :searchterm', ['searchterm' => '<span class="text-primary">"@{{ value }}"</span>'])
</div>
<div class="flex flex-col text-sm pt-7">
<span class="font-bold">@lang('Have you tried:')</span>
<ul class="flex flex-col pt-1.5 gap-y-1 *:flex *:gap-x-2 *:items-center">
<li>
<x-heroicon-s-check class="size-4"/>
@lang('Check the spelling of your search term')
</li>
<li>
<x-heroicon-s-check class="size-4"/>
@lang('Make your search term less specific')
</li>
<li>
<x-heroicon-s-check class="size-4"/>
@lang('Use other search terms')
</li>
</ul>
</div>
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
<ul class="gap-5 grid md:grid-cols-2">
<li v-for="suggestion in suggestions" :key="suggestion.source._id">
<a :href="suggestion.source.url | url" class="flex flex-wrap flex-1">
<img :src="resizedPath(suggestion.source.thumbnail + '.webp', '80x80')" class="self-center object-contain w-14 aspect-square" />
<div class="flex flex-1 flex-wrap px-2">
<strong class="hyphens block w-full" v-html="highlight(suggestion, 'name')"></strong>
<div class="self-end">@{{ suggestion.source.price | price }}</div>
</div>
</a>
</li>
</ul>
<div class="pt-4 pb-2">
<x-rapidez::autocomplete.title>@lang('Products')</x-rapidez::autocomplete.title>
<ul class="gap-2 flex flex-col">
<li v-for="suggestion in dataSearchScope.data" :key="suggestion.source._id">
<a v-bind:href="suggestion.source.url | url" class="group relative flex flex-wrap py-2">
<img :src="'/storage/{{ config('rapidez.store') }}/resizes/200/magento/catalog/product' + suggestion.source.thumbnail + '.webp'" class="shrink-0 self-center object-contain size-16 mix-blend-multiply" />
<div class="flex flex-1 justify-center flex-col px-2">
<div class="text-sm font-medium font-sans hyphens-auto line-clamp-2 w-full" v-html="autocompleteScope.highlight(suggestion, 'name')"></div>
<div class="flex items-center gap-x-0.5 mt-0.5">
<div v-if="suggestion.source.special_price" class="text-muted font-sans line-through text-xs">
@{{ suggestion.source.price | price }}
</div>
<div class="text-sm text font-sans font-bold">
@{{ (suggestion.source.special_price || suggestion.source.price) | price }}
</div>
</div>
</div>
</a>
</li>
</ul>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="relative" v-if="hasCart" v-on-click-away="close" slot-scope="{ toggle, close, isOpen }" v-cloak>
<button class="flex my-1 focus:outline-none" v-on:click="toggle">
<x-heroicon-o-shopping-cart class="size-6"/>
<span class="bg-secondary text-secondary-text rounded-full size-6 text-white text-center" dusk="minicart-count">@{{ Math.round(cart.total_quantity) }}</span>
<span class="bg-secondary text-secondary-text rounded-full size-6 text-center" dusk="minicart-count">@{{ Math.round(cart.total_quantity) }}</span>
</button>
<div v-if="isOpen" class="absolute right-0 bg-white border shadow rounded-xl p-5 z-header-minicart">
<table class="w-full mb-3">
Expand Down
2 changes: 1 addition & 1 deletion resources/views/listing/partials/stats.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div class="justify-self-end mr-5">
<div class="flex items-center gap-1 flex-wrap">
<label class="flex items-center gap-x-1.5">
<x-rapidez::label class="text-sm text-inactive whitespace-nowrap mb-0">@lang('Items per page'):</x-rapidez::label>
<x-rapidez::label class="text-sm text-muted whitespace-nowrap mb-0">@lang('Items per page'):</x-rapidez::label>
<x-rapidez::input.select v-model="listingSlotProps.pageSize" class="w-20">
<option
v-for="size in $root.config.grid_per_page_values.concat($root.config.translations.all)"
Expand Down
4 changes: 2 additions & 2 deletions resources/views/product/partials/gallery/popup.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ class="object-contain max-h-full mx-auto block"
</div>
</div>
<button class="z-popup-actions top-1/2 left-3 -translate-y-1/2 absolute" v-if="active" v-on:click="change(active-1)" aria-label="@lang('Prev')">
<x-heroicon-o-chevron-left class="size-8 text-inactive" />
<x-heroicon-o-chevron-left class="size-8 text-muted" />
</button>
<button class="z-popup-actions top-1/2 right-3 -translate-y-1/2 absolute" v-if="active != images.length-1" v-on:click="change(active+1)" aria-label="@lang('Next')">
<x-heroicon-o-chevron-right class="size-8 text-inactive" />
<x-heroicon-o-chevron-right class="size-8 text-muted" />
</button>
</div>
Loading
Loading