reworked the octave css layout to get rid of the Zindex added support for showNoteNames policy and added an onhover policy

This commit is contained in:
Clément Le Bihan
2023-03-19 17:59:20 +01:00
parent f43561460d
commit 6a10ad2398
3 changed files with 114 additions and 81 deletions
+107 -77
View File
@@ -19,21 +19,37 @@ const getKeyIndex = (n: Note, keys: PianoKey[]) => {
return -1;
};
type OctaveProps = {
const isNoteVisible = (
showNoteNamesPolicy: NoteNameBehavior,
isPressed: boolean,
isHovered: boolean,
isHighlighted: boolean
) => {
if (showNoteNamesPolicy === "always") return true;
if (showNoteNamesPolicy === "never") return false;
if (showNoteNamesPolicy === "onpress") {
return isPressed;
} else if (showNoteNamesPolicy === "onhover") {
return isHovered;
} else if (showNoteNamesPolicy === "onhighlight") {
return isHighlighted;
}
return false;
};
type OctaveProps = Parameters<typeof Box>[0] & {
number: number;
startNote: Note;
endNote: Note;
showNoteNames: NoteNameBehavior;
onNoteDown: (note: PianoKey) => void;
onNoteUp: (note: PianoKey) => void;
};
const Octave = ({
number,
startNote,
endNote,
onNoteDown,
onNoteUp,
}: OctaveProps) => {
const Octave = (props: OctaveProps) => {
const { number, startNote, endNote, showNoteNames, onNoteDown, onNoteUp } =
props;
const oK: PianoKey[] = octaveKeys.map((k) => {
return new PianoKey(k.note, k.accidental, number);
});
@@ -45,38 +61,41 @@ const Octave = ({
const whiteKeys = keys.filter((k) => k?.accidental === undefined);
const blackKeys = keys.filter((k) => k?.accidental !== undefined);
const whiteKeyWidthExpr = "50px";
const whiteKeyHeightExpr = "200px";
const blackKeyWidthExpr = "25px";
const blackKeyHeightExpr = "100px";
const whiteKeyWidthExpr = "calc(100% / 7)";
const whiteKeyHeightExpr = "100%";
const blackKeyWidthExpr = "calc(100% / 13)";
const blackKeyHeightExpr = "calc(100% / 1.5)";
return (
<Box width={"350px"} height={"200px"}>
<ZStack>
<Row>
{whiteKeys.map((key, i) => {
return (
<Pressable
key={i}
onPressIn={() => onNoteDown(key)}
onPressOut={() => onNoteUp(key)}
>
{({ isHovered, isPressed }) => (
<Box
bg={
isHovered
? isPressed
? "gray.300"
: "gray.100"
: "white"
}
w="50px"
h="200px"
borderWidth="1px"
borderColor="black"
justifyContent="flex-end"
alignItems="center"
>
<Box {...props}>
<Row height={"100%"} width={"100%"}>
{whiteKeys.map((key, i) => {
return (
<Pressable
width={whiteKeyWidthExpr}
height={whiteKeyHeightExpr}
key={i}
onPressIn={() => onNoteDown(key)}
onPressOut={() => onNoteUp(key)}
>
{({ isHovered, isPressed }) => (
<Box
bg={
isHovered ? (isPressed ? "gray.300" : "gray.100") : "white"
}
w="100%"
h="100%"
borderWidth="1px"
borderColor="black"
justifyContent="flex-end"
alignItems="center"
>
{isNoteVisible(
showNoteNames,
isPressed,
isHovered,
false
) && (
<Text
style={{
userSelect: "none",
@@ -88,38 +107,49 @@ const Octave = ({
>
{key.note}
</Text>
</Box>
)}
</Pressable>
);
})}
</Row>
<Row>
{blackKeys.map((key, i) => {
return (
<Pressable
key={i}
onPressIn={() => onNoteDown(key)}
onPressOut={() => onNoteUp(key)}
>
{({ isHovered, isPressed }) => (
<Box
bg={isHovered ? (isPressed ? "gray.700" : "gray.800") : "black"}
w="25px"
h="120px"
borderWidth="1px"
borderColor="black"
color="white"
style={{
position: "absolute",
left: `${
(i + ((i > 1) as unknown as number)) * 50 + (50 - 25 / 2)
}px`,
top: "0px",
justifyContent: "flex-end",
alignItems: "center",
}}
>
)}
</Box>
)}
</Pressable>
);
})}
{blackKeys.map((key, i) => {
return (
<Pressable
key={i}
onPressIn={() => onNoteDown(key)}
onPressOut={() => onNoteUp(key)}
width={blackKeyWidthExpr}
height={blackKeyHeightExpr}
style={{
position: "absolute",
left: `calc(calc(${whiteKeyWidthExpr} * ${
i + ((i > 1) as unknown as number) + 1
}) - calc(${blackKeyWidthExpr} / 2))`,
top: "0px",
}}
>
{({ isHovered, isPressed }) => (
<Box
bg={
isHovered ? (isPressed ? "gray.700" : "gray.800") : "black"
}
w="100%"
h="100%"
borderWidth="1px"
borderColor="black"
color="white"
style={{
justifyContent: "flex-end",
alignItems: "center",
}}
>
{isNoteVisible(
showNoteNames,
isPressed,
isHovered,
false
) && (
<Text
style={{
userSelect: "none",
@@ -132,13 +162,13 @@ const Octave = ({
>
{key.note + key.accidental}
</Text>
</Box>
)}
</Pressable>
);
})}
</Row>
</ZStack>
)}
</Box>
)}
</Pressable>
);
})}
</Row>
</Box>
);
};
@@ -48,8 +48,11 @@ const VirtualPiano = ({
{octaveList.map((octaveNum) => {
return (
<Octave
width={"350px"}
height={"200px"}
key={octaveNum}
number={octaveNum}
showNoteNames={showNoteNames}
startNote={octaveNum == startOctave ? startNote : notesList[0]}
endNote={octaveNum == endOctave ? endNote : notesList[notesList.length - 1]}
onNoteDown={onNoteDown}
@@ -70,9 +73,9 @@ VirtualPiano.defaultProps = {
},
startOctave: 2,
startNote: "C",
endOctave: 6,
endNote: "C",
showNoteNames: "onpress",
endOctave: 2,
endNote: "B",
showNoteNames: "onhover",
highlightedNotes: [],
highlightColor: "red",
specialHighlightedNotes: [],
+1 -1
View File
@@ -3,7 +3,7 @@
export type Note = "C" | "D" | "E" | "F" | "G" | "A" | "B";
export type Accidental = "#" | "b" | "##" | "bb";
export type NoteNameBehavior = "always" | "onpress" | "onhighlight" | "never";
export type NoteNameBehavior = "always" | "onpress" | "onhighlight" | "onhover" | "never";
export type KeyPressStyle = "subtle" | "vivid";
export class PianoKey {