Skip to content

Commit 9990ca9

Browse files
committed
fix(ui): reset location dropdown list styling and show required mark when only timezone is required
1 parent 5b1d577 commit 9990ca9

3 files changed

Lines changed: 47 additions & 3 deletions

File tree

packages/ui/src/components/endpoint-form.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,10 +522,12 @@ export class RoxyEndpointForm extends LitElement {
522522
return LOCATION_TRIO.every((n) => inGroup.some((f) => f.name === n));
523523
}
524524

525-
/** True when the location trio in a group is required, so the block shows a required mark. */
525+
/**
526+
* True when the location block must show a required mark, i.e. ANY member of the trio is required. The block is a single city-search input that fills all three, so if even one is required (e.g. bodygraph requires `timezone` while `latitude`/`longitude` are optional) the input is required and `collectMissing` blocks submit without it. Requiring ALL three understated that: the asterisk went missing on a block the form still enforced, which reads as optional to a non-technical embedder.
527+
*/
526528
private locationRequired(group?: string): boolean {
527529
const inGroup = this.fields.filter((f) => f.group === group);
528-
return LOCATION_TRIO.every((n) =>
530+
return LOCATION_TRIO.some((n) =>
529531
inGroup.some((f) => f.name === n && f.required),
530532
);
531533
}

packages/ui/src/components/location-search.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ export class RoxyLocationSearch extends LitElement {
8686
top: calc(100% + 4px);
8787
left: 0;
8888
right: 0;
89+
/* Reset the UA <ul> defaults, or the listbox shows disc bullets and a
90+
* ~40px inline indent. Small even inset so rounded rows never clip the
91+
* container corners. */
92+
margin: 0;
93+
padding: var(--roxy-space-xs, 0.25rem);
94+
list-style: none;
8995
background: var(--roxy-bg, #fff);
9096
border: 1px solid var(--roxy-border, #e4e4e7);
9197
border-radius: var(--roxy-radius-md, 8px);
@@ -97,12 +103,13 @@ export class RoxyLocationSearch extends LitElement {
97103
}
98104
.option {
99105
display: flex;
100-
align-items: baseline;
106+
align-items: center;
101107
gap: var(--roxy-space-sm, 0.5rem);
102108
width: 100%;
103109
padding: var(--roxy-space-sm, 0.5rem) var(--roxy-space-md, 1rem);
104110
background: transparent;
105111
border: 0;
112+
border-radius: var(--roxy-radius-sm, 6px);
106113
text-align: left;
107114
font-family: inherit;
108115
font-size: var(--roxy-text-sm, 0.875rem);

packages/ui/tests/endpoint-form.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,41 @@ describe('endpoint-form input registry rendering', () => {
176176
el.remove();
177177
});
178178

179+
test('location block shows a required mark when only timezone is required (bodygraph shape)', async () => {
180+
// Bodygraph requires timezone but defaults latitude/longitude, so the single
181+
// city-search input is still required (collectMissing blocks submit without it).
182+
// The asterisk must reflect that, or the block reads as optional to an embedder.
183+
const el = await mountForm(
184+
{
185+
title: 'Generate full Human Design bodygraph',
186+
hasLang: true,
187+
fields: [
188+
{ key: 'date', name: 'date', kind: 'date', required: true },
189+
{ key: 'time', name: 'time', kind: 'time', required: true },
190+
{
191+
key: 'latitude',
192+
name: 'latitude',
193+
kind: 'number',
194+
required: false,
195+
},
196+
{
197+
key: 'longitude',
198+
name: 'longitude',
199+
kind: 'number',
200+
required: false,
201+
},
202+
{ key: 'timezone', name: 'timezone', kind: 'number', required: true },
203+
],
204+
},
205+
{ 'data-endpoint': 'human-design/bodygraph', method: 'POST' },
206+
);
207+
const root = el.shadowRoot as ShadowRoot;
208+
const block = root.querySelector('.location-block');
209+
expect(block).not.toBeNull();
210+
expect(block?.querySelector('.req')).not.toBeNull();
211+
el.remove();
212+
});
213+
179214
test('a failed submit renders an inline role=alert listing humanized missing fields', async () => {
180215
const el = await mountForm(
181216
{

0 commit comments

Comments
 (0)