Skip to content

Commit

Permalink
Enhancements to Camera Feed Component (#8140)
Browse files Browse the repository at this point in the history
  • Loading branch information
rithviknishad authored Jul 24, 2024
1 parent fe63a07 commit c3e1b1a
Show file tree
Hide file tree
Showing 13 changed files with 536 additions and 391 deletions.
2 changes: 1 addition & 1 deletion src/CAREUI/display/NetworkSignal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function NetworkSignal({ strength, children }: Props) {
i === 2 && "h-[15px]",

// Whether to infill with strength color or not
strength > i ? "bg-current" : "bg-zinc-600",
strength > i ? "bg-current" : "bg-zinc-500/30",
)}
/>
))
Expand Down
42 changes: 28 additions & 14 deletions src/CAREUI/interactive/KeyboardShortcut.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,50 @@ import useKeyboardShortcut from "use-keyboard-shortcut";
import { classNames, isAppleDevice } from "../../Utils/utils";

interface Props {
children: React.ReactNode;
children?: React.ReactNode;
shortcut: string[];
altShortcuts?: string[][];
onTrigger: () => void;
shortcutSeperator?: string;
helpText?: string;
tooltipClassName?: string;
}

export default function KeyboardShortcut(props: Props) {
useKeyboardShortcut(props.shortcut, props.onTrigger, {
overrideSystem: true,
});
useKeyboardShortcut(props.shortcut, props.onTrigger);

if (!props.children) {
return null;
}

return (
<div className="tooltip">
{props.children}
<span
className={classNames(
"tooltip-text flex items-center gap-0.5 text-xs",
"tooltip-text space-x-1 text-xs",
props.tooltipClassName || "tooltip-bottom",
)}
>
<span className="px-1 font-bold">{props.helpText}</span>
<kbd className="hidden items-center px-1.5 font-sans font-medium text-zinc-300 shadow md:inline-flex">
{getShortcutKeyDescription(props.shortcut).join(" + ")}
</kbd>
{props.helpText && (
<span className="pl-1 font-bold">{props.helpText}</span>
)}
{(props.altShortcuts || [props.shortcut]).map((shortcut, idx, arr) => (
<>
<kbd className="hidden items-center px-1.5 font-sans font-medium text-zinc-300 shadow lg:inline-flex">
{shortcut.map((key, idx, keys) => (
<>
{SHORTCUT_KEY_MAP[key] || key}
{idx !== keys.length - 1 && (
<span className="px-1 text-zinc-300/60"> + </span>
)}
</>
))}
</kbd>
{idx !== arr.length - 1 && (
<span className="text-zinc-300/60">or</span>
)}
</>
))}
</span>
</div>
);
Expand All @@ -43,7 +61,3 @@ const SHORTCUT_KEY_MAP = {
ArrowLeft: "←",
ArrowRight: "→",
} as Record<string, string>;

export const getShortcutKeyDescription = (shortcut: string[]) => {
return shortcut.map((key) => SHORTCUT_KEY_MAP[key] || key);
};
83 changes: 45 additions & 38 deletions src/Components/CameraFeed/AssetBedSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { AssetBedModel } from "../Assets/AssetTypes";
import { Listbox, Transition } from "@headlessui/react";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { classNames } from "../../Utils/utils";
import { dropdownOptionClassNames } from "../Form/MultiSelectMenuV2";
import ButtonV2 from "../Common/components/ButtonV2";

interface Props {
disabled?: boolean;
options: AssetBedModel[];
value?: AssetBedModel;
label?: (value: AssetBedModel) => string;
Expand All @@ -15,34 +18,44 @@ export default function CameraPresetSelect(props: Props) {
const label = props.label ?? defaultLabel;
return (
<>
<div className="hidden gap-4 whitespace-nowrap pr-2 lg:flex lg:gap-2">
{/* Desktop View */}
{/* Desktop View */}
<div className="hidden gap-4 whitespace-nowrap pr-2 lg:flex lg:gap-1.5">
{props.options
.slice(0, props.options.length > 5 ? 4 : 5)
.map((option) => (
<button
className={classNames(
"min-w-16 max-w-40 overflow-hidden text-ellipsis whitespace-nowrap rounded-lg border-2 px-2 py-0.5 text-base transition-all duration-200 ease-in-out hover:bg-zinc-600",
props.value?.id === option.id
? "border-white bg-zinc-100 font-bold text-black"
: "border-zinc-700 font-medium text-zinc-300",
)}
onClick={() => props.onChange?.(option)}
>
{label(option)}
</button>
))}
.map((option) => {
const selected = props.value?.id === option.id;

return (
<ButtonV2
key={option.id}
variant={selected ? "primary" : "secondary"}
className="min-w-16 max-w-40 text-ellipsis text-sm"
onClick={() => props.onChange?.(option)}
border
size="small"
>
{label(option)}
{selected && (
<CareIcon
icon="l-check"
className="rounded-full bg-primary-500 text-base text-white"
/>
)}
</ButtonV2>
);
})}
{props.options.length > 5 && (
<CameraPresetDropdown
{...props}
placeholder="More preset"
placeholder="More presets"
options={props.options.slice(4)}
value={props.options.slice(4).find((o) => o.id === props.value?.id)}
/>
)}
</div>

{/* Mobile View */}
<div className="w-full lg:hidden">
{/* Mobile View */}
<CameraPresetDropdown {...props} placeholder="Select preset" />
</div>
</>
Expand All @@ -62,15 +75,15 @@ export const CameraPresetDropdown = (
<Listbox
value={selected}
onChange={props.onChange}
disabled={options.length === 0}
disabled={options.length === 0 || props.disabled}
>
<div className="relative flex-1">
<Listbox.Button
className={classNames(
"relative min-w-32 max-w-40 overflow-hidden text-ellipsis whitespace-nowrap rounded-lg border-2 px-2 py-1 pr-8 text-left text-sm font-medium transition-all duration-200 ease-in-out hover:bg-zinc-600 focus:outline-none disabled:cursor-not-allowed disabled:bg-transparent disabled:text-zinc-700 md:py-0.5 md:text-base",
"button-size-small button-shape-square relative inline-flex h-min min-w-32 cursor-pointer items-center gap-2 whitespace-pre pr-12 text-left text-sm font-medium shadow outline-offset-1 transition-all duration-200 ease-in-out enabled:hover:shadow-md disabled:cursor-not-allowed disabled:bg-secondary-200 disabled:text-secondary-500 md:min-w-40",
selected
? "border-zinc-700 bg-zinc-700/50 text-white md:font-bold"
: "border-zinc-700 text-zinc-300",
? "button-primary-default button-primary-border"
: "button-secondary-default button-secondary-border",
)}
>
<span className="block truncate">
Expand All @@ -80,38 +93,32 @@ export const CameraPresetDropdown = (
? label(selected)
: props.placeholder}
</span>
{selected && (
<CareIcon
icon="l-check"
className="absolute inset-y-0 right-7 mt-1.5 rounded-full bg-primary-500 text-base text-white"
/>
)}
<span className="pointer-events-none absolute inset-y-0 right-0 mr-1 mt-1 flex items-center">
<CareIcon icon="l-angle-down" className="text-xl text-zinc-400" />
</span>
</Listbox.Button>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leave="transition ease-in duration-300"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="absolute z-20 mt-1 max-h-48 w-full overflow-auto rounded-b-lg bg-zinc-900/75 py-1 text-base shadow-lg ring-1 ring-white/5 backdrop-blur-sm focus:outline-none md:max-h-60">
<Listbox.Options className="absolute z-20 max-h-48 w-full overflow-auto rounded-b-lg bg-white py-1 text-base shadow-lg ring-1 ring-gray-500 focus:outline-none md:max-h-60">
{options?.map((obj) => (
<Listbox.Option
key={obj.id}
className={({ active }) =>
`relative cursor-default select-none px-2 py-1 ${
active ? "bg-zinc-700 text-white" : "text-zinc-400"
}`
className={(args) =>
classNames(dropdownOptionClassNames(args), "px-2 py-1.5")
}
value={obj}
>
{({ selected }) => (
<>
<span
className={`block truncate text-sm md:text-base ${
selected ? "font-bold text-white" : "font-normal"
}`}
>
{label(obj)}
</span>
</>
)}
<span>{label(obj)}</span>
</Listbox.Option>
))}
</Listbox.Options>
Expand Down
Loading

0 comments on commit c3e1b1a

Please sign in to comment.