Remove conflicting focus styles; use global :focus-visible rule

Audit found 10 overrides across 8 files that suppressed or replaced
the global focus ring. Removed all of them:

- templates/_file_form.html.erb: remove outline-none + focus:ring-*
- templates_clone/_form.html.erb: same
- templates_preferences/_recipients.html.erb: same
- template_builder/contenteditable.vue: remove outline-none
- template_builder/document.vue: remove focus:ring-2 from tab buttons
- template_builder/area.vue: remove focus:ring-1 from 3 elements
- template_builder/font_modal.vue: remove focus:ring-2 from contenteditable
- submission_form/phone_step.vue: remove focus-within:outline from container

All interactive elements now rely solely on the global :focus-visible
rule (8px solid rgb(14,99,200), 4px offset) in application.scss/form.scss.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pull/599/head
Marcelo Paiva 3 weeks ago
parent d26cde59e7
commit 30b97357dc

@ -68,7 +68,7 @@
</div> </div>
<div <div
v-show="!isCodeSent" v-show="!isCodeSent"
class="flex w-full rounded-full outline-neutral-content outline-2 outline-offset-2 focus-within:outline phone-number-input-container" class="flex w-full rounded-full phone-number-input-container"
> >
<div <div
id="country_code" id="country_code"

@ -67,7 +67,7 @@
:aria-multiline="editable && !defaultField && field.type !== 'heading' ? 'false' : undefined" :aria-multiline="editable && !defaultField && field.type !== 'heading' ? 'false' : undefined"
:aria-label="editable && !defaultField && field.type !== 'heading' ? t('field_name') : undefined" :aria-label="editable && !defaultField && field.type !== 'heading' ? t('field_name') : undefined"
dir="auto" dir="auto"
class="pr-1 cursor-text block focus:ring-1 focus:ring-base-content/40 focus:rounded-sm" class="pr-1 cursor-text block"
style="min-width: 2px" style="min-width: 2px"
@paste.prevent="onPaste" @paste.prevent="onPaste"
@keydown.enter.prevent="onNameEnter" @keydown.enter.prevent="onNameEnter"
@ -278,7 +278,7 @@
<select <select
v-else-if="isSelectInput" v-else-if="isSelectInput"
ref="defaultValueSelect" ref="defaultValueSelect"
class="bg-transparent w-full focus:ring-1 focus:ring-base-content/40 focus:rounded-sm" class="bg-transparent w-full"
@change="[field.default_value = $event.target.value, field.readonly = !!field.default_value?.length, save()]" @change="[field.default_value = $event.target.value, field.readonly = !!field.default_value?.length, save()]"
@focus="selectedAreasRef.value = [area]" @focus="selectedAreasRef.value = [area]"
@keydown.enter="onDefaultValueEnter" @keydown.enter="onDefaultValueEnter"
@ -303,7 +303,7 @@
v-else v-else
ref="defaultValue" ref="defaultValue"
:contenteditable="isValueInput" :contenteditable="isValueInput"
class="whitespace-pre-wrap empty:before:content-[attr(placeholder)] before:text-base-content/60 focus:ring-1 focus:ring-base-content/40 focus:rounded-sm" class="whitespace-pre-wrap empty:before:content-[attr(placeholder)] before:text-base-content/60"
:class="{ 'cursor-text': isValueInput }" :class="{ 'cursor-text': isValueInput }"
:placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : (field.type === 'date' ? field.preferences?.format || t('type_value') : t('type_value'))" :placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : (field.type === 'date' ? field.preferences?.format || t('type_value') : t('type_value'))"
@blur="onDefaultValueBlur" @blur="onDefaultValueBlur"

@ -11,7 +11,7 @@
:data-empty="isEmpty" :data-empty="isEmpty"
:style="{ minWidth }" :style="{ minWidth }"
:class="[iconInline ? (isEmpty ? 'inline-block' : 'inline') : 'block', hideIcon ? 'focus:block' : '']" :class="[iconInline ? (isEmpty ? 'inline-block' : 'inline') : 'block', hideIcon ? 'focus:block' : '']"
class="peer relative inline-block outline-none before:pointer-events-none before:absolute before:left-0 before:top-0 before:select-none before:whitespace-pre before:text-neutral-600 before:content-[attr(data-placeholder)] before:opacity-0 data-[empty=true]:before:opacity-100" class="peer relative inline-block before:pointer-events-none before:absolute before:left-0 before:top-0 before:select-none before:whitespace-pre before:text-neutral-600 before:content-[attr(data-placeholder)] before:opacity-0 data-[empty=true]:before:opacity-100"
@paste.prevent="onPaste" @paste.prevent="onPaste"
@keydown.enter.prevent="blurContenteditable" @keydown.enter.prevent="blurContenteditable"
@input="updateInputValue" @input="updateInputValue"

@ -11,7 +11,7 @@
type="button" type="button"
:aria-selected="!textViewActive ? 'true' : 'false'" :aria-selected="!textViewActive ? 'true' : 'false'"
:tabindex="!textViewActive ? 0 : -1" :tabindex="!textViewActive ? 0 : -1"
:class="['px-4 py-2 text-sm border-b-2 -mb-px focus:ring-2 focus:ring-inset focus:ring-base-content/50', !textViewActive ? 'border-neutral text-base-content font-semibold' : 'border-transparent text-base-content font-medium']" :class="['px-4 py-2 text-sm border-b-2 -mb-px', !textViewActive ? 'border-neutral text-base-content font-semibold' : 'border-transparent text-base-content font-medium']"
@click="textViewActive = false" @click="textViewActive = false"
@keydown="onTabKeydown($event, false)" @keydown="onTabKeydown($event, false)"
> >
@ -22,7 +22,7 @@
type="button" type="button"
:aria-selected="textViewActive ? 'true' : 'false'" :aria-selected="textViewActive ? 'true' : 'false'"
:tabindex="textViewActive ? 0 : -1" :tabindex="textViewActive ? 0 : -1"
:class="['px-4 py-2 text-sm border-b-2 -mb-px focus:ring-2 focus:ring-inset focus:ring-base-content/50', textViewActive ? 'border-neutral text-base-content font-semibold' : 'border-transparent text-base-content font-medium']" :class="['px-4 py-2 text-sm border-b-2 -mb-px', textViewActive ? 'border-neutral text-base-content font-semibold' : 'border-transparent text-base-content font-medium']"
@click="textViewActive = true" @click="textViewActive = true"
@keydown="onTabKeydown($event, true)" @keydown="onTabKeydown($event, true)"
> >

