Skip to content

Commit 89b38b3

Browse files
committed
feat: Better physical layout picker with preview.
1 parent 630e6cd commit 89b38b3

File tree

8 files changed

+292
-193
lines changed

8 files changed

+292
-193
lines changed

src/keyboard/Key.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const meta = {
1717
// backgroundColor: { control: 'color' },
1818
},
1919
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
20-
args: { onClick: fn() },
20+
args: { oneU: 48, onClick: fn() },
2121
} satisfies Meta<typeof Key>;
2222

2323
export default meta;

src/keyboard/Key.tsx

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// import './key.css';
22

33
import { PropsWithChildren, Children, CSSProperties } from "react";
4-
import { scale } from "./geometry";
54

65
interface KeyProps {
76
/**
@@ -13,10 +12,14 @@ interface KeyProps {
1312
*/
1413
width: number;
1514
height: number;
15+
16+
oneU: number;
17+
18+
hoverZoom?: boolean;
1619
/**
1720
* Button contents
1821
*/
19-
header: string;
22+
header?: string;
2023
/**
2124
* Optional click handler
2225
*/
@@ -28,9 +31,12 @@ interface KeyDimension {
2831
height: number;
2932
}
3033

31-
function makeSize({ width, height }: KeyDimension): CSSProperties {
32-
width = scale(width);
33-
height = scale(height);
34+
function makeSize(
35+
{ width, height }: KeyDimension,
36+
oneU: number
37+
): CSSProperties {
38+
width *= oneU;
39+
height *= oneU;
3440

3541
return {
3642
"--zmk-key-center-width": "calc(" + width + "px - 2px)",
@@ -41,30 +47,40 @@ function makeSize({ width, height }: KeyDimension): CSSProperties {
4147
export const Key = ({
4248
selected = false,
4349
header,
50+
oneU,
51+
hoverZoom = true,
4452
...props
4553
}: PropsWithChildren<KeyProps>) => {
46-
const size = makeSize(props);
54+
const size = makeSize(props, oneU);
55+
4756
const children = Children.map(props.children, (c) => (
48-
<div className="justify-self-center self-center row-start-2 row-end-3 col-start-2 col-end-3 font-keycap text-lg group-hover:text-3xl">
57+
<div
58+
data-zoomer={hoverZoom}
59+
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-3xl"
60+
>
4961
{c}
5062
</div>
5163
));
5264

5365
return (
5466
<div
55-
className="group inline-flex b-0 justify-content-center items-center hover:translate-y-[calc(-1em-7px)] hover:translate-x-[calc(-1em)]"
67+
className="group inline-flex b-0 justify-content-center items-center data-[zoomer=true]:hover:translate-y-[calc(-1em-7px)] data-[zoomer=true]:hover:translate-x-[calc(-1em)]"
68+
data-zoomer={hoverZoom}
5669
style={size}
5770
{...props}
5871
>
5972
<button
6073
aria-selected={selected}
61-
className={
62-
"rounded-md 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] hover:grid-rows-[1em_var(--zmk-key-center-height)_1em] hover:grid-cols-[1em_var(--zmk-key-center-width)_1em] shadow-[0_0_0_1px_inset] shadow-text-base hover:z-50 text-text-base bg-bg-base aria-selected:bg-secondary"
63-
}
74+
data-zoomer={hoverZoom}
75+
className={`rounded${
76+
oneU > 20 ? "-md" : ""
77+
} 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-text-base data-[zoomer=true]:hover:z-50 text-text-base bg-bg-base aria-selected:bg-secondary`}
6478
>
65-
<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">
66-
{header}
67-
</span>
79+
{header && (
80+
<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">
81+
{header}
82+
</span>
83+
)}
6884
{children}
6985
</button>
7086
</div>

src/keyboard/Keymap.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ export const Keymap = ({
5959
return (
6060
<PhysicalLayoutComp
6161
positions={positions}
62+
oneU={48}
63+
hoverZoom={true}
6264
selectedPosition={selectedKeyPosition}
6365
onPositionClicked={onKeyPositionClicked}
6466
/>

src/keyboard/PhysicalLayout.stories.tsx

Lines changed: 146 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -25,138 +25,153 @@ const TOP = ["Esc", ..."QWERTYUIOP"];
2525
const MIDDLE = [..."ASDFGHJKL;"];
2626
const LOWER = [..."ZXCVBNM<>", "Up", "Shift"];
2727

28-
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
28+
const MINIVAN_POSITIONS = [
29+
...TOP.map((k, i) => ({
30+
width: 1,
31+
height: 1,
32+
x: i,
33+
y: 0,
34+
header: "Key Press",
35+
children: [<span>{k}</span>],
36+
})),
37+
{
38+
x: TOP.length,
39+
y: 0,
40+
width: 1.75,
41+
height: 1,
42+
header: "Key Press",
43+
children: [<span>Backspace</span>],
44+
},
45+
{
46+
x: 0,
47+
y: 1,
48+
width: 1.25,
49+
height: 1,
50+
header: "Key Press",
51+
children: [<span>Tab</span>],
52+
},
53+
...MIDDLE.map((k, i) => ({
54+
x: i + 1.25,
55+
y: 1,
56+
width: 1,
57+
height: 1,
58+
header: "Key Press",
59+
children: [<span>{k}</span>],
60+
})),
61+
{
62+
x: MIDDLE.length + 1.25,
63+
y: 1,
64+
width: 1.5,
65+
height: 1,
66+
header: "Key Press",
67+
children: [<span>Enter</span>],
68+
},
69+
{
70+
x: 0,
71+
y: 2,
72+
width: 1.75,
73+
height: 1,
74+
header: "Key Press",
75+
children: [<span>Shift</span>],
76+
},
77+
...LOWER.map((k, i) => ({
78+
x: i + 1.75,
79+
y: 2,
80+
width: 1,
81+
height: 1,
82+
header: "Key Press",
83+
children: [<span>{k}</span>],
84+
})),
85+
{
86+
x: 0,
87+
y: 3,
88+
width: 1.25,
89+
height: 1,
90+
header: "Key Press",
91+
children: [<span>Control</span>],
92+
},
93+
{
94+
x: 1.25,
95+
y: 3,
96+
width: 1.5,
97+
height: 1,
98+
header: "Key Press",
99+
children: [<span>Code</span>],
100+
},
101+
{
102+
x: 2.75,
103+
y: 3,
104+
width: 1.25,
105+
height: 1,
106+
header: "Key Press",
107+
children: [<span>Alt</span>],
108+
},
109+
{
110+
x: 4,
111+
y: 3,
112+
width: 2.25,
113+
height: 1,
114+
header: "Key Press",
115+
children: [<span></span>],
116+
},
117+
{
118+
x: 6.25,
119+
y: 3,
120+
width: 2,
121+
height: 1,
122+
header: "Key Press",
123+
children: [<span></span>],
124+
},
125+
{
126+
x: 8.25,
127+
y: 3,
128+
width: 1.5,
129+
height: 1,
130+
header: "Key Press",
131+
children: [<span>Alt</span>],
132+
},
133+
{
134+
x: 9.75,
135+
y: 3,
136+
width: 1,
137+
height: 1,
138+
header: "Key Press",
139+
children: [<span>Left</span>],
140+
},
141+
{
142+
x: 10.75,
143+
y: 3,
144+
width: 1,
145+
height: 1,
146+
header: "Key Press",
147+
children: [<span>Down</span>],
148+
},
149+
{
150+
x: 11.75,
151+
y: 3,
152+
width: 1,
153+
height: 1,
154+
header: "Key Press",
155+
children: [<span>Right</span>],
156+
},
157+
];
158+
29159
export const Minivan: Story = {
30160
args: {
31-
positions: [
32-
...TOP.map((k, i) => ({
33-
width: 1,
34-
height: 1,
35-
x: i,
36-
y: 0,
37-
header: "Key Press",
38-
children: [<span>{k}</span>],
39-
})),
40-
{
41-
x: TOP.length,
42-
y: 0,
43-
width: 1.75,
44-
height: 1,
45-
header: "Key Press",
46-
children: [<span>Backspace</span>],
47-
},
48-
{
49-
x: 0,
50-
y: 1,
51-
width: 1.25,
52-
height: 1,
53-
header: "Key Press",
54-
children: [<span>Tab</span>],
55-
},
56-
...MIDDLE.map((k, i) => ({
57-
x: i + 1.25,
58-
y: 1,
59-
width: 1,
60-
height: 1,
61-
header: "Key Press",
62-
children: [<span>{k}</span>],
63-
})),
64-
{
65-
x: MIDDLE.length + 1.25,
66-
y: 1,
67-
width: 1.5,
68-
height: 1,
69-
header: "Key Press",
70-
children: [<span>Enter</span>],
71-
},
72-
{
73-
x: 0,
74-
y: 2,
75-
width: 1.75,
76-
height: 1,
77-
header: "Key Press",
78-
children: [<span>Shift</span>],
79-
},
80-
...LOWER.map((k, i) => ({
81-
x: i + 1.75,
82-
y: 2,
83-
width: 1,
84-
height: 1,
85-
header: "Key Press",
86-
children: [<span>{k}</span>],
87-
})),
88-
{
89-
x: 0,
90-
y: 3,
91-
width: 1.25,
92-
height: 1,
93-
header: "Key Press",
94-
children: [<span>Control</span>],
95-
},
96-
{
97-
x: 1.25,
98-
y: 3,
99-
width: 1.5,
100-
height: 1,
101-
header: "Key Press",
102-
children: [<span>Code</span>],
103-
},
104-
{
105-
x: 2.75,
106-
y: 3,
107-
width: 1.25,
108-
height: 1,
109-
header: "Key Press",
110-
children: [<span>Alt</span>],
111-
},
112-
{
113-
x: 4,
114-
y: 3,
115-
width: 2.25,
116-
height: 1,
117-
header: "Key Press",
118-
children: [<span></span>],
119-
},
120-
{
121-
x: 6.25,
122-
y: 3,
123-
width: 2,
124-
height: 1,
125-
header: "Key Press",
126-
children: [<span></span>],
127-
},
128-
{
129-
x: 8.25,
130-
y: 3,
131-
width: 1.5,
132-
height: 1,
133-
header: "Key Press",
134-
children: [<span>Alt</span>],
135-
},
136-
{
137-
x: 9.75,
138-
y: 3,
139-
width: 1,
140-
height: 1,
141-
header: "Key Press",
142-
children: [<span>Left</span>],
143-
},
144-
{
145-
x: 10.75,
146-
y: 3,
147-
width: 1,
148-
height: 1,
149-
header: "Key Press",
150-
children: [<span>Down</span>],
151-
},
152-
{
153-
x: 11.75,
154-
y: 3,
155-
width: 1,
156-
height: 1,
157-
header: "Key Press",
158-
children: [<span>Right</span>],
159-
},
160-
],
161+
positions: MINIVAN_POSITIONS,
162+
hoverZoom: true,
163+
},
164+
};
165+
166+
export const MiniMinivan: Story = {
167+
args: {
168+
positions: MINIVAN_POSITIONS.map(({ x, y, width, height }) => ({
169+
x,
170+
y,
171+
width,
172+
height,
173+
})),
174+
oneU: 15,
175+
hoverZoom: false,
161176
},
162177
};

0 commit comments

Comments
 (0)