Skip to content

Commit 4d4f64a

Browse files
committed
feat(health-details): improve layout and accessibility of health details
1 parent b5c0c69 commit 4d4f64a

3 files changed

Lines changed: 41 additions & 20 deletions

File tree

spring-boot-admin-server-ui/src/main/frontend/components/sba-icon-button.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ export default defineComponent({
4141
default: null,
4242
},
4343
icon: {
44-
type: [Object, Array, String] as PropType<Array<string> | string | IconDefinition>,
44+
type: [Object, Array, String] as PropType<
45+
Array<string> | string | IconDefinition
46+
>,
4547
required: true,
4648
},
4749
size: {

spring-boot-admin-server-ui/src/main/frontend/views/instances/details/details-health.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,15 @@
7676
'rotate-90': isHealthGroupOpen(group.name),
7777
}"
7878
/>
79-
<span v-text="$t('instances.details.health_group.title')"></span
80-
>:&nbsp;
81-
<span v-text="group.name"></span>
79+
<span
80+
v-text="$t('instances.details.health_group.title')"
81+
/>:&nbsp; <span v-text="group.name"></span>
82+
<sba-status-badge
83+
v-if="group.data?.status"
84+
class="ml-2 fade"
85+
:status="group.data?.status"
86+
/>
87+
8288
<font-awesome-icon
8389
v-if="healthGroupLoadingMap[group.name]"
8490
icon="sync-alt"

spring-boot-admin-server-ui/src/main/frontend/views/instances/details/health-details.vue

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616

1717
<template>
1818
<dl
19-
class="px-4 py-3"
20-
:class="{ 'bg-white': index % 2 === 0, 'bg-gray-100': index % 2 !== 0 }"
19+
class="px-4 py-3 even:bg-white odd:bg-gray-50"
2120
role="group"
2221
:aria-label="name"
2322
>
@@ -32,21 +31,27 @@
3231
<sba-status-badge v-if="health.status" :status="health.status" />
3332
</div>
3433
<div v-if="details && details.length > 0" class="w-12 text-right">
35-
<sba-icon-button
36-
class="p-0!"
34+
<sba-button
35+
class="p-0! border-none"
3736
:class="
3837
classNames({
3938
'text-sba-600!': !isCollapsed,
4039
'text-black': isCollapsed,
4140
})
4241
"
43-
:icon="faCircleInfo"
4442
:title="t('instances.details.health.toggle_details', { name })"
4543
:aria-label="t('instances.details.health.toggle_details', { name })"
4644
:aria-expanded="String(!isCollapsed)"
4745
:aria-controls="`health-details-${id}__${safeNameId}`"
4846
@click="() => toggleCollapsed()"
49-
/>
47+
>
48+
<font-awesome-icon
49+
:icon="faChevronRight"
50+
class="transition-transform"
51+
:class="{ 'rotate-90': !isCollapsed }"
52+
/>
53+
<font-awesome-icon :icon="faCircleInfo" />
54+
</sba-button>
5055
</div>
5156
</dt>
5257
<dd
@@ -55,7 +60,10 @@
5560
:aria-labelledby="`health-${id}__${safeNameId}`"
5661
>
5762
<dl v-if="!isCollapsed" class="grid grid-cols-6 mt-2">
58-
<template v-for="(detail, idx) in details" :key="`${detail.name}_${idx}`">
63+
<template
64+
v-for="(detail, idx) in details"
65+
:key="`${detail.name}_${idx}`"
66+
>
5967
<dt
6068
:id="`health-detail-${id}__${safeDetailId(detail.name, idx)}`"
6169
class="font-medium col-span-2"
@@ -73,7 +81,9 @@
7381
v-text="prettyBytes(detail.value as number)"
7482
/>
7583
<dd
76-
v-else-if="detail.value !== null && typeof detail.value === 'object'"
84+
v-else-if="
85+
detail.value !== null && typeof detail.value === 'object'
86+
"
7787
class="col-span-4"
7888
role="definition"
7989
:aria-label="detail.name"
@@ -101,7 +111,6 @@
101111
v-for="(child, idx) in childHealth"
102112
:key="`${child.name}_${idx}`"
103113
:instance="instance"
104-
:index="idx"
105114
:depth="depth + 1"
106115
:name="child.name"
107116
:health="child.value"
@@ -110,30 +119,34 @@
110119
</template>
111120

112121
<script lang="ts" setup>
113-
import { faCircleInfo } from '@fortawesome/free-solid-svg-icons';
122+
import {
123+
faChevronRight,
124+
faCircleInfo,
125+
} from '@fortawesome/free-solid-svg-icons';
114126
import classNames from 'classnames';
115127
import prettyBytes from 'pretty-bytes';
116128
import { computed, ref, useId, watch } from 'vue';
117129
import { useI18n } from 'vue-i18n';
118130
119131
import SbaFormattedObj from '@/components/sba-formatted-obj.vue';
120-
import SbaIconButton from '@/components/sba-icon-button.vue';
121132
122133
import Instance from '@/services/instance';
123134
import autolink from '@/utils/autolink';
124135
125136
const { t } = useI18n();
126137
const id = useId();
127138
128-
const { health, name, instance, index = 0, depth = 0 } = defineProps<{
139+
const {
140+
health,
141+
name,
142+
instance,
143+
depth = 0,
144+
} = defineProps<{
129145
instance: Instance;
130146
name: string;
131147
health: Record<string, any>;
132-
/** Row position within siblings — drives even/odd background alternation. */
133-
index?: number;
134-
/** Recursion depth — used to prevent infinite nesting. */
135148
depth?: number;
136-
}>();
149+
}>();
137150
138151
// Sanitised name safe for use in HTML id attributes
139152
const safeNameId = computed(() => (name ?? '').replace(/[^a-zA-Z0-9_-]/g, '_'));

0 commit comments

Comments
 (0)