Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 13 additions & 11 deletions resources/js/components/blueprints/Tab.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<template>
<TabTrigger :name="tab._id" class="blueprint-tab flex items-center">
<Icon
v-if="tab.icon"
:name="tab.icon"
:set="iconSet"
class="h-4 w-4 me-1"
/>

<span class="block max-w-48 overflow-clip text-ellipsis whitespace-nowrap" v-tooltip="__(tab.display).length > 24 ? __(tab.display) : null">{{ __(tab.display) }}</span>
<div class="blueprint-tab relative flex items-center">
<TabTrigger :name="tab._id" class="flex items-center">
<Icon
v-if="tab.icon"
:name="tab.icon"
:set="iconSet"
class="h-4 w-4 me-1"
/>

<span class="block max-w-48 overflow-clip text-ellipsis whitespace-nowrap" v-tooltip="__(tab.display).length > 24 ? __(tab.display) : null">{{ __(tab.display) }}</span>
</TabTrigger>

<Dropdown v-if="isActive" placement="left-start" class="me-3">
<template #trigger>
Expand All @@ -20,7 +22,7 @@
</Dropdown>

<Stack
size="narrow"
size="narrow"
:open="editing"
@opened="() => $nextTick(() => $refs.title.select())"
@update:open="editCancelled"
Expand Down Expand Up @@ -75,7 +77,7 @@
</div>
</div>
</Stack>
</TabTrigger>
</div>
</template>

<script>
Expand Down
79 changes: 42 additions & 37 deletions resources/js/components/blueprints/Tabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<div>
<Tabs v-model="currentTab" :unmount-on-hide="false">
<div v-if="!singleTab && tabs.length > 0" class="flex items-center justify-between gap-x-2 mb-6">
<TabList class="flex-1 min-w-0 overflow-x-clip overflow-y-visible pe-0.25">
<div ref="tabs" class="flex-1 flex items-center gap-x-2.5 min-w-0">
<div ref="tabs" class="flex-1 flex items-center gap-x-2.5 min-w-0">
<TabList class="flex-1 min-w-0 overflow-x-clip overflow-y-visible pe-0.25">
<div ref="tabWrapper" class="min-w-0 flex-1 flex overflow-clip px-0.25">
<div ref="tabInner" class="flex items-center gap-x-2.5 shrink-0">
<BlueprintTab
Expand All @@ -21,41 +21,41 @@
/>
</div>
</div>
<Dropdown
v-if="overflowedTabs.length"
align="end"
side="bottom"
class="shrink-0"
>
<template #trigger>
<Button
icon="dots"
variant="ghost"
size="sm"
:aria-label="__('Open dropdown menu')"
/>
</TabList>
<Dropdown
v-if="overflowedTabs.length"
align="end"
side="bottom"
class="shrink-0"
>
<template #trigger>
<Button
icon="dots"
variant="ghost"
size="sm"
:aria-label="__('Open dropdown menu')"
/>
</template>
<DropdownMenu>
<DropdownItem
v-for="tab in overflowedTabs"
:key="tab._id"
:icon="tab.icon"
:class="{ 'bg-gray-100 dark:bg-gray-800': currentTab === tab._id }"
@click="selectTab(tab._id)"
>
<span class="block max-w-48 overflow-hidden text-ellipsis whitespace-nowrap">
{{ __(tab.display) }}
</span>
</DropdownItem>
<template v-if="activeTabIsOverflowed">
<DropdownSeparator />
<DropdownItem :text="__('Edit')" icon="edit" @click="editActiveOverflowedTab" />
<DropdownItem :text="__('Delete')" icon="trash" variant="destructive" @click="removeActiveOverflowedTab" />
</template>
<DropdownMenu>
<DropdownItem
v-for="tab in overflowedTabs"
:key="tab._id"
:icon="tab.icon"
:class="{ 'bg-gray-100 dark:bg-gray-800': currentTab === tab._id }"
@click="selectTab(tab._id)"
>
<span class="block max-w-48 overflow-hidden text-ellipsis whitespace-nowrap">
{{ __(tab.display) }}
</span>
</DropdownItem>
<template v-if="activeTabIsOverflowed">
<DropdownSeparator />
<DropdownItem :text="__('Edit')" icon="edit" @click="editActiveOverflowedTab" />
<DropdownItem :text="__('Delete')" icon="trash" variant="destructive" @click="removeActiveOverflowedTab" />
</template>
</DropdownMenu>
</Dropdown>
</div>
</TabList>
</DropdownMenu>
</Dropdown>
</div>

<Button icon="plus" size="sm" round v-tooltip="addTabText" @click="addAndEditTab" />
</div>
Expand Down Expand Up @@ -89,7 +89,7 @@
</template>

