mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-22 22:29:30 +00:00
Take the section rules from the device menu's new design
- The camera menu drew its own rule under each heading, because the menu suppressed Compound's. It no longer does, so ours drew a second one: the separator, its class and the heading override all go. - The grid is its section's first control, so it starts under its rule where a device row's control starts under that one. - Guarded in the story: two headings, each ruled edge to edge, nothing else dividing them, and both sections' first controls level. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -136,22 +136,6 @@ Please see LICENSE in the repository root for full details.
|
||||
outline-offset: calc(-1 * var(--cpd-border-width-2));
|
||||
}
|
||||
|
||||
/* A heading that is ruled off sits closer to its rule than the menu's own
|
||||
spacing allows, which is set for a heading with nothing under it. */
|
||||
.menu .sectionHeadingRuled h3 {
|
||||
padding-block-end: var(--cpd-space-1x);
|
||||
}
|
||||
|
||||
/* The rule under a section heading, drawn edge to edge. A separator insets
|
||||
itself by default, which leaves it floating short of the menu's sides.
|
||||
The menu also gives a separator room beneath it, for one dividing two
|
||||
sections; under a heading that reads as the heading floating away from
|
||||
what it names. */
|
||||
.menu .sectionRule {
|
||||
margin-inline: 0;
|
||||
margin-block-end: var(--cpd-space-3x);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Background effects grid.
|
||||
*
|
||||
@@ -183,11 +167,12 @@ Please see LICENSE in the repository root for full details.
|
||||
their left edge up with the "B" of the heading above them and with the
|
||||
radio buttons above that. Matching the surrounding boxes instead puts the
|
||||
tiles to the left of both, since a heading insets its own text. */
|
||||
/* The same distance to the menu's frame on every side. The rule above and
|
||||
the menu's own bottom padding already supply part of that, so what is set
|
||||
here is only the remainder: the sides carry it all, the top is topped up
|
||||
over the rule's spacing, and the bottom is left to the menu. */
|
||||
padding: var(--cpd-space-1x) var(--cpd-space-4x) 0;
|
||||
/* The sides carry the full inset to the menu's frame. Above, the grid is
|
||||
the first control of its section, so it starts where a device row's
|
||||
control starts under its own rule: the heading's spacing supplies most of
|
||||
that, and this adds the same step a device row holds above its control.
|
||||
Below, the menu's own padding is already the inset, so nothing is set. */
|
||||
padding: var(--cpd-space-2x) var(--cpd-space-4x) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -823,6 +823,40 @@ export const BackgroundEffects: Story = {
|
||||
const canvas = within(canvasElement);
|
||||
await userEvent.click(canvas.getByRole("button", { name: "Camera" }));
|
||||
|
||||
// The section is headed by its own rule, drawn edge to edge like the
|
||||
// camera section's above it, and nothing divides the two besides.
|
||||
const menu = document.body.querySelector("[role='menu']")!;
|
||||
await expect(
|
||||
document.body.querySelectorAll("[role='separator']"),
|
||||
).toHaveLength(0);
|
||||
const headings = document.body.querySelectorAll<HTMLElement>(
|
||||
`.${styles.sectionHeading}`,
|
||||
);
|
||||
await expect(headings).toHaveLength(2);
|
||||
const frame = menu.getBoundingClientRect();
|
||||
const rules = [...headings].map((h) => h.querySelector("h3")!);
|
||||
for (const rule of rules) {
|
||||
await expect(
|
||||
Number.parseFloat(getComputedStyle(rule).borderBottomWidth),
|
||||
).toBeGreaterThan(0);
|
||||
const box = rule.getBoundingClientRect();
|
||||
await expect(box.left - frame.left).toBeLessThanOrEqual(2);
|
||||
await expect(frame.right - box.right).toBeLessThanOrEqual(2);
|
||||
}
|
||||
|
||||
// The grid is its section's first control, so it starts under its rule
|
||||
// where the camera list's first control starts under that one. Stated as
|
||||
// the two being level, because the design draws them level; measured off
|
||||
// the mock they sit within a couple of pixels of each other.
|
||||
const radio = document.body.querySelector("input[type='radio']")!;
|
||||
const tile = document.body.querySelector(`.${styles.effectTile}`)!;
|
||||
const under = (control: Element, rule: Element): number =>
|
||||
control.getBoundingClientRect().top -
|
||||
rule.getBoundingClientRect().bottom;
|
||||
await expect(
|
||||
Math.abs(under(radio, rules[0]) - under(tile, rules[1])),
|
||||
).toBeLessThanOrEqual(1);
|
||||
|
||||
const blur = await within(document.body).findByRole("menuitemradio", {
|
||||
name: "Blur",
|
||||
});
|
||||
|
||||
@@ -721,21 +721,9 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
|
||||
</>
|
||||
)}
|
||||
<div role="group" aria-label={optionsButtonLabel}>
|
||||
<div
|
||||
ref={heading}
|
||||
aria-hidden
|
||||
className={classNames(styles.sectionHeading, {
|
||||
[styles.sectionHeadingRuled]: iconsAndLabels === "video",
|
||||
})}
|
||||
>
|
||||
<div ref={heading} aria-hidden className={styles.sectionHeading}>
|
||||
<MenuTitle title={optionsButtonLabel} />
|
||||
</div>
|
||||
{/* The camera menu rules off under each heading. The microphone
|
||||
menu still divides its two sections instead, which is the
|
||||
design the audio menu was drawn to. */}
|
||||
{iconsAndLabels === "video" && (
|
||||
<Separator className={styles.sectionRule} />
|
||||
)}
|
||||
{/* The heading sits outside, so the meter can never ride up over it:
|
||||
sticky only holds while this block is in view. */}
|
||||
<div role="none">
|
||||
@@ -762,16 +750,9 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
|
||||
role="group"
|
||||
aria-label={t("settings.background_effects_header")}
|
||||
>
|
||||
<div
|
||||
aria-hidden
|
||||
className={classNames(
|
||||
styles.sectionHeading,
|
||||
styles.sectionHeadingRuled,
|
||||
)}
|
||||
>
|
||||
<div aria-hidden className={styles.sectionHeading}>
|
||||
<MenuTitle title={t("settings.background_effects_header")} />
|
||||
</div>
|
||||
<Separator className={styles.sectionRule} />
|
||||
<div role="none" className={styles.effectGrid}>
|
||||
{effectTiles()}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user