mirror of
https://github.com/modrinth/code.git
synced 2026-07-31 13:16:38 +00:00
feat: improve the "New group" jank
This commit is contained in:
@@ -21,10 +21,10 @@
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
<div class="ml-auto flex items-center gap-0.5">
|
||||
<ButtonStyled type="transparent">
|
||||
<ButtonStyled v-if="displayState.group === 'Group'" type="transparent">
|
||||
<button type="button" :disabled="busy" @click="createGroupFromSelection">
|
||||
<PlusIcon />
|
||||
<span class="bar-label">{{ formatMessage(messages.createGroup) }}</span>
|
||||
<SquarePlusIcon />
|
||||
<span class="bar-label">{{ formatMessage(messages.newGroup) }}</span>
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-if="selectedGroupedInstances.length > 0" type="transparent">
|
||||
@@ -55,7 +55,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { MinusIcon, PlusIcon, TrashIcon } from '@modrinth/assets'
|
||||
import { MinusIcon, SquarePlusIcon, TrashIcon } from '@modrinth/assets'
|
||||
import {
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
@@ -80,6 +80,7 @@ const {
|
||||
setSelectedLibraryInstances,
|
||||
creatingGroup,
|
||||
createDefaultGroup,
|
||||
displayState,
|
||||
} = useLibrary()
|
||||
|
||||
const confirmDeleteModal = ref<InstanceType<typeof ConfirmDeleteInstanceModal>>()
|
||||
@@ -111,9 +112,9 @@ const messages = defineMessages({
|
||||
id: 'app.library.selection.deleting',
|
||||
defaultMessage: 'Deleting selected instances',
|
||||
},
|
||||
createGroup: {
|
||||
id: 'app.library.selection.create-group',
|
||||
defaultMessage: 'Create group',
|
||||
newGroup: {
|
||||
id: 'app.library.selection.new-group',
|
||||
defaultMessage: 'New group',
|
||||
},
|
||||
removeFromGroup: {
|
||||
id: 'app.library.selection.remove-from-group',
|
||||
@@ -124,7 +125,9 @@ const messages = defineMessages({
|
||||
async function createGroupFromSelection() {
|
||||
if (busy.value) return
|
||||
|
||||
await createDefaultGroup(selectedInstanceIds.value)
|
||||
const instanceIds = selectedInstanceIds.value
|
||||
clearLibraryInstanceSelection()
|
||||
await createDefaultGroup(instanceIds)
|
||||
}
|
||||
|
||||
async function removeSelectedInstancesFromGroups() {
|
||||
|
||||
@@ -130,21 +130,29 @@ watch(selectedLibraryInstances, (selectedInstances) => {
|
||||
<section data-library-page-background class="flex flex-col gap-3 pb-16">
|
||||
<h2 class="m-0 text-2xl font-semibold text-contrast">Library</h2>
|
||||
<LibraryToolbar />
|
||||
<div data-library-page-background class="flex flex-col">
|
||||
<InstanceGroup
|
||||
v-for="instanceGroup in visibleInstanceGroups"
|
||||
:key="instanceGroup.id"
|
||||
:hide-header="instanceGroup.key === 'None' && visibleInstanceGroups.length === 1"
|
||||
:instance-group="instanceGroup"
|
||||
:selection-anchor-instance-id="
|
||||
anchorInstance?.groupId === instanceGroup.id ? anchorInstance.instanceId : null
|
||||
"
|
||||
@toggle-selection="
|
||||
(instanceId: string, shiftKey: boolean) =>
|
||||
handleToggleInstance(instanceGroup.id, instanceId, shiftKey)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<TransitionGroup
|
||||
data-library-page-background
|
||||
tag="div"
|
||||
class="flex flex-col"
|
||||
move-class="transition-transform duration-200 ease-out"
|
||||
enter-active-class="transition-[opacity,transform] duration-200 ease-out"
|
||||
enter-from-class="opacity-0 -translate-y-2"
|
||||
enter-to-class="opacity-100 translate-y-0"
|
||||
>
|
||||
<div v-for="instanceGroup in visibleInstanceGroups" :key="instanceGroup.id" class="min-w-0">
|
||||
<InstanceGroup
|
||||
:hide-header="instanceGroup.key === 'None' && visibleInstanceGroups.length === 1"
|
||||
:instance-group="instanceGroup"
|
||||
:selection-anchor-instance-id="
|
||||
anchorInstance?.groupId === instanceGroup.id ? anchorInstance.instanceId : null
|
||||
"
|
||||
@toggle-selection="
|
||||
(instanceId: string, shiftKey: boolean) =>
|
||||
handleToggleInstance(instanceGroup.id, instanceId, shiftKey)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</TransitionGroup>
|
||||
</section>
|
||||
</InstanceGroupDnd>
|
||||
<LibrarySelectionActionBar />
|
||||
|
||||
@@ -296,6 +296,7 @@ watch(
|
||||
if (groupId !== pendingGroupId) return
|
||||
|
||||
await nextTick()
|
||||
groupDropTarget.value?.scrollIntoView({ block: 'nearest' })
|
||||
await groupNameInput.value?.startEditing()
|
||||
completePendingGroupNameEdit(groupId)
|
||||
},
|
||||
|
||||
@@ -94,11 +94,16 @@ function createLibraryState(instances: Ref<GameInstance[]>) {
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const search = ref('')
|
||||
const filters = ref<LibraryFilters>({
|
||||
instanceType: [],
|
||||
gameVersion: [],
|
||||
loader: [],
|
||||
})
|
||||
const filters = useStorage<LibraryFilters>(
|
||||
'Instances-grid-filters',
|
||||
{
|
||||
instanceType: [],
|
||||
gameVersion: [],
|
||||
loader: [],
|
||||
},
|
||||
localStorage,
|
||||
{ mergeDefaults: true },
|
||||
)
|
||||
const serverProjectIds = ref(new Set<string>())
|
||||
const libraryGroups = ref<InstanceGroupDefinition[]>([])
|
||||
const isNewGroupModalOpen = ref(false)
|
||||
@@ -146,6 +151,10 @@ function createLibraryState(instances: Ref<GameInstance[]>) {
|
||||
displayState.value.sortBy = 'Name'
|
||||
}
|
||||
|
||||
if (!libraryGroupOptions.some((option) => option.value === displayState.value.group)) {
|
||||
displayState.value.group = 'Group'
|
||||
}
|
||||
|
||||
const linkedInstances = computed(() => instances.value.filter((instance) => instance.link))
|
||||
const collapsedSectionKeys = computed(() => new Set(displayState.value.collapsedGroups))
|
||||
const groupNames = computed(
|
||||
@@ -804,11 +813,6 @@ function createLibraryState(instances: Ref<GameInstance[]>) {
|
||||
|
||||
try {
|
||||
const group = await createInstanceGroup(getDefaultNewGroupName())
|
||||
libraryGroups.value = [
|
||||
...libraryGroups.value.filter((existingGroup) => existingGroup.id !== group.id),
|
||||
group,
|
||||
]
|
||||
|
||||
const selectedInstanceIds = new Set(instanceIds)
|
||||
const instancesToAdd = instances.value.filter((instance) =>
|
||||
selectedInstanceIds.has(instance.id),
|
||||
@@ -821,14 +825,10 @@ function createLibraryState(instances: Ref<GameInstance[]>) {
|
||||
),
|
||||
)
|
||||
|
||||
if (instancesToAdd.length > 0) {
|
||||
setSelectedLibraryInstances(
|
||||
instancesToAdd.map((instance) => ({
|
||||
instanceId: instance.id,
|
||||
groupId: group.id,
|
||||
})),
|
||||
)
|
||||
}
|
||||
libraryGroups.value = [
|
||||
...libraryGroups.value.filter((existingGroup) => existingGroup.id !== group.id),
|
||||
group,
|
||||
]
|
||||
|
||||
displayState.value.group = 'Group'
|
||||
groupIdPendingNameEdit.value = group.id
|
||||
|
||||
Reference in New Issue
Block a user