@ -169,7 +169,7 @@
> >
<span <span
contenteditable="true" contenteditable="true"
class="whitespace-nowrap truncate focus:ring-2 focus:ring-base-content focus:ring-inset focus:rounded-sm" class="whitespace-nowrap truncate"
> >
{{ field.default_value || field.name || buildDefaultName(field) }} {{ field.default_value || field.name || buildDefaultName(field) }}
</span> </span>

@ -8,7 +8,7 @@
</label> </label>
<folder-autocomplete class="flex justify-between w-full"> <folder-autocomplete class="flex justify-between w-full">
<set-value data-on="blur" data-value="<%= TemplateFolder::DEFAULT_NAME %>" data-empty-only="true" class="peer w-full whitespace-nowrap"> <set-value data-on="blur" data-value="<%= TemplateFolder::DEFAULT_NAME %>" data-empty-only="true" class="peer w-full whitespace-nowrap">
<input id="folder_name" placeholder="<%= t('folder_name') %>" type="text" class="w-full outline-none border-transparent focus:border-base-content/50 focus:ring-1 focus:ring-base-content/20 bg-base-100 px-1 focus:rounded-sm" name="folder_name" value="<%= params[:folder_name].presence || TemplateFolder::DEFAULT_NAME %>" autocomplete="off"> <input id="folder_name" placeholder="<%= t('folder_name') %>" type="text" class="w-full border-transparent focus:border-base-content/50 bg-base-100 px-1" name="folder_name" value="<%= params[:folder_name].presence || TemplateFolder::DEFAULT_NAME %>" autocomplete="off">
</set-value> </set-value>
<set-value data-on="click" data-value="" data-input-id="folder_name" class="peer-focus-within:hidden whitespace-nowrap"> <set-value data-on="click" data-value="" data-input-id="folder_name" class="peer-focus-within:hidden whitespace-nowrap">
<label for="folder_name" data-clear-on-focus="true" class="shrink-0 link mr-1.5 cursor-pointer"> <label for="folder_name" data-clear-on-focus="true" class="shrink-0 link mr-1.5 cursor-pointer">

@ -14,7 +14,7 @@
</label> </label>
<folder-autocomplete class="flex justify-between w-full"> <folder-autocomplete class="flex justify-between w-full">
<set-value data-on="blur" data-value="<%= TemplateFolder::DEFAULT_NAME %>" data-empty-only="true" class="peer w-full whitespace-nowrap"> <set-value data-on="blur" data-value="<%= TemplateFolder::DEFAULT_NAME %>" data-empty-only="true" class="peer w-full whitespace-nowrap">
<input id="folder_name" placeholder="<%= t('folder_name') %>" type="text" class="w-full outline-none border-transparent focus:border-base-content/50 focus:ring-1 focus:ring-base-content/20 bg-base-100 px-1 focus:rounded-sm" name="folder_name" value="<%= params[:folder_name].presence || @base_template&.folder&.full_name || TemplateFolder::DEFAULT_NAME %>" autocomplete="off"> <input id="folder_name" placeholder="<%= t('folder_name') %>" type="text" class="w-full border-transparent focus:border-base-content/50 bg-base-100 px-1" name="folder_name" value="<%= params[:folder_name].presence || @base_template&.folder&.full_name || TemplateFolder::DEFAULT_NAME %>" autocomplete="off">
</set-value> </set-value>
<set-value data-on="click" data-value="" data-input-id="folder_name" class="peer-focus-within:hidden whitespace-nowrap"> <set-value data-on="click" data-value="" data-input-id="folder_name" class="peer-focus-within:hidden whitespace-nowrap">
<label for="folder_name" data-clear-on-focus="true" class="shrink-0 link mr-1.5 cursor-pointer"> <label for="folder_name" data-clear-on-focus="true" class="shrink-0 link mr-1.5 cursor-pointer">

@ -12,7 +12,7 @@
<%= ff.hidden_field :uuid %> <%= ff.hidden_field :uuid %>
<div class="form-control"> <div class="form-control">
<div class="flex justify-between"> <div class="flex justify-between">
<%= ff.text_field :name, class: 'w-full outline-none border-transparent focus:border-base-content/50 focus:ring-1 focus:ring-base-content/20 bg-base-100 px-1 peer mb-2 focus:rounded-sm', autocomplete: 'off', placeholder: "#{index + 1}#{(index + 1).ordinal} Party", required: true %> <%= ff.text_field :name, class: 'w-full border-transparent focus:border-base-content/50 bg-base-100 px-1 peer mb-2', autocomplete: 'off', placeholder: "#{index + 1}#{(index + 1).ordinal} Party", required: true %>
<% if template.submitters.size > 2 %> <% if template.submitters.size > 2 %>
<div id="order_<%= submitter['uuid'] %>" class="mr-0.5"> <div id="order_<%= submitter['uuid'] %>" class="mr-0.5">
<% if is_order_set %> <% if is_order_set %>

Loading…
Cancel
Save