Account · Profile and access: a key's ends stay whole, keys drawn literally

A key's name gives way before its ends, which keep their width. The
ends and a new secret draw through typography::literal. Tests show this
device listing first and the name field emptying after Create.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-09-27 13:38:40 -04:00
1 parent 24e0366e0e
commit 91d939e21e
4 files changed
+36 -10

No files matched your search

+1
View File
@@ -404,3 +404,4 @@ Per-component lines live in `tasks/`. Tags there:
| T35 | 3 | PASS | | | T35 | 3 | PASS | |
| T36a | 1 | FAIL | Sign in waiting for a password and resting while busy, Create account waiting for a name, the other providers resting, and Send again resting while busy untested | | T36a | 1 | FAIL | Sign in waiting for a password and resting while busy, Create account waiting for a name, the other providers resting, and Send again resting while busy untested |
| T36a | 2 | PASS | | | T36a | 2 | PASS | |
| T36b | 1 | FAIL | a long key name hid its ends at 280px; the secret and ends skipped typography::literal; this device's place first and the name clearing after Create untested |
+9 -9
View File
@@ -12,7 +12,7 @@ use crate::{
forms::{Enter, Input}, forms::{Enter, Input},
primitives::Severity, primitives::Severity,
theme::{ActiveTheme, ControlSize, TextSize}, theme::{ActiveTheme, ControlSize, TextSize},
typography::Ellipsis, typography::{Ellipsis, literal},
}; };
type OnKey = Rc<dyn Fn(&SharedString, &mut Window, &mut App)>; type OnKey = Rc<dyn Fn(&SharedString, &mut Window, &mut App)>;
@@ -114,7 +114,7 @@ impl RenderOnce for ApiKeyManager {
.gap_2() .gap_2()
.child( .child(
div().flex().child( div().flex().child(
div() literal(div())
.flex_1() .flex_1()
.min_w_0() .min_w_0()
.font_family(mono.clone()) .font_family(mono.clone())
@@ -154,19 +154,19 @@ impl RenderOnce for ApiKeyManager {
div() div()
.flex() .flex()
.gap_2() .gap_2()
.child(
div()
.flex_none()
.font_weight(FontWeight::MEDIUM)
.child(each.name.clone()),
)
.child( .child(
div() div()
.flex_1() .flex_1()
.min_w_0() .min_w_0()
.font_weight(FontWeight::MEDIUM)
.child(Ellipsis::new(each.name.clone())),
)
.child(
literal(div())
.flex_none()
.font_family(mono.clone()) .font_family(mono.clone())
.text_color(theme.colors.fg_muted) .text_color(theme.colors.fg_muted)
.child(Ellipsis::new(each.hint.clone())), .child(each.hint.clone()),
), ),
) )
.child( .child(
+2
View File
@@ -93,7 +93,9 @@ impl RenderOnce for SessionList {
.into_any_element() .into_any_element()
} }
}; };
let tag = format!("session-{}", session.key);
div() div()
.debug_selector(move || tag)
.flex() .flex()
.items_center() .items_center()
.gap_3() .gap_3()
+24 -1
View File
@@ -104,6 +104,17 @@ fn a_key_is_made_by_name_revoked_on_the_second_press_and_its_secret_dismissed(
write("Deploys", cx); write("Deploys", cx);
tap("enter", cx); tap("enter", cx);
assert_eq!(said(&host, cx), ["revoke ci", "make Deploys"]); assert_eq!(said(&host, cx), ["revoke ci", "make Deploys"]);
cx.executor()
.advance_clock(std::time::Duration::from_secs(10));
settle(cx);
tab(2, cx);
tap("space", cx);
tap("space", cx);
assert_eq!(
said(&host, cx),
["revoke ci", "make Deploys", "revoke ci"],
"the name field emptied, so Create rests and the second stop is Revoke"
);
host.update(cx, |bench, cx| { host.update(cx, |bench, cx| {
bench.sent = true; bench.sent = true;
cx.notify(); cx.notify();
@@ -111,7 +122,10 @@ fn a_key_is_made_by_name_revoked_on_the_second_press_and_its_secret_dismissed(
settle(cx); settle(cx);
tab(2, cx); tab(2, cx);
tap("space", cx); tap("space", cx);
assert_eq!(said(&host, cx), ["revoke ci", "make Deploys", "done"]); assert_eq!(
said(&host, cx),
["revoke ci", "make Deploys", "revoke ci", "done"]
);
} }
fn profile() -> Profile { fn profile() -> Profile {
@@ -223,3 +237,12 @@ fn this_device_alone_offers_no_sign_out(cx: &mut TestAppContext) {
tap("space", cx); tap("space", cx);
assert!(said(&host, cx).is_empty()); assert!(said(&host, cx).is_empty());
} }
/// The phone comes first in what the owner hands over, this device second; this device lists first.
#[gpui::test]
fn this_device_lists_first(cx: &mut TestAppContext) {
let (_, cx) = bench(sessions, cx);
let here = cx.debug_bounds("session-mac").expect("this device");
let phone = cx.debug_bounds("session-phone").expect("the phone");
assert!(here.top() < phone.top(), "{here:?} over {phone:?}");
}