feat: condense acct (#10753)
* feat: condense acct * fix: watch parent element size --------- Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
parent
53498991bb
commit
2cfed3395e
5 changed files with 117 additions and 2 deletions
|
@ -41,3 +41,19 @@ export const Detail = {
|
|||
detail: true,
|
||||
},
|
||||
} satisfies StoryObj<typeof MkAcct>;
|
||||
export const Long = {
|
||||
...Default,
|
||||
args: {
|
||||
...Default.args,
|
||||
user: {
|
||||
...userDetailed(),
|
||||
username: '2c7cc62a697ea3a7826521f3fd34f0cb273693cbe5e9310f35449f43622a5cdc',
|
||||
host: 'nostr.example',
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
() => ({
|
||||
template: '<div style="width: 360px;"><story/></div>',
|
||||
}),
|
||||
],
|
||||
} satisfies StoryObj<typeof MkAcct>;
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
<template>
|
||||
<span>
|
||||
<MkCondensedLine>
|
||||
<span>@{{ user.username }}</span>
|
||||
<span v-if="user.host || detail || defaultStore.state.showFullAcct" style="opacity: 0.5;">@{{ user.host || host }}</span>
|
||||
</span>
|
||||
</MkCondensedLine>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as misskey from 'misskey-js';
|
||||
import { toUnicode } from 'punycode/';
|
||||
import MkCondensedLine from './MkCondensedLine.vue';
|
||||
import { host as hostRaw } from '@/config';
|
||||
import { defaultStore } from '@/store';
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { StoryObj } from '@storybook/vue3';
|
||||
import MkCondensedLine from './MkCondensedLine.vue';
|
||||
export const Default = {
|
||||
render(args) {
|
||||
return {
|
||||
components: {
|
||||
MkCondensedLine,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
args,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
props() {
|
||||
return {
|
||||
...this.args,
|
||||
};
|
||||
},
|
||||
},
|
||||
template: '<MkCondensedLine>{{ props.text }}</MkCondensedLine>',
|
||||
};
|
||||
},
|
||||
args: {
|
||||
text: 'This is a condensed line.',
|
||||
},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
} satisfies StoryObj<typeof MkCondensedLine>;
|
||||
export const ContainerIs100px = {
|
||||
...Default,
|
||||
decorators: [
|
||||
() => ({
|
||||
template: '<div style="width: 100px;"><story/></div>',
|
||||
}),
|
||||
],
|
||||
} satisfies StoryObj<typeof MkCondensedLine>;
|
56
packages/frontend/src/components/global/MkCondensedLine.vue
Normal file
56
packages/frontend/src/components/global/MkCondensedLine.vue
Normal file
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<span :class="$style.container">
|
||||
<span ref="content" :class="$style.content">
|
||||
<slot/>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
const contentSymbol = Symbol();
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
const content = (entry.target[contentSymbol] ? entry.target : entry.target.firstElementChild) as HTMLSpanElement;
|
||||
const container = content.parentElement as HTMLSpanElement;
|
||||
const contentWidth = content.getBoundingClientRect().width;
|
||||
const containerWidth = container.getBoundingClientRect().width;
|
||||
container.style.transform = `scaleX(${Math.min(1, containerWidth / contentWidth)})`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const content = ref<HTMLSpanElement>();
|
||||
|
||||
watch(content, (value, oldValue) => {
|
||||
if (oldValue) {
|
||||
delete oldValue[contentSymbol];
|
||||
observer.unobserve(oldValue);
|
||||
if (oldValue.parentElement) {
|
||||
observer.unobserve(oldValue.parentElement);
|
||||
}
|
||||
}
|
||||
if (value) {
|
||||
value[contentSymbol] = contentSymbol;
|
||||
observer.observe(value);
|
||||
if (value.parentElement) {
|
||||
observer.observe(value.parentElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style module lang="scss">
|
||||
.container {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
transform-origin: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
|
@ -5,6 +5,7 @@ import MkA from './global/MkA.vue';
|
|||
import MkAcct from './global/MkAcct.vue';
|
||||
import MkAvatar from './global/MkAvatar.vue';
|
||||
import MkEmoji from './global/MkEmoji.vue';
|
||||
import MkCondensedLine from './global/MkCondensedLine.vue';
|
||||
import MkCustomEmoji from './global/MkCustomEmoji.vue';
|
||||
import MkUserName from './global/MkUserName.vue';
|
||||
import MkEllipsis from './global/MkEllipsis.vue';
|
||||
|
@ -33,6 +34,7 @@ export const components = {
|
|||
MkAcct: MkAcct,
|
||||
MkAvatar: MkAvatar,
|
||||
MkEmoji: MkEmoji,
|
||||
MkCondensedLine: MkCondensedLine,
|
||||
MkCustomEmoji: MkCustomEmoji,
|
||||
MkUserName: MkUserName,
|
||||
MkEllipsis: MkEllipsis,
|
||||
|
@ -55,6 +57,7 @@ declare module '@vue/runtime-core' {
|
|||
MkAcct: typeof MkAcct;
|
||||
MkAvatar: typeof MkAvatar;
|
||||
MkEmoji: typeof MkEmoji;
|
||||
MkCondensedLine: typeof MkCondensedLine;
|
||||
MkCustomEmoji: typeof MkCustomEmoji;
|
||||
MkUserName: typeof MkUserName;
|
||||
MkEllipsis: typeof MkEllipsis;
|
||||
|
|
Loading…
Reference in a new issue