Various polishing around the product (#2427)

* Update header navigation

Logo, share button color, breadcrumb colors, spacings

* Updates to main button component

Shadows, border on secondary button, less spacings to icons

* Update spacings in dialog after bew button styling

* Use secondary button in embed dialog

* Update select inputs

Spacing, icon, border on dropdown, smaller avatars

* Update inputs to use the new styling

* Various copy updates

* Update icons

Smaller icons, outline instead of solid, removed some icons that were unnecessary

* Switch order of actions in Delete dialog

* Update styling of inline New model action

* Remove strange BG effect on comments component

* Update styling of hide/isolate actions in viewer

Was necessary after the button styling change. But new copy also makes it more usable.

* Fix alignment issue in selection info panel

* Align styling in Viewer panel component

* Clean up measure usage tips

A permanent "Right click to cancel measurement" tip isn't needed

* Panel spacing

* Update actions in the add model to viewer dialog

* Update permissions input in new project dialog

* Two minor things

* Remove unnecessary flex classes

---------

Co-authored-by: andrewwallacespeckle <andrew@speckle.systems>
This commit is contained in:
Benjamin Ottensten
2024-06-25 14:43:50 +02:00
committed by GitHub
parent c4bd9f73df
commit fc76fd9f4f
36 changed files with 128 additions and 166 deletions
@@ -1,7 +1,7 @@
<template>
<div class="w-full flex justify-center">
<FormButton :to="to" size="sm" color="card" @click="$emit('click', $event)">
View All
View all
</FormButton>
</div>
</template>
@@ -33,7 +33,7 @@
:key="user.id"
:user="user"
no-border
size="sm"
size="xs"
/>
</div>
<div v-if="hiddenSelectedItemCount > 0" class="text-foreground-2 normal">
@@ -47,7 +47,7 @@
:user="isArrayValue(value) ? value[0] : value"
no-border
class="mr-2"
size="sm"
size="xs"
/>
<span class="truncate label label--light min-w-0">
{{ (isArrayValue(value) ? value[0] : value).name }}
@@ -6,14 +6,14 @@
:target="target"
>
<img
class="h-8 w-8 block"
class="h-8 w-8 block mr-1"
src="~~/assets/images/speckle_logo_big.png"
alt="Speckle"
/>
<div
v-if="!minimal"
class="text-primary text-base mt-0 font-bold leading-7"
class="text-sm mt-0 font-semibold"
:class="showTextOnMobile ? '' : 'hidden md:flex'"
>
Speckle
@@ -1,7 +1,9 @@
<template>
<div>
<nav class="fixed z-20 top-0 h-14 bg-foundation shadow hover:shadow-md transition">
<div class="flex gap-4 items-center justify-between h-full w-screen px-4">
<nav class="fixed z-20 top-0 h-14 bg-foundation shadow">
<div
class="flex gap-4 items-center justify-between h-full w-screen py-4 pl-3 pr-4"
>
<div class="flex items-center truncate">
<HeaderLogoBlock :active="false" to="/" />
<HeaderNavLink
@@ -3,10 +3,10 @@
<NuxtLink
:to="to"
class="flex gap-1 items-center text-sm ml-0.5"
active-class="text-primary font-bold group is-active"
active-class="text-primary font-semibold group is-active"
>
<div v-if="separator">
<ChevronRightIcon class="flex w-4 h-4" />
<ChevronRightIcon class="flex w-4 h-4 text-foreground-2" />
</div>
<div class="group-[.is-active]:truncate">
{{ name || to }}
@@ -2,15 +2,10 @@
<template>
<Menu
as="div"
class="flex items-center relative sm:border-r border-outline-1 sm:pr-4"
class="flex items-center relative sm:border-r border-outline-3 sm:pr-4"
>
<MenuButton :id="menuButtonId" as="div">
<FormButton
class="hidden sm:flex"
size="sm"
outlined
:icon-right="ChevronDownIcon"
>
<FormButton class="hidden sm:flex" size="sm" :icon-right="ChevronDownIcon">
Share
</FormButton>
<button class="sm:hidden mt-1.5">
@@ -75,12 +70,12 @@
<script setup lang="ts">
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue'
import {
ChevronDownIcon,
LinkIcon,
FingerPrintIcon,
CodeBracketIcon,
ShareIcon
} from '@heroicons/vue/24/outline'
import { ChevronDownIcon } from '@heroicons/vue/20/solid'
import { SpeckleViewer } from '@speckle/shared'
import { keyboardClick } from '@speckle/ui-components'
import { graphql } from '~/lib/common/generated/gql/gql'
@@ -18,7 +18,7 @@
>
<template #something-selected="{ value }">
<div class="text-sm">
<div class="font-bold">
<div class="label">
{{ isArray(value) ? value[0].title : value.title }}
</div>
<span class="text-foreground-2 text-xs sm:text-sm">
@@ -28,6 +28,7 @@
label="Version message"
placeholder="Version message"
show-required
color="foundation"
:rules="[isRequired]"
:disabled="loading"
/>
@@ -198,7 +198,7 @@ const isPrivate = computed(() => {
const discoverableButtons = computed((): LayoutDialogButton[] => [
{
text: 'Cancel',
props: { color: 'invert', fullWidth: true, outline: true },
props: { color: 'secondary', fullWidth: true, outline: true },
onClick: () => {
isOpen.value = false
}
@@ -15,6 +15,7 @@
label="Model Name"
placeholder="model/name/here"
help="Use forward slashes in the model name to nest it below other models."
color="foundation"
:custom-icon="CubeIcon"
:rules="rules"
:disabled="disabled"
@@ -29,7 +30,7 @@
<script setup lang="ts">
import type { ProjectModelPageDialogMoveToVersionFragment } from '~~/lib/common/generated/gql/graphql'
import { useModelNameValidationRules } from '~~/lib/projects/composables/modelManagement'
import { CubeIcon } from '@heroicons/vue/24/solid'
import { CubeIcon } from '@heroicons/vue/24/outline'
import { useForm } from 'vee-validate'
import { sanitizeModelName } from '~~/lib/projects/helpers/models'
@@ -6,16 +6,12 @@
v-model="search"
name="search"
size="lg"
placeholder="Search"
placeholder="Search by email or username..."
:disabled="disabled"
:help="
disabled
? 'You must be the project owner to invite users'
: 'Search by username or email'
"
:help="disabled ? 'You must be the project owner to invite users' : ''"
input-classes="pr-[85px] text-sm"
color="foundation"
label="Add people by email or username"
label="Add people"
show-label
>
<template #input-right>
@@ -7,7 +7,7 @@
<FormTextInput
name="search"
color="foundation"
placeholder="Search Automations"
placeholder="Search automations..."
wrapper-classes="shrink-0"
show-clear
:model-value="bind.modelValue.value"
@@ -28,14 +28,14 @@
:disabled="!!disabledCreateBecauseOf"
@click="$emit('new-automation')"
>
New Automation
New
</FormButton>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ArrowTopRightOnSquareIcon, PlusIcon } from '@heroicons/vue/24/outline'
import { ArrowTopRightOnSquareIcon, PlusIcon } from '@heroicons/vue/20/solid'
import { useDebouncedTextInput } from '@speckle/ui-components'
import { automationFunctionsRoute } from '~/lib/common/helpers/route'
@@ -8,7 +8,6 @@
<div class="flex items-center space-x-2 w-full mt-2 sm:w-auto sm:mt-0">
<FormButton
color="secondary"
:icon-right="CubeIcon"
:to="allModelsRoute"
class="grow inline-flex sm:grow-0 lg:hidden"
@click="trackFederateAll"
@@ -18,7 +17,7 @@
<FormButton
v-if="canContribute"
class="grow inline-flex sm:grow-0 lg:hidden"
:icon-right="PlusIcon"
:icon-left="PlusIcon"
@click="showNewDialog = true"
>
New
@@ -32,7 +31,7 @@
v-model="localSearch"
name="modelsearch"
:show-label="false"
placeholder="Search"
placeholder="Search models..."
color="foundation"
wrapper-classes="grow lg:grow-0 lg:ml-2 lg:w-40 xl:w-60"
:show-clear="localSearch !== ''"
@@ -69,7 +68,6 @@
</div>
<FormButton
color="secondary"
:icon-right="CubeIcon"
:to="allModelsRoute"
class="hidden lg:inline-flex shrink-0"
@click="trackFederateAll"
@@ -79,7 +77,7 @@
<FormButton
v-if="canContribute"
class="hidden lg:inline-flex shrink-0"
:icon-right="PlusIcon"
:icon-left="PlusIcon"
@click="showNewDialog = true"
>
New
@@ -101,9 +99,8 @@ import type {
} from '~~/lib/common/generated/gql/graphql'
import { modelRoute } from '~~/lib/common/helpers/route'
import type { GridListToggleValue } from '~~/lib/layout/helpers/components'
import { PlusIcon } from '@heroicons/vue/24/solid'
import { PlusIcon } from '@heroicons/vue/20/solid'
import { canModifyModels } from '~~/lib/projects/helpers/permissions'
import { CubeIcon } from '@heroicons/vue/24/outline'
import { useMixpanel } from '~~/lib/core/composables/mp'
const emit = defineEmits<{
@@ -36,7 +36,7 @@
</LayoutDialog>
</template>
<script setup lang="ts">
import { CubeIcon } from '@heroicons/vue/24/solid'
import { CubeIcon } from '@heroicons/vue/24/outline'
import type { LayoutDialogButton } from '@speckle/ui-components'
import { useMutationLoading } from '@vue/apollo-composable'
import { useForm } from 'vee-validate'
@@ -6,11 +6,11 @@
@click="showNewModelCard = true"
>
+
<span class="font-bold ml-1">NEW</span>
<span class="font-semibold ml-1">NEW</span>
</button>
<div
v-if="showNewModelCard"
class="w-full py-2 px-3 flex items-center rounded-md transition bg-foundation-focus dark:bg-primary-muted"
class="w-full p-2 flex items-center rounded-md transition bg-foundation-focus dark:bg-primary-muted"
>
<form
class="flex items-center justify-between w-full space-x-2"
@@ -21,21 +21,17 @@
v-model="name"
name="name"
label="Model name"
placeholder="name"
placeholder="Model name"
auto-focus
color="foundation"
:rules="rules"
:disabled="anyMutationsLoading"
autocomplete="off"
/>
</div>
<div class="flex flex-wrap gap-1 sm:gap-2">
<FormButton submit :disabled="anyMutationsLoading" size="sm">Save</FormButton>
<FormButton
outlined
color="danger"
size="sm"
@click="showNewModelCard = false"
>
<FormButton submit :disabled="anyMutationsLoading">Save</FormButton>
<FormButton color="secondary" @click="showNewModelCard = false">
Cancel
</FormButton>
</div>
@@ -88,7 +88,7 @@
<div
class="text-xs text-foreground-2 absolute top-2 right-2 z-10 sm:relative sm:top-auto sm:right-auto"
>
updated
Updated
<b>{{ updatedAt }}</b>
</div>
<div class="text-xs text-foreground-2 flex items-center space-x-1">
@@ -172,7 +172,7 @@
</div>
</div> -->
<div class="text-xs text-foreground-2">
updated
Updated
<b>{{ updatedAt }}</b>
</div>
<div class="text-xs text-foreground-2">
@@ -184,7 +184,7 @@
:disabled="!viewAllUrl"
@click.stop="trackFederateModels"
>
View All
View all
</FormButton>
</div>
<div :class="`ml-4 w-24 h-20`">
@@ -234,16 +234,15 @@
<script lang="ts" setup>
import dayjs from 'dayjs'
import { modelVersionsRoute, modelRoute } from '~~/lib/common/helpers/route'
import { ChevronDownIcon, PlusIcon } from '@heroicons/vue/20/solid'
import {
ChevronDownIcon,
FolderIcon,
CubeIcon,
CubeTransparentIcon,
PlusIcon,
ChatBubbleLeftRightIcon,
ArrowTopRightOnSquareIcon
} from '@heroicons/vue/24/solid'
import { ArrowUpOnSquareIcon } from '@heroicons/vue/24/outline'
ArrowTopRightOnSquareIcon,
ArrowUpOnSquareIcon
} from '@heroicons/vue/24/outline'
import type {
PendingFileUploadFragment,
ProjectPageModelsStructureItem_ProjectFragment,
@@ -2,19 +2,19 @@
<LayoutDialog
v-model:open="isOpen"
:buttons="[
{
text: 'Delete',
props: { color: 'danger', fullWidth: true, disabled: loading },
onClick: () => {
onDelete()
}
},
{
text: 'Cancel',
props: { color: 'secondary', fullWidth: true },
onClick: () => {
isOpen = false
}
},
{
text: 'Delete',
props: { color: 'danger', fullWidth: true, disabled: loading },
onClick: () => {
onDelete()
}
}
]"
max-width="sm"
@@ -28,7 +28,7 @@
</p>
<p>
This action is irreversible and all of the versions inside of this model will be
deleted also!
deleted.
</p>
</div>
</LayoutDialog>
@@ -28,10 +28,10 @@
show-label
label="Model Name"
placeholder="model/name/here"
size="lg"
:rules="rules"
show-required
auto-focus
color="foundation"
:disabled="loading"
help="Use forward slashes in the model name to nest it below other models."
autocomplete="off"
@@ -42,7 +42,7 @@
show-label
label="Model Description"
placeholder="Description (Optional)"
size="lg"
color="foundation"
:disabled="loading"
/>
</div>
@@ -6,21 +6,20 @@
Are you sure you want to permanently
<strong>delete {{ project.name }}</strong>
and all its contents, including
<strong>({{ project.models.totalCount }}) {{ modelText }}</strong>
<strong>{{ project.models.totalCount }} {{ modelText }}</strong>
<span v-if="project.commentThreads.totalCount">
and
<strong>
({{ project.commentThreads.totalCount }}) {{ discussionText }}
</strong>
<strong>{{ project.commentThreads.totalCount }} {{ discussionText }}</strong>
</span>
?
</p>
<p>To confirm deletion, type the project name below and press Delete.</p>
<p>To confirm deletion, type the project name below.</p>
<FormTextInput
v-model="projectNameInput"
name="projectNameConfirm"
label="Project name"
placeholder="Type the project name here"
size="lg"
placeholder="Type the project name here..."
full-width
hide-error-message
class="text-sm"
@@ -7,7 +7,6 @@
<template #top-buttons>
<FormButton
color="secondary"
text-color="primary"
:icon-left="BookOpenIcon"
to="https://speckle.guide/dev/server-webhooks.html"
external
@@ -16,7 +15,7 @@
Docs
</FormButton>
<FormButton :icon-left="PlusIcon" @click="openCreateWebhookDialog">
Create
New
</FormButton>
</template>
<template v-if="webhooks.length !== 0">
@@ -124,12 +123,11 @@
import { useMutation, useQuery } from '@vue/apollo-composable'
import {
PlusIcon,
BookOpenIcon,
InformationCircleIcon,
CheckCircleIcon,
XCircleIcon
} from '@heroicons/vue/20/solid'
import { TrashIcon, PencilIcon } from '@heroicons/vue/24/outline'
import { TrashIcon, PencilIcon, BookOpenIcon } from '@heroicons/vue/24/outline'
import { FormSwitch, LayoutTable } from '@speckle/ui-components'
import { projectWebhooksQuery } from '~~/lib/projects/graphql/queries'
import { updateWebhookMutation } from '~~/lib/projects/graphql/mutations'
@@ -2,11 +2,12 @@
<LayoutDialog v-model:open="open" max-width="sm" :buttons="dialogButtons">
<template #header>Create new project</template>
<form class="flex flex-col text-foreground" @submit="onSubmit">
<div class="flex flex-col space-y-3 mb-6">
<div class="flex flex-col gap-3 mb-6">
<FormTextInput
name="name"
label="Project name"
placeholder="Project name"
color="foundation"
:rules="[isRequired, isStringOfLength({ maxLength: 512 })]"
show-required
auto-focus
@@ -16,19 +17,17 @@
name="description"
label="Project description"
placeholder="Description (optional)"
color="foundation"
size="lg"
:rules="[isStringOfLength({ maxLength: 65536 })]"
/>
</div>
<div
class="flex flex-col space-y-4 items-end md:flex-row md:justify-between md:items-center md:space-y-0"
>
<ProjectVisibilitySelect
v-model="visibility"
class="sm:max-w-none w-full sm:w-80"
mount-menu-on-body
/>
</div>
<h3 class="label mb-3">Access permissions</h3>
<ProjectVisibilitySelect
v-model="visibility"
class="sm:max-w-none w-full"
mount-menu-on-body
/>
</form>
</LayoutDialog>
</template>
@@ -31,7 +31,7 @@
v-model="search"
name="modelsearch"
:show-label="false"
placeholder="Search"
placeholder="Search projects..."
color="foundation"
wrapper-classes="grow md:grow-0 md:w-60"
:show-clear="!!search"
@@ -79,7 +79,7 @@ import {
useSubscription
} from '@vue/apollo-composable'
import { projectsDashboardQuery } from '~~/lib/projects/graphql/queries'
import { PlusIcon } from '@heroicons/vue/24/solid'
import { PlusIcon } from '@heroicons/vue/20/solid'
import { debounce } from 'lodash-es'
import { graphql } from '~~/lib/common/generated/gql'
import {
@@ -58,7 +58,7 @@
</LayoutDialog>
</template>
<script setup lang="ts">
import { EnvelopeIcon } from '@heroicons/vue/24/solid'
import { EnvelopeIcon } from '@heroicons/vue/24/outline'
import { Roles } from '@speckle/shared'
import type { Optional, ServerRoles } from '@speckle/shared'
import type { LayoutDialogButton } from '@speckle/ui-components'
@@ -22,7 +22,7 @@
>
<div
v-show="item.expanded"
class="transition hover:bg-foundation bg-white/80 dark:bg-neutral-800/90 dark:hover:bg-neutral-800 backdrop-blur-sm rounded-lg shadow-md mb-8 mx-2 px-4 py-4 gap-2 sm:gap-4 sm:ml-12 sm:max-w-xs pointer-events-auto"
class="transition bg-foundation rounded-lg shadow-md mb-8 mx-2 px-4 py-4 gap-2 sm:gap-4 sm:ml-12 sm:max-w-xs pointer-events-auto"
>
<div
class="sm:hidden flex items-center justify-center w-full gap-3 mt-1 mb-3"
@@ -48,11 +48,11 @@
</div>
<div class="flex items-center gap-0.5">
<button class="p-0.5 text-foreground hover:text-primary" @click="onClose">
<XMarkIcon class="h-4 w-4" />
<XMarkIcon class="size-4" />
</button>
</div>
</div>
<div v-if="$slots.actions" class="w-full px-3 h-8">
<div v-if="$slots.actions" class="w-full px-2 h-8">
<div class="flex items-center gap-1 h-full">
<slot name="actions"></slot>
</div>
@@ -35,7 +35,7 @@
<div
v-if="modelValue.isExpanded && canPostComment"
ref="threadContainer"
class="sm:absolute min-w-[200px] hover:bg-foundation bg-white/80 dark:bg-neutral-800/90 dark:hover:bg-neutral-800 backdrop-blur-sm sm:rounded-lg shadow-md"
class="sm:absolute min-w-[200px] bg-foundation sm:rounded-lg shadow-md"
>
<div class="relative">
<ViewerCommentsEditor
@@ -458,7 +458,7 @@ const onCopyLink = async () => {
triggerNotification({
type: ToastNotificationType.Info,
title: 'Thread link copied'
title: 'Link copied'
})
}
@@ -6,7 +6,7 @@
class="absolute top-1.5 sm:top-2 right-0.5 sm:right-0 z-10"
>
<FormButton size="sm" color="secondary" text @click="$emit('close')">
<XMarkIcon class="size-4 sm:size-3 text-primary sm:text-foreground" />
<XMarkIcon class="size-3 text-primary sm:text-foreground" />
</FormButton>
</div>
<div
@@ -5,9 +5,7 @@
class="flex items-center gap-2 text-xs sm:text-sm px-3 py-1.5 sm:py-2 border-b border-outline-3 text-foreground-2"
>
<InformationCircleIcon class="h-5 w-5 sm:h-6 sm:h-6 shrink-0" />
<span class="max-w-[210px]">
Reloading the model will delete all measurements.
</span>
<span class="text-xs">Reloading will delete all measurements</span>
</div>
<template #actions>
<FormButton
@@ -74,12 +72,6 @@
</div>
</div>
</div>
<Portal to="pocket-tip">
<ViewerTip class="hidden sm:flex">
<strong>Tip:</strong>
Right click to cancel measurement
</ViewerTip>
</Portal>
</ViewerLayoutPanel>
</template>
<script setup lang="ts">
@@ -6,7 +6,7 @@
name="modelsearch"
:show-label="false"
:size="isSmallerOrEqualSm ? 'sm' : 'base'"
placeholder="Search"
placeholder="Search models..."
color="foundation"
class="w-48 sm:w-60"
:show-clear="search !== ''"
@@ -11,31 +11,24 @@
name="objectIdsOrUrl"
label="Value"
full-width
:size="isSmallerOrEqualSm ? 'base' : 'lg'"
:custom-icon="LinkIcon"
:rules="[isRequired, isValidValue]"
placeholder="Comma-delimited object IDs/URLs"
color="foundation"
auto-focus
/>
<FormButton
:icon-left="PlusIcon"
:size="isSmallerOrEqualSm ? 'base' : 'lg'"
submit
>
Add
</FormButton>
<FormButton :icon-left="PlusIcon" submit>Add</FormButton>
</form>
</div>
</template>
<script setup lang="ts">
import { useForm } from 'vee-validate'
import type { RuleExpression } from 'vee-validate'
import { PlusIcon, LinkIcon } from '@heroicons/vue/24/solid'
import { PlusIcon, LinkIcon } from '@heroicons/vue/20/solid'
import { isRequired } from '~~/lib/common/helpers/validation'
import { isObjectId } from '~~/lib/common/helpers/resources'
import { useInjectedViewerLoadedResources } from '~~/lib/viewer/composables/setup'
import { difference } from 'lodash-es'
import { useIsSmallerOrEqualThanBreakpoint } from '~~/composables/browser'
const emit = defineEmits<{
(e: 'chosen', val: { objectIds: string[] }): void
@@ -46,7 +39,6 @@ const urlRegexp = /\/models\/([a-zA-Z0-_9,@$]+)$/i
const { handleSubmit } = useForm<FormPayload>()
const { resourceItems } = useInjectedViewerLoadedResources()
const { isSmallerOrEqualSm } = useIsSmallerOrEqualThanBreakpoint()
const explodeValidatedObjectIds = (commaDelimitedIdList: string) => {
const idParts = commaDelimitedIdList.split(',')
@@ -8,7 +8,7 @@
>
<div class="mb-1 flex items-center">
<button
class="flex h-full w-full px-2 py-0.5 items-center gap-1 rounded bg-foundation-2 hover:sm:bg-primary-muted hover:text-primary"
class="flex h-full w-full pl-1 pr-2 py-0.5 items-center gap-1 rounded bg-foundation-2 hover:sm:bg-primary-muted hover:text-primary"
:class="unfold && 'text-primary'"
@click="unfold = !unfold"
@mouseenter="highlightObject"
@@ -91,14 +91,14 @@
:key="index"
class="text-xs"
>
<div class="text-foreground-2 grid grid-cols-3">
<div class="text-foreground-2 grid grid-cols-3 pl-2">
<div
class="col-span-1 truncate text-xs font-bold"
:title="(kvp.key as string)"
>
{{ kvp.key }}
</div>
<div class="col-span-2 flex w-full min-w-0 truncate text-xs">
<div class="col-span-2 flex w-full min-w-0 truncate text-xs pl-1">
<div class="flex-grow truncate">{{ kvp.innerType }} array</div>
<div class="text-foreground-2">({{ kvp.arrayLength }})</div>
</div>
@@ -107,7 +107,7 @@
<div v-for="(kvp, index) in categorisedValuePairs.primitiveArrays" :key="index">
<div class="grid grid-cols-3">
<div
class="col-span-1 truncate text-xs font-bold"
class="col-span-1 truncate text-xs font-bold pl-2"
:title="(kvp.key as string)"
>
{{ kvp.key }}
@@ -3,39 +3,41 @@
<ViewerSidebar :open="sidebarOpen" @close="onClose">
<template #title><div class="select-none">Selection Info</div></template>
<template #actions>
<FormButton
size="xs"
color="secondary"
class="opacity-80 hover:opacity-100"
@click.stop="hideOrShowSelection"
>
<div v-if="!isHidden" class="flex items-center gap-1">
<FormButton size="xs" text color="secondary" @click.stop="hideOrShowSelection">
<div
v-if="!isHidden"
class="flex items-center gap-1 text-foreground hover:text-primary"
>
<EyeSlashIcon class="h-4 w-4" />
Hide
</div>
<div v-else class="flex items-center gap-1">
<EyeIcon class="h-4 w-4" />
Unhide
<div v-else class="flex items-center gap-1 text-primary">
<EyeSlashIcon class="h-4 w-4" />
Hidden
</div>
</FormButton>
<FormButton
size="xs"
color="secondary"
class="hover:opacity-100"
:class="isIsolated ? 'text-primary opacity-100' : 'opacity-80'"
@click.stop="isolateOrUnisolateSelection"
>
<FormButton size="xs" text @click.stop="isolateOrUnisolateSelection">
<div class="flex items-center gap-1">
<FunnelIconOutline v-if="!isIsolated" class="h-4 w-4" />
<FunnelIcon v-else class="h-4 w-4" />
Isolate
<div
v-if="!isIsolated"
class="flex items-center gap-1 text-foreground hover:text-primary"
>
<FunnelIconOutline class="h-4 w-4" />
Isolate
</div>
<div v-else class="flex items-center gap-1 text-primary">
<FunnelIcon class="h-4 w-4" />
Isolated
</div>
</div>
</FormButton>
<div class="flex justify-end w-full">
<div v-tippy="`Open selection in new window`" class="max-w-max">
<FormButton size="xs" :to="selectionLink" color="secondary" target="_blank">
<FormButton size="xs" text :to="selectionLink" target="_blank">
<span class="sr-only">Open selection in new window</span>
<ArrowTopRightOnSquareIcon class="w-4" />
<ArrowTopRightOnSquareIcon
class="w-4 text-foreground hover:text-primary"
/>
</FormButton>
</div>
</div>
@@ -66,7 +68,6 @@
</template>
<script setup lang="ts">
import {
EyeIcon,
EyeSlashIcon,
FunnelIcon,
ArrowTopRightOnSquareIcon
@@ -13,13 +13,13 @@
<Component
:is="finalLeftIcon"
v-if="finalLeftIcon"
:class="`${iconClasses} ${hideText ? '' : 'mr-2'}`"
:class="`${iconClasses} ${hideText ? '' : 'mr-1'}`"
/>
<slot v-if="!hideText">Button</slot>
<Component
:is="iconRight"
v-if="iconRight || !loading"
:class="`${iconClasses} ${hideText ? '' : 'ml-2'}`"
:class="`${iconClasses} ${hideText ? '' : 'ml-1'}`"
/>
</Component>
</template>
@@ -196,27 +196,25 @@ const finalLeftIcon = computed(() => (props.loading ? ArrowPathIcon : props.icon
const bgAndBorderClasses = computed(() => {
const classParts: string[] = []
classParts.push('border-2')
classParts.push('border')
if (isDisabled.value) {
classParts.push(
props.outlined
? 'border-foreground-disabled'
: 'bg-foundation-disabled border-transparent'
props.outlined ? 'border-outline-3' : 'bg-foundation-disabled border-transparent'
)
} else {
switch (props.color) {
case 'invert':
classParts.push(
props.outlined
? 'border-foundation dark:border-foreground'
: 'bg-foundation dark:bg-foreground border-transparent'
? 'border-outline-3'
: 'border-outline-3 bg-foundation dark:bg-foreground'
)
break
case 'card':
classParts.push(
props.outlined
? 'border-foundation-2 shadow'
: 'bg-foundation-2 dark:bg-foundation-2 border-foundation shadow'
? 'border-outline-3'
: 'bg-foundation-2 dark:bg-foundation-2 border-foundation'
)
break
case 'danger':
@@ -224,7 +222,7 @@ const bgAndBorderClasses = computed(() => {
break
case 'secondary':
classParts.push(
props.outlined ? 'border-foundation' : 'bg-foundation border-foundation-2'
props.outlined ? 'border-outline-3' : 'bg-foundation border-outline-3'
)
break
case 'warning':
@@ -308,11 +306,7 @@ const foregroundClasses = computed(() => {
)
break
case 'secondary':
classParts.push(
props.outlined
? 'text-foreground hover:text-primary'
: 'text-foreground hover:text-primary'
)
classParts.push(props.outlined ? 'text-foreground' : 'text-foreground')
break
case 'default':
default:
@@ -433,7 +427,7 @@ const generalClasses = computed(() => {
const decoratorClasses = computed(() => {
const classParts: string[] = []
if (!isDisabled.value && !props.link && !props.text) {
classParts.push('active:scale-[0.97]')
classParts.push('shadow active:scale-[0.97]')
}
if (!isDisabled.value && props.link) {
@@ -200,7 +200,7 @@ import {
MagnifyingGlassIcon,
XMarkIcon,
ExclamationCircleIcon
} from '@heroicons/vue/24/solid'
} from '@heroicons/vue/20/solid'
import { debounce, isArray, isObjectLike } from 'lodash'
import type { CSSProperties, PropType, Ref } from 'vue'
import { computed, onMounted, ref, unref, watch } from 'vue'
@@ -525,7 +525,7 @@ const buttonClasses = computed(() => {
]
if (props.buttonStyle !== 'simple') {
classParts.push('py-2 px-3')
classParts.push('p-2')
if (!isDisabled.value) {
if (props.buttonStyle === 'tinted') {
@@ -623,7 +623,7 @@ const finalItems = computed(() => {
const listboxOptionsClasses = computed(() => {
const classParts = [
'rounded-md bg-foundation-2 py-1 label label--light outline outline-2 outline-primary-muted focus:outline-none shadow mt-1 '
'rounded-md bg-foundation-2 py-1 label label--light border border-outline-3 shadow-md mt-1 '
]
if (props.mountMenuOnBody) {
@@ -37,7 +37,7 @@
<div :class="scrolledFromTop && 'relative z-20 shadow-lg'">
<div
v-if="hasTitle"
class="flex items-center justify-start rounded-t-lg shrink-0 min-h-[2rem] sm:min-h-[4rem] py-2 px-4 sm:px-8 truncate text-lg sm:text-2xl font-bold"
class="flex items-center justify-start rounded-t-lg shrink-0 min-h-[2rem] sm:min-h-[4rem] p-4 sm:p-6 truncate text-lg sm:text-2xl font-bold"
>
<div class="w-full truncate pr-12">
{{ title }}
@@ -65,14 +65,14 @@
<div
ref="slotContainer"
class="flex-1 simple-scrollbar overflow-y-auto text-sm sm:text-base"
:class="hasTitle ? 'p-3 sm:py-6 sm:px-8' : 'p-6 pt-10 sm:p-10'"
:class="hasTitle ? 'px-4 pb-4 sm:px-6' : 'p-4 sm:p-6'"
@scroll="onScroll"
>
<slot>Put your content here!</slot>
</div>
<div
v-if="hasButtons"
class="relative z-50 flex px-4 py-2 sm:py-4 sm:px-6 gap-2 shrink-0 bg-foundation"
class="relative z-50 flex p-4 sm:p-6 gap-3 shrink-0 bg-foundation"
:class="{
'shadow-t': !scrolledToBottom,
[buttonsWrapperClasses || '']: true