Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
e9cae01
feat(button): ✨ enhance button component with new styles and props
LovelessCodes Oct 27, 2025
a845e02
feat(badge): ✨ enhance `Badge` component with new variants and improv…
LovelessCodes Oct 27, 2025
8b2cac0
feat(avatar): ✨ refactor `Avatar` component to use new base UI primit…
LovelessCodes Oct 27, 2025
9ed7d28
feat(dialogs): ✨ replace `AlertDialogAction` and `AlertDialogCancel` …
LovelessCodes Oct 27, 2025
0df467a
chore(deps): 🔧 update dependencies in `package.json` and `bun.lock`
LovelessCodes Oct 27, 2025
0b044e1
feat(checkbox): ✨ refactor `Checkbox` component to use new base UI pr…
LovelessCodes Oct 27, 2025
074f612
feat(separator): ✨ refactor `Separator` component to use new base UI …
LovelessCodes Oct 27, 2025
3568c87
feat(tooltip): ✨ refactor `Tooltip` component to use new base UI prim…
LovelessCodes Oct 27, 2025
da020ae
feat(installation-card): ✨ refactor `InstallationCard` to use `Group`…
LovelessCodes Oct 27, 2025
1a3c0f8
feat(server-card): ✨ refactor `ServerCard` to use `Group` and `GroupI…
LovelessCodes Oct 27, 2025
7bca21f
feat(mod-item): ✨ refactor `ModItem` to utilize `Group`, `GroupItem`,…
LovelessCodes Oct 27, 2025
1d917e3
feat(version-item): ✨ refactor `VersionItem` to improve `TooltipTrigg…
LovelessCodes Oct 27, 2025
f036a56
feat(world-item): ✨ refactor `WorldItem` to utilize `Group`, `GroupIt…
LovelessCodes Oct 27, 2025
160dac0
feat(installation-row): ✨ refactor `InstallationRow` to utilize `Grou…
LovelessCodes Oct 27, 2025
fe70178
feat(server-row): ✨ refactor `ServerRow` to utilize `Group`, `GroupIt…
LovelessCodes Oct 27, 2025
25eb00d
feat(version-row): ✨ refactor `VersionRow` to utilize `Group`, `Group…
LovelessCodes Oct 27, 2025
897fc21
feat(group): ✨ add `Group`, `GroupItem`, and `GroupSeparator` components
LovelessCodes Oct 27, 2025
c9308ff
feat(toggle-group): ✨ refactor `ToggleGroup` and `Toggle` components
LovelessCodes Oct 27, 2025
53df5c0
feat(tabs): ✨ refactor `Tabs`, `TabsList`, `TabsTab`, and `TabsPanel`…
LovelessCodes Oct 27, 2025
122ee89
feat(toggle): ✨ refactor `Toggle` component to use `@base-ui-componen…
LovelessCodes Oct 27, 2025
596c2a9
feat(route): ✨ update `Button` component to use `render` prop for nav…
LovelessCodes Oct 27, 2025
72b7eef
feat(toggle-group): ✨ refactor `SideToggleGroup` to simplify state ha…
LovelessCodes Oct 27, 2025
4155e9d
feat(number-field): ✨ add `NumberField` component with increment and …
LovelessCodes Oct 27, 2025
b34ce5d
refactor(label): ✨ simplify `Label` component by removing dependency …
LovelessCodes Oct 27, 2025
07bcc92
refactor(switch): ✨ update `Switch` component to use `@base-ui-compon…
LovelessCodes Oct 27, 2025
35dda88
refactor(tabs): ✨ update `TabsList` styling for improved appearance
LovelessCodes Oct 27, 2025
cff2d0f
refactor(switch): ✨ update `TextSwitch` to use `@base-ui-components/r…
LovelessCodes Oct 27, 2025
e664fde
refactor(input): ✨ update `Input` component to use `@base-ui-componen…
LovelessCodes Oct 27, 2025
aff0e53
feat(autocomplete): ✨ add `Autocomplete` component with various subco…
LovelessCodes Oct 28, 2025
6ba1186
feat(autocomplete): ✨ add `AuthorAutocomplete` component and remove `…
LovelessCodes Oct 28, 2025
eb4b603
fix(button): 🐛 correct import path for `Button` component
LovelessCodes Oct 28, 2025
47eba2b
refactor(installation.card): ✨ reorganize imports for `InstallationCa…
LovelessCodes Oct 28, 2025
65a4586
refactor(server.card): ✨ reorganize import statements for `ServerCard…
LovelessCodes Oct 28, 2025
96f2f60
refactor(dialog.addinstallation): ✨ update `TooltipTrigger` usage for…
LovelessCodes Oct 28, 2025
2aa2718
refactor(dialog.addserver): ✨ update `TooltipTrigger` usage for impro…
LovelessCodes Oct 28, 2025
20c4a69
refactor(dialog.adduser): ✨ update `TooltipTrigger` usage for improve…
LovelessCodes Oct 28, 2025
932b977
refactor(dialog.addversion): ✨ update `TooltipTrigger` usage for impr…
LovelessCodes Oct 28, 2025
ac06390
refactor(dialog.connectserver): ✨ update import statements for improv…
LovelessCodes Oct 28, 2025
6c31bbe
refactor(dialog.deleteinstallation): ✨ update `AlertDialogClose` usag…
LovelessCodes Oct 28, 2025
914401d
refactor(dialog.deleteserver): ✨ update `AlertDialogClose` usage for …
LovelessCodes Oct 28, 2025
06db8b5
refactor(dialog.deleteversion): ✨ update `AlertDialogClose` usage for…
LovelessCodes Oct 28, 2025
67558ed
refactor(dialog.deleteworld): ✨ update `AlertDialogClose` usage for i…
LovelessCodes Oct 28, 2025
ec85947
refactor(dialog.editinstallation): ✨ update `TooltipTrigger` usage fo…
LovelessCodes Oct 28, 2025
80a1220
refactor(dialog.editserver): ✨ update `TooltipTrigger` usage for impr…
LovelessCodes Oct 28, 2025
2cabb84
refactor(dialog.editworld): ✨ update `TooltipTrigger` usage for impro…
LovelessCodes Oct 28, 2025
d4fb2a6
refactor(dialog.importinstallation): ✨ update `Button` import for imp…
LovelessCodes Oct 28, 2025
fd83d9f
refactor(dialog.removemod): ✨ update `AlertDialogClose` usage for imp…
LovelessCodes Oct 28, 2025
bc9c578
refactor(dialog.viewmap): ✨ update imports for improved structure
LovelessCodes Oct 28, 2025
0564f59
refactor(inputs.email): ✨ remove unused `ref` prop from `EmailInput`
LovelessCodes Oct 28, 2025
684e737
refactor(inputs.password): ✨ remove unused `ref` prop from `PasswordI…
LovelessCodes Oct 28, 2025
22971d6
refactor(inputs.search): ✨ remove unused `ref` handling in `SearchInput`
LovelessCodes Oct 28, 2025
6e7683a
refactor(items.mod): ✨ remove duplicate import of `Group`, `GroupItem…
LovelessCodes Oct 28, 2025
fcf4cb6
refactor(version.item): ✨ update imports for improved structure
LovelessCodes Oct 28, 2025
0ecdef4
refactor(world.item): ✨ update import statements for `Group`, `GroupI…
LovelessCodes Oct 28, 2025
f190486
refactor(lists.mod): ✨ update author filter to be case-insensitive
LovelessCodes Oct 28, 2025
a08281c
refactor(public.servers.list): ✨ reorganize imports and update `Toolt…
LovelessCodes Oct 28, 2025
b97f280
refactor(installation.row): ✨ reorganize import statements for `Group…
LovelessCodes Oct 28, 2025
4f1df7f
refactor(server.row): ✨ reorganize import statements for `Group`, `Gr…
LovelessCodes Oct 28, 2025
465d3b0
refactor(version.row): ✨ reorganize import statement for `Group`, `Gr…
LovelessCodes Oct 28, 2025
9f92b2d
refactor(app.sidebar): ✨ reorganize import statements and update `Too…
LovelessCodes Oct 28, 2025
58fcb01
refactor(side.tab): ✨ update import statement for `Tabs`, `TabsList`,…
LovelessCodes Oct 28, 2025
0ffa42a
refactor(installations.row): ✨ update `TooltipTrigger` usage for impr…
LovelessCodes Oct 28, 2025
f71b663
refactor(settings.row): ✨ update `TooltipTrigger` usage for improved …
LovelessCodes Oct 28, 2025
cc92c23
refactor(app.sidebar): ✨ update `DropdownMenu` items to use `Group` c…
LovelessCodes Oct 28, 2025
2e37419
refactor(context-menu): ✨ update `ContextMenuPrimitive` imports for c…
LovelessCodes Oct 28, 2025
3496a2b
refactor(context-menu): ✨ enhance context menu structure with `Contex…
LovelessCodes Oct 28, 2025
a07111e
refactor(select): ✨ update `SelectPrimitive` imports and enhance comp…
LovelessCodes Oct 28, 2025
6bd8746
refactor(auto-complete): ✨ enhance `AutocompletePopup` styling for im…
LovelessCodes Oct 28, 2025
311ea31
refactor(public-servers): ✨ replace `DropdownMenu` with `Select` for …
LovelessCodes Oct 28, 2025
fb5381c
refactor(worlds): ✨ replace `DropdownMenu` with `Select` for installa…
LovelessCodes Oct 28, 2025
8881ad8
refactor(install-mods): ✨ replace `DropdownMenu` with `Select` for ga…
LovelessCodes Oct 28, 2025
b5d3684
refactor(addinstallation.dialog): ✨ update `SelectContent` alignment …
LovelessCodes Oct 28, 2025
c93cb06
refactor(addmod.dialog): ✨ update `SelectContent` alignment for impro…
LovelessCodes Oct 28, 2025
adf1cef
refactor(addserver.dialog): ✨ update `SelectContent` alignment for co…
LovelessCodes Oct 28, 2025
6ed5a42
refactor(addversion.dialog): ✨ update `SelectContent` alignment for i…
LovelessCodes Oct 28, 2025
cb1c0de
refactor(connectserver.dialog): ✨ update `SelectContent` alignment fo…
LovelessCodes Oct 28, 2025
91f3a66
refactor(editinstallation.dialog): ✨ update `SelectContent` alignment…
LovelessCodes Oct 28, 2025
549e865
refactor(editserver.dialog): ✨ update `SelectContent` alignment for c…
LovelessCodes Oct 28, 2025
89f005a
refactor(editworld.dialog): ✨ update `SelectContent` alignment for co…
LovelessCodes Oct 28, 2025
8ac7b8c
refactor(updatemod.dialog): ✨ update `SelectContent` alignment for co…
LovelessCodes Oct 28, 2025
f45bf98
refactor(viewmap.dialog): ✨ update `SelectContent` alignment for cons…
LovelessCodes Oct 28, 2025
ea936c9
refactor(dialog): ✨ remove unused `"use client"` directive
LovelessCodes Oct 28, 2025
9c9fa01
refactor(dashboard): ✨ add `z-10` class to sticky links for improved …
LovelessCodes Oct 28, 2025
0ccc17f
refactor(app.sidebar): ✨ replace `DropdownMenu` with `Menu` for impro…
LovelessCodes Oct 28, 2025
1d8561f
refactor(menu): ✨ implement `Menu` component replacing `DropdownMenu`
LovelessCodes Oct 28, 2025
9105c32
refactor(scroll-area): ✨ update `ScrollArea` and `ScrollBar` componen…
LovelessCodes Oct 28, 2025
d7da909
refactor(popover): ✨ remove `Popover` component and related files
LovelessCodes Oct 28, 2025
d77a35f
refactor(public-servers): ✨ update `SelectTrigger` class for improved…
LovelessCodes Oct 28, 2025
429893c
refactor(dialogs): ✨ reorganize `DeleteVersionDialog` component struc…
LovelessCodes Oct 28, 2025
2dc8c87
refactor(dialogs): ✨ improve `DeleteWorldDialog` structure and user c…
LovelessCodes Oct 28, 2025
81909f3
refactor(command): 🗑️ remove `Command` component and related files
LovelessCodes Oct 29, 2025
da595ed
Merge branch 'release' into feat/base-ui
LovelessCodes Oct 29, 2025
ccd6c92
refactor(sidebar): ✨ update sidebar components to use `useRender` and…
LovelessCodes Nov 3, 2025
b3f377b
chore: 🔧 update dependencies in `bun.lock` and `package.json`
LovelessCodes Nov 3, 2025
e8bb03e
chore: 🔧 update dependencies in `package.json`
LovelessCodes Nov 3, 2025
3b7f3b1
Merge branch 'release' into feat/base-ui
LovelessCodes Nov 3, 2025
4243f61
chore: 🔧 update changelog for version 0.5.4
LovelessCodes Nov 3, 2025
bfcc6c0
refactor(sheet): ✨ update Sheet component to use new `@base-ui-compon…
LovelessCodes Nov 3, 2025
7c46c49
refactor(routes): ✨ integrate `Toaster` component with dynamic theme
LovelessCodes Nov 3, 2025
86be503
fix(settings): 🐛 update toast IDs for error and success messages
LovelessCodes Nov 3, 2025
c9fc988
refactor(routes): ✨ update `Toaster` component to use `richColors` prop
LovelessCodes Nov 3, 2025
fc68af2
chore: 🔧 update changelog to reflect UI revamp after migrating to Bas…
LovelessCodes Nov 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Moved away from using Radix UI to Base UI for all components in the UI stack.
- Revamp on the whole UI after introducing Base UI.

## [0.5.4] - 2025-10-31

### Fixed

- Resolve an issue with our build steps that would introduce blank screen on some linux distros using AppImage.
Expand Down Expand Up @@ -250,6 +257,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Stabilized login dialog and authentication flow.

<!-- Version links for diff and release pages -->
[0.5.4]: https://github.com/LovelessCodes/StoryForge/releases/tag/storyforge-v0.5.4
[0.5.3]: https://github.com/LovelessCodes/StoryForge/releases/tag/storyforge-v0.5.3
[0.5.2]: https://github.com/LovelessCodes/StoryForge/releases/tag/storyforge-v0.5.2
[0.5.1]: https://github.com/LovelessCodes/StoryForge/releases/tag/storyforge-v0.5.1
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.1/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.3/schema.json",
"assist": {
"actions": {
"source": {
Expand Down
528 changes: 169 additions & 359 deletions bun.lock

Large diffs are not rendered by default.

48 changes: 15 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,18 @@
{
"dependencies": {
"@base-ui-components/react": "^1.0.0-beta.3",
"@base-ui-components/react": "^1.0.0-beta.4",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@monaco-editor/react": "^4.7.0",
"@radix-ui/react-alert-dialog": "^1.1.15",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.3",
"@radix-ui/react-context-menu": "^2.2.16",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.6",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-toggle": "^1.1.10",
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@tailwindcss/vite": "^4.1.16",
"@tanstack/react-devtools": "^0.7.9",
"@tanstack/react-devtools": "^0.8.0",
"@tanstack/react-form": "^1.23.8",
"@tanstack/react-query": "^5.90.5",
"@tanstack/react-query": "^5.90.6",
"@tanstack/react-query-devtools": "^5.90.2",
"@tanstack/react-router": "^1.133.32",
"@tanstack/react-router-devtools": "^1.133.34",
"@tanstack/react-router": "^1.134.9",
"@tanstack/react-router-devtools": "^1.134.9",
"@tanstack/react-virtual": "^3.13.12",
"@tauri-apps/api": "^2.9.0",
"@tauri-apps/plugin-dialog": "~2.4.2",
Expand All @@ -38,33 +21,32 @@
"@tauri-apps/plugin-os": "~2.3.2",
"@tauri-apps/plugin-process": "~2.3.1",
"@tauri-apps/plugin-shell": "~2.3.3",
"@tauri-apps/plugin-updater": "~2",
"@tauri-apps/plugin-updater": "~2.9.0",
"@tauri-apps/plugin-window-state": "^2.4.1",
"@tauri-store/zustand": "^1.0.2",
"@tauri-store/zustand": "^1.1.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"date-fns": "^4.1.0",
"input-otp": "^1.4.2",
"lucide-react": "^0.548.0",
"lucide-react": "^0.552.0",
"motion": "^12.23.24",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.16",
"zod": "^4.1.12",
"zustand": "^5.0.8"
},
"devDependencies": {
"@biomejs/biome": "^2.3.1",
"@tanstack/devtools-vite": "^0.3.10",
"@tanstack/router-plugin": "^1.133.32",
"@tauri-apps/cli": "^2.9.1",
"@biomejs/biome": "^2.3.3",
"@tanstack/devtools-vite": "^0.3.11",
"@tanstack/router-plugin": "^1.134.9",
"@tauri-apps/cli": "^2.9.2",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^5.1.0",
"lefthook": "^2.0.1",
"lefthook": "^2.0.2",
"tw-animate-css": "^1.4.0",
"typescript": "~5.9.3",
"vite": "^7.1.12",
Expand Down
162 changes: 162 additions & 0 deletions src/components/auto-completes/author.auto-complete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { Autocomplete as AutocompletePrimitive } from "@base-ui-components/react/autocomplete";
import { useQueryClient } from "@tanstack/react-query";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useCallback, useMemo, useRef, useState } from "react";
import type { Mod } from "@/components/lists/mod.list";
import {
Autocomplete,
AutocompleteInput,
AutocompleteItem,
AutocompleteList,
AutocompletePopup,
} from "@/components/ui/auto-complete";
import { useModsFilters } from "@/stores/modsFilters";

export const AuthorAutocomplete = (
props: React.InputHTMLAttributes<HTMLInputElement>,
) => {
const { contains } = AutocompletePrimitive.useFilter({
sensitivity: "base",
usage: "search",
});
const [internalValue, setInternalValue] = useState("");
const actualValue = props.value || internalValue;
const { searchText, selectedGameVersions } = useModsFilters();
const scrollElementRef = useRef<HTMLDivElement>(null);

const handleValueChange = (value: string) => {
setInternalValue(value);
props.onChange?.({
target: { value },
} as React.ChangeEvent<HTMLInputElement>);
};

const queryClient = useQueryClient();
const mods = queryClient.getQueryData<Mod[] | undefined>([
"mods",
{
search: searchText,
versions: selectedGameVersions,
},
]);
const modAuthors = useMemo(
() =>
mods?.reduce(
(acc, mod) => {
// Extract unique authors with how many mods they have
if (mod.author) {
acc[mod.author] = (acc[mod.author] || 0) + 1;
}
return acc;
},
{} as Record<string, number>,
),
[mods],
);

// biome-ignore lint/correctness/useExhaustiveDependencies: Shouldn't recompute on every function change
const filteredItems = useMemo(() => {
return modAuthors
? Object.entries(modAuthors)
.filter(([author]) => contains(author, actualValue as string))
.sort(([_authorA, countA], [_authorB, countB]) => countB - countA)
.map(([author]) => author)
: [];
}, [modAuthors, actualValue]);

const shouldRenderPopup = actualValue !== "";

const virtualizer = useVirtualizer({
count: filteredItems.length,
enabled: shouldRenderPopup,
estimateSize: () => 40,
getScrollElement: () => scrollElementRef.current,
overscan: 20,
});

const handleScrollElementRef = useCallback(
(element: HTMLDivElement) => {
scrollElementRef.current = element;
if (element) {
virtualizer.measure();
}
},
[virtualizer],
);

const totalSize = virtualizer.getTotalSize();
const totalSizePx = `${totalSize}px`;

return (
<div className="relative w-48">
<Autocomplete
autoHighlight
items={(modAuthors && Object.keys(modAuthors)) || []}
itemToStringValue={(author: unknown) => author as string}
onValueChange={handleValueChange}
value={actualValue as string}
virtualized
>
<AutocompleteInput
aria-label="Select author"
className="h-9"
placeholder="Select author..."
showClear
showTrigger
/>
{shouldRenderPopup && (
<AutocompletePopup>
<AutocompleteList>
{filteredItems.length > 0 && (
<div
className="h-[min(22rem,var(--total-size))] max-h-[var(--available-height)] overflow-auto overscroll-contain scroll-pt-2"
ref={handleScrollElementRef}
role="presentation"
style={{ "--total-size": totalSizePx } as React.CSSProperties}
>
<div
className="relative w-full"
role="presentation"
style={{ height: totalSizePx }}
>
{virtualizer.getVirtualItems().map((virtualItem) => {
const author = filteredItems[virtualItem.index];
if (!author) return null;
if (!modAuthors) return null;
const modCount = modAuthors[author];
return (
<AutocompleteItem
aria-posinset={virtualItem.index + 1}
aria-setsize={filteredItems.length}
className="flex cursor-default py-2 pr-8 pl-4 text-base leading-4 outline-none"
index={virtualItem.index}
key={virtualItem.key}
style={{
height: `${virtualItem.size}px`,
left: 0,
position: "absolute",
top: 0,
transform: `translateY(${virtualItem.start}px)`,
width: "100%",
}}
value={author}
>
<div className="flex w-full flex-col">
<div className="font-medium">{author}</div>
<div className="text-xs text-muted-foreground">
{modCount} mod{modCount > 1 ? "s" : ""}
</div>
</div>
</AutocompleteItem>
);
})}
</div>
</div>
)}
</AutocompleteList>
</AutocompletePopup>
)}
</Autocomplete>
</div>
);
};
2 changes: 1 addition & 1 deletion src/components/buttons/update-all.button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { invoke } from "@tauri-apps/api/core";
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { useAddModUpdateToInstallation } from "@/hooks/use-add-mod-update-to-installation";
import { installedModsQueryKey } from "@/hooks/use-installed-mods";
import {
Expand All @@ -11,7 +12,6 @@ import {
} from "@/hooks/use-mod-updates";
import type { OutputMod } from "@/routes/install-mods/$id";
import type { Installation } from "@/stores/installations";
import { Button } from "../ui/button";

export const UpdateAllButton = ({
installation,
Expand Down
Loading