use and add info to fieldlabel

This commit is contained in:
Andrew Davis 2025-04-03 23:15:40 +10:00
parent 54d011897d
commit 0651cb8256
No known key found for this signature in database
GPG Key ID: 30AB5B89A109D044
4 changed files with 43 additions and 44 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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}`}