refactor(webapp): ds-grid (#9248)

This commit is contained in:
Ulf Gebhardt 2026-02-20 00:57:58 +01:00 committed by GitHub
parent 5ef4fecf99
commit c269e971f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 165 additions and 130 deletions

View File

@ -194,11 +194,32 @@ Tier A ds-* → Plain HTML + CSS: ✅
## Aktueller Stand
**Letzte Aktualisierung:** 2026-02-19 (Session 27)
**Letzte Aktualisierung:** 2026-02-19 (Session 28)
**Aktuelle Phase:** Phase 4 - OsIcon ✅, BaseIcon → OsIcon Migration ✅, OsSpinner ✅, Spinner Webapp-Migration ✅, OsCard ✅, BaseCard → OsCard Migration ✅, Tier A ds-* → Plain HTML ✅
**Zuletzt abgeschlossen (Session 27 - Tier A: ds-* Komponenten → Plain HTML):**
**Zuletzt abgeschlossen (Session 28 - CodeRabbit Review Fixes für Tier A PR):**
- [x] GroupForm.vue: Fehlende `buttons`-Klasse auf Button-Container ergänzt (CSS-Regel `.group-form > .buttons` griff nicht)
- [x] ComponentSlider.vue: `<h1>``<h3>` (Original war `<ds-heading size="h3">`, falsch zu h1 migriert)
- [x] SearchHeading.vue: `<h1>``<h5>` (Original war `<ds-heading size="h5">`, falsch zu h1 migriert)
- [x] MySomethingList.vue: Redundantes verschachteltes `<div class="ds-mt-base ds-mb-large">` entfernt (Überbleibsel von verschachtelten ds-space)
- [x] Empty.vue: Prop-Type `[String, Object]``String` (Object-Support war ds-space-Relikt, nicht implementiert)
- [x] ChangePassword.vue: Inline-Spans → separate `<p class="ds-text">` Elemente (visuelle Regression: fehlende Block-Level-Trennung)
- [x] RegistrationSlideEmail.vue: Label `for="checkbox0"``for="sendEmailAgain"` passend zu `id="sendEmailAgain"` (A11y WCAG 1.3.1/4.1.2)
- [x] Signup.vue: `margin="large"` (totes ds-space-Attribut auf div) → `class="ds-my-large"` + `<style>``<style scoped>`
- [x] SocialMedia.vue: `:key="link.id"``:key="link.url"` (link.id war immer undefined, socialMediaLinks() gibt kein id zurück)
- [x] logout.vue: Hardcodierter "Logging out..." → `$t('login.loggingOut')` mit Übersetzungen in allen 9 Sprachen
- [x] maintenance/index.vue: `alt="Under maintenance"``:alt="$t('maintenance.title', metadata)"` (i18n-Konsistenz) + `<style scoped>`
- [x] admin/index.vue: `33%``33.333%` (Rundungsfehler bei 3-Spalten-Layout)
- [x] profile/_id/_slug.vue: Inline-Style `margin-bottom: 10px; text-align: center``ds-text-center ds-mb-x-small` Utility-Klassen
- [x] post/edit/_id.vue: `&nbsp;` aus Aside-Div entfernt (Screenreader-Problem) + zwei Style-Blöcke zu einem scoped Block gemergt
- [x] post/create/_type.vue: Zwei Style-Blöcke (scoped + unscoped) zu einem scoped Block gemergt
- [x] _ds-compat.scss: `display: flex` zu `.ds-space-centered` hinzugefügt (justify-content/align-items wirkten ohne display:flex nicht)
- [x] blocked-users.vue: Unnötiges Wrapper-Div `ds-mb-large` am Kartenende entfernt
- [x] Cypress SocialMedia: `cy.get('.ds-list-item a')``cy.get('.ds-list-item a[href="${link}"]')` (nutzt link-Parameter)
- [x] Als "nicht in diesem PR" bewertet: pre-existing Code-Style Nitpicks (required:false, Ternary-Syntax, Prop-Validierung, Spacer-Divs, flex:1 0 0 Einheit, v-if="user", CSS-Nesting, Dark-Mode SVG-Farbe)
**Zuvor abgeschlossen (Session 27 - Tier A: ds-* Komponenten → Plain HTML):**
- [x] `_ds-compat.scss` erstellt (Utility-Klassen für Margins, Flex, Centered)
- [x] `ds-section``<section class="ds-section">` (5 Dateien)
- [x] `ds-placeholder``<div class="ds-placeholder">` (4 Dateien)
@ -1737,6 +1758,13 @@ Bei der Migration werden:
| 2026-02-19 | **ds-flex/ds-flex-item** | 103 Nutzungen in 29 Dateien → Plain HTML + CSS `@media` Queries; JS window.innerWidth → CSS Media Queries; `gap` statt negative-margin/padding |
| 2026-02-19 | **HTML-Validierung Bugfix** | `<p>` mit Block-Level-Kindern → `<div>` in DateTimeRange.vue und verify.vue |
| 2026-02-19 | **Test-Fix** | Empty.spec.js: `attributes().margin``classes().toContain('ds-my-xxx-small')` |
| 2026-02-19 | **Review Fixes (Session 28)** | ~20 CodeRabbit Review-Kommentare für Tier A PR bearbeitet; Bugfixes, A11y, i18n, Scoping |
| 2026-02-19 | **Heading-Semantik** | ComponentSlider h1→h3, SearchHeading h1→h5 (ds-heading size-Prop wurde falsch zu h1 migriert) |
| 2026-02-19 | **A11y Fixes** | Label-for Mismatch (RegistrationSlideEmail), &nbsp; in Aside entfernt, link.id→link.url Key |
| 2026-02-19 | **i18n** | logout.vue "Logging out..." → $t() mit 9 Sprachen; maintenance alt-Text → $t() |
| 2026-02-19 | **CSS Fixes** | .buttons Klasse ergänzt (GroupForm), display:flex auf .ds-space-centered, 33%→33.333%, inline-style→Utilities |
| 2026-02-19 | **Scoping** | Signup.vue, maintenance/index.vue, post/create/_type.vue, post/edit/_id.vue: unscoped → scoped Style-Blöcke |
| 2026-02-19 | **Migration-Artefakte** | Redundante Wrapper-Divs, tote Attribute (margin="large"), Span→P Block-Level Regression |
---

View File

@ -53,6 +53,9 @@
background-size: 0.6em;
}
// ds-grid Ersatz
.ds-grid { display: grid; }
// ds-flex Ersatz
.ds-flex { display: flex; flex-wrap: wrap; }
.ds-flex-no-wrap { flex-wrap: nowrap; }

