mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-28 18:48:31 +01:00
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,
|
detail: true,
|
||||||
},
|
},
|
||||||
} satisfies StoryObj<typeof MkAcct>;
|
} 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>
|
<template>
|
||||||
<span>
|
<MkCondensedLine>
|
||||||
<span>@{{ user.username }}</span>
|
<span>@{{ user.username }}</span>
|
||||||
<span v-if="user.host || detail || defaultStore.state.showFullAcct" style="opacity: 0.5;">@{{ user.host || host }}</span>
|
<span v-if="user.host || detail || defaultStore.state.showFullAcct" style="opacity: 0.5;">@{{ user.host || host }}</span>
|
||||||
</span>
|
</MkCondensedLine>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as misskey from 'misskey-js';
|
import * as misskey from 'misskey-js';
|
||||||
import { toUnicode } from 'punycode/';
|
import { toUnicode } from 'punycode/';
|
||||||
|
import MkCondensedLine from './MkCondensedLine.vue';
|
||||||
import { host as hostRaw } from '@/config';
|
import { host as hostRaw } from '@/config';
|
||||||
import { defaultStore } from '@/store';
|
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 MkAcct from './global/MkAcct.vue';
|
||||||
import MkAvatar from './global/MkAvatar.vue';
|
import MkAvatar from './global/MkAvatar.vue';
|
||||||
import MkEmoji from './global/MkEmoji.vue';
|
import MkEmoji from './global/MkEmoji.vue';
|
||||||
|
import MkCondensedLine from './global/MkCondensedLine.vue';
|
||||||
import MkCustomEmoji from './global/MkCustomEmoji.vue';
|
import MkCustomEmoji from './global/MkCustomEmoji.vue';
|
||||||
import MkUserName from './global/MkUserName.vue';
|
import MkUserName from './global/MkUserName.vue';
|
||||||
import MkEllipsis from './global/MkEllipsis.vue';
|
import MkEllipsis from './global/MkEllipsis.vue';
|
||||||
|
@ -33,6 +34,7 @@ export const components = {
|
||||||
MkAcct: MkAcct,
|
MkAcct: MkAcct,
|
||||||
MkAvatar: MkAvatar,
|
MkAvatar: MkAvatar,
|
||||||
MkEmoji: MkEmoji,
|
MkEmoji: MkEmoji,
|
||||||
|
MkCondensedLine: MkCondensedLine,
|
||||||
MkCustomEmoji: MkCustomEmoji,
|
MkCustomEmoji: MkCustomEmoji,
|
||||||
MkUserName: MkUserName,
|
MkUserName: MkUserName,
|
||||||
MkEllipsis: MkEllipsis,
|
MkEllipsis: MkEllipsis,
|
||||||
|
@ -55,6 +57,7 @@ declare module '@vue/runtime-core' {
|
||||||
MkAcct: typeof MkAcct;
|
MkAcct: typeof MkAcct;
|
||||||
MkAvatar: typeof MkAvatar;
|
MkAvatar: typeof MkAvatar;
|
||||||
MkEmoji: typeof MkEmoji;
|
MkEmoji: typeof MkEmoji;
|
||||||
|
MkCondensedLine: typeof MkCondensedLine;
|
||||||
MkCustomEmoji: typeof MkCustomEmoji;
|
MkCustomEmoji: typeof MkCustomEmoji;
|
||||||
MkUserName: typeof MkUserName;
|
MkUserName: typeof MkUserName;
|
||||||
MkEllipsis: typeof MkEllipsis;
|
MkEllipsis: typeof MkEllipsis;
|
||||||
|
|
Loading…
Reference in a new issue