<script>
import { Sortable, Plugins } from '@shopify/draggable';
import { Sortable, Plugins, Draggable } from '@shopify/draggable';
import { nanoid as uniqid } from 'nanoid';
import { createTabsOverflowTracker } from '@/util/tabs-overflow.js';
import BlueprintTab from './Tab.vue';
Expand Down Expand Up @@ -259,6 +259,11 @@ export default {
swapAnimation: { horizontal: true },
plugins: [Plugins.SwapAnimation],
distance: 10,
// Focusable adds tabindex to sortable wrappers, which puts non-tab
// focusables inside the tablist and fails aria-required-children.
exclude: {
plugins: [Draggable.Plugins.Focusable],
},
})
.on('sortable:stop', (e) => {
this.tabs.splice(e.newIndex, 0, this.tabs.splice(e.oldIndex, 1)[0]);
Expand Down
64 changes: 32 additions & 32 deletions resources/js/components/ui/Publish/Tabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ onUnmounted(() => {
<div>
<Tabs v-if="width" v-model:modelValue="activeTab">
<div v-if="hasMultipleVisibleMainTabs" class="flex items-center gap-x-2 -mt-2 mb-6">
<TabList class="flex-1 min-w-0 overflow-x-clip overflow-y-visible pe-0.25">
<div class="flex-1 flex items-center gap-x-2.5 min-w-0">
<div class="flex-1 flex items-center gap-x-2.5 min-w-0">
<TabList class="flex-1 min-w-0 overflow-x-clip overflow-y-visible pe-0.25">
<div ref="tabWrapper" class="min-w-0 flex-1 flex overflow-clip px-0.25">
<div ref="tabInner" class="flex items-center gap-x-2.5 shrink-0">
<TabTrigger
Expand All @@ -162,36 +162,36 @@ onUnmounted(() => {
</TabTrigger>
</div>
</div>
<Dropdown
v-if="overflowedTabs.length"
align="end"
side="bottom"
class="shrink-0"
>
<template #trigger>
<Button
icon="dots"
variant="ghost"
size="sm"
:aria-label="__('Open dropdown menu')"
/>
</template>
<DropdownMenu>
<DropdownItem
v-for="tab in overflowedTabs"
:key="tab.handle"
:icon="tab.icon"
:class="{ 'bg-gray-100 dark:bg-gray-800': activeTab === tab.handle }"
@click="setActive(tab.handle)"
>
<span class="block max-w-48 overflow-hidden text-ellipsis whitespace-nowrap">
{{ __(tab.display) }}
</span>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
</TabList>
</TabList>
<Dropdown
v-if="overflowedTabs.length"
align="end"
side="bottom"
class="shrink-0"
>
<template #trigger>
<Button
icon="dots"
variant="ghost"
size="sm"
:aria-label="__('Open dropdown menu')"
/>
</template>
<DropdownMenu>
<DropdownItem
v-for="tab in overflowedTabs"
:key="tab.handle"
:icon="tab.icon"
:class="{ 'bg-gray-100 dark:bg-gray-800': activeTab === tab.handle }"
@click="setActive(tab.handle)"
>
<span class="block max-w-48 overflow-hidden text-ellipsis whitespace-nowrap">
{{ __(tab.display) }}
</span>
</DropdownItem>
</DropdownMenu>
</Dropdown>
</div>
</div>

<div :class="{ 'grid grid-cols-[1fr_320px] gap-8': shouldShowSidebar }">
Expand Down
27 changes: 17 additions & 10 deletions resources/js/pages/auth/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -97,24 +97,23 @@ onUnmounted(() => passkey.cancel());
class="flex flex-col gap-6"
>
<Field :label="__('Email')" :error="errors?.email">
<Input v-model="email" name="email" autofocus tabindex="1" :autocomplete="emailAutocomplete" />
<Input v-model="email" name="email" autofocus :autocomplete="emailAutocomplete" />
</Field>

<Field :label="__('Password')" :error="errors?.password">
<Input v-model="password" name="password" type="password" :autocomplete="passwordAutocomplete" tabindex="2" />
<template #actions>
<Link
:href="forgotPasswordUrl"
class="text-ui-accent-text mb-1.5 text-sm hover:text-ui-accent-text/80"
tabindex="6"
v-text="__('Forgot password?')"
/>
<span
class="mb-1.5 text-sm text-transparent select-none pointer-events-none"
style="anchor-name: --login-forgot-password"
aria-hidden="true"
>{{ __('Forgot password?') }}</span>
</template>
<Input v-model="password" name="password" type="password" :autocomplete="passwordAutocomplete" />
</Field>

<Checkbox v-model="remember" name="remember" :label="__('Remember me')" tabindex="4" />
<Checkbox v-model="remember" name="remember" :label="__('Remember me')" />

<Button type="submit" variant="primary" :disabled="processing" :text="__('Continue')" tabindex="5" />
<Button type="submit" variant="primary" :disabled="processing" :text="__('Continue')" />
</form>

<template v-if="showOAuth || showPasskeyLogin">
Expand Down Expand Up @@ -148,6 +147,14 @@ onUnmounted(() => passkey.cancel());
</div>
</div>
</template>

<Link
v-if="emailLoginEnabled"
:href="forgotPasswordUrl"
class="absolute z-(--z-index-above) text-ui-accent-text mb-1.5 text-sm hover:text-ui-accent-text/80"
style="position-anchor: --login-forgot-password; top: anchor(top); left: anchor(left); position-visibility: always"
v-text="__('Forgot password?')"
/>
</div>
</AuthCard>
</template>
Loading