View File

@ -58,8 +58,8 @@
<div v-if="createEvent" class="eventDatas">
<hr />
<div class="ds-mt-x-small ds-mb-large"></div>
<ds-grid>
<ds-grid-item class="event-grid-item">
<div class="ds-grid event-date-grid">
<div class="event-grid-item">
<!-- <label>Beginn</label> -->
<div class="event-grid-item-z-helper">
<date-picker
@ -85,8 +85,8 @@
<os-icon :icon="icons.warning" />
</ds-chip>
</div>
</ds-grid-item>
<ds-grid-item class="event-grid-item">
</div>
<div class="event-grid-item">
<!-- <label>Ende (optional)</label> -->
<date-picker
@ -104,10 +104,10 @@
:show-second="false"
@change="changeEventEnd($event)"
></date-picker>
</ds-grid-item>
</ds-grid>
<ds-grid class="event-location-grid">
<ds-grid-item class="event-grid-item">
</div>
</div>
<div class="ds-grid event-location-grid">
<div class="event-grid-item">
<ds-input
model="eventVenue"
name="eventVenue"
@ -119,8 +119,8 @@
<os-icon v-if="errors && errors.eventVenue" :icon="icons.warning" />
</ds-chip>
</div>
</ds-grid-item>
<ds-grid-item v-if="showEventLocationName" class="event-grid-item">
</div>
<div v-if="showEventLocationName" class="event-grid-item">
<ds-input
model="eventLocationName"
name="eventLocationName"
@ -132,8 +132,8 @@
<os-icon v-if="errors && errors.eventLocationName" :icon="icons.warning" />
</ds-chip>
</div>
</ds-grid-item>
</ds-grid>
</div>
</div>
<div>
<input
@ -520,14 +520,15 @@ export default {
margin-top: -10px;
}
}
// style override to handle dynamic inputs
.event-date-grid,
.event-location-grid {
grid-template-columns: repeat(2, 1fr) !important;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: auto;
gap: $space-small;
}
.event-grid-item {
// important needed because of component inline style
grid-row-end: span 3 !important;
grid-row-end: span 3;
}
.event-grid-item-z-helper {
z-index: 20;

View File

@ -15,7 +15,6 @@
</os-button>
</div>
<div class="category-filter-list">
<!-- <ds-space margin="small" /> -->
<os-button
v-for="category in sortCategories(categories)"
:key="category.id"

View File

@ -6,11 +6,9 @@ const localVue = global.localVue
describe('MasonryGrid', () => {
let wrapper
let masonryGridItem
beforeEach(() => {
wrapper = mount(MasonryGrid, { localVue })
masonryGridItem = wrapper.vm.$children[0]
})
it('adds the "reset-grid-height" class when itemsCalculating is more than 0', async () => {
@ -25,16 +23,16 @@ describe('MasonryGrid', () => {
expect(wrapper.classes()).not.toContain('reset-grid-height')
})
it('adds 1 to itemsCalculating when a child emits "calculating-item-height"', async () => {
it('adds 1 to itemsCalculating when "calculating-item-height" is emitted', async () => {
wrapper.setData({ itemsCalculating: 0 })
masonryGridItem.$emit('calculating-item-height')
wrapper.vm.$emit('calculating-item-height')
await Vue.nextTick()
expect(wrapper.vm.itemsCalculating).toBe(1)
})
it('subtracts 1 from itemsCalculating when a child emits "finished-calculating-item-height"', async () => {
it('subtracts 1 from itemsCalculating when "finished-calculating-item-height" is emitted', async () => {
wrapper.setData({ itemsCalculating: 2 })
masonryGridItem.$emit('finished-calculating-item-height')
wrapper.vm.$emit('finished-calculating-item-height')
await Vue.nextTick()
expect(wrapper.vm.itemsCalculating).toBe(1)
})

View File

@ -1,11 +1,11 @@
<template>
<ds-grid
v-on:calculating-item-height="startCalculation"
v-on:finished-calculating-item-height="endCalculation"
<div
class="ds-grid"
:style="{ gridAutoRows: '20px', rowGap: '16px', columnGap: '16px' }"
:class="[itemsCalculating ? 'reset-grid-height' : '']"
>
<slot></slot>
</ds-grid>
</div>
</template>
<script>
@ -15,6 +15,14 @@ export default {
itemsCalculating: 0,
}
},
created() {
this.$on('calculating-item-height', this.startCalculation)
this.$on('finished-calculating-item-height', this.endCalculation)
},
beforeDestroy() {
this.$off('calculating-item-height', this.startCalculation)
this.$off('finished-calculating-item-height', this.endCalculation)
},
methods: {
startCalculation() {
this.itemsCalculating += 1
@ -27,11 +35,8 @@ export default {
</script>
<style lang="scss">
/* dirty fix to override broken styleguide inline-styles */
.ds-grid {
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)) !important;
gap: 16px !important;
grid-auto-rows: 20px;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
}
.reset-grid-height {

View File

@ -3,44 +3,40 @@ import MasonryGridItem from './MasonryGridItem'
const localVue = global.localVue
const stubs = {
'ds-grid-item': true,
}
describe('MasonryGridItem', () => {
let wrapper
describe('given an imageAspectRatio', () => {
it('sets the initial rowSpan to 13 when the ratio is higher than 1.3', () => {
const propsData = { imageAspectRatio: 2 }
wrapper = mount(MasonryGridItem, { localVue, propsData, stubs })
wrapper = mount(MasonryGridItem, { localVue, propsData })
expect(wrapper.vm.rowSpan).toBe(13)
})
it('sets the initial rowSpan to 15 when the ratio is between 1.3 and 1', () => {
const propsData = { imageAspectRatio: 1.1 }
wrapper = mount(MasonryGridItem, { localVue, propsData, stubs })
wrapper = mount(MasonryGridItem, { localVue, propsData })
expect(wrapper.vm.rowSpan).toBe(15)
})
it('sets the initial rowSpan to 18 when the ratio is between 1 and 0.7', () => {
const propsData = { imageAspectRatio: 0.7 }
wrapper = mount(MasonryGridItem, { localVue, propsData, stubs })
wrapper = mount(MasonryGridItem, { localVue, propsData })
expect(wrapper.vm.rowSpan).toBe(18)
})
it('sets the initial rowSpan to 25 when the ratio is lower than 0.7', () => {
const propsData = { imageAspectRatio: 0.3 }
wrapper = mount(MasonryGridItem, { localVue, propsData, stubs })
wrapper = mount(MasonryGridItem, { localVue, propsData })
expect(wrapper.vm.rowSpan).toBe(25)
})
describe('given no aspect ratio', () => {
it('sets the initial rowSpan to 8 when not given an imageAspectRatio', () => {
wrapper = mount(MasonryGridItem, { localVue, stubs })
wrapper = mount(MasonryGridItem, { localVue })
expect(wrapper.vm.rowSpan).toBe(8)
})
})

View File

@ -1,7 +1,7 @@
<template>
<ds-grid-item :rowSpan="rowSpan">
<div :style="{ gridRowEnd: 'span ' + rowSpan }">
<slot></slot>
</ds-grid-item>
</div>
</template>
<script>

View File

@ -1,21 +1,21 @@
<template>
<div class="notification-grid" v-if="notifications && notifications.length">
<ds-grid>
<ds-grid-item v-if="!isMobile" column-span="fullWidth">
<ds-grid class="header-grid">
<ds-grid-item v-for="field in fields" :key="field.label" class="ds-table-head-col">
<div class="ds-grid">
<div v-if="!isMobile" style="grid-column: 1 / -1">
<div class="ds-grid header-grid">
<div v-for="field in fields" :key="field.label" class="ds-table-head-col">
{{ field.label }}
</ds-grid-item>
</ds-grid>
</ds-grid-item>
<ds-grid-item
</div>
</div>
</div>
<div
v-for="notification in notifications"
:key="notification.id"
column-span="fullWidth"
style="grid-column: 1 / -1"
class="notification-grid-row"
>
<ds-grid>
<ds-grid-item>
<div class="ds-grid">
<div>
<div class="ds-flex user-section">
<div class="ds-flex-item">
<user-teaser
@ -30,8 +30,8 @@
/>
</div>
</div>
</ds-grid-item>
<ds-grid-item>
</div>
<div>
<div class="notification-container">
<!-- Icon with responsive sizing -->
<div class="notification-icon">
@ -78,10 +78,10 @@
</p>
</div>
</div>
</ds-grid-item>
</ds-grid>
</ds-grid-item>
</ds-grid>
</div>
</div>
</div>
</div>
</div>
<hc-empty v-else icon="alert" :message="$t('notifications.empty')" />
</template>
@ -171,7 +171,6 @@ export default {
.notification-grid .content-section {
flex-wrap: nowrap;
}
/* dirty fix to override broken styleguide inline-styles */
.notification-grid .ds-grid {
grid-template-columns: 5fr 6fr !important;
grid-auto-rows: auto !important;

View File

@ -3,14 +3,14 @@
<div class="search-results__content">
<masonry-grid>
<!-- search text -->
<ds-grid-item class="grid-total-search-results" :row-span="1" column-span="fullWidth">
<div class="grid-total-search-results" style="grid-row-end: span 1; grid-column: 1 / -1">
<div class="ds-mb-xxx-small ds-mt-xxx-small ds-space-centered">
<p class="ds-text total-search-results">
{{ $t('search.for') }}
<strong>{{ '"' + (search || '') + '"' }}</strong>
</p>
</div>
</ds-grid-item>
</div>
<!-- tabs -->
<tab-navigation :tabs="tabOptions" :activeTab="activeTab" @switch-tab="switchTab" />
@ -19,7 +19,10 @@
<template v-if="!(!activeResourceCount || searchCount === 0)">
<!-- pagination buttons -->
<ds-grid-item v-if="activeResourceCount > pageSize" :row-span="2" column-span="fullWidth">
<div
v-if="activeResourceCount > pageSize"
style="grid-row-end: span 2; grid-column: 1 / -1"
>
<div class="ds-mb-large ds-space-centered">
<pagination-buttons
:hasNext="hasNext"
@ -33,7 +36,7 @@
@next="nextResults"
/>
</div>
</ds-grid-item>
</div>
<!-- posts -->
<template v-if="activeTab === 'Post'">
@ -61,31 +64,34 @@
</template>
<!-- users -->
<template v-if="activeTab === 'User'">
<ds-grid-item v-for="user in activeResources" :key="user.id" :row-span="2">
<div v-for="user in activeResources" :key="user.id" style="grid-row-end: span 2">
<os-card>
<user-teaser :user="user" />
</os-card>
</ds-grid-item>
</div>
</template>
<!-- groups -->
<template v-if="activeTab === 'Group'">
<ds-grid-item v-for="group in activeResources" :key="group.id" :row-span="2">
<div v-for="group in activeResources" :key="group.id" style="grid-row-end: span 2">
<os-card class="group-teaser-card-wrapper">
<group-teaser :group="{ ...group, name: group.groupName }" />
</os-card>
</ds-grid-item>
</div>
</template>
<!-- hashtags -->
<template v-if="activeTab === 'Hashtag'">
<ds-grid-item v-for="hashtag in activeResources" :key="hashtag.id" :row-span="2">
<div v-for="hashtag in activeResources" :key="hashtag.id" style="grid-row-end: span 2">
<os-card>
<hc-hashtag :id="hashtag.id" />
</os-card>
</ds-grid-item>
</div>
</template>
<!-- pagination buttons -->
<ds-grid-item v-if="activeResourceCount > pageSize" :row-span="2" column-span="fullWidth">
<div
v-if="activeResourceCount > pageSize"
style="grid-row-end: span 2; grid-column: 1 / -1"
>
<div class="ds-mb-large ds-space-centered">
<pagination-buttons
:hasNext="hasNext"
@ -100,15 +106,15 @@
@next="nextResults"
/>
</div>
</ds-grid-item>
</div>
</template>
<!-- no results -->
<ds-grid-item v-else :row-span="7" column-span="fullWidth">
<div v-else style="grid-row-end: span 7; grid-column: 1 / -1">
<div class="ds-mb-large ds-space-centered">
<hc-empty icon="tasks" :message="$t('search.no-results', { search })" />
</div>
</ds-grid-item>
</div>
</masonry-grid>
</div>
</div>

View File

@ -1,5 +1,5 @@
<template>
<ds-grid-item class="tab-navigation" :row-span="tabs.length" column-span="fullWidth">
<div class="tab-navigation" :style="{ gridRowEnd: 'span ' + tabs.length, gridColumn: '1 / -1' }">
<os-card class="ds-tab-nav">
<ul class="Tabs">
<li
@ -25,7 +25,7 @@
</li>
</ul>
</os-card>
</ds-grid-item>
</div>
</template>
<script>

View File

@ -161,28 +161,28 @@ storiesOf('TabNavigator', module)
</template>
<!-- users -->
<template v-if="activeTab === 'User'">
<ds-grid-item v-for="user in activeResources" :key="user.id" :row-span="2">
<div v-for="user in activeResources" :key="user.id" style="grid-row-end: span 2;">
<os-card>
<user-teaser :user="user" />
</os-card>
</ds-grid-item>
</div>
</template>
<!-- hashtags -->
<template v-if="activeTab === 'Hashtag'">
<ds-grid-item v-for="hashtag in activeResources" :key="hashtag.id" :row-span="2">
<div v-for="hashtag in activeResources" :key="hashtag.id" style="grid-row-end: span 2;">
<os-card>
<hc-hashtag :id="hashtag.id" />
</os-card>
</ds-grid-item>
</div>
</template>
</template>
<!-- no results -->
<ds-grid-item v-else :row-span="7" column-span="fullWidth">
<div v-else style="grid-row-end: span 7; grid-column: 1 / -1;">
<div class="ds-mb-large ds-space-centered">
<hc-empty icon="tasks" :message="$t('search.no-results', { search })" />
</div>
</ds-grid-item>
</div>
</masonry-grid>
</ds-flex-item>
</div>

View File

@ -1001,10 +1001,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -1509,10 +1509,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -2037,10 +2037,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -3066,10 +3066,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -4115,10 +4115,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -4926,10 +4926,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -5757,10 +5757,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -6717,10 +6717,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -7851,10 +7851,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"
@ -8908,10 +8908,10 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div
data-test="icon-empty"

View File

@ -270,16 +270,16 @@
</masonry-grid-item>
</template>
<template v-else-if="$apollo.loading">
<ds-grid-item column-span="fullWidth">
<div style="grid-row-end: span 4; grid-column: 1 / -1">
<div style="text-align: center; padding: 48px 0">
<os-spinner size="lg" />
</div>
</ds-grid-item>
</div>
</template>
<template v-else>
<ds-grid-item column-span="fullWidth">
<div style="grid-row-end: span 4; grid-column: 1 / -1">
<empty margin="xx-large" icon="file" data-test="icon-empty" />
</ds-grid-item>
</div>
</template>
</masonry-grid>
<client-only>

View File

@ -136,11 +136,11 @@
</masonry-grid-item>
</template>
<template v-else>
<ds-grid-item :row-span="2" column-span="fullWidth">
<div style="grid-row-end: span 2; grid-column: 1 / -1">
<hc-empty icon="docs" />
<p class="ds-text ds-text-center">{{ $t('index.no-results') }}</p>
<p class="ds-text ds-text-center">{{ $t('index.change-filter-settings') }}</p>
</ds-grid-item>
</div>
</template>
</masonry-grid>

View File

@ -465,11 +465,11 @@ exports[`ProfileSlug given an authenticated user given another profile user and
>
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
class="tab-navigation"
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 3; grid-column: 1 / -1;"
>
<div
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
@ -619,7 +619,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
<!---->
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div>
<div
@ -1232,11 +1232,11 @@ exports[`ProfileSlug given an authenticated user given another profile user and
>
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
class="tab-navigation"
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 3; grid-column: 1 / -1;"
>
<div
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
@ -1386,7 +1386,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
<!---->
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div>
<div
@ -1823,11 +1823,11 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
>
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
class="tab-navigation"
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 3; grid-column: 1 / -1;"
>
<div
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
@ -1975,7 +1975,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
</div>
<div
style="grid-row-end: span 2; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 2; grid-column: 1 / -1;"
>
<div
class="profile-post-add-button-container"
@ -2015,7 +2015,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
</div>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div>
<div
@ -2493,11 +2493,11 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
>
<div
class="ds-grid"
style="grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: 20px;"
style="grid-auto-rows: 20px; row-gap: 16px; column-gap: 16px;"
>
<div
class="tab-navigation"
style="grid-row-end: span 3; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 3; grid-column: 1 / -1;"
>
<div
class="ds-tab-nav os-card relative rounded-[5px] break-words bg-white shadow-[0px_12px_26px_-4px_rgba(0,0,0,0.1)] p-6 ds-tab-nav"
@ -2645,7 +2645,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
</div>
<div
style="grid-row-end: span 2; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 2; grid-column: 1 / -1;"
>
<div
class="profile-post-add-button-container"
@ -2685,7 +2685,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
</div>
<div
style="grid-row-end: span 4; grid-column-start: 1; grid-column-end: -1;"
style="grid-row-end: span 4; grid-column: 1 / -1;"
>
<div>
<div

View File

@ -144,7 +144,7 @@
<tab-navigation :tabs="tabOptions" :activeTab="tabActive" @switch-tab="handleTab" />
<!-- feed -->
<ds-grid-item v-if="myProfile" :row-span="2" column-span="fullWidth">
<div v-if="myProfile" style="grid-row-end: span 2; grid-column: 1 / -1">
<div class="profile-post-add-button-container">
<os-button
as="nuxt-link"
@ -164,7 +164,7 @@
</template>
</os-button>
</div>
</ds-grid-item>
</div>
<template v-if="posts.length">
<masonry-grid-item
@ -189,16 +189,16 @@
</masonry-grid-item>
</template>
<template v-else-if="$apollo.loading">
<ds-grid-item column-span="fullWidth">
<div style="grid-row-end: span 4; grid-column: 1 / -1">
<div style="text-align: center; padding: 48px 0">
<os-spinner size="lg" />
</div>
</ds-grid-item>
</div>
</template>
<template v-else>
<ds-grid-item column-span="fullWidth">
<div style="grid-row-end: span 4; grid-column: 1 / -1">
<hc-empty margin="xx-large" icon="file" />
</ds-grid-item>
</div>
</template>
</masonry-grid>
<client-only>