mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-08-29 01:08:59 +00:00
FIX - refine Radio Sky UI controls
This commit is contained in:
@@ -1887,6 +1887,8 @@ label.sky-list-item__row {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: 28px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
flex: 1;
|
||||
|
||||
@@ -61,4 +61,13 @@ describe('SkyRange', () => {
|
||||
)
|
||||
expect(tokens).toContain('--sky-shadow-glass-thumb-glow')
|
||||
})
|
||||
|
||||
it('keeps the native range above its enlarged pointer target', () => {
|
||||
const uiDirectory = fileURLToPath(new URL('..', import.meta.url))
|
||||
const controls = readFileSync(`${uiDirectory}/controls.css`, 'utf8')
|
||||
|
||||
expect(controls).toMatch(
|
||||
/\.sky-range__input\s*\{[^}]*position:\s*relative;[^}]*z-index:\s*1;/s,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -236,6 +236,20 @@ label.sky-settings-row__title {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sky-settings-group__list
|
||||
> .sky-field:not(.sky-field--has-label)
|
||||
.sky-field__inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sky-settings-group__list
|
||||
> .sky-field:not(.sky-field--has-label)
|
||||
.sky-field__control {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sky-settings-group__list > .sky-field .sky-field__label {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
|
||||
@@ -65,4 +65,13 @@ describe('SkySettingsGroup', () => {
|
||||
/\.sky-settings-group__title\s*\{[^}]*margin:\s*32px 16px 8px/s,
|
||||
)
|
||||
})
|
||||
|
||||
it('centers standalone fields without the base field negative margins', () => {
|
||||
expect(settingsStyles).toMatch(
|
||||
/\.sky-settings-group__list\s*>\s*\.sky-field:not\(\.sky-field--has-label\)\s*\.sky-field__inner\s*\{[^}]*display:\s*flex[^}]*justify-content:\s*center/s,
|
||||
)
|
||||
expect(settingsStyles).toMatch(
|
||||
/\.sky-settings-group__list\s*>\s*\.sky-field:not\(\.sky-field--has-label\)\s*\.sky-field__control\s*\{[^}]*margin:\s*0/s,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -78,6 +78,69 @@ describe('RadioApp Sky UI contract', () => {
|
||||
expect(source).toContain('connectHistory(entry)')
|
||||
})
|
||||
|
||||
it('keeps the volume slider inside its Sky list row and exposes speaker progress', () => {
|
||||
const volumeTitle = ':title="phone.t(\'Apps.radio.volume\')"'
|
||||
const volumeRowStart = source.lastIndexOf(
|
||||
'<SkyListItem',
|
||||
source.indexOf(volumeTitle),
|
||||
)
|
||||
const volumeRow = source.slice(
|
||||
volumeRowStart,
|
||||
source.indexOf(
|
||||
'</SkyListItem>',
|
||||
volumeRowStart,
|
||||
) + '</SkyListItem>'.length,
|
||||
)
|
||||
|
||||
expect(volumeRow).toContain('<template #after>')
|
||||
expect(volumeRow).toContain('<template #inner>')
|
||||
expect(volumeRow).toContain('<SkyRange')
|
||||
expect(volumeRow).not.toContain(':caption=')
|
||||
expect(source.match(/media-class="radio-audio-control-icon"/g)).toHaveLength(
|
||||
2,
|
||||
)
|
||||
expect(source.match(/:strong-title="false"/g)).toHaveLength(2)
|
||||
expect(
|
||||
source.match(/title-font-size-ios="radio-audio-control-title"/g),
|
||||
).toHaveLength(2)
|
||||
expect(source).toMatch(
|
||||
/:deep\(\.radio-audio-control-icon\)\s*\{[^}]*color:\s*var\(--sky-text\)/s,
|
||||
)
|
||||
expect(source).toMatch(
|
||||
/:deep\(\.radio-audio-control-title\)\s*\{[^}]*font-size:\s*12px[^}]*font-weight:\s*400[^}]*line-height:\s*16px/s,
|
||||
)
|
||||
expect(source).toContain('inner-class="radio-speaker-content"')
|
||||
expect(source).toMatch(
|
||||
/:deep\(\.radio-speaker-content \.sky-list-item__subtitle\)\s*\{[^}]*color:\s*var\(--sky-muted\)[^}]*font-size:\s*12px[^}]*line-height:\s*16px/s,
|
||||
)
|
||||
expect(source).toContain(':aria-busy="radio.speakerPending || undefined"')
|
||||
expect(source).toContain(
|
||||
':disabled="!radio.data.connected || radio.speakerPending"',
|
||||
)
|
||||
})
|
||||
|
||||
it('uses the rounded Sky button treatment for both primary actions', () => {
|
||||
const primaryActions = source.slice(
|
||||
source.indexOf('<div class="radio-primary-action">'),
|
||||
source.indexOf(
|
||||
'</div>',
|
||||
source.indexOf('<div class="radio-primary-action">'),
|
||||
) + '</div>'.length,
|
||||
)
|
||||
|
||||
expect(primaryActions.match(/<SkyButton\b/g)).toHaveLength(2)
|
||||
expect(primaryActions.match(/\r?\n\s+rounded\r?\n/g)).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('keeps the recently connected list close to its section title', () => {
|
||||
expect(source).toContain(
|
||||
'<SkyList v-else inset strong class="radio-history-list">',
|
||||
)
|
||||
expect(source).toMatch(
|
||||
/\.radio-history-list\s*\{[^}]*margin-top:\s*var\(--sky-space-2\)/s,
|
||||
)
|
||||
})
|
||||
|
||||
it('preserves theme, labels, loading, empty, error and feedback states', () => {
|
||||
expect(source).toContain(':dark="phone.isDarkMode"')
|
||||
expect(source).toContain(':label="phone.t(\'Apps.radio.name\')"')
|
||||
|
||||
@@ -291,27 +291,42 @@ onBeforeUnmount(() => {
|
||||
<span class="radio-unit">{{ phone.t('Apps.radio.mhz') }}</span>
|
||||
</template>
|
||||
</SkyField>
|
||||
<SkyListItem>
|
||||
<SkyListItem
|
||||
media-class="radio-audio-control-icon"
|
||||
:strong-title="false"
|
||||
:title="phone.t('Apps.radio.volume')"
|
||||
title-font-size-ios="radio-audio-control-title"
|
||||
>
|
||||
<template #media>
|
||||
<Volume2 :size="20" aria-hidden="true" />
|
||||
</template>
|
||||
<SkyRange
|
||||
id="radio-volume"
|
||||
v-model="volumeInput"
|
||||
:aria-label="phone.t('Apps.radio.volume')"
|
||||
:aria-value-text="`${volumeInput}%`"
|
||||
:caption="phone.t('Apps.radio.volume')"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="1"
|
||||
@change="saveVolume"
|
||||
>
|
||||
<output for="radio-volume">{{ volumeInput }}%</output>
|
||||
</SkyRange>
|
||||
<template #after>
|
||||
<output class="radio-volume-value" for="radio-volume">
|
||||
{{ volumeInput }}%
|
||||
</output>
|
||||
</template>
|
||||
<template #inner>
|
||||
<SkyRange
|
||||
id="radio-volume"
|
||||
v-model="volumeInput"
|
||||
class="radio-volume-slider"
|
||||
:aria-label="phone.t('Apps.radio.volume')"
|
||||
:aria-value-text="`${volumeInput}%`"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:step="1"
|
||||
@change="saveVolume"
|
||||
/>
|
||||
</template>
|
||||
</SkyListItem>
|
||||
<SkyListItem
|
||||
v-if="radio.data.speakerSupported"
|
||||
inner-class="radio-speaker-content"
|
||||
media-class="radio-audio-control-icon"
|
||||
:aria-busy="radio.speakerPending || undefined"
|
||||
:strong-title="false"
|
||||
:title="phone.t('Apps.radio.speaker')"
|
||||
title-font-size-ios="radio-audio-control-title"
|
||||
:subtitle="phone.t('Apps.radio.speakerDescription')"
|
||||
>
|
||||
<template #media>
|
||||
@@ -333,6 +348,7 @@ onBeforeUnmount(() => {
|
||||
v-if="!radio.data.connected"
|
||||
block
|
||||
large
|
||||
rounded
|
||||
:disabled="radio.isLoading"
|
||||
@click="connect()"
|
||||
>
|
||||
@@ -342,6 +358,7 @@ onBeforeUnmount(() => {
|
||||
v-else
|
||||
block
|
||||
large
|
||||
rounded
|
||||
variant="danger"
|
||||
:disabled="radio.isLoading"
|
||||
@click="disconnect"
|
||||
@@ -392,7 +409,7 @@ onBeforeUnmount(() => {
|
||||
<Clock3 :size="32" aria-hidden="true" />
|
||||
</template>
|
||||
</SkyEmptyState>
|
||||
<SkyList v-else inset strong>
|
||||
<SkyList v-else inset strong class="radio-history-list">
|
||||
<SkyListItem
|
||||
v-for="entry in radio.data.history"
|
||||
:key="`${entry.primary}-${entry.secondary}`"
|
||||
@@ -549,10 +566,41 @@ onBeforeUnmount(() => {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.radio-volume-slider {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.radio-volume-value {
|
||||
color: var(--sky-muted);
|
||||
font-size: 12px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
:deep(.radio-audio-control-icon) {
|
||||
color: var(--sky-text);
|
||||
}
|
||||
|
||||
:deep(.radio-audio-control-title) {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
:deep(.radio-speaker-content .sky-list-item__subtitle) {
|
||||
color: var(--sky-muted);
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.radio-primary-action {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.radio-history-list {
|
||||
margin-top: var(--sky-space-2);
|
||||
}
|
||||
|
||||
.radio-error {
|
||||
margin: 9px 4px 0;
|
||||
color: var(--sky-danger);
|
||||
|
||||
Reference in New Issue
Block a user