| 660 |
660 |
|
// `pointer-events` rides along because opacity leaves the hit area
|
| 661 |
661 |
|
// behind: without it a renderer with no hover carries an invisible
|
| 662 |
662 |
|
// tappable control. Keyboard focus is unaffected by it.
|
| 663 |
|
- |
let _ = writeln!(
|
| 664 |
|
- |
css,
|
| 665 |
|
- |
".{c} {{\n opacity: 0;\n pointer-events: none;\n}}"
|
| 666 |
|
- |
);
|
|
663 |
+ |
// The hide is gated too, which it was not in 0.10.0, and that was
|
|
664 |
+ |
// an incomplete capability answer rather than a deliberate one.
|
|
665 |
+ |
// Ungated, a fingertip got actions hidden with no hover to bring
|
|
666 |
+ |
// them back, so both webview apps hand-wrote the same
|
|
667 |
+ |
// `opacity: 1` to undo it: goingson in its touch block and
|
|
668 |
+ |
// Balanced Breakfast in its own. A primitive that owns the hiding
|
|
669 |
+ |
// owes the answer for the device that cannot unhide, and the
|
|
670 |
+ |
// answer both consumers already reached is not to hide at all.
|
|
671 |
+ |
css.push_str(&gated(
|
|
672 |
+ |
hover_condition(),
|
|
673 |
+ |
&format!(".{c} {{\n opacity: 0;\n pointer-events: none;\n}}\n"),
|
|
674 |
+ |
));
|
| 667 |
675 |
|
|
| 668 |
676 |
|
// The two halves split here, where they used to be one selector
|
| 669 |
677 |
|
// list. Hover-to-reveal is the literal case `Affordance::Hover`
|
| 1028 |
1036 |
|
};
|
| 1029 |
1037 |
|
let hover = indent(".row:hover .row-actions");
|
| 1030 |
1038 |
|
let keyboard = indent(".row:focus-within .row-actions");
|
|
1039 |
+ |
// The hide is gated with the reveal. Ungated it leaves a fingertip
|
|
1040 |
+ |
// with actions it cannot bring back, which is what both webview apps
|
|
1041 |
+ |
// were undoing by hand.
|
|
1042 |
+ |
let hide = css
|
|
1043 |
+ |
.lines()
|
|
1044 |
+ |
.position(|l| l.trim() == ".row-actions {")
|
|
1045 |
+ |
.expect("hide rule");
|
|
1046 |
+ |
let query = css
|
|
1047 |
+ |
.lines()
|
|
1048 |
+ |
.take(hide)
|
|
1049 |
+ |
.enumerate()
|
|
1050 |
+ |
.filter(|(_, l)| l.trim_start().starts_with("@media"))
|
|
1051 |
+ |
.map(|(i, _)| i)
|
|
1052 |
+ |
.last()
|
|
1053 |
+ |
.expect("a query precedes it");
|
|
1054 |
+ |
assert!(hide - query < 3, "the hide is not inside the query");
|
| 1031 |
1055 |
|
assert!(
|
| 1032 |
1056 |
|
hover > keyboard,
|
| 1033 |
1057 |
|
"hover reveal must be nested inside the capability query and the \
|
| 1152 |
1176 |
|
#[test]
|
| 1153 |
1177 |
|
fn row_actions_are_revealed_without_moving_the_row() {
|
| 1154 |
1178 |
|
let css = row_rules(&Emit::default());
|
| 1155 |
|
- |
assert!(css.contains(".row-actions {\n opacity: 0;"));
|
|
1179 |
+ |
assert!(css.contains(".row-actions {\n opacity: 0;"));
|
| 1156 |
1180 |
|
// Not display:none, which would reflow the row under the pointer.
|
| 1157 |
1181 |
|
assert!(!css.contains("display: none"));
|
| 1158 |
1182 |
|
// Hover alone would lock the keyboard out.
|
| 1166 |
1190 |
|
// `visibility: hidden` takes the actions out of the focus order, so the
|
| 1167 |
1191 |
|
// `focus-within` reveal above could never fire from an action itself.
|
| 1168 |
1192 |
|
assert!(!css.contains("visibility:"));
|
| 1169 |
|
- |
// Opacity leaves the hit area behind; the row must not carry an
|
| 1170 |
|
- |
// invisible tappable control where there is no hover to reveal it.
|
| 1171 |
|
- |
assert!(css.contains(".row-actions {\n opacity: 0;\n pointer-events: none;\n}"));
|
|
1193 |
+ |
// Opacity leaves the hit area behind, so the pair travels together or
|
|
1194 |
+ |
// the row carries an invisible tappable control.
|
|
1195 |
+ |
assert!(css.contains(".row-actions {\n opacity: 0;\n pointer-events: none;\n }"));
|
| 1172 |
1196 |
|
assert!(css.contains("opacity: 1;\n pointer-events: auto;"));
|
|
1197 |
+ |
|
|
1198 |
+ |
// And on a device with no hover the row carries no such control at
|
|
1199 |
+ |
// all, because the hide never applies there. That is what the comment
|
|
1200 |
+ |
// above used to be asking for and could not get: the hide is inside
|
|
1201 |
+ |
// the capability query with the reveal.
|
|
1202 |
+ |
let hide = css.find(".row-actions {").expect("hide rule");
|
|
1203 |
+ |
let query = css[..hide].rfind("@media").expect("a query precedes it");
|
|
1204 |
+ |
assert!(css[query..hide].find('}').is_none(), "the hide escaped the query");
|
| 1173 |
1205 |
|
}
|
| 1174 |
1206 |
|
|
| 1175 |
1207 |
|
#[test]
|