chore: hoppscotch-ui improvements (#3497)

Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
Anwarul Islam
2023-12-06 00:38:44 +06:00
committed by GitHub
parent 18864bfecf
commit 6fa722df7b
69 changed files with 726 additions and 640 deletions

View File

@@ -5,5 +5,4 @@ module.exports = {
printWidth: 80,
useTabs: false,
tabWidth: 2,
plugins: ["prettier-plugin-tailwindcss"],
}

View File

@@ -29,14 +29,6 @@
@apply antialiased;
accent-color: var(--accent-color);
font-variant-ligatures: common-ligatures;
// Colors
--info-color: #ec4899;
--success-color: #10b981;
--blue-color: #3b82f6;
--warning-color: #f59e0b;
--cl-error-color: #ef4444;
--sv-error-color: #dc2626;
}
::-webkit-scrollbar-track {
@@ -65,7 +57,7 @@ input::placeholder,
textarea::placeholder,
.cm-placeholder {
@apply text-secondary;
@apply opacity-50;
@apply opacity-50 #{!important};
}
input,
@@ -84,7 +76,7 @@ body {
@apply font-medium;
@apply select-none;
@apply overflow-x-hidden;
@apply leading-body;
@apply leading-body #{!important};
animation: fade 300ms forwards;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
@@ -182,7 +174,7 @@ a {
@apply font-semibold;
@apply px-2 py-1;
@apply truncate;
@apply leading-normal;
@apply leading-body;
@apply items-center;
kbd {
@@ -229,7 +221,7 @@ a {
@apply overflow-y-auto;
@apply text-body text-secondary;
@apply p-2;
@apply leading-normal;
@apply leading-body;
@apply focus:outline-none;
scroll-behavior: smooth;
@@ -261,7 +253,7 @@ a {
hr {
@apply border-b border-dividerLight;
@apply my-2;
@apply my-2 #{!important};
}
.heading {
@@ -350,44 +342,28 @@ pre.ace_editor {
}
}
.select-wrapper {
@apply flex flex-1;
@apply relative;
@apply after:absolute;
@apply after:flex;
@apply after:inset-y-0;
@apply after:items-center;
@apply after:justify-center;
@apply after:pointer-events-none;
@apply after:font-icon;
@apply after:text-current;
@apply after:right-3;
@apply after:content-["\e5cf"];
@apply after:text-lg;
}
.info-response {
color: var(--info-color);
color: var(--status-info-color);
}
.success-response {
color: var(--success-color);
color: var(--status-success-color);
}
.redir-response {
color: var(--warning-color);
.redirect-response {
color: var(--status-redirect-color);
}
.cl-error-response {
color: var(--cl-error-color);
.critical-error-response {
color: var(--status-critical-error-color);
}
.sv-error-response {
color: var(--sv-error-color);
.server-error-response {
color: var(--status-server-error-color);
}
.missing-data-response {
@apply text-secondaryLight;
color: var(--status-missing-data-color);
}
.toasted-container {
@@ -537,12 +513,12 @@ pre.ace_editor {
@apply inline-flex;
@apply font-sans;
@apply text-tiny;
@apply bg-divider;
@apply bg-dividerLight;
@apply rounded;
@apply ml-2;
@apply px-1;
@apply min-w-5;
@apply min-h-5;
@apply min-w-[1.25rem];
@apply min-h-[1.25rem];
@apply items-center;
@apply justify-center;
@apply border border-dividerDark;

View File

@@ -1,89 +1,89 @@
@mixin green-theme {
--accent-color: #10b981;
--accent-light-color: #34d399;
--accent-dark-color: #059669;
--accent-contrast-color: #fff;
--gradient-from-color: #a7f3d0;
--gradient-via-color: #34d399;
--gradient-to-color: #059669;
--accent-color: theme("colors.emerald.500");
--accent-light-color: theme("colors.emerald.400");
--accent-dark-color: theme("colors.emerald.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.emerald.400");
--gradient-via-color: theme("colors.emerald.500");
--gradient-to-color: theme("colors.emerald.600");
}
@mixin teal-theme {
--accent-color: #14b8a6;
--accent-light-color: #2dd4bf;
--accent-dark-color: #0d9488;
--accent-contrast-color: #fff;
--gradient-from-color: #99f6e4;
--gradient-via-color: #2dd4bf;
--gradient-to-color: #0d9488;
--accent-color: theme("colors.teal.500");
--accent-light-color: theme("colors.teal.400");
--accent-dark-color: theme("colors.teal.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.teal.400");
--gradient-via-color: theme("colors.teal.500");
--gradient-to-color: theme("colors.teal.600");
}
@mixin blue-theme {
--accent-color: #3b82f6;
--accent-light-color: #60a5fa;
--accent-dark-color: #2563eb;
--accent-contrast-color: #fff;
--gradient-from-color: #bfdbfe;
--gradient-via-color: #60a5fa;
--gradient-to-color: #2563eb;
--accent-color: theme("colors.blue.500");
--accent-light-color: theme("colors.blue.400");
--accent-dark-color: theme("colors.blue.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.blue.400");
--gradient-via-color: theme("colors.blue.500");
--gradient-to-color: theme("colors.blue.600");
}
@mixin indigo-theme {
--accent-color: #6366f1;
--accent-light-color: #818cf8;
--accent-dark-color: #4f46e5;
--accent-contrast-color: #fff;
--gradient-from-color: #c7d2fe;
--gradient-via-color: #818cf8;
--gradient-to-color: #4f46e5;
--accent-color: theme("colors.indigo.500");
--accent-light-color: theme("colors.indigo.400");
--accent-dark-color: theme("colors.indigo.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.indigo.400");
--gradient-via-color: theme("colors.indigo.500");
--gradient-to-color: theme("colors.indigo.600");
}
@mixin purple-theme {
--accent-color: #8b5cf6;
--accent-light-color: #a78bfa;
--accent-dark-color: #7c3aed;
--accent-contrast-color: #fff;
--gradient-from-color: #ddd6fe;
--gradient-via-color: #a78bfa;
--gradient-to-color: #7c3aed;
--accent-color: theme("colors.purple.500");
--accent-light-color: theme("colors.purple.400");
--accent-dark-color: theme("colors.purple.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.purple.400");
--gradient-via-color: theme("colors.purple.500");
--gradient-to-color: theme("colors.purple.600");
}
@mixin yellow-theme {
--accent-color: #f59e0b;
--accent-light-color: #fbbf24;
--accent-dark-color: #d97706;
--accent-contrast-color: #fff;
--gradient-from-color: #fde68a;
--gradient-via-color: #fbbf24;
--gradient-to-color: #d97706;
--accent-color: theme("colors.amber.500");
--accent-light-color: theme("colors.amber.400");
--accent-dark-color: theme("colors.amber.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.amber.400");
--gradient-via-color: theme("colors.amber.500");
--gradient-to-color: theme("colors.amber.600");
}
@mixin orange-theme {
--accent-color: #f97316;
--accent-light-color: #fb923c;
--accent-dark-color: #ea580c;
--accent-contrast-color: #fff;
--gradient-from-color: #fed7aa;
--gradient-via-color: #fb923c;
--gradient-to-color: #ea580c;
--accent-color: theme("colors.orange.500");
--accent-light-color: theme("colors.orange.400");
--accent-dark-color: theme("colors.orange.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.orange.400");
--gradient-via-color: theme("colors.orange.500");
--gradient-to-color: theme("colors.orange.600");
}
@mixin red-theme {
--accent-color: #ef4444;
--accent-light-color: #f87171;
--accent-dark-color: #dc2626;
--accent-contrast-color: #fff;
--gradient-from-color: #fecaca;
--gradient-via-color: #f87171;
--gradient-to-color: #dc2626;
--accent-color: theme("colors.red.500");
--accent-light-color: theme("colors.red.400");
--accent-dark-color: theme("colors.red.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.red.400");
--gradient-via-color: theme("colors.red.500");
--gradient-to-color: theme("colors.red.600");
}
@mixin pink-theme {
--accent-color: #ec4899;
--accent-light-color: #f472b6;
--accent-dark-color: #db2777;
--accent-contrast-color: #fff;
--gradient-from-color: #fbcfe8;
--gradient-via-color: #f472b6;
--gradient-to-color: #db2777;
--accent-color: theme("colors.pink.500");
--accent-light-color: theme("colors.pink.400");
--accent-dark-color: theme("colors.pink.600");
--accent-contrast-color: theme("colors.white");
--gradient-from-color: theme("colors.pink.400");
--gradient-via-color: theme("colors.pink.500");
--gradient-to-color: theme("colors.pink.600");
}

View File

@@ -1,17 +1,16 @@
@mixin base-theme {
--font-sans: "Inter Variable", sans-serif;
--font-icon: "Material Symbols Rounded Variable";
--font-mono: "Roboto Mono Variable", monospace;
--font-size-body: 0.75rem;
--font-size-tiny: 0.688rem;
--font-size-tiny: 0.625rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-fourth-sticky-fold: 10.2rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-primary-sticky-fold: 6.75rem;
--upper-mobile-secondary-sticky-fold: 8.813rem;
--upper-mobile-sticky-fold: 10.875rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
@@ -21,67 +20,121 @@
}
@mixin light-theme {
--primary-color: #ffffff;
--primary-light-color: #f9fafb;
--primary-dark-color: #f3f4f6;
--primary-color: theme("colors.white");
--primary-light-color: theme("colors.gray.50");
--primary-dark-color: theme("colors.gray.100");
--primary-contrast-color: #fdfdfd;
--secondary-color: #6b7280;
--secondary-light-color: #9ca3af;
--secondary-dark-color: #111827;
--secondary-color: theme("colors.gray.500");
--secondary-light-color: theme("colors.gray.400");
--secondary-dark-color: theme("colors.gray.900");
--divider-color: #f3f4f6;
--divider-light-color: #f3f4f6;
--divider-dark-color: #d1d5db;
--divider-color: theme("colors.gray.100");
--divider-light-color: theme("colors.gray.100");
--divider-dark-color: theme("colors.gray.300");
--banner-info-color: theme("colors.stone.100");
--banner-warning-color: theme("colors.yellow.100");
--banner-error-color: theme("colors.red.100");
--tooltip-color: theme("colors.neutral.800");
--popover-color: theme("colors.white");
--method-get-color: theme("colors.green.500");
--method-post-color: theme("colors.amber.500");
--method-put-color: theme("colors.blue.500");
--method-patch-color: theme("colors.purple.500");
--method-delete-color: theme("colors.red.500");
--method-head-color: theme("colors.lime.500");
--method-options-color: theme("colors.pink.500");
--method-default-color: theme("colors.gray.500");
--status-info-color: theme("colors.blue.500");
--status-success-color: theme("colors.green.500");
--status-redirect-color: theme("colors.amber.500");
--status-critical-error-color: theme("colors.red.500");
--status-server-error-color: theme("colors.rose.500");
--status-missing-data-color: theme("colors.slate.500");
--info-color: #fef3c7;
--warning-color: #fef9c3;
--error-color: #fee2e2;
--tooltip-color: #262626;
--popover-color: #ffffff;
--editor-theme: "textmate";
}
@mixin dark-theme {
--primary-color: #181818;
--primary-light-color: #1c1c1e;
--primary-dark-color: #262626;
--primary-contrast-color: #171717;
--primary-dark-color: theme("colors.neutral.800");
--primary-contrast-color: theme("colors.neutral.900");
--secondary-color: #a3a3a3;
--secondary-light-color: #737373;
--secondary-dark-color: #fafafa;
--secondary-color: theme("colors.neutral.400");
--secondary-light-color: theme("colors.neutral.500");
--secondary-dark-color: theme("colors.zinc.50");
--divider-color: #262626;
--divider-color: #1f1f1f;
--divider-light-color: #1f1f1f;
--divider-dark-color: #2d2d2d;
--divider-dark-color: theme("colors.zinc.800");
--info-color: #292524;
--warning-color: #854d0e;
--error-color: #991b1b;
--tooltip-color: #f5f5f5;
--banner-info-color: theme("colors.stone.800");
--banner-warning-color: theme("colors.yellow.800");
--banner-error-color: theme("colors.red.800");
--tooltip-color: theme("colors.neutral.100");
--popover-color: #1b1b1b;
--method-get-color: theme("colors.emerald.500");
--method-post-color: theme("colors.yellow.500");
--method-put-color: theme("colors.sky.500");
--method-patch-color: theme("colors.violet.500");
--method-delete-color: theme("colors.rose.500");
--method-head-color: theme("colors.teal.500");
--method-options-color: theme("colors.indigo.500");
--method-default-color: theme("colors.neutral.500");
--status-info-color: theme("colors.blue.500");
--status-success-color: theme("colors.green.500");
--status-redirect-color: theme("colors.amber.500");
--status-critical-error-color: theme("colors.red.500");
--status-server-error-color: theme("colors.rose.500");
--status-missing-data-color: theme("colors.slate.500");
--editor-theme: "merbivore_soft";
}
@mixin black-theme {
--primary-color: #0f0f0f;
--primary-light-color: #171717;
--primary-light-color: theme("colors.neutral.900");
--primary-dark-color: #181818;
--primary-contrast-color: #0f0f0f;
--secondary-color: #a3a3a3;
--secondary-light-color: #737373;
--secondary-dark-color: #f5f5f5;
--secondary-color: theme("colors.neutral.400");
--secondary-light-color: theme("colors.neutral.500");
--secondary-dark-color: theme("colors.neutral.50");
--divider-color: #1c1c1e;
--divider-light-color: #181818;
--divider-dark-color: #323232;
--divider-color: theme("colors.neutral.900");
--divider-light-color: theme("colors.neutral.900");
--divider-dark-color: theme("colors.zinc.800");
--banner-info-color: theme("colors.stone.900");
--banner-warning-color: theme("colors.yellow.900");
--banner-error-color: theme("colors.red.900");
--tooltip-color: theme("colors.neutral.100");
--popover-color: theme("colors.stone.950");
--method-get-color: theme("colors.emerald.500");
--method-post-color: theme("colors.yellow.500");
--method-put-color: theme("colors.sky.500");
--method-patch-color: theme("colors.violet.500");
--method-delete-color: theme("colors.rose.500");
--method-head-color: theme("colors.teal.500");
--method-options-color: theme("colors.indigo.500");
--method-default-color: theme("colors.zinc.500");
--status-info-color: theme("colors.blue.500");
--status-success-color: theme("colors.green.500");
--status-redirect-color: theme("colors.amber.500");
--status-critical-error-color: theme("colors.red.500");
--status-server-error-color: theme("colors.rose.500");
--status-missing-data-color: theme("colors.slate.500");
--info-color: #1c1917;
--warning-color: #713f12;
--error-color: #7f1d1d;
--tooltip-color: #f5f5f5;
--popover-color: #0f0f0f;
--editor-theme: "twilight";
}

View File

@@ -1,41 +1,41 @@
@mixin dark-editor-theme {
--editor-type-color: #a78bfa;
--editor-name-color: #60a5fa;
--editor-operator-color: #818cf8;
--editor-invalid-color: #f87171;
--editor-separator-color: #9ca3af;
--editor-meta-color: #9ca3af;
--editor-variable-color: #34d399;
--editor-link-color: #22d3ee;
--editor-process-color: #e879f9;
--editor-constant-color: #a78bfa;
--editor-keyword-color: #f472b6;
@mixin light-editor-theme {
--editor-type-color: theme("colors.violet.600");
--editor-name-color: theme("colors.red.600");
--editor-operator-color: theme("colors.indigo.600");
--editor-invalid-color: theme("colors.red.600");
--editor-separator-color: theme("colors.gray.600");
--editor-meta-color: theme("colors.gray.600");
--editor-variable-color: theme("colors.emerald.600");
--editor-link-color: theme("colors.cyan.600");
--editor-process-color: theme("colors.blue.600");
--editor-constant-color: theme("colors.fuchsia.600");
--editor-keyword-color: theme("colors.pink.600");
}
@mixin light-editor-theme {
--editor-type-color: #7c3aed;
--editor-name-color: #dc2626;
--editor-operator-color: #4f46e5;
--editor-invalid-color: #dc2626;
--editor-separator-color: #4b5563;
--editor-meta-color: #4b5563;
--editor-variable-color: #059669;
--editor-link-color: #0891b2;
--editor-process-color: #2563eb;
--editor-constant-color: #c026d3;
--editor-keyword-color: #db2777;
@mixin dark-editor-theme {
--editor-type-color: theme("colors.violet.400");
--editor-name-color: theme("colors.blue.400");
--editor-operator-color: theme("colors.indigo.400");
--editor-invalid-color: theme("colors.red.400");
--editor-separator-color: theme("colors.gray.400");
--editor-meta-color: theme("colors.gray.400");
--editor-variable-color: theme("colors.emerald.400");
--editor-link-color: theme("colors.cyan.400");
--editor-process-color: theme("colors.fuchsia.400");
--editor-constant-color: theme("colors.violet.400");
--editor-keyword-color: theme("colors.pink.400");
}
@mixin black-editor-theme {
--editor-type-color: #a78bfa;
--editor-name-color: #e879f9;
--editor-operator-color: #818cf8;
--editor-invalid-color: #f87171;
--editor-separator-color: #9ca3af;
--editor-meta-color: #9ca3af;
--editor-variable-color: #34d399;
--editor-link-color: #22d3ee;
--editor-process-color: #a78bfa;
--editor-constant-color: #60a5fa;
--editor-keyword-color: #f472b6;
--editor-type-color: theme("colors.violet.400");
--editor-name-color: theme("colors.fuchsia.400");
--editor-operator-color: theme("colors.indigo.400");
--editor-invalid-color: theme("colors.red.400");
--editor-separator-color: theme("colors.gray.400");
--editor-meta-color: theme("colors.gray.400");
--editor-variable-color: theme("colors.emerald.400");
--editor-link-color: theme("colors.cyan.400");
--editor-process-color: theme("colors.violet.400");
--editor-constant-color: theme("colors.blue.400");
--editor-keyword-color: theme("colors.pink.400");
}

View File

@@ -345,7 +345,7 @@
"authorization": "The authorization header will be automatically generated when you send the request.",
"generate_documentation_first": "Generate documentation first",
"network_fail": "Unable to reach the API endpoint. Check your network connection or select a different Interceptor and try again.",
"offline": "You're using Hoppscotch offline. Updates will sync when you're online, based on workspace settings",
"offline": "You're using Hoppscotch offline. Updates will sync when you're online, based on workspace settings.",
"offline_short": "You're using Hoppscotch offline.",
"post_request_tests": "Test scripts are written in JavaScript, and are run after the response is received.",
"pre_request_script": "Pre-request scripts are written in JavaScript, and are run before the request is sent.",

View File

@@ -108,6 +108,7 @@ declare module 'vue' {
HoppSmartProgressRing: typeof import('@hoppscotch/ui')['HoppSmartProgressRing']
HoppSmartRadio: typeof import('@hoppscotch/ui')['HoppSmartRadio']
HoppSmartRadioGroup: typeof import('@hoppscotch/ui')['HoppSmartRadioGroup']
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper']
HoppSmartSlideOver: typeof import('@hoppscotch/ui')['HoppSmartSlideOver']
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
HoppSmartTab: typeof import('@hoppscotch/ui')['HoppSmartTab']
@@ -215,6 +216,7 @@ declare module 'vue' {
SmartProgressRing: typeof import('./../../hoppscotch-ui/src/components/smart/ProgressRing.vue')['default']
SmartRadio: typeof import('./../../hoppscotch-ui/src/components/smart/Radio.vue')['default']
SmartRadioGroup: typeof import('./../../hoppscotch-ui/src/components/smart/RadioGroup.vue')['default']
SmartSelectWrapper: typeof import('./../../hoppscotch-ui/src/components/smart/SelectWrapper.vue')['default']
SmartSlideOver: typeof import('./../../hoppscotch-ui/src/components/smart/SlideOver.vue')['default']
SmartSpinner: typeof import('./../../hoppscotch-ui/src/components/smart/Spinner.vue')['default']
SmartTab: typeof import('./../../hoppscotch-ui/src/components/smart/Tab.vue')['default']

View File

@@ -1,25 +1,21 @@
<template>
<div
:role="bannerRole"
class="flex items-center justify-between px-4 py-2 text-tiny"
class="flex items-center justify-between px-4 py-2 text-tiny text-secondaryDark"
:class="bannerColor"
>
<div class="flex items-center">
<component :is="bannerIcon" class="mr-2 text-secondaryDark" />
<span class="text-secondaryDark">
<span v-if="banner.alternateText" class="md:hidden">
{{ banner.alternateText(t) }}
</span>
<span :class="{ '<md:hidden': banner.alternateText }">
{{ banner.text(t) }}
</span>
<component :is="bannerIcon" class="mr-2" />
<span :class="{ 'hidden sm:inline-flex': banner.alternateText }">
{{ banner.text(t) }}
</span>
<span v-if="banner.alternateText" class="inline-flex sm:hidden">
{{ banner.alternateText(t) }}
</span>
</div>
<icon-lucide-x
v-if="dismissible"
class="text-white hover:cursor-pointer hover:text-gray-300"
class="opacity-50 hover:cursor-pointer hover:opacity-100"
@click="emit('dismiss')"
/>
</div>
@@ -57,9 +53,9 @@ const ariaRoles: Record<BannerType, string> = {
}
const bgColors: Record<BannerType, string> = {
info: "bg-info",
warning: "bg-warning",
error: "bg-error",
info: "bg-bannerInfo",
warning: "bg-bannerWarning",
error: "bg-bannerError",
}
const icons = {

View File

@@ -2,25 +2,27 @@
<div>
<header
ref="headerRef"
class="flex flex-1 flex-shrink-0 items-center justify-between space-x-2 overflow-x-auto overflow-y-hidden px-2 py-2"
class="grid grid-cols-5 grid-rows-1 gap-2 overflow-x-auto overflow-y-hidden p-2"
@mousedown.prevent="platform.ui?.appHeader?.onHeaderAreaClick?.()"
>
<div
class="inline-flex flex-1 items-center justify-start space-x-2"
class="col-span-2 flex items-center justify-between space-x-2"
:style="{
paddingTop: platform.ui?.appHeader?.paddingTop?.value,
paddingLeft: platform.ui?.appHeader?.paddingLeft?.value,
}"
>
<HoppButtonSecondary
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
:label="t('app.name')"
to="/"
/>
<div class="flex">
<HoppButtonSecondary
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
:label="t('app.name')"
to="/"
/>
</div>
</div>
<div class="inline-flex flex-1 items-center justify-center space-x-2">
<div class="col-span-1 flex items-center justify-between space-x-2">
<button
class="flex max-w-[15rem] flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 py-1 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
class="flex h-full flex-1 cursor-text items-center justify-between self-stretch rounded border border-dividerDark bg-primaryDark px-2 text-secondaryLight transition hover:border-dividerDark hover:bg-primaryLight hover:text-secondary focus-visible:border-dividerDark focus-visible:bg-primaryLight focus-visible:text-secondary"
@click="invokeAction('modals.search.toggle')"
>
<span class="inline-flex flex-1 items-center">
@@ -32,169 +34,180 @@
<kbd class="shortcut-key">K</kbd>
</span>
</button>
<HoppButtonSecondary
v-if="showInstallButton"
v-tippy="{ theme: 'tooltip' }"
:title="t('header.install_pwa')"
:icon="IconDownload"
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
@click="installPWA()"
/>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${
mdAndLarger ? t('support.title') : t('app.options')
} <kbd>?</kbd>`"
:icon="IconLifeBuoy"
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
@click="invokeAction('modals.support.toggle')"
/>
</div>
<div class="inline-flex flex-1 items-center justify-end space-x-2">
<div
v-if="currentUser === null"
class="inline-flex items-center space-x-2"
>
<div class="col-span-2 flex items-center justify-between space-x-2">
<div class="flex">
<HoppButtonSecondary
:icon="IconUploadCloud"
:label="t('header.save_workspace')"
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 hidden border border-green-600/25 bg-green-500/[.15] !text-green-500 hover:border-green-800/50 hover:bg-green-400/10 focus-visible:border-green-800/50 focus-visible:bg-green-400/10 md:flex"
@click="invokeAction('modals.login.toggle')"
v-if="showInstallButton"
v-tippy="{ theme: 'tooltip' }"
:title="t('header.install_pwa')"
:icon="IconDownload"
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
@click="installPWA()"
/>
<HoppButtonPrimary
:label="t('header.login')"
@click="invokeAction('modals.login.toggle')"
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip', allowHTML: true }"
:title="`${
mdAndLarger ? t('support.title') : t('app.options')
} <kbd>?</kbd>`"
:icon="IconLifeBuoy"
class="rounded hover:bg-primaryDark focus-visible:bg-primaryDark"
@click="invokeAction('modals.support.toggle')"
/>
</div>
<div v-else class="inline-flex items-center space-x-2">
<TeamsMemberStack
v-if="
workspace.type === 'team' &&
selectedTeam &&
selectedTeam.teamMembers.length > 1
"
:team-members="selectedTeam.teamMembers"
show-count
class="mx-2"
@handle-click="handleTeamEdit()"
/>
<div class="flex">
<div
class="flex divide-x divide-green-600/25 rounded border border-green-600/25 bg-green-500/[.15] focus-within:divide-green-800/50 focus-within:border-green-800/50 focus-within:bg-green-400/10 hover:divide-green-800/50 hover:border-green-800/50 hover:bg-green-400/10"
v-if="currentUser === null"
class="inline-flex items-center space-x-2"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="t('team.invite_tooltip')"
:icon="IconUserPlus"
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
@click="handleInvite()"
:icon="IconUploadCloud"
:label="t('header.save_workspace')"
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 hidden h-8 border border-emerald-600/25 bg-emerald-500/10 !text-emerald-500 hover:border-emerald-600/20 hover:bg-emerald-600/20 focus-visible:border-emerald-600/20 focus-visible:bg-emerald-600/20 md:flex"
@click="invokeAction('modals.login.toggle')"
/>
<HoppButtonSecondary
<HoppButtonPrimary
:label="t('header.login')"
class="h-8"
@click="invokeAction('modals.login.toggle')"
/>
</div>
<div v-else class="inline-flex items-center space-x-2">
<TeamsMemberStack
v-if="
workspace.type === 'team' &&
selectedTeam &&
selectedTeam?.myRole === 'OWNER'
selectedTeam.teamMembers.length > 1
"
v-tippy="{ theme: 'tooltip' }"
:title="t('team.edit')"
:icon="IconSettings"
class="py-1.75 !focus-visible:text-green-600 !hover:text-green-600 !text-green-500"
@click="handleTeamEdit()"
:team-members="selectedTeam.teamMembers"
show-count
class="mx-2"
@handle-click="handleTeamEdit()"
/>
</div>
<tippy
interactive
trigger="click"
theme="popover"
:on-shown="() => accountActions.focus()"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="t('workspace.change')"
:label="mdAndLarger ? workspaceName : ``"
:icon="workspace.type === 'personal' ? IconUser : IconUsers"
class="select-wrapper !focus-visible:text-blue-600 !hover:text-blue-600 rounded border border-blue-600/25 bg-blue-500/[.15] py-[0.4375rem] pr-8 !text-blue-500 hover:border-blue-800/50 hover:bg-blue-400/10 focus-visible:border-blue-800/50 focus-visible:bg-blue-400/10"
/>
<template #content="{ hide }">
<div
ref="accountActions"
class="flex flex-col focus:outline-none"
tabindex="0"
@keyup.escape="hide()"
@click="hide()"
>
<WorkspaceSelector />
</div>
</template>
</tippy>
<span class="px-2">
<div
class="flex h-8 divide-x divide-emerald-600/25 rounded border border-emerald-600/25 bg-emerald-500/10 focus-within:divide-emerald-600/20 focus-within:border-emerald-600/20 focus-within:bg-emerald-600/20 hover:divide-emerald-600/20 hover:border-emerald-600/20 hover:bg-emerald-600/20"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="t('team.invite_tooltip')"
:icon="IconUserPlus"
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
@click="handleInvite()"
/>
<HoppButtonSecondary
v-if="
workspace.type === 'team' &&
selectedTeam &&
selectedTeam?.myRole === 'OWNER'
"
v-tippy="{ theme: 'tooltip' }"
:title="t('team.edit')"
:icon="IconSettings"
class="!focus-visible:text-emerald-600 !hover:text-emerald-600 !text-emerald-500"
@click="handleTeamEdit()"
/>
</div>
<tippy
interactive
trigger="click"
theme="popover"
:on-shown="() => tippyActions.focus()"
:on-shown="() => accountActions.focus()"
>
<HoppSmartPicture
v-tippy="{
theme: 'tooltip',
}"
:name="currentUser.uid"
:title="
currentUser.displayName ||
currentUser.email ||
t('profile.default_hopp_displayname')
"
indicator
:indicator-styles="
network.isOnline ? 'bg-green-500' : 'bg-red-500'
"
/>
<HoppSmartSelectWrapper
class="!text-blue-500 !focus-visible:text-blue-600 !hover:text-blue-600"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="t('workspace.change')"
:label="mdAndLarger ? workspaceName : ``"
:icon="workspace.type === 'personal' ? IconUser : IconUsers"
class="!focus-visible:text-blue-600 !hover:text-blue-600 h-8 rounded border border-blue-600/25 bg-blue-500/10 pr-8 !text-blue-500 hover:border-blue-600/20 hover:bg-blue-600/20 focus-visible:border-blue-600/20 focus-visible:bg-blue-600/20"
/>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"
ref="accountActions"
class="flex flex-col focus:outline-none"
tabindex="0"
@keyup.p="profile.$el.click()"
@keyup.s="settings.$el.click()"
@keyup.l="logout.$el.click()"
@keyup.escape="hide()"
@click="hide()"
>
<div class="flex flex-col px-2 text-tiny">
<span class="inline-flex truncate font-semibold">
{{
currentUser.displayName ||
t("profile.default_hopp_displayname")
}}
</span>
<span class="inline-flex truncate text-secondaryLight">
{{ currentUser.email }}
</span>
</div>
<hr />
<HoppSmartItem
ref="profile"
to="/profile"
:icon="IconUser"
:label="t('navigation.profile')"
:shortcut="['P']"
@click="hide()"
/>
<HoppSmartItem
ref="settings"
to="/settings"
:icon="IconSettings"
:label="t('navigation.settings')"
:shortcut="['S']"
@click="hide()"
/>
<FirebaseLogout
ref="logout"
:shortcut="['L']"
@confirm-logout="hide()"
/>
<WorkspaceSelector />
</div>
</template>
</tippy>
</span>
<span class="px-2">
<tippy
interactive
trigger="click"
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<HoppSmartPicture
v-tippy="{
theme: 'tooltip',
}"
:name="currentUser.uid"
:title="
currentUser.displayName ||
currentUser.email ||
t('profile.default_hopp_displayname')
"
indicator
:indicator-styles="
network.isOnline ? 'bg-green-500' : 'bg-red-500'
"
/>
<template #content="{ hide }">
<div
ref="tippyActions"
class="flex flex-col focus:outline-none"
tabindex="0"
@keyup.p="profile.$el.click()"
@keyup.s="settings.$el.click()"
@keyup.l="logout.$el.click()"
@keyup.escape="hide()"
>
<div class="flex flex-col px-2">
<span class="inline-flex truncate font-semibold">
{{
currentUser.displayName ||
t("profile.default_hopp_displayname")
}}
</span>
<span
class="inline-flex truncate text-secondaryLight text-tiny"
>
{{ currentUser.email }}
</span>
</div>
<hr />
<HoppSmartItem
ref="profile"
to="/profile"
:icon="IconUser"
:label="t('navigation.profile')"
:shortcut="['P']"
@click="hide()"
/>
<HoppSmartItem
ref="settings"
to="/settings"
:icon="IconSettings"
:label="t('navigation.settings')"
:shortcut="['S']"
@click="hide()"
/>
<FirebaseLogout
ref="logout"
:shortcut="['L']"
@confirm-logout="hide()"
/>
</div>
</template>
</tippy>
</span>
</div>
</div>
</div>
</header>
@@ -219,7 +232,6 @@
@invite-team="inviteTeam(editingTeamName, editingTeamID)"
@refetch-teams="refetchTeams"
/>
<HoppSmartConfirmModal
:show="confirmRemove"
:title="t('confirm.remove_team')"
@@ -279,7 +291,7 @@ const bannerContent = computed(() => banner.content.value?.content)
let bannerID: number | null = null
const offlineBanner: BannerContent = {
type: "info",
type: "warning",
text: (t) => t("helpers.offline"),
alternateText: (t) => t("helpers.offline_short"),
score: BANNER_PRIORITY_HIGH,

View File

@@ -9,8 +9,8 @@
>
<component
:is="entry.icon"
class="svg-icons opacity-50"
:class="{ 'opacity-100': active }"
class="svg-icons opacity-80"
:class="{ 'opacity-25': active }"
/>
<template
v-if="entry.text.type === 'text' && typeof entry.text.text === 'string'"
@@ -82,9 +82,9 @@ const props = defineProps<{
const formattedShortcutKeys = computed(
() =>
props.entry.meta?.keyboardShortcut?.map((key) => {
return SPECIAL_KEY_CHARS[key] ?? capitalize(key)
})
props.entry.meta?.keyboardShortcut?.map(
(key) => SPECIAL_KEY_CHARS[key] ?? capitalize(key)
)
)
const emit = defineEmits<{

View File

@@ -16,7 +16,7 @@
autocomplete="off"
name="command"
:placeholder="`${t('app.type_a_command_search')}`"
class="flex flex-1 bg-transparent px-6 py-5 text-base text-secondaryDark"
class="flex flex-1 bg-transparent px-6 pt-5 pb-3 text-base text-secondaryDark"
/>
<HoppSmartSpinner v-if="searchSession?.loading" class="mr-6" />
</div>

View File

@@ -14,14 +14,14 @@
></div>
<div class="relative flex flex-col">
<div
class="z-1 pointer-events-none absolute inset-0 bg-accent opacity-0 transition"
class="z-[1] pointer-events-none absolute inset-0 bg-accent opacity-0 transition"
:class="{
'opacity-25':
dragging && notSameDestination && notSameParentDestination,
}"
></div>
<div
class="z-3 group pointer-events-auto relative flex cursor-pointer items-stretch"
class="z-[3] group pointer-events-auto relative flex cursor-pointer items-stretch"
:draggable="!hasNoTeamAccess"
@dragstart="dragStart"
@drop="handelDrop($event)"

View File

@@ -78,7 +78,7 @@
v-else-if="step.name === 'TARGET_MY_COLLECTION'"
class="flex flex-col"
>
<div class="select-wrapper">
<HoppSmartSelectWrapper>
<select
v-model="mySelectedCollectionID"
autocomplete="off"
@@ -97,7 +97,7 @@
{{ collection.name }}
</option>
</select>
</div>
</HoppSmartSelectWrapper>
</div>
</div>
</div>

View File

@@ -28,8 +28,7 @@
>
<span
class="pointer-events-none flex w-16 items-center justify-center truncate px-2"
:class="requestLabelColor"
:style="{ color: requestLabelColor }"
:style="{ color: getMethodLabelColorClassOf(request) }"
>
<component
:is="IconCheckCircle"
@@ -277,10 +276,6 @@ const currentReorderingStatus = useReadonlyStream(currentReorderingStatus$, {
parentID: "",
})
const requestLabelColor = computed(() =>
getMethodLabelColorClassOf(props.request)
)
watch(
() => props.duplicateLoading,
(val) => {

View File

@@ -15,12 +15,12 @@
class="!rounded-none"
:icon="IconPlus"
:title="t('team.no_access')"
:label="t('add.new')"
:label="t('action.new')"
/>
<HoppButtonSecondary
v-else
:icon="IconPlus"
:label="t('add.new')"
:label="t('action.new')"
class="!rounded-none"
@click="emit('display-modal-add')"
/>

View File

@@ -11,7 +11,7 @@
@dragend="draggingToRoot = false"
>
<div
class="sticky z-10 flex flex-shrink-0 flex-col overflow-x-auto border-b border-dividerLight bg-primary"
class="sticky z-10 flex flex-shrink-0 flex-col overflow-x-auto bg-primary border-b border-dividerLight"
:class="{ 'rounded-t': saveRequest }"
:style="
saveRequest ? 'top: calc(-1 * var(--line-height-body))' : 'top: 0'
@@ -22,7 +22,7 @@
v-model="filterTexts"
type="search"
autocomplete="off"
class="flex h-8 w-full bg-transparent p-4 py-2"
class="flex w-full bg-transparent px-4 py-2"
:placeholder="t('action.search')"
:disabled="collectionsType.type === 'team-collections'"
/>

View File

@@ -7,7 +7,7 @@
<template #body>
<div class="flex flex-1 flex-col space-y-4">
<div class="ml-2 flex items-center space-x-8">
<label for="name" class="min-w-10 font-semibold">{{
<label for="name" class="min-w-[2.5rem] font-semibold">{{
t("environment.name")
}}</label>
<input
@@ -18,7 +18,7 @@
/>
</div>
<div class="ml-2 flex items-center space-x-8">
<label for="value" class="min-w-10 font-semibold">{{
<label for="value" class="min-w-[2.5rem] font-semibold">{{
t("environment.value")
}}</label>
<input
@@ -29,7 +29,7 @@
/>
</div>
<div class="ml-2 flex items-center space-x-8">
<label for="scope" class="min-w-10 font-semibold">
<label for="scope" class="min-w-[2.5rem] font-semibold">
{{ t("environment.scope") }}
</label>
<div
@@ -39,7 +39,7 @@
</div>
</div>
<div v-if="replaceWithVariable" class="mt-3 flex space-x-2">
<div class="min-w-18" />
<div class="min-w-[4rem]" />
<HoppSmartCheckbox
:on="replaceWithVariable"
:title="t('environment.replace_with_variable')"

View File

@@ -6,10 +6,9 @@
theme="popover"
:on-shown="() => envSelectorActions!.focus()"
>
<span
<HoppSmartSelectWrapper
v-tippy="{ theme: 'tooltip' }"
:title="`${t('environment.select')}`"
class="select-wrapper"
>
<HoppButtonSecondary
:icon="IconLayers"
@@ -22,7 +21,7 @@
"
class="flex-1 !justify-start rounded-none pr-8"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="envSelectorActions"
@@ -207,10 +206,14 @@
</div>
<div class="my-2 flex flex-1 flex-col space-y-2 pl-4 pr-2">
<div class="flex flex-1 space-x-4">
<span class="min-w-32 w-1/4 truncate text-tiny font-semibold">
<span
class="min-w-[9rem] w-1/4 truncate text-tiny font-semibold"
>
{{ t("environment.name") }}
</span>
<span class="min-w-32 w-full truncate text-tiny font-semibold">
<span
class="min-w-[9rem] w-full truncate text-tiny font-semibold"
>
{{ t("environment.value") }}
</span>
</div>
@@ -219,10 +222,10 @@
:key="index"
class="flex flex-1 space-x-4"
>
<span class="min-w-32 w-1/4 truncate text-secondaryLight">
<span class="min-w-[9rem] w-1/4 truncate text-secondaryLight">
{{ variable.key }}
</span>
<span class="min-w-32 w-full truncate text-secondaryLight">
<span class="min-w-[9rem] w-full truncate text-secondaryLight">
{{ variable.value }}
</span>
</div>
@@ -258,10 +261,14 @@
</div>
<div v-else class="my-2 flex flex-1 flex-col space-y-2 pl-4 pr-2">
<div class="flex flex-1 space-x-4">
<span class="min-w-32 w-1/4 truncate text-tiny font-semibold">
<span
class="min-w-[9rem] w-1/4 truncate text-tiny font-semibold"
>
{{ t("environment.name") }}
</span>
<span class="min-w-32 w-full truncate text-tiny font-semibold">
<span
class="min-w-[9rem] w-full truncate text-tiny font-semibold"
>
{{ t("environment.value") }}
</span>
</div>
@@ -270,10 +277,10 @@
:key="index"
class="flex flex-1 space-x-4"
>
<span class="min-w-32 w-1/4 truncate text-secondaryLight">
<span class="min-w-[9rem] w-1/4 truncate text-secondaryLight">
{{ variable.key }}
</span>
<span class="min-w-32 w-full truncate text-secondaryLight">
<span class="min-w-[9rem] w-full truncate text-secondaryLight">
{{ variable.value }}
</span>
</div>

View File

@@ -13,12 +13,12 @@
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
class="ml-2 rounded-none pr-8"
:label="authName"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"
@@ -171,7 +171,7 @@
</div>
</div>
<div
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
>
<div class="pb-2 text-secondaryLight">
{{ t("helpers.authorization") }}

View File

@@ -30,7 +30,7 @@
v-model="graphqlFieldsFilterText"
type="search"
autocomplete="off"
class="flex h-8 w-full bg-transparent p-4 py-2"
class="flex w-full bg-transparent px-4 py-2"
:placeholder="`${t('action.search')}`"
/>
<div class="flex">

View File

@@ -14,7 +14,7 @@
theme="popover"
:on-shown="() => tippyActions!.focus()"
>
<span class="truncate px-2 leading-8">
<span class="truncate">
{{ tab.document.request.name }}
</span>
<template #content="{ hide }">

View File

@@ -9,7 +9,7 @@
v-model="filterText"
type="search"
autocomplete="off"
class="flex h-8 w-full bg-transparent p-4 py-2"
class="flex w-full bg-transparent px-4 py-2"
:placeholder="`${t('action.search')}`"
/>
<div class="flex">

View File

@@ -13,12 +13,12 @@
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
class="ml-2 rounded-none pr-8"
:label="authName"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"
@@ -149,7 +149,7 @@
</div>
</div>
<div
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
>
<div class="pb-2 text-secondaryLight">
{{ t("helpers.authorization") }}

View File

@@ -13,12 +13,12 @@
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
:label="body.contentType || t('state.none')"
class="ml-2 rounded-none pr-8"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"

View File

@@ -17,7 +17,7 @@
placement="bottom"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
:label="
CodegenDefinitions.find((x) => x.name === codegenType)!.caption
@@ -25,7 +25,7 @@
outline
class="flex-1 pr-8"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div class="flex flex-col space-y-2">
<div class="sticky top-0 z-10 flex-shrink-0 overflow-x-auto">

View File

@@ -34,7 +34,7 @@
<div ref="preRequestEditor" class="h-full"></div>
</div>
<div
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
>
<div class="pb-2 text-secondaryLight">
{{ t("helpers.pre_request_script") }}

View File

@@ -3,7 +3,7 @@
class="sticky top-0 z-20 flex-none flex-shrink-0 bg-primary p-4 sm:flex sm:flex-shrink-0 sm:space-x-2"
>
<div
class="min-w-52 flex flex-1 whitespace-nowrap rounded border border-divider"
class="min-w-[12rem] flex flex-1 whitespace-nowrap rounded border border-divider"
>
<div class="relative flex">
<label for="method">
@@ -13,7 +13,7 @@
theme="popover"
:on-shown="() => methodTippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<input
id="method"
class="flex w-26 cursor-pointer rounded-l bg-primaryLight px-4 py-2 font-semibold text-secondaryDark transition"
@@ -22,7 +22,7 @@
:placeholder="`${t('request.method')}`"
@input="onSelectMethod($event)"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="methodTippyActions"
@@ -34,6 +34,9 @@
v-for="(method, index) in methods"
:key="`method-${index}`"
:label="method"
:style="{
color: getMethodLabelColor(method),
}"
@click="
() => {
updateMethod(method)
@@ -67,7 +70,7 @@
'action.send'
)} <kbd>${getSpecialKey()}</kbd><kbd>↩</kbd>`"
:label="`${!loading ? t('action.send') : t('action.cancel')}`"
class="min-w-20 flex-1 rounded-r-none"
class="min-w-[5rem] flex-1 rounded-r-none"
@click="!loading ? newSendRequest() : cancelRequest()"
/>
<span class="flex">
@@ -259,6 +262,7 @@ import { InterceptorService } from "~/services/interceptor.service"
import { HoppTab } from "~/services/tab"
import { HoppRESTDocument } from "~/helpers/rest/document"
import { RESTTabService } from "~/services/tab/rest"
import { getMethodLabelColor } from "~/helpers/rest/labelColoring"
const t = useI18n()
const interceptorService = useService(InterceptorService)
@@ -270,8 +274,8 @@ const methods = [
"PATCH",
"DELETE",
"HEAD",
"CONNECT",
"OPTIONS",
"CONNECT",
"TRACE",
"CUSTOM",
]

View File

@@ -8,12 +8,11 @@
@click.middle="emit('close-tab')"
>
<span
class="text-tiny font-semibold"
class="text-tiny font-semibold mr-2"
:style="{ color: getMethodLabelColorClassOf(tab.document.request) }"
>
{{ tab.document.request.method }}
</span>
<tippy
ref="options"
trigger="manual"
@@ -21,7 +20,7 @@
theme="popover"
:on-shown="() => tippyActions!.focus()"
>
<span class="truncate px-2 leading-8">
<span class="truncate">
{{ tab.document.request.name }}
</span>
<template #content="{ hide }">

View File

@@ -34,7 +34,7 @@
<div ref="testScriptEditor" class="h-full"></div>
</div>
<div
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
>
<div class="pb-2 text-secondaryLight">
{{ t("helpers.post_request_tests") }}

View File

@@ -16,12 +16,12 @@
theme="popover"
:on-shown="() => authTippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
:label="auth.addTo || t('state.none')"
class="ml-2 rounded-none pr-8"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="authTippyActions"

View File

@@ -33,12 +33,12 @@
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
:label="contentType || t('state.none').toLowerCase()"
class="ml-2 rounded-none pr-8"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"
@@ -279,6 +279,7 @@ defineActionHandler("request.send-cancel", sendMessage)
:deep(.cm-panels) {
@apply top-upperSecondaryStickyFold #{!important};
}
.eventFeildShown :deep(.cm-panels),
.cmResponsePrimaryStickyFold :deep(.cm-panels) {
@apply top-upperTertiaryStickyFold #{!important};

View File

@@ -62,12 +62,12 @@
{{ t("mqtt.lw_qos") }}
</label>
<tippy interactive trigger="click" theme="popover">
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
class="ml-2 rounded-none pr-8"
:label="`${config.lwQos}`"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div class="flex flex-col" role="menu">
<HoppSmartItem

View File

@@ -35,8 +35,8 @@
autoScrollEnabled ? t('action.turn_off') : t('action.turn_on')
}`"
:icon="IconChevronsDown"
:class="toggleAutoscrollColor"
@click="toggleAutoscroll()"
:color="autoScrollEnabled ? 'green' : 'red'"
@click="autoScrollEnabled = !autoScrollEnabled"
/>
</div>
</div>
@@ -60,7 +60,7 @@
</template>
<script setup lang="ts">
import { ref, PropType, computed, watch, Ref } from "vue"
import { ref, PropType, watch, Ref } from "vue"
import IconTrash from "~icons/lucide/trash"
import IconArrowUp from "~icons/lucide/arrow-up"
import IconArrowDown from "~icons/lucide/arrow-down"
@@ -123,12 +123,4 @@ watch(
}, 200),
{ flush: "post" }
)
const toggleAutoscroll = () => {
autoScrollEnabled.value = !autoScrollEnabled.value
}
const toggleAutoscrollColor = computed(() =>
autoScrollEnabled.value ? "text-green-500" : "text-red-500"
)
</script>

View File

@@ -12,7 +12,7 @@
</div>
<div
v-if="entry.ts !== undefined"
class="w-34 hidden items-center px-1 sm:inline-flex"
class="w-36 hidden items-center px-1 sm:inline-flex"
>
<span
v-tippy="{ theme: 'tooltip' }"

View File

@@ -9,9 +9,9 @@
{{ t("mqtt.qos") }}
</label>
<tippy interactive trigger="click" theme="popover">
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary class="pr-8" :label="`${QoS}`" />
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div class="flex flex-col" role="menu">
<HoppSmartItem

View File

@@ -6,7 +6,7 @@
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="t('settings.choose_language')"
@@ -15,7 +15,7 @@
outline
:label="currentLocale.name"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div class="flex flex-col space-y-2">
<HoppSmartInput

View File

@@ -19,7 +19,7 @@
class="svg-icons opacity-75"
:class="label ? (reverse ? 'ml-4' : 'mr-4') : ''"
/>
<div class="max-w-54 truncate">
<div class="max-w-[16rem] truncate">
{{ label }}
</div>
</HoppSmartLink>

View File

@@ -25,7 +25,7 @@
class="svg-icons"
:class="label ? 'mr-4 opacity-75' : ''"
/>
<div class="max-w-54 truncate">
<div class="max-w-[16rem] truncate">
{{ label }}
</div>
</HoppSmartLink>

View File

@@ -75,7 +75,7 @@
theme="popover"
:on-shown="() => tippyActions![index].focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<input
class="flex flex-1 cursor-pointer bg-transparent px-4 py-2"
:placeholder="`${t('team.permissions')}`"
@@ -83,7 +83,7 @@
:value="member.role"
readonly
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"

View File

@@ -169,7 +169,7 @@
theme="popover"
:on-shown="() => tippyActions![index].focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<input
class="flex flex-1 cursor-pointer bg-transparent px-4 py-2"
:placeholder="`${t('team.permissions')}`"
@@ -177,7 +177,7 @@
:value="invitee.value"
readonly
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"
@@ -272,7 +272,7 @@
<ul class="mt-4 space-y-4">
<li class="flex">
<span
class="max-w-16 w-1/4 truncate font-semibold uppercase text-secondaryDark"
class="max-w-[4rem] w-1/4 truncate font-semibold uppercase text-secondaryDark"
>
{{ t("profile.owner") }}
</span>
@@ -282,7 +282,7 @@
</li>
<li class="flex">
<span
class="max-w-16 w-1/4 truncate font-semibold uppercase text-secondaryDark"
class="max-w-[4rem] w-1/4 truncate font-semibold uppercase text-secondaryDark"
>
{{ t("profile.editor") }}
</span>
@@ -292,7 +292,7 @@
</li>
<li class="flex">
<span
class="max-w-16 w-1/4 truncate font-semibold uppercase text-secondaryDark"
class="max-w-[4rem] w-1/4 truncate font-semibold uppercase text-secondaryDark"
>
{{ t("profile.viewer") }}
</span>

View File

@@ -14,19 +14,19 @@ export default function (responseStatus) {
if (responseStatus >= 300 && responseStatus < 400)
return {
name: "redirection",
className: "redir-response",
className: "redirect-response",
}
if (responseStatus >= 400 && responseStatus < 500)
return {
name: "client error",
className: "cl-error-response",
className: "critical-error-response",
}
if (responseStatus >= 500 && responseStatus < 600)
return {
name: "server error",
className: "sv-error-response",
className: "server-error-response",
}
// this object is a catch-all for when no other objects match and should always be last

View File

@@ -4,11 +4,14 @@ import * as RR from "fp-ts/ReadonlyRecord"
import { HoppRESTRequest } from "@hoppscotch/data"
export const REQUEST_METHOD_LABEL_COLORS = {
get: "var(--success-color)",
post: "var(--warning-color)",
put: "var(--blue-color)",
delete: "var(--cl-error-color)",
default: "#6b7280",
get: "var(--method-get-color)",
post: "var(--method-post-color)",
put: "var(--method-put-color)",
patch: "var(--method-patch-color)",
delete: "var(--method-delete-color)",
head: "var(--method-head-color)",
options: "var(--method-options-color)",
default: "var(--method-default-color)",
} as const
/**
@@ -23,3 +26,11 @@ export function getMethodLabelColorClassOf(request: HoppRESTRequest) {
O.getOrElseW(() => REQUEST_METHOD_LABEL_COLORS.default)
)
}
export function getMethodLabelColor(method: string) {
return pipe(
REQUEST_METHOD_LABEL_COLORS,
RR.lookup(method.toLowerCase()),
O.getOrElseW(() => REQUEST_METHOD_LABEL_COLORS.default)
)
}

View File

@@ -98,7 +98,7 @@
filled
outline
:label="t('action.save')"
class="min-w-16 ml-2"
class="min-w-[4rem] ml-2"
type="submit"
:loading="updatingDisplayName"
@click="updateDisplayName"
@@ -121,7 +121,7 @@
filled
outline
:label="t('action.save')"
class="min-w-16 ml-2"
class="min-w-[4rem] ml-2"
type="submit"
:loading="updatingEmailAddress"
@click="updateEmailAddress"

View File

@@ -2,7 +2,7 @@
<HoppSmartTabs
v-model="currentTab"
styles="sticky overflow-x-auto flex-shrink-0 bg-primary top-0 z-10"
content-styles="h-[calc(100%-var(--sidebar-primary-sticky-fold)-1px)] !flex"
content-styles="!h-[calc(100%-var(--sidebar-primary-sticky-fold)-1px)] !flex"
>
<HoppSmartTab
v-for="{ target, title } in REALTIME_NAVIGATION"

View File

@@ -13,7 +13,7 @@
theme="popover"
:on-shown="() => tippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<input
id="client-version"
v-tippy="{ theme: 'tooltip' }"
@@ -26,7 +26,7 @@
connectionState === 'CONNECTING'
"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"
@@ -129,12 +129,12 @@
theme="popover"
:on-shown="() => authTippyActions.focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<HoppButtonSecondary
class="ml-2 rounded-none pr-8"
:label="authType"
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="authTippyActions"
@@ -216,7 +216,7 @@
</div>
</div>
<div
class="z-9 sticky top-upperTertiaryStickyFold h-full min-w-46 max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
class="z-[9] sticky top-upperTertiaryStickyFold h-full min-w-[12rem] max-w-1/3 flex-shrink-0 overflow-auto overflow-x-auto bg-primary p-4"
>
<div class="p-2">
<div class="pb-2 text-secondaryLight">

View File

@@ -7,4 +7,26 @@ export default {
"../hoppscotch-ui/src/**/*.{vue,html}",
],
presets: [preset],
theme: {
extend: {
inset: {
upperPrimaryStickyFold: "var(--upper-primary-sticky-fold)",
upperSecondaryStickyFold: "var(--upper-secondary-sticky-fold)",
upperTertiaryStickyFold: "var(--upper-tertiary-sticky-fold)",
upperFourthStickyFold: "var(--upper-fourth-sticky-fold)",
upperMobilePrimaryStickyFold: "var(--upper-mobile-primary-sticky-fold)",
upperMobileSecondaryStickyFold:
"var(--upper-mobile-secondary-sticky-fold)",
upperMobileStickyFold: "var(--upper-mobile-sticky-fold)",
upperMobileTertiaryStickyFold:
"var(--upper-mobile-tertiary-sticky-fold)",
lowerPrimaryStickyFold: "var(--lower-primary-sticky-fold)",
lowerSecondaryStickyFold: "var(--lower-secondary-sticky-fold)",
lowerTertiaryStickyFold: "var(--lower-tertiary-sticky-fold)",
lowerFourthStickyFold: "var(--lower-fourth-sticky-fold)",
sidebarPrimaryStickyFold: "var(--sidebar-primary-sticky-fold)",
sidebarSecondaryStickyFold: "var(--line-height-body)",
},
},
},
} satisfies Config

View File

@@ -1,4 +1,3 @@
module.exports = {
semi: false,
plugins: [require("prettier-plugin-tailwindcss")],
}
};

View File

@@ -5,18 +5,17 @@
@mixin base-theme {
--font-sans: 'Inter Variable', sans-serif;
--font-icon: 'Material Symbols Rounded Variable';
--font-mono: 'Roboto Mono Variable', monospace;
--font-size-body: 0.75rem;
--font-size-tiny: 0.688rem;
--font-size-tiny: 0.625rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-primary-sticky-fold: 4rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-fourth-sticky-fold: 10.2rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-primary-sticky-fold: 6.75rem;
--upper-mobile-secondary-sticky-fold: 8.813rem;
--upper-mobile-sticky-fold: 10.875rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
@@ -95,14 +94,6 @@
@apply antialiased;
accent-color: var(--accent-color);
font-variant-ligatures: common-ligatures;
// Colors
--info-color: #ec4899;
--success-color: #10b981;
--blue-color: #3b82f6;
--warning-color: #f59e0b;
--cl-error-color: #ef4444;
--sv-error-color: #dc2626;
}
::-webkit-scrollbar-track {
@@ -131,7 +122,7 @@ input::placeholder,
textarea::placeholder,
.cm-placeholder {
@apply text-secondary;
@apply opacity-50;
@apply opacity-50 #{!important};
}
input,
@@ -150,7 +141,7 @@ body {
@apply font-medium;
@apply select-none;
@apply overflow-x-hidden;
@apply leading-body;
@apply leading-body #{!important};
animation: fade 300ms forwards;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
@@ -248,7 +239,7 @@ a {
@apply font-semibold;
@apply px-2 py-1;
@apply truncate;
@apply leading-normal;
@apply leading-body;
@apply items-center;
kbd {
@@ -295,7 +286,7 @@ a {
@apply overflow-y-auto;
@apply text-body text-secondary;
@apply p-2;
@apply leading-normal;
@apply leading-body;
@apply focus:outline-none;
scroll-behavior: smooth;
@@ -327,7 +318,7 @@ a {
hr {
@apply border-b border-dividerLight;
@apply my-2;
@apply my-2 #{!important};
}
.heading {
@@ -416,44 +407,28 @@ pre.ace_editor {
}
}
.select-wrapper {
@apply flex flex-1;
@apply relative;
@apply after:absolute;
@apply after:flex;
@apply after:inset-y-0;
@apply after:items-center;
@apply after:justify-center;
@apply after:pointer-events-none;
@apply after:font-icon;
@apply after:text-current;
@apply after:right-3;
@apply after:content-["\e5cf"];
@apply after:text-lg;
}
.info-response {
color: var(--info-color);
color: var(--status-info-color);
}
.success-response {
color: var(--success-color);
color: var(--status-success-color);
}
.redir-response {
color: var(--warning-color);
.redirect-response {
color: var(--status-redirect-color);
}
.cl-error-response {
color: var(--cl-error-color);
.critical-error-response {
color: var(--status-critical-error-color);
}
.sv-error-response {
color: var(--sv-error-color);
.server-error-response {
color: var(--status-server-error-color);
}
.missing-data-response {
@apply text-secondaryLight;
color: var(--status-missing-data-color);
}
.toasted-container {
@@ -603,12 +578,12 @@ pre.ace_editor {
@apply inline-flex;
@apply font-sans;
@apply text-tiny;
@apply bg-divider;
@apply bg-dividerLight;
@apply rounded;
@apply ml-2;
@apply px-1;
@apply min-w-5;
@apply min-h-5;
@apply min-w-[1.25rem];
@apply min-h-[1.25rem];
@apply items-center;
@apply justify-center;
@apply border border-dividerDark;

View File

@@ -2,7 +2,7 @@
<div>
<button
@click="open = true"
class="inline-flex items-center bg-emerald-700 h-8 ml-3 pl-2.5 pr-2 rounded-md shadow border-gray-800 border border-gray-200 leading-none py-0 hover:bg-emerald-700 focus:outline-none focus:bg-emerald-800"
class="inline-flex items-center bg-emerald-700 h-8 ml-3 pl-2.5 pr-2 rounded-md shadow border-gray-800 border border-gray-200 py-0 hover:bg-emerald-700 focus:outline-none focus:bg-emerald-800"
>
Invite User
</button>

View File

@@ -41,7 +41,7 @@
theme="popover"
:on-shown="() => tippyActions![index].focus()"
>
<span class="select-wrapper">
<HoppSmartSelectWrapper>
<input
class="flex flex-1 px-4 py-2 bg-transparent cursor-pointer"
placeholder="Permissions"
@@ -49,7 +49,7 @@
:value="member.value"
readonly
/>
</span>
</HoppSmartSelectWrapper>
<template #content="{ hide }">
<div
ref="tippyActions"
@@ -140,7 +140,7 @@
<ul class="mt-4 space-y-4">
<li class="flex">
<span
class="w-1/4 font-semibold uppercase truncate text-secondaryDark max-w-16"
class="w-1/4 font-semibold uppercase truncate text-secondaryDark max-w-[4rem]"
>
Owner
</span>
@@ -151,7 +151,7 @@
</li>
<li class="flex">
<span
class="w-1/4 font-semibold uppercase truncate text-secondaryDark max-w-16"
class="w-1/4 font-semibold uppercase truncate text-secondaryDark max-w-[4rem]"
>
Editor
</span>
@@ -161,7 +161,7 @@
</li>
<li class="flex">
<span
class="w-1/4 font-semibold uppercase truncate text-secondaryDark max-w-16"
class="w-1/4 font-semibold uppercase truncate text-secondaryDark max-w-[4rem]"
>
Viewer
</span>

View File

@@ -37,13 +37,13 @@
class="text-secondaryDark hover:bg-divider hover:cursor-pointer rounded-xl"
@click="goToTeamDetails(team.id)"
>
<td class="flex py-4 px-7 max-w-50">
<td class="flex py-4 px-7 max-w-[16rem]">
<span class="truncate">
{{ team.id }}
</span>
</td>
<td class="py-4 px-7 min-w-80">
<td class="py-4 px-7 min-w-[20rem]">
<span
class="flex items-center truncate"
:class="{ truncate: team.name }"

View File

@@ -49,7 +49,7 @@
class="text-secondaryDark hover:bg-divider hover:cursor-pointer rounded-xl"
@click="goToUserDetails(user.uid)"
>
<td class="py-2 px-7 max-w-30 truncate">
<td class="py-2 px-7 max-w-[8rem] truncate">
{{ user.uid }}
</td>

View File

@@ -1,4 +1,3 @@
module.exports = {
semi: false,
plugins: ["prettier-plugin-tailwindcss"],
}

View File

@@ -5,18 +5,17 @@
@mixin base-theme {
--font-sans: "Inter Variable", sans-serif;
--font-icon: "Material Symbols Rounded Variable";
--font-mono: "Roboto Mono Variable", monospace;
--font-size-body: 0.75rem;
--font-size-tiny: 0.688rem;
--font-size-tiny: 0.625rem;
--line-height-body: 1rem;
--upper-primary-sticky-fold: 4.125rem;
--upper-primary-sticky-fold: 4rem;
--upper-secondary-sticky-fold: 6.188rem;
--upper-tertiary-sticky-fold: 8.25rem;
--upper-fourth-sticky-fold: 10.2rem;
--upper-mobile-primary-sticky-fold: 6.625rem;
--upper-mobile-secondary-sticky-fold: 8.688rem;
--upper-mobile-sticky-fold: 10.75rem;
--upper-mobile-primary-sticky-fold: 6.75rem;
--upper-mobile-secondary-sticky-fold: 8.813rem;
--upper-mobile-sticky-fold: 10.875rem;
--upper-mobile-tertiary-sticky-fold: 8.25rem;
--lower-primary-sticky-fold: 3rem;
--lower-secondary-sticky-fold: 5.063rem;
@@ -78,23 +77,13 @@
}
:root {
@include base-theme;
@include dark-theme;
@include green-theme;
@include base-theme;
@include dark-theme;
@include green-theme;
@apply antialiased;
accent-color: var(--accent-color);
font-variant-ligatures: common-ligatures;
// Colors
--info-color: #ec4899;
--success-color: #10b981;
--blue-color: #3b82f6;
--warning-color: #f59e0b;
--cl-error-color: #ef4444;
--sv-error-color: #dc2626;
}
::-webkit-scrollbar-track {
@@ -123,7 +112,7 @@ input::placeholder,
textarea::placeholder,
.cm-placeholder {
@apply text-secondary;
@apply opacity-50;
@apply opacity-50 #{!important};
}
input,
@@ -142,7 +131,7 @@ body {
@apply font-medium;
@apply select-none;
@apply overflow-x-hidden;
@apply leading-body;
@apply leading-body #{!important};
animation: fade 300ms forwards;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
@@ -240,7 +229,7 @@ a {
@apply font-semibold;
@apply px-2 py-1;
@apply truncate;
@apply leading-normal;
@apply leading-body;
@apply items-center;
kbd {
@@ -287,7 +276,7 @@ a {
@apply overflow-y-auto;
@apply text-body text-secondary;
@apply p-2;
@apply leading-normal;
@apply leading-body;
@apply focus:outline-none;
scroll-behavior: smooth;
@@ -319,7 +308,7 @@ a {
hr {
@apply border-b border-dividerLight;
@apply my-2;
@apply my-2 #{!important};
}
.heading {
@@ -408,44 +397,28 @@ pre.ace_editor {
}
}
.select-wrapper {
@apply flex flex-1;
@apply relative;
@apply after:absolute;
@apply after:flex;
@apply after:inset-y-0;
@apply after:items-center;
@apply after:justify-center;
@apply after:pointer-events-none;
@apply after:font-icon;
@apply after:text-current;
@apply after:right-3;
@apply after:content-["\e5cf"];
@apply after:text-lg;
}
.info-response {
color: var(--info-color);
color: var(--status-info-color);
}
.success-response {
color: var(--success-color);
color: var(--status-success-color);
}
.redir-response {
color: var(--warning-color);
.redirect-response {
color: var(--status-redirect-color);
}
.cl-error-response {
color: var(--cl-error-color);
.critical-error-response {
color: var(--status-critical-error-color);
}
.sv-error-response {
color: var(--sv-error-color);
.server-error-response {
color: var(--status-server-error-color);
}
.missing-data-response {
@apply text-secondaryLight;
color: var(--status-missing-data-color);
}
.toasted-container {
@@ -595,12 +568,12 @@ pre.ace_editor {
@apply inline-flex;
@apply font-sans;
@apply text-tiny;
@apply bg-divider;
@apply bg-dividerLight;
@apply rounded;
@apply ml-2;
@apply px-1;
@apply min-w-5;
@apply min-h-5;
@apply min-w-[1.25rem];
@apply min-h-[1.25rem];
@apply items-center;
@apply justify-center;
@apply border border-dividerDark;

View File

@@ -40,7 +40,7 @@
label ? (reverse ? 'ml-2' : 'mr-2') : '',
]"
/>
<div class="max-w-54 truncate">
<div class="max-w-[16rem] truncate">
{{ label }}
</div>
<div v-if="shortcut.length" class="<sm:hidden">

View File

@@ -41,7 +41,7 @@
label ? (reverse ? 'ml-2' : 'mr-2') : '',
]"
/>
<div class="truncate max-w-54">
<div class="truncate max-w-[16rem]">
{{ label }}
</div>
<div v-if="shortcut.length" class="<sm:hidden">

View File

@@ -6,51 +6,62 @@
@click="emit('change')"
>
<input
id="checkbox"
:id="checkboxID"
type="checkbox"
name="checkbox"
:name="name"
class="checkbox"
:checked="on"
@change="emit('change')"
/>
<label
for="checkbox"
:for="checkboxID"
class="pl-0 font-semibold truncate align-middle cursor-pointer"
:class="{
'before:mr-2': labelSlot.default
}"
>
<slot></slot>
</label>
</div>
</template>
<script setup lang="ts">
import { useSlots } from 'vue';
<script lang="ts">
/*
This checkboxIDCounter is tracked in the global scope in order to ensure that each checkbox has a unique ID.
When we use this component multiple times on the same page, we need to ensure that each checkbox has a unique ID.
This is because the label's for attribute needs to match the checkbox's id attribute.
That's why we use a global counter that increments each time we use this component.
*/
let checkboxIDCounter = 564275
</script>
<script setup lang="ts">
// Unique ID for checkbox
const checkboxID = `checkbox-${checkboxIDCounter++}`
defineProps({
on: {
type: Boolean,
default: false,
},
name: {
type: String,
default: "checkbox",
},
})
const emit = defineEmits<{
(e: "change"): void
}>()
// used to check if the default slot is used and add a margin to the label if exists
const labelSlot = useSlots()
</script>
<style lang="scss" scoped>
.checkbox[type="checkbox"] {
@apply relative;
@apply appearance-none;
@apply hidden;
& + label {
@apply inline-flex items-center justify-center;
@apply cursor-pointer;
@apply relative;
&::before {
@apply border-2 border-divider;
@@ -62,9 +73,22 @@ const labelSlot = useSlots()
@apply text-transparent;
@apply h-4;
@apply w-4;
@apply font-icon;
@apply mr-2;
@apply transition;
@apply content-["\e5ca"];
content: "";
}
&::after {
content: "";
border: solid;
border-width: 0 1.9px 1.9px 0;
height: 0.6rem;
width: 0.3rem;
left: 0.35rem;
position: absolute;
top: 2px;
transform: rotate(45deg);
opacity: 0;
}
}
@@ -73,5 +97,10 @@ const labelSlot = useSlots()
@apply border-accent;
@apply text-accentContrast;
}
&:checked + label::after {
@apply text-accentContrast;
opacity: 1;
}
}
</style>

View File

@@ -1,12 +1,23 @@
<template>
<div class="relative flex flex-col space-y-2 overflow-hidden" :class="expand ? 'h-full' : 'max-h-32'">
<div
class="relative flex flex-col space-y-2 overflow-hidden"
:class="expand ? 'h-full' : 'max-h-32'"
>
<slot name="body"></slot>
<div class="sticky inset-x-0 bottom-0 flex items-center justify-center flex-shrink-0 overflow-x-auto">
<HoppButtonSecondary :icon="expand ? IconChevronUp : IconChevronDown" :label="
expand
? less ?? t?.('action.less') ?? 'Less'
: more ?? t?.('action.more') ?? 'More'
" filled rounded @click="expand = !expand" />
<div
class="sticky inset-x-0 bottom-0 flex items-center justify-center flex-shrink-0 overflow-x-auto"
>
<HoppButtonSecondary
:icon="expand ? IconChevronUp : IconChevronDown"
:label="
expand
? less ?? t?.('action.less') ?? 'Less'
: more ?? t?.('action.more') ?? 'More'
"
filled
rounded
@click="expand = !expand"
/>
</div>
</div>
</template>

View File

@@ -3,7 +3,7 @@
class="inline-flex items-center space-x-1 justify-center rounded px-2 bg-primaryDark"
>
<IconLucideFile class="opacity-75 svg-icons" />
<span class="truncate max-w-54"><slot></slot></span>
<span class="truncate max-w-[16rem]"><slot></slot></span>
</span>
</template>

View File

@@ -1,5 +1,8 @@
<template>
<HoppSmartLink :to="to" :exact="exact" :blank="blank"
<HoppSmartLink
:to="to"
:exact="exact"
:blank="blank"
class="inline-flex items-center flex-shrink-0 px-4 py-2 rounded transition hover:bg-primaryDark hover:text-secondaryDark focus:outline-none focus-visible:bg-primaryDark focus-visible:text-secondaryDark"
:class="[
{ 'opacity-75 cursor-not-allowed': disabled },
@@ -10,16 +13,32 @@
'border border-divider hover:border-dividerDark focus-visible:border-dividerDark':
outline,
},
]" :disabled="disabled" :tabindex="loading ? '-1' : '0'" role="menuitem">
<span v-if="!loading" class="inline-flex items-center" :class="{ 'self-start': !!infoIcon }">
<component :is="icon" v-if="icon" class="opacity-75 svg-icons" :class="[
label ? (reverse ? 'ml-4' : 'mr-4') : '',
{ 'text-accent': active },
]" />
]"
:disabled="disabled"
:tabindex="loading ? '-1' : '0'"
role="menuitem"
>
<span
v-if="!loading"
class="inline-flex items-center"
:class="{ 'self-start': !!infoIcon }"
>
<component
:is="icon"
v-if="icon"
class="opacity-75 svg-icons"
:class="[
label ? (reverse ? 'ml-4' : 'mr-4') : '',
{ 'text-accent': active },
]"
/>
</span>
<HoppSmartSpinner v-else class="mr-4 text-secondaryDark" />
<div class="inline-flex items-start flex-1 truncate" :class="{ 'flex-col': description }">
<div class="font-semibold truncate max-w-54">
<div
class="inline-flex items-start flex-1 truncate"
:class="{ 'flex-col': description }"
>
<div class="font-semibold truncate max-w-[16rem]">
{{ label }}
</div>
<p v-if="description" class="my-2 text-left text-secondaryLight">
@@ -33,7 +52,11 @@
:class="{ 'text-accent': activeInfoIcon }"
/>
<div v-if="shortcut.length" class="ml-4 <sm:hidden font-medium">
<kbd v-for="(key, index) in shortcut" :key="`key-${index}`" class="-mr-2 shortcut-key">
<kbd
v-for="(key, index) in shortcut"
:key="`key-${index}`"
class="-mr-2 shortcut-key"
>
{{ key }}
</kbd>
</div>
@@ -48,7 +71,7 @@ import { defineComponent } from "vue"
export default defineComponent({
components: {
HoppSmartLink,
HoppSmartSpinner
HoppSmartSpinner,
},
props: {
to: {

View File

@@ -44,7 +44,6 @@
</h3>
<span class="flex items-center">
<slot name="actions"></slot>
<kbd class="shortcut-key mr-2">ESC</kbd>
<HoppButtonSecondary
v-if="dimissible"
v-tippy="{ theme: 'tooltip', delay: [500, 20] }"

View File

@@ -19,7 +19,7 @@
</template>
<script setup lang="ts">
import { Avatar } from "@boringer-avatars/vue3";
import { Avatar } from "@boringer-avatars/vue3"
withDefaults(
defineProps<{
@@ -32,7 +32,7 @@ withDefaults(
name: "",
indicator: false,
indicatorStyles: "bg-green-500",
size: 24,
size: 22,
}
)
</script>

View File

@@ -0,0 +1,30 @@
<template>
<div class="select-wrapper">
<span class="down-icon text-xs">
<IconChevronDown />
</span>
<slot />
</div>
</template>
<script setup lang="ts">
import IconChevronDown from '~icons/lucide/chevron-down'
</script>
<style scoped lang="scss">
.select-wrapper {
@apply flex flex-1;
@apply relative;
}
.down-icon {
@apply absolute;
@apply flex;
@apply inset-y-0;
@apply items-center;
@apply justify-center;
@apply pointer-events-none;
@apply text-current;
@apply right-3;
}
</style>

View File

@@ -26,7 +26,7 @@
v-for="cellHeading in headings"
:key="cellHeading.key"
@click="!cellHeading.preventClick && onRowClicked(rowData)"
class="max-w-40 pl-6 py-1"
class="max-w-[10rem] pl-6 py-1"
>
<!-- Dynamic column slot -->
<slot :name="cellHeading.key" :item="rowData">

View File

@@ -1,7 +1,7 @@
<template>
<div
class="flex h-full flex-1 flex-nowrap"
:class="{ 'h-auto flex-col': !vertical }"
:class="{ '!h-auto !flex-col': !vertical }"
>
<div
class="tabs relative border-dividerLight"
@@ -221,8 +221,8 @@ const selectTab = (id: string) => {
@apply items-center;
@apply justify-center;
@apply px-1;
@apply leading-[15px];
@apply min-w-4;
@apply min-w-[1rem];
@apply h-4;
@apply ml-2;
@apply text-[8px];
@apply border border-divider;

View File

@@ -24,7 +24,7 @@
<button
:key="`removable-tab-${tabID}`"
:id="`removable-tab-${tabID}`"
class="px-2 tab group"
class="tab group"
:class="[{ active: modelValue === tabID }]"
:aria-label="tabMeta.label || ''"
role="button"
@@ -81,11 +81,11 @@
</draggable>
</div>
<div
class="sticky right-0 flex items-center justify-center flex-shrink-0 overflow-x-auto z-14"
class="sticky right-0 flex items-center justify-center flex-shrink-0 overflow-x-auto z-20"
>
<span
v-if="canAddNewTab"
class="flex items-center justify-center h-full px-3 bg-primaryLight z-8"
class="flex items-center justify-center h-full px-3 bg-primaryLight z-[8]"
>
<HoppButtonSecondary
v-tippy="{ theme: 'tooltip' }"
@@ -382,9 +382,10 @@ watch(
.tab {
@apply relative;
@apply flex;
@apply py-2;
@apply p-2;
@apply font-semibold;
@apply w-46;
@apply h-12;
@apply transition;
@apply flex-1;
@apply items-center;

View File

@@ -24,3 +24,4 @@ export { default as HoppSmartPicture } from "./Picture.vue"
export { default as HoppSmartPlaceholder } from "./Placeholder.vue"
export { default as HoppSmartTree } from "./Tree.vue"
export { default as HoppSmartTreeBranch } from "./TreeBranch.vue"
export { default as HoppSmartSelectWrapper } from "./SelectWrapper.vue"

View File

@@ -29,7 +29,7 @@
<td
v-for="cellHeading in headings"
:key="cellHeading.key"
class="max-w-40 pl-6 py-1"
class="max-w-[10rem] pl-6 py-1"
>
{{ item[cellHeading.key] ?? "-" }}
</td>

View File

@@ -1,5 +1,5 @@
import { Config } from "tailwindcss";
import { theme } from 'tailwindcss/defaultConfig'
import { Config } from "tailwindcss"
import { theme } from "tailwindcss/defaultConfig"
export default {
content: [],
@@ -8,22 +8,6 @@ export default {
center: true,
},
extend: {
inset: {
upperPrimaryStickyFold: "var(--upper-primary-sticky-fold)",
upperSecondaryStickyFold: "var(--upper-secondary-sticky-fold)",
upperTertiaryStickyFold: "var(--upper-tertiary-sticky-fold)",
upperFourthStickyFold: "var(--upper-fourth-sticky-fold)",
upperMobilePrimaryStickyFold: "var(--upper-mobile-primary-sticky-fold)",
upperMobileSecondaryStickyFold: "var(--upper-mobile-secondary-sticky-fold)",
upperMobileStickyFold: "var(--upper-mobile-sticky-fold)",
upperMobileTertiaryStickyFold: "var(--upper-mobile-tertiary-sticky-fold)",
lowerPrimaryStickyFold: "var(--lower-primary-sticky-fold)",
lowerSecondaryStickyFold: "var(--lower-secondary-sticky-fold)",
lowerTertiaryStickyFold: "var(--lower-tertiary-sticky-fold)",
lowerFourthStickyFold: "var(--lower-fourth-sticky-fold)",
sidebarPrimaryStickyFold: "var(--sidebar-primary-sticky-fold)",
sidebarSecondaryStickyFold: "var(--line-height-body)",
},
colors: {
primary: "var(--primary-color)",
primaryLight: "var(--primary-light-color)",
@@ -39,9 +23,9 @@ export default {
divider: "var(--divider-color)",
dividerLight: "var(--divider-light-color)",
dividerDark: "var(--divider-dark-color)",
info: "var(--info-color)",
warning: "var(--warning-color)",
error: "var(--error-color)",
bannerInfo: "var(--banner-info-color)",
bannerWarning: "var(--banner-warning-color)",
bannerError: "var(--banner-error-color)",
tooltip: "var(--tooltip-color)",
popover: "var(--popover-color)",
gradientFrom: "var(--gradient-from-color)",
@@ -66,7 +50,6 @@ export default {
fontFamily: {
sans: "var(--font-sans)",
mono: "var(--font-mono)",
icon: "var(--font-icon)",
},
fontSize: {
tiny: "var(--font-size-tiny)",
@@ -98,9 +81,9 @@ export default {
46: "11.5rem",
},
maxWidth: {
'1/2': '50%',
'1/3': '33%',
'3/4': '75%',
"1/2": "50%",
"1/3": "33%",
"3/4": "75%",
46: "11.5rem",
},
maxHeight: {
@@ -112,15 +95,9 @@ export default {
backgroundOpacity: {
15: "0.15",
},
},
screens: {
sm: "639px",
"<2xl": { max: "1536px" },
"<xl": { max: "1280px" },
"<lg": { max: "1024px" },
"<md": { max: "768px" },
"<sm": { max: "640px" },
...theme?.screens,
screens: {
"<sm": { max: "640px" },
},
},
},
} satisfies Config