Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion src/modules/home/components/utils/home.content.component.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<div>
<v-card-title :class="[alignmentClass, variant === 'default' ? 'pa-0' : '']">
<!-- Level 1: Icon + Title (inline) -->
<div v-if="setup.icon || setup.title" :class="['d-flex align-center ga-2 my-0', justifyClass]">
<div v-if="setup.icon || setup.title" :class="['d-flex align-center ga-2 my-0', titleRowClass]">
<v-icon v-if="setup.icon" size="x-small" :color="themeColor || 'primary'">{{ setup.icon }}</v-icon>
<span
v-if="setup.title"
Expand Down Expand Up @@ -150,6 +150,28 @@ export default {
if (this.computedAlignment === 'right') return 'justify-end';
return 'justify-start';
},
/**
* Justify + (optional) row-reverse class for the icon+title row only.
*
* When `computedAlignment === 'right'`, the row is visually reversed via
* `flex-row-reverse` so the icon sits on the right side of the title.
* Because `flex-row-reverse` also inverts the main axis, `justify-end`
* would push items to the LEFT edge, so we use `justify-start` instead —
* under a reversed row `flex-start` is the right edge, which is what we
* want for a right-aligned block.
*
* Note: `flex-row-reverse` only changes the visual order, not the DOM
* order. Assistive tech still reads `[icon][title]`, so screen-reader
* order is preserved.
*
* Scoped to the title row only — `v-card-actions` keeps using
* `justifyClass` so button content order is untouched.
* @returns {string} space-separated utility classes
*/
titleRowClass() {
if (this.computedAlignment === 'right') return 'justify-start flex-row-reverse';
return this.justifyClass;
},
themeColor() {
if (this.color === 'light') {
return this.theme.themes.light.colors.onSurface;
Expand Down
40 changes: 38 additions & 2 deletions src/modules/home/tests/home.content.component.unit.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,50 @@ describe('HomeContentComponent', () => {
});
const title = wrapper.findComponent({ name: 'VCardTitle' });
expect(title.classes()).toContain('text-right');
const iconRow = title.find('div.d-flex');
expect(iconRow.classes()).toContain('justify-end');
const text = wrapper.findComponent({ name: 'VCardText' });
expect(text.classes()).toContain('text-right');
const actions = wrapper.findComponent({ name: 'VCardActions' });
expect(actions.classes()).toContain('justify-end');
});

it('reverses icon+title row order (flex-row-reverse) when right-aligned so the icon hugs the right edge', () => {
const wrapper = mount(HomeContentComponent, {
props: { setup: { ...baseSetup }, alignment: 'right' },
global: globalOpts(vuetify),
});
const title = wrapper.findComponent({ name: 'VCardTitle' });
const iconRow = title.find('div.d-flex');
// flex-row-reverse visually swaps icon + title
expect(iconRow.classes()).toContain('flex-row-reverse');
// under flex-row-reverse, justify-start = right edge (main axis is inverted)
// so we MUST use justify-start (not justify-end) to hug the right edge
expect(iconRow.classes()).toContain('justify-start');
expect(iconRow.classes()).not.toContain('justify-end');
// must not leak onto v-card-actions (would flip button content order)
const actions = wrapper.findComponent({ name: 'VCardActions' });
expect(actions.classes()).not.toContain('flex-row-reverse');
});

it('does NOT apply flex-row-reverse to the icon+title row when left-aligned', () => {
const wrapper = mount(HomeContentComponent, {
props: { setup: { ...baseSetup }, alignment: 'left' },
global: globalOpts(vuetify),
});
const iconRow = wrapper.findComponent({ name: 'VCardTitle' }).find('div.d-flex');
expect(iconRow.classes()).not.toContain('flex-row-reverse');
expect(iconRow.classes()).toContain('justify-start');
});

it('does NOT apply flex-row-reverse to the icon+title row when center-aligned', () => {
const wrapper = mount(HomeContentComponent, {
props: { setup: { ...baseSetup }, alignment: 'center' },
global: globalOpts(vuetify),
});
const iconRow = wrapper.findComponent({ name: 'VCardTitle' }).find('div.d-flex');
expect(iconRow.classes()).not.toContain('flex-row-reverse');
expect(iconRow.classes()).toContain('justify-center');
});

it('applies text-center and justify-center classes in the DOM when center-aligned', () => {
const wrapper = mount(HomeContentComponent, {
props: { setup: { ...baseSetup }, alignment: 'center' },
Expand Down
Loading