svelte with tailwind showing different output in Firefox and Chrome - firefox

I was designing a Tags input field much like StackOverflow. I designed it using Sveltekit and Tailwindcss . But it was showing different outputs in Firefox and Chrome. I searched through the code using debugger tools. As a result, I was unable to find any solution.
I designed this :
Code of this :
<script lang="ts">
let TagObj: { Input: string; Focus: boolean; List: string[]; Suggested: string[] } = {
Input: '' as string,
Focus: false as boolean,
List: [] as string[],
Suggested: [] as string[]
};
/ TAGS
function onKeyPressTags(e: { keyCode: any }) {
switch (e.keyCode) {
case 32:
onKeyTag();
break;
case 13:
onKeyTag();
break;
}
}
function onKeyTag() {
if (TagObj.Input.trim() != ("" as String)) {
TagObj.List = [...TagObj.List, TagObj.Input.trim()];
TagObj.Input = '' as string;
}
}
</script>
<div class="mx-4 mt-3 h-fit w-[95%] rounded-lg border-2 border-[#24262b] bg-[#303338] p-2 text-lg font-medium text-[#98999e] outline-0 {TagObj.Focus ? 'border-sky-500' : ''} ">
<ul class="flex flex-row flex-wrap gap-2">
{#each TagObj.List as t}
<li class="m-1 rounded-md bg-[#3d4951] px-2 py-1 text-[#9bc0da] hover:cursor-pointer hover:bg-slate-600 hover:text-teal-200">
{t}
</li>
{/each}
<input on:keypress={onKeyPressTags} maxlength=20 bind:value={TagObj.Input} on:focus={() => { TagObj.Focus = true;}} on:blur={() => { TagObj.Focus = false; }} type="text" class=" inline w-fit grow bg-inherit border-0 outline-0 " />
</ul>
</div>
This is how chrome is showing :
This is how Firefox is showing :
A small blue border is showing around the input field in Firefox. I couldn't find the reason behind it. How i show the exact same UI in Firefox ?

It seems to be the focus:outline behavior that's different in Firefox than chrome.
See this REPL
Adding focus:outline-none to the input gets rid of it.
<input maxlength=20 type="text" class=" inline w-fit grow bg-inherit border-0 outline-0 focus:outline-none" />
Sidenote: outlines are relevant pieces of functionality useful for a11y and keyboard users. So it is generally recommended to keep some form of physical indication when an input has focus and is active.

Related

Alpinejs property bound to x-show not defined

I'm building a form in Laravel's Blade syntax, and using AlpineJs for some interactivity stuff like showing and hiding content.
My code is here:
<div class="flex items-center" x-data="destinationBuilder">
<x-label required="true" class="mr-5">Destination:</x-label>
<x-basic-input #change="handleDestinationChange" ::value="destination" placeholder="https://google.com"/>
<x-buttons.primary class="ml-5" #check="validateDestination">Check</x-buttons.primary>
</div>
<div class="mt-4">
<button type="button"
class="p-5 w-full text-sm grid grid-cols-[min-content_min-content_auto_min-content] items-center gap-x-3 font-light text-gray-400 hover:bg-gray-300 rounded-full"
#click.camel="toggleAdvancedOptions">
<i class="lni lni-cog"></i>
<span class="whitespace-nowrap">Advanced options</span>
<div class="h-px w-full bg-gray-400"></div>
<i class="lni lni-chevron-down"></i>
</button>
<div x-show="advanced" x-transition x-cloak>
{{-- <x-links.get-parameter-form/>--}}
</div>
</div>
#push('footer-scripts')
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('destinationBuilder', () => ({
destination: '',
advanced: false,
handleDestinationChange() {
if (this.validateDestination()) {
// emit constructed destination up
}
},
validateDestination() {
// check url is in a legit form (with https)
// basic is just url input
// advanced dropdown with get parameters, fragment, http protocol and port
},
toggleAdvancedOptions() {
this.advanced = !this.advanced;
}
}));
})
</script>
#endpush
I'm using a property named advanced to bind to x-show for another component.
When I look in my browser I get the following message: app.js:434 Uncaught ReferenceError: advanced is not defined
I'm not sure if this is due to a weird collision with blade or if I'm missing something fundamental with Alpinejs. I tried renaming the variable to showAdvanced but that didn't work either. I would expect advanced to be recognised as a property and bind to x-show as expected. What am I doing wrong here?
You have the following HTML structure:
<div x-data="destinationBuilder">
...
</div>
<div>
<div x-show="advanced">
...
</div>
</div>
As you see, the second div is not a child element of the first one where the x-data is defined, so it's outside of the scope of destinationBuilder component. Just create a common div (or similar) element that embeds both divs and apply the component x-data there, so each div will have access to the component's scope.

Why doesn't infinite-loading-vue3 work in a Laravel Project?

