mirror of https://github.com/jetkvm/kvm.git
use and add info to fieldlabel
This commit is contained in:
parent
54d011897d
commit
0651cb8256
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { LuInfo } from "react-icons/lu";
|
||||||
|
|
||||||
import { cx } from "@/cva.config";
|
import { cx } from "@/cva.config";
|
||||||
|
|
||||||
|
@ -8,6 +9,7 @@ interface Props {
|
||||||
as?: "label" | "span";
|
as?: "label" | "span";
|
||||||
description?: string | React.ReactNode | null;
|
description?: string | React.ReactNode | null;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
info?: string;
|
||||||
}
|
}
|
||||||
export default function FieldLabel({
|
export default function FieldLabel({
|
||||||
label,
|
label,
|
||||||
|
@ -15,7 +17,36 @@ export default function FieldLabel({
|
||||||
as = "label",
|
as = "label",
|
||||||
description,
|
description,
|
||||||
disabled,
|
disabled,
|
||||||
|
info,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
|
const labelContent = (
|
||||||
|
<>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
{label}
|
||||||
|
{info && (
|
||||||
|
<div className="group relative cursor-pointer">
|
||||||
|
<LuInfo className={cx(
|
||||||
|
"h-4 w-4",
|
||||||
|
"text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300"
|
||||||
|
)} />
|
||||||
|
<div className={cx(
|
||||||
|
"absolute left-1/2 top-full z-10 mt-1 hidden w-64 -translate-x-1/2",
|
||||||
|
"rounded-md bg-slate-800 px-3 py-2 text-xs text-white shadow-lg",
|
||||||
|
"group-hover:block dark:bg-slate-700"
|
||||||
|
)}>
|
||||||
|
<p>{info}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{description && (
|
||||||
|
<span className="my-0.5 text-[13px] font-normal text-slate-600 dark:text-slate-400">
|
||||||
|
{description}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
if (as === "label") {
|
if (as === "label") {
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
|
@ -25,25 +56,15 @@ export default function FieldLabel({
|
||||||
disabled && "opacity-50",
|
disabled && "opacity-50",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{label}
|
{labelContent}
|
||||||
{description && (
|
|
||||||
<span className="my-0.5 text-[13px] font-normal text-slate-600 dark:text-slate-400">
|
|
||||||
{description}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
} else if (as === "span") {
|
} else if (as === "span") {
|
||||||
return (
|
return (
|
||||||
<div className="flex select-none flex-col">
|
<div className="flex select-none flex-col">
|
||||||
<span className="font-display text-[13px] font-medium leading-snug text-black dark:text-white">
|
<span className="font-display text-[13px] font-medium leading-snug text-black dark:text-white">
|
||||||
{label}
|
{labelContent}
|
||||||
</span>
|
</span>
|
||||||
{description && (
|
|
||||||
<span className="my-0.5 text-[13px] font-normal text-slate-600 dark:text-slate-400">
|
|
||||||
{description}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import Fieldset from "@/components/Fieldset";
|
||||||
import { MacroStepCard } from "@/components/MacroStepCard";
|
import { MacroStepCard } from "@/components/MacroStepCard";
|
||||||
import Modal from "@/components/Modal";
|
import Modal from "@/components/Modal";
|
||||||
import { DEFAULT_DELAY, MAX_STEPS_PER_MACRO, MAX_KEYS_PER_STEP } from "@/constants/macros";
|
import { DEFAULT_DELAY, MAX_STEPS_PER_MACRO, MAX_KEYS_PER_STEP } from "@/constants/macros";
|
||||||
|
import FieldLabel from "@/components/FieldLabel";
|
||||||
|
|
||||||
interface ValidationErrors {
|
interface ValidationErrors {
|
||||||
name?: string;
|
name?: string;
|
||||||
|
@ -192,15 +193,7 @@ export function MacroForm({
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center justify-between text-sm">
|
<div className="flex items-center justify-between text-sm">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<label className="font-medium text-slate-700 dark:text-slate-200">
|
<FieldLabel label="Steps" info={`Each step is a collection of keys and/or modifiers that will be executed in order. You can add up to a maximum of ${MAX_STEPS_PER_MACRO} steps per macro.`} />
|
||||||
Steps
|
|
||||||
</label>
|
|
||||||
<div className="group relative cursor-pointer">
|
|
||||||
<LuInfo className="h-4 w-4 text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-400" />
|
|
||||||
<div className="absolute left-1/2 top-full z-10 mt-1 hidden w-64 -translate-x-1/2 rounded-md bg-slate-800 px-3 py-2 text-xs text-white shadow-lg group-hover:block dark:bg-slate-700">
|
|
||||||
<p>Each step is a collection of keys and/or modifiers that will be executed in order. You can add up to a maximum of {MAX_STEPS_PER_MACRO} steps per macro.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<span className="text-slate-500 dark:text-slate-400">
|
<span className="text-slate-500 dark:text-slate-400">
|
||||||
{macro.steps?.length || 0}/{MAX_STEPS_PER_MACRO} steps
|
{macro.steps?.length || 0}/{MAX_STEPS_PER_MACRO} steps
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { SelectMenuBasic } from "@/components/SelectMenuBasic";
|
||||||
import Card from "@/components/Card";
|
import Card from "@/components/Card";
|
||||||
import { keys, modifiers, keyDisplayMap } from "@/keyboardMappings";
|
import { keys, modifiers, keyDisplayMap } from "@/keyboardMappings";
|
||||||
import { MAX_KEYS_PER_STEP } from "@/constants/macros";
|
import { MAX_KEYS_PER_STEP } from "@/constants/macros";
|
||||||
|
import FieldLabel from "@/components/FieldLabel";1
|
||||||
|
|
||||||
// Filter out modifier keys since they're handled in the modifiers section
|
// Filter out modifier keys since they're handled in the modifiers section
|
||||||
const modifierKeyPrefixes = ['Alt', 'Control', 'Shift', 'Meta'];
|
const modifierKeyPrefixes = ['Alt', 'Control', 'Shift', 'Meta'];
|
||||||
|
@ -128,9 +129,7 @@ export function MacroStepCard({
|
||||||
|
|
||||||
<div className="space-y-4 mt-2">
|
<div className="space-y-4 mt-2">
|
||||||
<div className="w-full flex flex-col gap-2">
|
<div className="w-full flex flex-col gap-2">
|
||||||
<label className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
<FieldLabel label="Modifiers" />
|
||||||
Modifiers
|
|
||||||
</label>
|
|
||||||
<div className="inline-flex flex-wrap gap-3">
|
<div className="inline-flex flex-wrap gap-3">
|
||||||
{Object.entries(groupedModifiers).map(([group, mods]) => (
|
{Object.entries(groupedModifiers).map(([group, mods]) => (
|
||||||
<div key={group} className="relative min-w-[120px] rounded-md border border-slate-200 dark:border-slate-700 p-2">
|
<div key={group} className="relative min-w-[120px] rounded-md border border-slate-200 dark:border-slate-700 p-2">
|
||||||
|
@ -139,7 +138,7 @@ export function MacroStepCard({
|
||||||
</span>
|
</span>
|
||||||
<div className="flex flex-wrap gap-1">
|
<div className="flex flex-wrap gap-1">
|
||||||
{mods.map(option => (
|
{mods.map(option => (
|
||||||
<label
|
<span
|
||||||
key={option.value}
|
key={option.value}
|
||||||
className={`flex items-center px-2 py-1 rounded border cursor-pointer text-xs font-medium transition-colors ${
|
className={`flex items-center px-2 py-1 rounded border cursor-pointer text-xs font-medium transition-colors ${
|
||||||
ensureArray(step.modifiers).includes(option.value)
|
ensureArray(step.modifiers).includes(option.value)
|
||||||
|
@ -160,7 +159,7 @@ export function MacroStepCard({
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{option.label.split(' ')[1] || option.label}
|
{option.label.split(' ')[1] || option.label}
|
||||||
</label>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -170,15 +169,7 @@ export function MacroStepCard({
|
||||||
|
|
||||||
<div className="w-full flex flex-col gap-1">
|
<div className="w-full flex flex-col gap-1">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<label className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
<FieldLabel label="Keys" info={`You can add up to a maximum of ${MAX_KEYS_PER_STEP} keys to press per step.`} />
|
||||||
Keys
|
|
||||||
</label>
|
|
||||||
<div className="group relative cursor-pointer">
|
|
||||||
<LuInfo className="h-4 w-4 text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-400" />
|
|
||||||
<div className="absolute left-1/2 top-full z-10 mt-1 hidden w-64 -translate-x-1/2 rounded-md bg-slate-800 px-3 py-2 text-xs text-white shadow-lg group-hover:block dark:bg-slate-700">
|
|
||||||
<p>You can add up to a maximum of {MAX_KEYS_PER_STEP} keys to press per step.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap gap-1 pb-2">
|
<div className="flex flex-wrap gap-1 pb-2">
|
||||||
{ensureArray(step.keys).map((key, keyIndex) => (
|
{ensureArray(step.keys).map((key, keyIndex) => (
|
||||||
|
@ -220,15 +211,7 @@ export function MacroStepCard({
|
||||||
|
|
||||||
<div className="w-full flex flex-col gap-1">
|
<div className="w-full flex flex-col gap-1">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<label className="text-sm font-medium text-slate-700 dark:text-slate-300">
|
<FieldLabel label="Step Duration" info="The time to wait after pressing the keys in this step before moving to the next step. This helps ensure reliable key presses when automating keyboard input." />
|
||||||
Step Duration
|
|
||||||
</label>
|
|
||||||
<div className="group relative cursor-pointer">
|
|
||||||
<LuInfo className="h-4 w-4 text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-400" />
|
|
||||||
<div className="absolute left-1/2 top-full z-10 mt-1 hidden w-64 -translate-x-1/2 rounded-md bg-slate-800 px-3 py-2 text-xs text-white shadow-lg group-hover:block dark:bg-slate-700">
|
|
||||||
<p>The time to wait after pressing the keys in this step before moving to the next step. This helps ensure reliable key presses when automating keyboard input.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<SelectMenuBasic
|
<SelectMenuBasic
|
||||||
|
|
|
@ -180,6 +180,7 @@ export default function SettingsMacrosRoute() {
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
LeadingIcon={LuCopy}
|
LeadingIcon={LuCopy}
|
||||||
|
text="Duplicate"
|
||||||
onClick={() => handleDuplicateMacro(macro)}
|
onClick={() => handleDuplicateMacro(macro)}
|
||||||
disabled={actionLoadingId === macro.id}
|
disabled={actionLoadingId === macro.id}
|
||||||
aria-label={`Duplicate macro ${macro.name}`}
|
aria-label={`Duplicate macro ${macro.name}`}
|
||||||
|
@ -188,6 +189,7 @@ export default function SettingsMacrosRoute() {
|
||||||
size="XS"
|
size="XS"
|
||||||
theme="light"
|
theme="light"
|
||||||
LeadingIcon={LuPenLine}
|
LeadingIcon={LuPenLine}
|
||||||
|
text="Edit"
|
||||||
onClick={() => navigate(`${macro.id}/edit`)}
|
onClick={() => navigate(`${macro.id}/edit`)}
|
||||||
disabled={actionLoadingId === macro.id}
|
disabled={actionLoadingId === macro.id}
|
||||||
aria-label={`Edit macro ${macro.name}`}
|
aria-label={`Edit macro ${macro.name}`}
|
||||||
|
|
Loading…
Reference in New Issue