-
-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathstyles.ts
126 lines (111 loc) · 4.23 KB
/
styles.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import Color from "color";
import { rgbaToRgb } from "../../lib/color-utils";
import { HintedIntersector } from "../../typing/types";
import {
getInheritedBackgroundColor,
getDefaultBackgroundColor,
} from "../utils/background-color";
import { getFirstTextNodeDescendant } from "../utils/nodes-utils";
import { getHintOption } from "../options/hint-style-options";
// This is necessary to calculate background colors with alpha different than 1.
// It's usually rgba(0, 0, 0, 0)
const defaultBackgroundColor = getDefaultBackgroundColor();
export function applyInitialStyles(intersector: HintedIntersector) {
// This is here in case we are using keyboard clicking so that once we press one
// key and the reachable elements are marked the style of those hints doesn't get reset
if (intersector.freezeHintStyle) {
return;
}
const subtleHints = getHintOption("hintStyle") === "subtle";
intersector.backgroundColor = intersector.backgroundColor
? intersector.backgroundColor
: getInheritedBackgroundColor(
intersector.element,
defaultBackgroundColor || "rgba(0, 0, 0, 0)"
);
const backgroundColor = intersector.backgroundColor;
// We want our hint font color to match the font color of the text it's hinting
intersector.firstTextNodeDescendant = intersector.firstTextNodeDescendant
?.isConnected
? intersector.firstTextNodeDescendant
: getFirstTextNodeDescendant(intersector.element);
const elementToGetColorFrom =
intersector.firstTextNodeDescendant?.parentElement;
const colorString = window.getComputedStyle(
elementToGetColorFrom ?? intersector.element
).color;
// Sometimes the color string we get is an empty string. We also need to convert to rgb
// because the contrast function doesn't take into account alpha values
let color = rgbaToRgb(new Color(colorString || "black"), backgroundColor);
// If the element doesn't have any text just make sure there is contrast
if (!elementToGetColorFrom) {
if (backgroundColor.isDark() && color.isDark()) {
color = new Color("white");
}
if (backgroundColor.isLight() && color.isLight()) {
color = new Color("black");
}
}
// A contrast value of 2.5 might seem low but it is necessary to match the look of some pages.
// Some pages use low contrast with big text and, in my experience, it's more pleasant to keep
// the aspect of the page. Having in mind that the text of the hints is not something that
// the user would need to read continuously it might be acceptable to allow such a low contrast
if (backgroundColor.contrast(color) < 2.5) {
color = backgroundColor.isLight() ? new Color("black") : new Color("white");
}
const outlineColor = new Color(color).alpha(0.3);
const hintFontSize = getHintOption("hintFontSize") as number;
const fontWeightOption = getHintOption("hintWeight");
let fontWeight;
if (fontWeightOption === "auto") {
fontWeight =
backgroundColor.contrast(color) < 7 && hintFontSize < 14
? "bold"
: "normal";
} else {
fontWeight = fontWeightOption;
}
const subtleBackground =
subtleHints &&
window.getComputedStyle(intersector.element).display.includes("inline");
const styles = {
backgroundColor: subtleBackground
? "transparent"
: backgroundColor.string(),
color: color.string(),
outline: subtleHints ? 0 : `1px solid ${outlineColor.string()}`,
fontSize: `${hintFontSize}px`,
fontWeight,
padding: "0 0.15em",
};
Object.assign(intersector.hintElement.style, styles);
intersector.hintElement.className = "rango-hint";
}
export function applyEmphasisStyles(
intersector: HintedIntersector,
dynamic: boolean,
fontColor?: string,
backgroundColor?: string
) {
// We invert the colors for a visual clue
const color = fontColor ?? intersector.backgroundColor;
const background = backgroundColor ?? intersector.hintElement.style.color;
const hintFontSize = getHintOption("hintFontSize") as number;
const fontSize = dynamic ? `${hintFontSize * 1.2}px` : `${hintFontSize}px`;
const styles = {
fontSize,
background,
color,
};
Object.assign(intersector.hintElement.style, styles);
}
export function flashHint(
intersector: HintedIntersector,
fontColor?: string,
backgroundColor?: string
) {
applyEmphasisStyles(intersector, true, fontColor, backgroundColor);
setTimeout(() => {
applyInitialStyles(intersector);
}, 300);
}