Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions e2e/pageobjects/canvas.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,49 @@ export const canvas = {
);
},

/**
* What the language badge is drawn outside its band, and how many boxes the selected chip
* in the rail draws around it.
*
* ⚠️ Both come from the badge having a border of its own. The band is `overflow: hidden`,
* so a badge taller than its line box is cut; and a chip that draws its own outline around
* a badge that already has one reads as two rings rather than as a selection.
*/
badgeBoxes(): Promise<{ cutByBand: number; outlines: number } | null> {
return browser.execute(() => {
const band = document.querySelector('.card-head');
const onCard = band?.querySelector('.lang-tag');
const chip = document.querySelector('.language-chip.on');
const inChip = chip?.querySelector('.lang-tag');
if (!band || !onCard || !chip || !inChip) return null;

// A border nobody can see is not an outline, whatever its width says. ⚠️ `transparent`
// computes to `rgba(…, 0)`, so the alpha is what decides — read by splitting rather
// than by matching, which is one escaping mistake fewer in a string sent to the page.
const drawn = (element: Element) => {
const style = getComputedStyle(element);
const channels = style.borderTopColor
.slice(style.borderTopColor.indexOf('(') + 1, style.borderTopColor.lastIndexOf(')'))
.split(',');
const alpha = channels.length > 3 ? Number(channels[3]) : 1;

return alpha > 0 && Number.parseFloat(style.borderTopWidth) > 0 ? 1 : 0;
};

const bandBox = band.getBoundingClientRect();
const badgeBox = onCard.getBoundingClientRect();

return {
cutByBand: Math.max(
0,
Math.round(bandBox.top - badgeBox.top),
Math.round(badgeBox.bottom - bandBox.bottom),
),
outlines: drawn(chip) + drawn(inChip),
};
});
},

/**
* How far each todo row is drawn **outside** the box that holds it, in pixels. ⚠️ Counting
* the rows in the DOM is not the same question: `.card-items` is `overflow: hidden` and
Expand Down
19 changes: 19 additions & 0 deletions e2e/specs/06-search-and-filters.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,25 @@ describe('Search, filters and facets', () => {
expect(await $(testid('search-matched')).isExisting()).toBe(false);
});

/**
* ⚠️ Both halves of #201, and both came from the hairline #196 gave the badge. On a card
* the band is `overflow: hidden` and a `<span>` is inline, so the badge's border hung
* outside the line box its host was sized to and was cut. In the rail the chip drew a
* second outline two pixels further out, at a different radius — two rings around one
* badge rather than a selection.
*/
it('draws the badge whole, with one outline around the selected one', async () => {
await canvas.toggleLanguage('sh');

const boxes = await canvas.badgeBoxes();

expect(boxes).not.toBeNull();
expect(boxes?.cutByBand).toBe(0);
expect(boxes?.outlines).toBe(1);

await canvas.toggleLanguage('sh');
});

it('drops the search, the tag and the language in one click', async () => {
await canvas.search('Docker');
await canvas.toggleTag('ops');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@
flex-shrink: 0;
}

.language-chip:hover {
// ⚠️ The chip's own box stays invisible: the badge carries a hairline of its own since
// #196, and a second outline two pixels further out — at a different radius — read as two
// rings around one badge rather than as a selection. The padding stays, because it is what
// the chip is clickable by.
.language-chip:hover .lang-tag {
border-color: var(--line);
}

.language-chip.on {
.language-chip.on .lang-tag {
border-color: var(--amber);
background: var(--bg-2);
}
Expand Down
5 changes: 5 additions & 0 deletions src/app/notes/ui/language-badge/language-badge.component.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
@use 'mixins' as *;

// ⚠️ A box of its own, not an inline run. A `<span>` is inline by default, so its padding
// and its border hang outside the line box its host is sized to — and `.card-head` is
// `overflow: hidden`, which cut the badge by three pixels once #196 gave it a hairline.
.lang-tag {
display: inline-flex;
align-items: center;
font-family: var(--font-mono), serif;
font-size: 9.5px;
padding: 2px 6px;
Expand Down