mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
refactor BaseCard to use slots and props
This commit is contained in:
parent
9c3378807c
commit
37959d8167
@ -8,14 +8,19 @@
|
||||
>
|
||||
<template slot-scope="{ errors }">
|
||||
<base-card>
|
||||
<section :class="['card-image', form.blurImage && '--blur-image']">
|
||||
<img v-if="contribution" class="preview-image" :src="contribution.image | proxyApiUrl" />
|
||||
<template v-slot:heroImage>
|
||||
<img
|
||||
v-if="contribution"
|
||||
:src="contribution.image | proxyApiUrl"
|
||||
:class="['image', form.blurImage && '--blur-image']"
|
||||
/>
|
||||
<teaser-image
|
||||
:contribution="contribution"
|
||||
:class="[form.blurImage && '--blur-image']"
|
||||
@addTeaserImage="addTeaserImage"
|
||||
@addImageAspectRatio="addImageAspectRatio"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
<div v-if="form.teaserImage || form.image" class="blur-toggle">
|
||||
<label for="blur-img">{{ $t('contribution.inappropriatePicture') }}</label>
|
||||
<input type="checkbox" id="blur-img" v-model="form.blurImage" />
|
||||
@ -259,45 +264,35 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.contribution-form {
|
||||
> .base-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.contribution-form > .base-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> .card-image {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin-bottom: $space-xx-small;
|
||||
|
||||
&.--blur-image img {
|
||||
filter: blur(22px);
|
||||
}
|
||||
}
|
||||
|
||||
> .ds-form-item {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
> .ds-chip {
|
||||
align-self: flex-end;
|
||||
margin: $space-xx-small 0 $space-base;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
> .select-field {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
> .buttons {
|
||||
align-self: flex-end;
|
||||
margin-top: $space-base;
|
||||
}
|
||||
> .hero-image {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.preview-image {
|
||||
width: 100%;
|
||||
max-height: 2000px;
|
||||
object-fit: contain;
|
||||
.image.--blur-image {
|
||||
filter: blur(22px);
|
||||
}
|
||||
|
||||
> .ds-form-item {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
> .ds-chip {
|
||||
align-self: flex-end;
|
||||
margin: $space-xx-small 0 $space-base;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
> .select-field {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
> .buttons {
|
||||
align-self: flex-end;
|
||||
margin-top: $space-base;
|
||||
}
|
||||
|
||||
.blur-toggle {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<base-card class="delete-data">
|
||||
<h2 class="card-heading">
|
||||
<h2 class="title">
|
||||
<base-icon name="warning" />
|
||||
{{ $t('settings.deleteUserAccount.name') }}
|
||||
</h2>
|
||||
@ -103,7 +103,7 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> .card-heading > .base-icon {
|
||||
> .title > .base-icon {
|
||||
color: $color-danger;
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
:to="{ name: 'post-id-slug', params, ...hashParam }"
|
||||
@click.native="$emit('read')"
|
||||
>
|
||||
<base-card class="--wide-content">
|
||||
<h2 class="card-heading">{{ from.title || from.post.title }}</h2>
|
||||
<base-card wideContent>
|
||||
<h2 class="title">{{ from.title || from.post.title }}</h2>
|
||||
<p>
|
||||
<strong v-if="isComment" class="comment">{{ $t(`notifications.comment`) }}:</strong>
|
||||
{{ from.contentExcerpt | removeHtml }}
|
||||
|
||||
@ -44,7 +44,7 @@ export const post = {
|
||||
__typename: 'Post',
|
||||
}
|
||||
|
||||
storiesOf('Post Card', module)
|
||||
storiesOf('PostTeaser', module)
|
||||
.addDecorator(withA11y)
|
||||
.addDecorator(helpers.layout)
|
||||
.add('without image', () => ({
|
||||
@ -82,11 +82,7 @@ storiesOf('Post Card', module)
|
||||
data: () => ({
|
||||
post: {
|
||||
...post,
|
||||
pinnedBy: {
|
||||
id: '4711',
|
||||
name: 'Ad Min',
|
||||
role: 'admin',
|
||||
},
|
||||
pinned: true,
|
||||
},
|
||||
}),
|
||||
template: `
|
||||
|
||||
@ -7,17 +7,17 @@
|
||||
:lang="post.language"
|
||||
:class="{
|
||||
'disabled-content': post.disabled,
|
||||
'--highlight': isPinned,
|
||||
'--blur-image': post.imageBlurred,
|
||||
}"
|
||||
:highlight="isPinned"
|
||||
>
|
||||
<div v-if="post.image" class="card-image">
|
||||
<template v-if="post.image" v-slot:heroImage>
|
||||
<img :src="post.image | proxyApiUrl" class="image" />
|
||||
</div>
|
||||
</template>
|
||||
<client-only>
|
||||
<user-teaser :user="post.author" :date-time="post.createdAt" />
|
||||
</client-only>
|
||||
<h2 class="card-heading hyphenate-text">{{ post.title }}</h2>
|
||||
<h2 class="title hyphenate-text">{{ post.title }}</h2>
|
||||
<!-- TODO: replace editor content with tiptap render view -->
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div class="content hyphenate-text" v-html="excerpt" />
|
||||
@ -87,7 +87,7 @@ export default {
|
||||
mounted() {
|
||||
const width = this.$el.offsetWidth
|
||||
const height = Math.min(width / this.post.imageAspectRatio, 2000)
|
||||
const imageElement = this.$el.querySelector('.card-image > .image')
|
||||
const imageElement = this.$el.querySelector('.hero-image')
|
||||
if (imageElement) {
|
||||
imageElement.style.height = `${height}px`
|
||||
}
|
||||
@ -157,24 +157,10 @@ export default {
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
&.--pinned {
|
||||
border: 1px solid $color-warning;
|
||||
}
|
||||
|
||||
&.--blur-image > .card-image > .image {
|
||||
&.--blur-image > .hero-image > .image {
|
||||
filter: blur(22px);
|
||||
}
|
||||
|
||||
> .card-image {
|
||||
overflow: hidden;
|
||||
|
||||
> .image {
|
||||
width: 100%;
|
||||
max-height: 2000px;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
> .content {
|
||||
flex-grow: 1;
|
||||
margin-bottom: $space-small;
|
||||
|
||||
@ -45,13 +45,13 @@ export default {
|
||||
border-style: solid;
|
||||
border-color: $background-color-secondary transparent transparent $background-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
.ribbon--pinned {
|
||||
background-color: $color-warning-active;
|
||||
&.--pinned {
|
||||
background-color: $color-warning;
|
||||
|
||||
&::before {
|
||||
border-color: $color-warning transparent transparent $color-warning;
|
||||
&::before {
|
||||
border-color: $color-warning transparent transparent $color-warning;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -91,7 +91,7 @@ export default {
|
||||
this.closeCropper()
|
||||
},
|
||||
setupPreview(url) {
|
||||
const previewElement = document.querySelector('.preview-image')
|
||||
const previewElement = document.querySelector('.image-uploader .preview-image')
|
||||
previewElement.src = url
|
||||
this.$nextTick((this.isLoadingImage = false))
|
||||
},
|
||||
@ -108,6 +108,14 @@ export default {
|
||||
min-height: 200px;
|
||||
cursor: pointer;
|
||||
|
||||
.image + & {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:only-child {
|
||||
background-color: $color-neutral-85;
|
||||
}
|
||||
@ -116,12 +124,14 @@ export default {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.preview-image + & {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
&.--blur-image .preview-image {
|
||||
filter: blur(22px);
|
||||
}
|
||||
|
||||
.preview-image {
|
||||
width: 100%;
|
||||
max-height: 2000px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
> .crop-overlay {
|
||||
|
||||
@ -9,18 +9,53 @@ storiesOf('Generic/BaseCard', module)
|
||||
components: { BaseCard },
|
||||
template: `
|
||||
<base-card>
|
||||
<h2 class="card-heading">I am a card heading</h2>
|
||||
<h2 class="title">I am a card heading</h2>
|
||||
<p>And I am a paragraph.</p>
|
||||
</base-card>
|
||||
`,
|
||||
}))
|
||||
|
||||
.add('with image', () => ({
|
||||
.add('with slot: hero image', () => ({
|
||||
components: { BaseCard },
|
||||
template: `
|
||||
<base-card style="width: 400px;">
|
||||
<img class="card-image" src="https://unsplash.com/photos/R4y_E5ZQDPg/download" />
|
||||
<h2 class="card-heading">I am a card heading</h2>
|
||||
<template v-slot:heroImage>
|
||||
<img class="image" src="https://unsplash.com/photos/R4y_E5ZQDPg/download" />
|
||||
</template>
|
||||
<h2 class="title">I am a card heading</h2>
|
||||
<p>And I am a paragraph.</p>
|
||||
</base-card>
|
||||
`,
|
||||
}))
|
||||
|
||||
.add('with slot: image column', () => ({
|
||||
components: { BaseCard },
|
||||
template: `
|
||||
<base-card style="width: 600px;">
|
||||
<template v-slot:imageColumn>
|
||||
<img class="image" src="/img/sign-up/humanconnection.svg" />
|
||||
</template>
|
||||
<h2 class="title">I am a card heading</h2>
|
||||
<p>And I am a paragraph.</p>
|
||||
</base-card>
|
||||
`,
|
||||
}))
|
||||
|
||||
.add('with highlight prop', () => ({
|
||||
components: { BaseCard },
|
||||
template: `
|
||||
<base-card highlight style="width: 400px;">
|
||||
<h2 class="title">I am a card heading</h2>
|
||||
<p>And I am a paragraph.</p>
|
||||
</base-card>
|
||||
`,
|
||||
}))
|
||||
|
||||
.add('with wideContent prop', () => ({
|
||||
components: { BaseCard },
|
||||
template: `
|
||||
<base-card wideContent style="width: 400px;">
|
||||
<h2 class="title">I am a card heading</h2>
|
||||
<p>And I am a paragraph.</p>
|
||||
</base-card>
|
||||
`,
|
||||
|
||||
@ -1,11 +1,49 @@
|
||||
<template>
|
||||
<article class="base-card">
|
||||
<slot />
|
||||
<article :class="classNames">
|
||||
<template v-if="$slots.imageColumn">
|
||||
<aside class="image-column">
|
||||
<slot name="imageColumn" />
|
||||
</aside>
|
||||
<section class="content-column">
|
||||
<slot />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<template v-else-if="$slots.heroImage">
|
||||
<section class="hero-image">
|
||||
<slot name="heroImage" />
|
||||
</section>
|
||||
<slot />
|
||||
</template>
|
||||
|
||||
<slot v-else />
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {}
|
||||
export default {
|
||||
props: {
|
||||
highlight: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
wideContent: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
classNames() {
|
||||
let classNames = 'base-card'
|
||||
|
||||
if (this.$slots.imageColumn) classNames += ' --columns'
|
||||
if (this.highlight) classNames += ' --highlight'
|
||||
if (this.wideContent) classNames += ' --wide-content'
|
||||
|
||||
return classNames
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@ -16,30 +54,58 @@ export default {}
|
||||
background-color: $color-neutral-100;
|
||||
box-shadow: $box-shadow-base;
|
||||
|
||||
&.--columns {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.--highlight {
|
||||
border: $border-size-base solid $color-primary;
|
||||
border: $border-size-base solid $color-warning;
|
||||
}
|
||||
|
||||
&.--wide-content {
|
||||
padding: $space-small;
|
||||
|
||||
> .card-image {
|
||||
> .hero-image {
|
||||
width: calc(100% + (2 * #{$space-small}));
|
||||
margin: -$space-small;
|
||||
margin-bottom: $space-base;
|
||||
margin-bottom: $space-small;
|
||||
}
|
||||
}
|
||||
|
||||
> .card-image {
|
||||
width: calc(100% + (2 * #{$space-base}));
|
||||
margin: -$space-base;
|
||||
margin-bottom: $space-base;
|
||||
font-size: $font-size-x-large;
|
||||
}
|
||||
|
||||
> .card-heading {
|
||||
> .title,
|
||||
> .content-column > .title {
|
||||
font-size: $font-size-large;
|
||||
margin-bottom: $space-x-small;
|
||||
}
|
||||
|
||||
> .hero-image {
|
||||
width: calc(100% + (2 * #{$space-base}));
|
||||
max-height: 2000px;
|
||||
margin: -$space-base;
|
||||
margin-bottom: $space-base;
|
||||
overflow: hidden;
|
||||
|
||||
> .image {
|
||||
width: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
> .image-column {
|
||||
flex-basis: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-right: $space-base;
|
||||
|
||||
> .image {
|
||||
width: 100%;
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
> .content-column {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,25 +1,24 @@
|
||||
<template>
|
||||
<ds-container width="medium">
|
||||
<ds-card>
|
||||
<ds-flex gutter="small">
|
||||
<ds-flex-item :width="{ base: '100%', sm: '50%' }">
|
||||
<locale-switch offset="5" />
|
||||
<ds-space margin-top="small" margin-bottom="xxx-small">
|
||||
<img class="signup-image" alt="Human Connection" src="/img/sign-up/nicetomeetyou.svg" />
|
||||
</ds-space>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item :width="{ base: '100%', sm: '50%' }" centered>
|
||||
<nuxt-child />
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</ds-card>
|
||||
<card-with-columns>
|
||||
<template v-slot:left>
|
||||
<locale-switch offset="5" />
|
||||
<img class="signup-image" alt="Human Connection" src="/img/sign-up/nicetomeetyou.svg" />
|
||||
</template>
|
||||
<template v-slot:right>
|
||||
<nuxt-child />
|
||||
</template>
|
||||
</card-with-columns>
|
||||
</ds-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CardWithColumns from '~/components/_new/generic/CardWithColumns/CardWithColumns'
|
||||
import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CardWithColumns,
|
||||
LocaleSwitch,
|
||||
},
|
||||
layout: 'no-header',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user