I am having a problem using this library in a Vue file. The project is being done with InertiaJS and Laravel.
The controller is composed of the following code:
public function getSaldosContables()
{
$saldocontables = SaldoContable::paginate(10);
return response()->json($saldocontables);
}
And the Vue file contains the following code:
<template>
<app-layout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">Listado</h2>
</template>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
<div id="app" #scroll.passive="scrollear">
<infinite-scroll
#infinite-scroll="loadDataFromServer"
:message="message"
:noResult="noResult"
>
<div>
<div
v-for="repo in saldocontables"
:key="repo.idsaldocont"
style="margin-bottom: 20px"
>
<div>
<img :src="repo.idsaldocont" alt="" style="height: 50px" />
</div>
<div>{{ repo.nombresaldocont }}</div>
</div>
</div>
</infinite-scroll>
</div>
</div>
</div>
</div>
</app-layout>
</template>
<script>
import AppLayout from "#/Layouts/AppLayout";
import InfiniteScroll from "infinite-loading-vue3";
import axios from "axios";
export default {
components: {
AppLayout,
InfiniteScroll,
},
data() {
return {
saldocontables: [],
page: 1,
noResult: false,
message: "",
};
},
methods: {
async loadDataFromServer() {
try {
const result = await axios.get("/obtenerSaldos?page=" + this.page);
if (result.data.data.length) {
console.log(this.page);
this.saldocontables.push(...result.data.data);
this.page++;
} else {
this.noResult = true;
this.message = "No result found";
}
} catch (err) {
this.noResult = true;
this.message = "Error loading data";
}
},
},
mounted() {
this.loadDataFromServer();
},
};
</script>
The Laravel route file handles the following encoding:
Route::get('/obtenerSaldos', [SaldoContableController::class, 'getSaldosContables']);
The data loaded in the database is rendered correctly. The problem is generated when the Infinite Scroll must load the following pages with the respective data. When it reaches the end of the page, it remains only loaded with the data of Page 1 and does not update the data contained in the following pages taking into account the pagination returned by the Backend.
This can be seen in the following image:
If I delete the following lines from my Vue:
<app-layout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">Listado</h2>
</template>
</app-layout>
The Template responds correctly and the Infinite Scroll also works perfectly.
You can see it in the following image:
The problem is that by doing this in the view the components that refer to the Side Menu, Top Menu, Responsive Menu, etc. do not appear.
I appreciate any help you can give me.

Error while making a multiselect using vue-select

I am using vue-select in my project along with tabulator. I was able to fetch data from json file and view it. But when selecting the options i get an error saying " Component emitted event "option:selecting" but it is neither declared in the emits option nor as an "onOption:selecting" prop. ". I could not resolve this error after multiple try. Below is the code.
**<template>
<form>
<div class="container h-25 w-10/12 mx-auto pb-3 border 2 border-gray-300 flex flex-col rounded-md items-left bg-gray-100" >
<label class="px-3 py-1 w-10/12 text-xs text-black font-medium">Employee</label>
<div class="px-2">
<v-select v-model="Selected" multiple :options="options" label="Employee" placeholder="---SELECT---" class="style-chooser"></v-select>
</div>
<!-- <span>Selected: {{ Employee_Id }}</span> -->
</div>
</form>
<!-- <ul><li v-for="item in datas" :key="item.Employee">{{ item.Employee }}</li></ul> -->
</template>
<script>
import dataset from './dataset.json'
export default {
data(){
return {
openCard: false,
Selected: ""
}
},
computed: {
options: () => dataset
},
methods:{
open(){
this.openCard = ! this.openCard
},
},
}
</script>**
Your help is highly appreciated la.

Vue JS Get value of each radio group

Hi Im struggling to get the value of each radio button groups. The functions is about getting answers from different questions.
{{form.answer_ids}}
<div v-for="ans in answers" :key="ans.id">
<div v-if="ans.question_id == question.id">
<div class="p-2 border rounded border-secondary m-2" >
<input
style="cursor:pointer;"
class="form-check-input m-2"
type="radio"
:name="ans.question_id"
:value="ans.id"
v-model="form.answer_ids"/>
<h5 class="ml-4 p-1" v-html="ans.description"> </h5>
</div>
</div>
</div>
<script>
data() {
return {
form: this.$inertia.form({
answer_ids:[]
}),
}
},
</script>
When there is v-model, the radio is not grouping yet returning only 1 value (not array), On the other hand, When I Remove v-model, The grouping is working but unable to get the data.
How can i possibly achieve this? Just taking the checked radio answer ids is enough for me.
Thank you very much and have a good day!

How to properly implement hover effect on icon links in Nuxt.js

I'm trying to implement a hover effect on an icon link for a component in a site built using Nuxt.js with Bootstrap 4. I've attempted using the #mouseover/#mouseenter and #mouseleave events to switch the src attribute from one icon image to another, but it doesn't cause a change unless the icon link is clicked. Does this have something to do with focus? Is there a better way to get the effect I want?
The component is below.
<template>
<b-row class="main-focus px-3 pt-3">
<b-col md="12" class="mb-4">
<h1 class="clr-t mb-4 px-2 pb-1 clr-brdr-btm">resume</h1>
<p class="drk-t pl-2">{{description[0].text}}</p>
<b-link
#mouseover="icon = 'assets/images/icons/resume-icon-clicked.svg'"
#mouseleave="icon = 'assets/images/icons/resume-icon.svg'"
:href="resume.url"
target="_blank"
>
<b-img
class="icon bg-lt"
v-bind="iconProps"
rounded
:src="icon"/>
</b-link>
</b-col>
</b-row>
</template>
<script>
export default {
props: {
description: Array,
resume: Object
},
data () {
return {
icon: 'assets/images/icons/resume-icon.svg',
iconProps: { width: 100 }
}
}
}
</script>
The above behaviour is because b-link supports only #click event as stated in docs.
You can achieve the functionality by wrapping b-link in a div as below.
<div #mouseover="icon = 'assets/images/icons/resume-icon-clicked.svg'"
#mouseleave="icon = 'assets/images/icons/resume-icon.svg'">
<b-link
:href="resume.url"
target="_blank"
>
<b-img
class="icon bg-lt"
v-bind="iconProps"
rounded
:src="icon"/>
</b-link>
</div>

Resources