diff options
| author | tamaina <tamaina@hotmail.co.jp> | 2021-12-30 00:46:35 +0900 |
|---|---|---|
| committer | tamaina <tamaina@hotmail.co.jp> | 2021-12-30 00:46:35 +0900 |
| commit | a44a43ed0fd188e9039e89b62d552c60ac2bbe86 (patch) | |
| tree | 8522a6e5770d6f10f5e3eddcb6264398f2f6d55a /packages/client/src | |
| parent | migrate (diff) | |
| parent | enhance: pizzaxでstreamingのuser storage updateイベントを監視して... (diff) | |
| download | misskey-a44a43ed0fd188e9039e89b62d552c60ac2bbe86.tar.gz misskey-a44a43ed0fd188e9039e89b62d552c60ac2bbe86.tar.bz2 misskey-a44a43ed0fd188e9039e89b62d552c60ac2bbe86.zip | |
Merge branch 'develop' into pizzax-indexeddb
Diffstat (limited to 'packages/client/src')
| -rw-r--r-- | packages/client/src/components/emoji-picker.vue | 8 | ||||
| -rw-r--r-- | packages/client/src/components/form/switch.vue | 42 | ||||
| -rw-r--r-- | packages/client/src/components/mfm.ts | 9 | ||||
| -rw-r--r-- | packages/client/src/components/reactions-viewer.reaction.vue | 2 | ||||
| -rw-r--r-- | packages/client/src/components/ripple.vue (renamed from packages/client/src/components/particle.vue) | 53 | ||||
| -rw-r--r-- | packages/client/src/components/sparkle.vue | 250 | ||||
| -rw-r--r-- | packages/client/src/components/updated.vue | 30 | ||||
| -rw-r--r-- | packages/client/src/directives/index.ts | 4 | ||||
| -rw-r--r-- | packages/client/src/directives/ripple.ts (renamed from packages/client/src/directives/particle.ts) | 8 | ||||
| -rw-r--r-- | packages/client/src/pizzax.ts | 2 | ||||
| -rw-r--r-- | packages/client/src/ui/_common_/sidebar.vue | 4 | ||||
| -rw-r--r-- | packages/client/src/widgets/calendar.vue | 8 |
12 files changed, 194 insertions, 226 deletions
diff --git a/packages/client/src/components/emoji-picker.vue b/packages/client/src/components/emoji-picker.vue index ff450246f9..a8eed1ca21 100644 --- a/packages/client/src/components/emoji-picker.vue +++ b/packages/client/src/components/emoji-picker.vue @@ -77,7 +77,7 @@ import { defineComponent, markRaw } from 'vue'; import { emojilist } from '@/scripts/emojilist'; import { getStaticImageUrl } from '@/scripts/get-static-image-url'; -import Particle from '@/components/particle.vue'; +import Ripple from '@/components/ripple.vue'; import * as os from '@/os'; import { isTouchUsing } from '@/scripts/touch'; import { isMobile } from '@/scripts/is-mobile'; @@ -296,9 +296,9 @@ export default defineComponent({ if (ev) { const el = ev.currentTarget || ev.target; const rect = el.getBoundingClientRect(); - const x = rect.left + (el.clientWidth / 2); - const y = rect.top + (el.clientHeight / 2); - os.popup(Particle, { x, y }, {}, 'end'); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); + os.popup(Ripple, { x, y }, {}, 'end'); } const key = this.getKey(emoji); diff --git a/packages/client/src/components/form/switch.vue b/packages/client/src/components/form/switch.vue index aa28292b97..aa9b09215e 100644 --- a/packages/client/src/components/form/switch.vue +++ b/packages/client/src/components/form/switch.vue @@ -9,7 +9,7 @@ :disabled="disabled" @keydown.enter="toggle" > - <span v-adaptive-border v-tooltip="checked ? $ts.itsOn : $ts.itsOff" class="button" @click.prevent="toggle"> + <span ref="button" v-adaptive-border v-tooltip="checked ? $ts.itsOn : $ts.itsOff" class="button" @click.prevent="toggle"> <i class="check fas fa-check"></i> </span> <span class="label"> @@ -20,7 +20,9 @@ </template> <script lang="ts"> -import { defineComponent } from 'vue'; +import { defineComponent, ref, toRefs } from 'vue'; +import * as os from '@/os'; +import Ripple from '@/components/ripple.vue'; export default defineComponent({ props: { @@ -33,17 +35,28 @@ export default defineComponent({ default: false } }, - computed: { - checked(): boolean { - return this.modelValue; - } + + setup(props, context) { + const button = ref<HTMLElement>(); + const checked = toRefs(props).modelValue; + const toggle = () => { + if (props.disabled) return; + context.emit('update:modelValue', !checked.value); + + if (!checked.value) { + const rect = button.value.getBoundingClientRect(); + const x = rect.left + (button.value.offsetWidth / 2); + const y = rect.top + (button.value.offsetHeight / 2); + os.popup(Ripple, { x, y, particle: false }, {}, 'end'); + } + }; + + return { + button, + checked, + toggle, + }; }, - methods: { - toggle() { - if (this.disabled) return; - this.$emit('update:modelValue', !this.checked); - } - } }); </script> @@ -51,7 +64,7 @@ export default defineComponent({ .ziffeoms { position: relative; display: flex; - transition: all 0.2s; + transition: all 0.2s ease; > * { user-select: none; @@ -85,6 +98,8 @@ export default defineComponent({ opacity: 0; color: var(--fgOnAccent); font-size: 13px; + transform: scale(0.5); + transition: all 0.2s ease; } } @@ -131,6 +146,7 @@ export default defineComponent({ > .check { opacity: 1; + transform: scale(1); } } } diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index d1da365d9a..2e6d26476a 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -175,14 +175,7 @@ export default defineComponent({ if (!this.$store.state.animatedMfm) { return genEl(token.children); } - let count = token.props.args.count ? parseInt(token.props.args.count) : 10; - if (count > 100) { - count = 100; - } - const speed = token.props.args.speed ? parseFloat(token.props.args.speed) : 1; - return h(MkSparkle, { - count, speed, - }, genEl(token.children)); + return h(MkSparkle, {}, genEl(token.children)); } case 'rotate': { const degrees = parseInt(token.props.args.deg) || '90'; diff --git a/packages/client/src/components/reactions-viewer.reaction.vue b/packages/client/src/components/reactions-viewer.reaction.vue index a1de99f018..bbf518549c 100644 --- a/packages/client/src/components/reactions-viewer.reaction.vue +++ b/packages/client/src/components/reactions-viewer.reaction.vue @@ -2,7 +2,7 @@ <button v-if="count > 0" ref="buttonRef" - v-particle="canToggle" + v-ripple="canToggle" class="hkzvhatu _button" :class="{ reacted: note.myReaction == reaction, canToggle }" @click="toggleReaction()" diff --git a/packages/client/src/components/particle.vue b/packages/client/src/components/ripple.vue index d82705c1e8..272eacbc6e 100644 --- a/packages/client/src/components/particle.vue +++ b/packages/client/src/components/ripple.vue @@ -1,5 +1,5 @@ <template> -<div class="vswabwbm" :style="{ top: `${y - 64}px`, left: `${x - 64}px` }" :class="{ active }"> +<div class="vswabwbm" :style="{ zIndex, top: `${y - 64}px`, left: `${x - 64}px` }" :class="{ active }"> <svg width="128" height="128" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"> <circle fill="none" cx="64" cy="64"> <animate attributeName="r" @@ -52,7 +52,8 @@ </template> <script lang="ts"> -import { defineComponent } from 'vue'; +import { defineComponent, onMounted } from 'vue'; +import * as os from '@/os'; export default defineComponent({ props: { @@ -63,37 +64,46 @@ export default defineComponent({ y: { type: Number, required: true + }, + particle: { + type: Boolean, + required: false, + default: true, } }, emits: ['end'], - data() { + setup(props, context) { const particles = []; const origin = 64; const colors = ['#FF1493', '#00FFFF', '#FFE202']; - for (let i = 0; i < 12; i++) { - const angle = Math.random() * (Math.PI * 2); - const pos = Math.random() * 16; - const velocity = 16 + (Math.random() * 48); - particles.push({ - size: 4 + (Math.random() * 8), - xA: origin + (Math.sin(angle) * pos), - yA: origin + (Math.cos(angle) * pos), - xB: origin + (Math.sin(angle) * (pos + velocity)), - yB: origin + (Math.cos(angle) * (pos + velocity)), - color: colors[Math.floor(Math.random() * colors.length)] - }); + if (props.particle) { + for (let i = 0; i < 12; i++) { + const angle = Math.random() * (Math.PI * 2); + const pos = Math.random() * 16; + const velocity = 16 + (Math.random() * 48); + particles.push({ + size: 4 + (Math.random() * 8), + xA: origin + (Math.sin(angle) * pos), + yA: origin + (Math.cos(angle) * pos), + xB: origin + (Math.sin(angle) * (pos + velocity)), + yB: origin + (Math.cos(angle) * (pos + velocity)), + color: colors[Math.floor(Math.random() * colors.length)] + }); + } } + onMounted(() => { + setTimeout(() => { + context.emit('end'); + }, 1100); + }); + return { - particles + particles, + zIndex: os.claimZIndex('high'), }; }, - mounted() { - setTimeout(() => { - this.$emit('end'); - }, 1100); - } }); </script> @@ -101,7 +111,6 @@ export default defineComponent({ .vswabwbm { pointer-events: none; position: fixed; - z-index: 1000000; width: 128px; height: 128px; diff --git a/packages/client/src/components/sparkle.vue b/packages/client/src/components/sparkle.vue index 21b57f1580..f52e5a3f9b 100644 --- a/packages/client/src/components/sparkle.vue +++ b/packages/client/src/components/sparkle.vue @@ -1,161 +1,121 @@ <template> <span class="mk-sparkle"> - <span ref="content"> + <span ref="el"> <slot></slot> </span> - <canvas ref="canvas"></canvas> + <!-- なぜか path に対する key が機能しないため + <svg :width="width" :height="height" :viewBox="`0 0 ${width} ${height}`" xmlns="http://www.w3.org/2000/svg"> + <path v-for="particle in particles" :key="particle.id" style="transform-origin: center; transform-box: fill-box;" + :transform="`translate(${particle.x} ${particle.y})`" + :fill="particle.color" + d="M29.427,2.011C29.721,0.83 30.782,0 32,0C33.218,0 34.279,0.83 34.573,2.011L39.455,21.646C39.629,22.347 39.991,22.987 40.502,23.498C41.013,24.009 41.653,24.371 42.354,24.545L61.989,29.427C63.17,29.721 64,30.782 64,32C64,33.218 63.17,34.279 61.989,34.573L42.354,39.455C41.653,39.629 41.013,39.991 40.502,40.502C39.991,41.013 39.629,41.653 39.455,42.354L34.573,61.989C34.279,63.17 33.218,64 32,64C30.782,64 29.721,63.17 29.427,61.989L24.545,42.354C24.371,41.653 24.009,41.013 23.498,40.502C22.987,39.991 22.347,39.629 21.646,39.455L2.011,34.573C0.83,34.279 0,33.218 0,32C0,30.782 0.83,29.721 2.011,29.427L21.646,24.545C22.347,24.371 22.987,24.009 23.498,23.498C24.009,22.987 24.371,22.347 24.545,21.646L29.427,2.011Z" + > + <animateTransform + attributeName="transform" + attributeType="XML" + type="rotate" + from="0 0 0" + to="360 0 0" + :dur="`${particle.dur}ms`" + repeatCount="indefinite" + additive="sum" + /> + <animateTransform + attributeName="transform" + attributeType="XML" + type="scale" + :values="`0; ${particle.size}; 0`" + :dur="`${particle.dur}ms`" + repeatCount="indefinite" + additive="sum" + /> + </path> + </svg> + --> + <svg v-for="particle in particles" :key="particle.id" :width="width" :height="height" :viewBox="`0 0 ${width} ${height}`" xmlns="http://www.w3.org/2000/svg"> + <path style="transform-origin: center; transform-box: fill-box;" + :transform="`translate(${particle.x} ${particle.y})`" + :fill="particle.color" + d="M29.427,2.011C29.721,0.83 30.782,0 32,0C33.218,0 34.279,0.83 34.573,2.011L39.455,21.646C39.629,22.347 39.991,22.987 40.502,23.498C41.013,24.009 41.653,24.371 42.354,24.545L61.989,29.427C63.17,29.721 64,30.782 64,32C64,33.218 63.17,34.279 61.989,34.573L42.354,39.455C41.653,39.629 41.013,39.991 40.502,40.502C39.991,41.013 39.629,41.653 39.455,42.354L34.573,61.989C34.279,63.17 33.218,64 32,64C30.782,64 29.721,63.17 29.427,61.989L24.545,42.354C24.371,41.653 24.009,41.013 23.498,40.502C22.987,39.991 22.347,39.629 21.646,39.455L2.011,34.573C0.83,34.279 0,33.218 0,32C0,30.782 0.83,29.721 2.011,29.427L21.646,24.545C22.347,24.371 22.987,24.009 23.498,23.498C24.009,22.987 24.371,22.347 24.545,21.646L29.427,2.011Z" + > + <animateTransform + attributeName="transform" + attributeType="XML" + type="rotate" + from="0 0 0" + to="360 0 0" + :dur="`${particle.dur}ms`" + repeatCount="1" + additive="sum" + /> + <animateTransform + attributeName="transform" + attributeType="XML" + type="scale" + :values="`0; ${particle.size}; 0`" + :dur="`${particle.dur}ms`" + repeatCount="1" + additive="sum" + /> + </path> + </svg> </span> </template> <script lang="ts"> -import { defineComponent } from 'vue'; +import { defineComponent, onMounted, onUnmounted, ref } from 'vue'; import * as os from '@/os'; -const sprite = new Image(); -sprite.src = '/client-assets/sparkle-spritesheet.png'; - export default defineComponent({ - props: { - count: { - type: Number, - required: true, - }, - speed: { - type: Number, - required: true, - }, - }, - data() { - return { - sprites: [0,6,13,20], - particles: [], - anim: null, - ctx: null, - }; - }, - unmounted() { - window.cancelAnimationFrame(this.anim); - }, - mounted() { - this.ctx = this.$refs.canvas.getContext('2d'); - - new ResizeObserver(this.resize).observe(this.$refs.content); - - this.resize(); - this.tick(); - }, - updated() { - this.resize(); - }, - methods: { - createSparkles(w, h, count) { - const holder = []; - - for (let i = 0; i < count; i++) { - - const color = '#' + ('000000' + Math.floor(Math.random() * 16777215).toString(16)).slice(-6); - - holder[i] = { - position: { - x: Math.floor(Math.random() * w), - y: Math.floor(Math.random() * h) - }, - style: this.sprites[ Math.floor(Math.random() * 4) ], - delta: { - x: Math.floor(Math.random() * 1000) - 500, - y: Math.floor(Math.random() * 1000) - 500 - }, - color: color, - opacity: Math.random(), - }; - - } - - return holder; - }, - draw(time) { - this.ctx.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height); - this.ctx.beginPath(); + setup() { + const particles = ref([]); + const el = ref<HTMLElement>(); + const width = ref(0); + const height = ref(0); + const colors = ['#FF1493', '#00FFFF', '#FFE202', '#FFE202', '#FFE202']; - const particleSize = Math.floor(this.fontSize / 2); - this.particles.forEach((particle) => { - var modulus = Math.floor(Math.random()*7); - - if (Math.floor(time) % modulus === 0) { - particle.style = this.sprites[ Math.floor(Math.random()*4) ]; - } - - this.ctx.save(); - this.ctx.globalAlpha = particle.opacity; - this.ctx.drawImage(sprite, particle.style, 0, 7, 7, particle.position.x, particle.position.y, particleSize, particleSize); - - this.ctx.globalCompositeOperation = "source-atop"; - this.ctx.globalAlpha = 0.5; - this.ctx.fillStyle = particle.color; - this.ctx.fillRect(particle.position.x, particle.position.y, particleSize, particleSize); - - this.ctx.restore(); + onMounted(() => { + const ro = new ResizeObserver((entries, observer) => { + width.value = el.value?.offsetWidth + 64; + height.value = el.value?.offsetHeight + 64; }); - this.ctx.stroke(); - }, - tick() { - this.anim = window.requestAnimationFrame((time) => { - if (!this.$refs.canvas) { - return; - } - this.particles.forEach((particle) => { - if (!particle) { - return; - } - var randX = Math.random() > Math.random() * 2; - var randY = Math.random() > Math.random() * 3; - - if (randX) { - particle.position.x += (particle.delta.x * this.speed) / 1500; - } - - if (!randY) { - particle.position.y -= (particle.delta.y * this.speed) / 800; - } - - if( particle.position.x > this.$refs.canvas.width ) { - particle.position.x = -7; - } else if (particle.position.x < -7) { - particle.position.x = this.$refs.canvas.width; - } - - if (particle.position.y > this.$refs.canvas.height) { - particle.position.y = -7; - particle.position.x = Math.floor(Math.random() * this.$refs.canvas.width); - } else if (particle.position.y < -7) { - particle.position.y = this.$refs.canvas.height; - particle.position.x = Math.floor(Math.random() * this.$refs.canvas.width); - } - - particle.opacity -= 0.005; - - if (particle.opacity <= 0) { - particle.opacity = 1; - } - }); - - this.draw(time); + ro.observe(el.value); + let stop = false; + const add = () => { + if (stop) return; + const x = (Math.random() * (width.value - 64)); + const y = (Math.random() * (height.value - 64)); + const sizeFactor = Math.random(); + const particle = { + id: Math.random().toString(), + x, + y, + size: 0.2 + ((sizeFactor / 10) * 3), + dur: 1000 + (sizeFactor * 1000), + color: colors[Math.floor(Math.random() * colors.length)], + }; + particles.value.push(particle); + window.setTimeout(() => { + particles.value = particles.value.filter(x => x.id !== particle.id); + }, particle.dur - 100); - this.tick(); + window.setTimeout(() => { + add(); + }, 500 + (Math.random() * 500)); + }; + add(); + onUnmounted(() => { + ro.disconnect(); + stop = true; }); - }, - resize() { - if (this.$refs.content) { - const contentRect = this.$refs.content.getBoundingClientRect(); - this.fontSize = parseFloat(getComputedStyle(this.$refs.content).fontSize); - const padding = this.fontSize * 0.2; + }); - this.$refs.canvas.width = parseInt(contentRect.width + padding); - this.$refs.canvas.height = parseInt(contentRect.height + padding); - - this.particles = this.createSparkles(this.$refs.canvas.width, this.$refs.canvas.height, this.count); - } - }, + return { + el, + width, + height, + particles, + }; }, }); </script> @@ -169,10 +129,10 @@ export default defineComponent({ display: inline-block; } - > canvas { + > svg { position: absolute; - top: -0.1em; - left: -0.1em; + top: -32px; + left: -32px; pointer-events: none; } } diff --git a/packages/client/src/components/updated.vue b/packages/client/src/components/updated.vue index 74f54524be..375ac0dbbb 100644 --- a/packages/client/src/components/updated.vue +++ b/packages/client/src/components/updated.vue @@ -1,7 +1,7 @@ <template> <MkModal ref="modal" :z-priority="'middle'" @click="$refs.modal.close()" @closed="$emit('closed')"> <div class="ewlycnyt"> - <div class="title">{{ $ts.misskeyUpdated }}</div> + <div class="title"><MkSparkle>{{ $ts.misskeyUpdated }}</MkSparkle></div> <div class="version">✨{{ version }}🚀</div> <MkButton full @click="whatIsNew">{{ $ts.whatIsNew }}</MkButton> <MkButton class="gotIt" primary full @click="$refs.modal.close()">{{ $ts.gotIt }}</MkButton> @@ -9,31 +9,19 @@ </MkModal> </template> -<script lang="ts"> -import { defineComponent } from 'vue'; +<script lang="ts" setup> +import { ref } from 'vue'; import MkModal from '@/components/ui/modal.vue'; import MkButton from '@/components/ui/button.vue'; +import MkSparkle from '@/components/sparkle.vue'; import { version } from '@/config'; -export default defineComponent({ - components: { - MkModal, - MkButton, - }, +const modal = ref(); - data() { - return { - version: version, - }; - }, - - methods: { - whatIsNew() { - this.$refs.modal.close(); - window.open(`https://misskey-hub.net/docs/releases.html#_${version.replace(/\./g, '-')}`, '_blank'); - } - } -}); +const whatIsNew = () => { + modal.value.close(); + window.open(`https://misskey-hub.net/docs/releases.html#_${version.replace(/\./g, '-')}`, '_blank'); +}; </script> <style lang="scss" scoped> diff --git a/packages/client/src/directives/index.ts b/packages/client/src/directives/index.ts index 8f13e792f3..fc9b6f86da 100644 --- a/packages/client/src/directives/index.ts +++ b/packages/client/src/directives/index.ts @@ -3,7 +3,7 @@ import { App } from 'vue'; import userPreview from './user-preview'; import size from './size'; import getSize from './get-size'; -import particle from './particle'; +import ripple from './ripple'; import tooltip from './tooltip'; import hotkey from './hotkey'; import appear from './appear'; @@ -18,7 +18,7 @@ export default function(app: App) { app.directive('user-preview', userPreview); app.directive('size', size); app.directive('get-size', getSize); - app.directive('particle', particle); + app.directive('ripple', ripple); app.directive('tooltip', tooltip); app.directive('hotkey', hotkey); app.directive('appear', appear); diff --git a/packages/client/src/directives/particle.ts b/packages/client/src/directives/ripple.ts index c90df89a5e..f1d41ddb0e 100644 --- a/packages/client/src/directives/particle.ts +++ b/packages/client/src/directives/ripple.ts @@ -1,4 +1,4 @@ -import Particle from '@/components/particle.vue'; +import Ripple from '@/components/ripple.vue'; import { popup } from '@/os'; export default { @@ -9,10 +9,10 @@ export default { el.addEventListener('click', () => { const rect = el.getBoundingClientRect(); - const x = rect.left + (el.clientWidth / 2); - const y = rect.top + (el.clientHeight / 2); + const x = rect.left + (el.offsetWidth / 2); + const y = rect.top + (el.offsetHeight / 2); - popup(Particle, { x, y }, {}, 'end'); + popup(Ripple, { x, y }, {}, 'end'); }); } }; diff --git a/packages/client/src/pizzax.ts b/packages/client/src/pizzax.ts index 3ac4c5c720..8156f99444 100644 --- a/packages/client/src/pizzax.ts +++ b/packages/client/src/pizzax.ts @@ -41,6 +41,8 @@ export class Storage<T extends StateDef> { return promise; } + private connection = stream.useChannel('main'); + constructor(key: string, def: T) { this.key = key; this.deviceStateKeyName = `pizzax::${key}`; diff --git a/packages/client/src/ui/_common_/sidebar.vue b/packages/client/src/ui/_common_/sidebar.vue index bf560e8dd6..fa712ba45d 100644 --- a/packages/client/src/ui/_common_/sidebar.vue +++ b/packages/client/src/ui/_common_/sidebar.vue @@ -285,7 +285,7 @@ export default defineComponent({ } &:before { - width: auto; + width: min-content; height: 100%; aspect-ratio: 1/1; border-radius: 8px; @@ -301,7 +301,7 @@ export default defineComponent({ &.post:before { width: calc(100% - 28px); - height: auto; + height: min-content; aspect-ratio: 1/1; border-radius: 100%; } diff --git a/packages/client/src/widgets/calendar.vue b/packages/client/src/widgets/calendar.vue index 545072e87b..c8b52d7afc 100644 --- a/packages/client/src/widgets/calendar.vue +++ b/packages/client/src/widgets/calendar.vue @@ -5,7 +5,8 @@ <span class="year">{{ $t('yearX', { year }) }}</span> <span class="month">{{ $t('monthX', { month }) }}</span> </p> - <p class="day">{{ $t('dayX', { day }) }}</p> + <p v-if="month === 1 && day === 1" class="day">🎉{{ $t('dayX', { day }) }}<span style="display: inline-block; transform: scaleX(-1);">🎉</span></p> + <p v-else class="day">{{ $t('dayX', { day }) }}</p> <p class="week-day">{{ weekDay }}</p> </div> <div class="info"> @@ -34,7 +35,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; import define from './define'; -import * as os from '@/os'; const widget = define({ name: 'calendar', @@ -127,12 +127,12 @@ export default defineComponent({ } } - > p { + > .month-and-year, > .week-day { margin: 0; line-height: 18px; font-size: 0.9em; - > span { + > .year, > .month { margin: 0 4px; } } |