mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-02-23 02:54:58 +01:00
Good start to multi-window
This commit is contained in:
@@ -45,7 +45,7 @@ const _Button = forwardRef<any, ButtonProps>(function Button(
|
||||
className,
|
||||
'outline-none whitespace-nowrap',
|
||||
// 'border border-transparent focus-visible:border-focus',
|
||||
'focus-visible:ring ring-blue-300',
|
||||
'focus-visible-or-class:ring ring-blue-300',
|
||||
'rounded-md flex items-center',
|
||||
colorStyles[color || 'default'],
|
||||
justify === 'start' && 'justify-start',
|
||||
|
||||
@@ -3,7 +3,7 @@ import FocusTrap from 'focus-trap-react';
|
||||
import { motion } from 'framer-motion';
|
||||
import type { CSSProperties, HTMLAttributes, MouseEvent, ReactElement, ReactNode } from 'react';
|
||||
import { Children, cloneElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useKeyPressEvent, useMount } from 'react-use';
|
||||
import { useKeyPressEvent } from 'react-use';
|
||||
import { Portal } from '../Portal';
|
||||
import { Separator } from './Separator';
|
||||
import { VStack } from './Stacks';
|
||||
@@ -83,10 +83,6 @@ interface MenuProps {
|
||||
function Menu({ className, items, onClose, triggerRect }: MenuProps) {
|
||||
if (triggerRect === undefined) return null;
|
||||
|
||||
useMount(() => {
|
||||
console.log(document.activeElement);
|
||||
});
|
||||
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [menuStyles, setMenuStyles] = useState<CSSProperties>({});
|
||||
|
||||
@@ -98,6 +94,10 @@ function Menu({ className, items, onClose, triggerRect }: MenuProps) {
|
||||
setMenuStyles({ maxHeight: windowBox.height - menuBox.top - 5 });
|
||||
}, []);
|
||||
|
||||
useKeyPressEvent('Escape', () => {
|
||||
onClose();
|
||||
});
|
||||
|
||||
useKeyPressEvent('ArrowUp', () => {
|
||||
setSelectedIndex((currIndex) => {
|
||||
let nextIndex = (currIndex ?? 0) - 1;
|
||||
|
||||
@@ -5,10 +5,11 @@ import { Icon } from './Icon';
|
||||
|
||||
export interface RadioDropdownItem<T> {
|
||||
label: string;
|
||||
shortLabel?: string;
|
||||
value: T;
|
||||
}
|
||||
|
||||
export interface RadioDropdownProps<T> {
|
||||
export interface RadioDropdownProps<T = string | null> {
|
||||
value: T;
|
||||
onChange: (value: T) => void;
|
||||
items: RadioDropdownItem<T>[];
|
||||
@@ -18,8 +19,9 @@ export interface RadioDropdownProps<T> {
|
||||
export function RadioDropdown<T>({ value, items, onChange, children }: RadioDropdownProps<T>) {
|
||||
const dropdownItems = useMemo(
|
||||
() =>
|
||||
items.map(({ label, value: v }) => ({
|
||||
items.map(({ label, shortLabel, value: v }) => ({
|
||||
label,
|
||||
shortLabel,
|
||||
onSelect: () => onChange(v),
|
||||
leftSlot: <Icon icon={value === v ? 'check' : 'empty'} />,
|
||||
})),
|
||||
|
||||
@@ -7,23 +7,27 @@ import type { RadioDropdownProps } from '../RadioDropdown';
|
||||
import { RadioDropdown } from '../RadioDropdown';
|
||||
import { HStack } from '../Stacks';
|
||||
|
||||
export type TabItem<T = string> = {
|
||||
value: string;
|
||||
label: string;
|
||||
options?: Omit<RadioDropdownProps<T>, 'children'>;
|
||||
};
|
||||
export type TabItem =
|
||||
| {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
| {
|
||||
value: string;
|
||||
options: Omit<RadioDropdownProps, 'children'>;
|
||||
};
|
||||
|
||||
interface Props<T = unknown> {
|
||||
interface Props {
|
||||
label: string;
|
||||
value?: string;
|
||||
onChangeValue: (value: string) => void;
|
||||
tabs: TabItem<T>[];
|
||||
tabs: TabItem[];
|
||||
tabListClassName?: string;
|
||||
className?: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function Tabs<T>({
|
||||
export function Tabs({
|
||||
value,
|
||||
onChangeValue,
|
||||
label,
|
||||
@@ -31,7 +35,7 @@ export function Tabs<T>({
|
||||
tabs,
|
||||
className,
|
||||
tabListClassName,
|
||||
}: Props<T>) {
|
||||
}: Props) {
|
||||
const ref = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const handleTabChange = (value: string) => {
|
||||
@@ -77,7 +81,8 @@ export function Tabs<T>({
|
||||
const btnClassName = classnames(
|
||||
isActive ? 'bg-gray-100 text-gray-800' : 'text-gray-600 hover:text-gray-900',
|
||||
);
|
||||
if (t.options) {
|
||||
if ('options' in t) {
|
||||
const option = t.options.items.find((i) => i.value === t.options?.value);
|
||||
return (
|
||||
<RadioDropdown
|
||||
key={t.value}
|
||||
@@ -91,7 +96,7 @@ export function Tabs<T>({
|
||||
onClick={isActive ? undefined : () => handleTabChange(t.value)}
|
||||
className={btnClassName}
|
||||
>
|
||||
{t.options.items.find((i) => i.value === t.options?.value)?.label ?? ''}
|
||||
{option?.shortLabel ?? option?.label ?? 'Unknown'}
|
||||
<Icon icon="triangleDown" className="-mr-1.5" />
|
||||
</Button>
|
||||
</RadioDropdown>
|
||||
|
||||
Reference in New Issue
Block a user