Modernize the UI and improve state for the API Tokens view.
Review Request #15345 — Created Sept. 25, 2026 and updated
The policy selection button is now using a standard Ink MenuButton,
instead of the flat list of radio buttons with an embedded link. This is
basically the same structure except that the "Custom" radio
button/editor link has been replaced with a standard "Custom policy..."
menu item at the bottom. Instead of a radio selection there, the menu
button label will just indicate that Custom is chosen.The button is sized to provide enough room for the longest policy name
in the menu. This prevents the button from resizing when changing
policies.During save, the menu button will now be set to a busy state. The
existing spinner is still shown, which kind of lasts a bit longer than
the busy state and provides the same feedback all edits provide.The previous custom policy is remembered during the page's session. This
allows the user to go from Custom to (say) Read-Only and then back
without losing the Custom policy, which was an issue before.Some of the layout has been fixed to be less squashed together and to
fix wrapping issues on mobile.
Tested switching policies on several tokens.
Tested going between new custom policies and built-in policies and
back, verifying the custom policies weren't lost.
| Summary | ID |
|---|---|
| 1332f9d292d6fdbfd4dde096e8a2a65975b79a96 |
| Description | From | Last Updated |
|---|---|---|
|
We should have tests for the new model state logic (setPolicyType(), saveCustomPolicy(), the #lastCustomPolicy round-trip, and rollback in savePolicy() should … |
|
|
|
policyType is only set to "custom" in initialize() and saveCustomPolicy(), both of which set this.#lastCustomPolicy. So this block seems redundant. |
|
|
|
Before, the policy editor would load this.model.get('policy'), so a token set to read-only would open the editor starting with a … |
|
|
|
typo: will shown -> will show |
|
|
|
This is only including the built-in labels, and not "Custom". While "Custom" in English is shorter than the built-in names, … |
|
|
|
typo: max width -> min width |
|
|
|
In ink, the busy state doesn't stop the menu from opening. We should probably set disabled alongside busy. |
|
-
-
We should have tests for the new model state logic (
setPolicyType(),saveCustomPolicy(), the#lastCustomPolicyround-trip, and rollback insavePolicy()should all be pretty easy to check) -
policyTypeis only set to "custom" ininitialize()andsaveCustomPolicy(), both of which setthis.#lastCustomPolicy. So this block seems redundant. -
Before, the policy editor would load
this.model.get('policy'), so a token set to read-only would open the editor starting with a read-only policy. Now it opensdefaultPolicies.customunless there was an earlier custom policy. Perhaps intentional, but if not, we should fall back tothis.get('policy')before the default. -
-
This is only including the built-in labels, and not "Custom". While "Custom" in English is shorter than the built-in names, it won't necessarily be if we translate it.
Can we initialize this to
this.model.collection.policiesMap[POLICY_CUSTOM].name.length? -
-
In ink, the busy state doesn't stop the menu from opening. We should probably set
disabledalongsidebusy.