Skip to content

Commit 02bc77e

Browse files
committed
fix: make accessibility and configuration improvements to TruncateToMiddle
- Outputs whole string in a second hidden span to play nicer with assistive technologies. - Accepts optional minCharsStart and minCharsEnd values to set the minimum number of characters to display. This is an approximation based on the width of the 0 (zero) character
1 parent e35da71 commit 02bc77e

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

apps/developer-hub/src/components/TruncateToMiddle/index.module.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
@use "@pythnetwork/component-library/theme";
22

3+
.sr-only {
4+
@include theme.sr-only;
5+
}
6+
37
.truncateToMiddle {
8+
// Defaults may get overridden by style on span
9+
--min-chars-start-ch: 0ch;
10+
--min-chars-end-ch: 0ch;
11+
412
&::before,
513
&::after {
614
display: inline-block;
@@ -12,11 +20,13 @@
1220
&::before {
1321
content: attr(data-text-start);
1422
text-overflow: ellipsis;
23+
min-width: var(--min-chars-start-ch);
1524
}
1625

1726
&::after {
1827
content: attr(data-text-end);
1928
text-overflow: clip;
2029
direction: rtl;
30+
min-width: var(--min-chars-end-ch);
2131
}
2232
}

apps/developer-hub/src/components/TruncateToMiddle/index.tsx

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,38 @@
1+
import type React from "react";
12
import styles from "./index.module.scss";
23

34
export type Props = {
45
text: string;
6+
minCharsStart?: number | undefined;
7+
minCharsEnd?: number | undefined;
58
};
69

7-
const TruncateToMiddle = ({ text }: Props) => {
10+
const TruncateToMiddle = ({
11+
text,
12+
minCharsStart = 0,
13+
minCharsEnd = 0,
14+
}: Props) => {
15+
// We're setting a minimum width using CSS 'ch' units, which are relative to the
16+
// width of the '0' character. This provides a good approximation for showing
17+
// a certain number of characters. However, since character widths vary
18+
// (e.g., 'i' is narrower than 'W'), the exact count of visible characters
19+
// might differ slightly from the specified 'ch' value.
20+
const style = {
21+
"--min-chars-start-ch": `${minCharsStart}ch`,
22+
"--min-chars-end-ch": `${minCharsEnd}ch`,
23+
} as React.CSSProperties;
24+
825
return (
9-
<span
10-
className={styles.truncateToMiddle}
11-
data-text-start={text.slice(0, Math.floor(text.length / 2))}
12-
data-text-end={text.slice(Math.floor(text.length / 2) * -1)}
13-
/>
26+
<>
27+
<span
28+
className={styles.truncateToMiddle}
29+
style={style}
30+
data-text-start={text.slice(0, Math.floor(text.length / 2))}
31+
data-text-end={text.slice(Math.floor(text.length / 2) * -1)}
32+
aria-hidden="true"
33+
/>
34+
<span className={styles["sr-only"]}>{text}</span>
35+
</>
1436
);
1537
};
1638

0 commit comments

Comments
 (0)