diff --git a/src/keyboard/Key.tsx b/src/keyboard/Key.tsx index 80babd4..134f51c 100644 --- a/src/keyboard/Key.tsx +++ b/src/keyboard/Key.tsx @@ -1,6 +1,6 @@ // import './key.css'; -import { PropsWithChildren, Children, CSSProperties } from "react"; +import { PropsWithChildren, Children, CSSProperties, FC } from "react"; interface KeyProps { /** @@ -33,17 +33,31 @@ interface KeyDimension { function makeSize( { width, height }: KeyDimension, - oneU: number + oneU: number, ): CSSProperties { width *= oneU; height *= oneU; return { - "--zmk-key-center-width": "calc(" + width + "px - 2px)", - "--zmk-key-center-height": "calc(" + height + "px - 2px)", + "--zmk-key-center-width": `calc(${width}px - 2px)`, + "--zmk-key-center-height": `calc(${height}px - 2px)`, }; } +const ChildItem: FC<PropsWithChildren<{ hoverZoom: boolean }>> = ({ + children, + hoverZoom, +}) => { + return ( + <div + data-zoomer={hoverZoom} + className="col-start-2 col-end-3 row-start-2 row-end-3 self-center justify-self-center font-keycap text-lg" + > + {children} + </div> + ); +}; + export const Key = ({ selected = false, header, @@ -53,18 +67,9 @@ export const Key = ({ }: PropsWithChildren<KeyProps>) => { const size = makeSize(props, oneU); - const children = Children.map(props.children, (c) => ( - <div - data-zoomer={hoverZoom} - className="justify-self-center self-center row-start-2 row-end-3 col-start-2 col-end-3 font-keycap text-lg data-[zoomer=true]:group-hover:text-2xl" - > - {c} - </div> - )); - return ( <div - className="group inline-flex b-0 justify-content-center items-center transition-all duration-100 data-[zoomer=true]:hover:translate-y-[calc(-1em-7px)] data-[zoomer=true]:hover:translate-x-[calc(-1em)]" + className="justify-content-center group origin-center select-none items-center transition-transform data-[zoomer=true]:hover:z-20 data-[zoomer=true]:hover:scale-[2]" data-zoomer={hoverZoom} style={size} {...props} @@ -72,16 +77,24 @@ export const Key = ({ <button aria-selected={selected} data-zoomer={hoverZoom} - className={`rounded${ - oneU > 20 ? "-md" : "" - } transition-all duration-100 m-auto p-0 b-0 box-border grid grid-rows-[0_var(--zmk-key-center-height)_0] grid-cols-[0_var(--zmk-key-center-width)_0] data-[zoomer=true]:hover:grid-rows-[1em_var(--zmk-key-center-height)_1em] data-[zoomer=true]:hover:grid-cols-[1em_var(--zmk-key-center-width)_1em] shadow-[0_0_0_1px_inset] shadow-base-content data-[zoomer=true]:shadow-base-200 data-[zoomer=true]:hover:shadow-base-content data-[zoomer=true]:hover:z-50 text-base-content bg-base-100 aria-selected:bg-primary aria-selected:text-primary-content grow @container`} + className={[ + oneU > 20 ? "rounded-md" : "rounded", + "relative w-[var(--zmk-key-center-width)] h-[var(--zmk-key-center-height)] bg-base-100 border border-transparent", + "group-hover:border-base-content aria-selected:bg-primary aria-selected:text-primary-content @container", + ].join(" ")} > {header && ( - <span className="p-0 b-0 m-0 text-xs w-full h-full text-nowrap justify-self-start row-start-1 row-end-2 col-start-1 col-end-4 hidden group-hover:inline-block group-hover:truncate @md:underline"> + <span className="absolute inset-x-1 top-1 hidden h-4 w-9/12 truncate whitespace-nowrap text-center text-micro uppercase leading-none group-hover:block"> {header} </span> )} - {children} + + {props.children && + Children.map(props.children, (child, index) => ( + <ChildItem key={index} hoverZoom={hoverZoom}> + {child} + </ChildItem> + ))} </button> </div> ); diff --git a/src/keyboard/Keymap.tsx b/src/keyboard/Keymap.tsx index 4d457b1..eb2d941 100644 --- a/src/keyboard/Keymap.tsx +++ b/src/keyboard/Keymap.tsx @@ -9,6 +9,7 @@ import { PhysicalLayout as PhysicalLayoutComp, } from "./PhysicalLayout"; import { HidUsageLabel } from "./HidUsageLabel"; +import { Dispatch, SetStateAction } from "react"; type BehaviorMap = Record<number, GetBehaviorDetailsResponse>; @@ -19,7 +20,7 @@ export interface KeymapProps { scale: LayoutZoom; selectedLayerIndex: number; selectedKeyPosition: number | undefined; - onKeyPositionClicked: (keyPosition: number) => void; + onKeyPositionClicked: Dispatch<SetStateAction<number | undefined>> } export const Keymap = ({ diff --git a/src/keyboard/PhysicalLayout.stories.tsx b/src/keyboard/PhysicalLayout.stories.tsx index fa1b2f0..3ff0333 100644 --- a/src/keyboard/PhysicalLayout.stories.tsx +++ b/src/keyboard/PhysicalLayout.stories.tsx @@ -10,6 +10,7 @@ const meta = { component: PhysicalLayout, parameters: { // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout + layout: "centered" }, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs tags: ["autodocs"], diff --git a/src/keyboard/PhysicalLayout.tsx b/src/keyboard/PhysicalLayout.tsx index 6c7d98c..0771d8e 100644 --- a/src/keyboard/PhysicalLayout.tsx +++ b/src/keyboard/PhysicalLayout.tsx @@ -1,4 +1,6 @@ import { + Dispatch, + SetStateAction, CSSProperties, PropsWithChildren, useLayoutEffect, @@ -33,7 +35,7 @@ interface PhysicalLayoutProps { oneU?: number; hoverZoom?: boolean; zoom?: LayoutZoom; - onPositionClicked?: (position: number) => void; + onPositionClicked?: Dispatch<SetStateAction<number | undefined>> } interface PhysicalLayoutPositionLocation { @@ -125,7 +127,11 @@ export const PhysicalLayout = ({ const positionItems = positions.map((p, idx) => ( <div key={idx} - onClick={() => onPositionClicked?.(idx)} + onClick={() => + onPositionClicked?.((prev: number | undefined) => + prev !== idx ? idx : undefined, + ) + } className="absolute data-[zoomer=true]:hover:z-[1000] leading-[0]" data-zoomer={hoverZoom} style={scalePosition(p, oneU)} diff --git a/tailwind.config.js b/tailwind.config.js index 2f14d26..a998139 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -9,6 +9,9 @@ export default { fontFamily: { sans: ["Inter", "system-ui"], }, + fontSize: { + micro: "6px", // size is intended for key header + }, colors: { primary: "light-dark(oklch(49.12% 0.3096 285.75), oklch(65.69% 0.196 285.75))",