Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
56fd44f
chore(deps): adjust packages adding @base-ui/react and removing radix-ui
Barata-Ribeiro Aug 7, 2026
f342038
chore: update style from radix-vega to base-vega in components config…
Barata-Ribeiro Aug 7, 2026
d4f62e7
refactor: migrate components to @base-ui/react library
Barata-Ribeiro Aug 7, 2026
44c4283
feat(UI): add direction provider and hook from @base-ui/react
Barata-Ribeiro Aug 7, 2026
c0797bd
refactor(UI): migrate ActionBar to @base-ui/react and enhance renderi…
Barata-Ribeiro Aug 7, 2026
2437452
refactor(UI): update ColorPicker and Dropzone components for improved…
Barata-Ribeiro Aug 7, 2026
8c27e42
chore(lockfile): fix lockfile install structure
Barata-Ribeiro Aug 7, 2026
710baa6
refactor(UI): update components to use @base-ui render prop as migrat…
Barata-Ribeiro Aug 7, 2026
4c7e204
fix(UI): update buttons to use nativeButton prop for consistency
Barata-Ribeiro Aug 7, 2026
044d810
refactor(UI): improve default value handling in Slider component
Barata-Ribeiro Aug 7, 2026
3d88ae2
fix(UI): update Slider components to handle value as array and improv…
Barata-Ribeiro Aug 7, 2026
075885f
fix(UI): clean up UrlSlugGenerator component by removing console log …
Barata-Ribeiro Aug 7, 2026
809a819
fix(UI): update Select component to use value prop and enhance Downlo…
Barata-Ribeiro Aug 7, 2026
3e9fe27
fix(UI): update Select component to use value prop and enhance placeh…
Barata-Ribeiro Aug 7, 2026
2de2282
refactor(calculator): update styles in GeneralCalculator component fo…
Barata-Ribeiro Aug 7, 2026
7b8b43b
feat(tailwind): add classAttributes and experimental classRegex setti…
Barata-Ribeiro Aug 7, 2026
587c803
refactor(UI): update calculation result styling to conditionally appl…
Barata-Ribeiro Aug 7, 2026
88a9da2
refactor(navigation): implement collapsible group state management in…
Barata-Ribeiro Aug 7, 2026
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
18 changes: 17 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,21 @@
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
},
"tailwindCSS.classAttributes": ["class", "className", "ngClass", "class:list", ".*Styles*"],
"tailwindCSS.experimental.classRegex": [
"(?:enter|leave)(?:From|To)?=\\s*(?:\"|'|{`)([^(?:\"|'|`})]*)",
["clsx\\(((?:[^()]|\\([^()]*\\))*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
["cn\\(((?:[^()]|\\([^()]*\\))*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"],
["cva\\(([^;]*)[\\);]", "[`'\"`]([^'\"`;]*)[`'\"`]"],
["(?:twMerge|twJoin)\\(([^;]*)[\\);]", "[`'\"`]([^'\"`;]*)[`'\"`]"],
[
"(tw`(?:(?:(?:[^`]*\\$\\{[^]*?\\})[^`]*)+|[^`]*`))",
"((?:(?<=`)(?:[^\"'`]*)(?=\\${|`))|(?:(?<=\\})(?:[^\"'`]*)(?=\\${))|(?:(?<=\\})(?:[^\"'`]*)(?=`))|(?:(?<=')(?:[^\"'`]*)(?='))|(?:(?<=\")(?:[^\"'`]*)(?=\"))|(?:(?<=`)(?:[^\"'`]*)(?=`)))"
],
[
"(?:\\b(?:const|let|var)\\s+)?[\\w$_]*(?:[Ss]tyles|[Cc]lasses|[Cc]lassnames)[\\w\\d]*\\s*=\\s*{([\\s\\S]*?)}",
"\\s?[\\w].*:\\s*?[\"'`]([^\"'`]*).*?,?\\s?"
]
]
}
17 changes: 10 additions & 7 deletions app/components/application/app-theme-switcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ export function AppThemeSwitcher() {
return (
<div className="fixed right-6 bottom-6 z-50">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon" className="rounded-full">
<SunIcon className="size-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" />
<MoonIcon className="absolute size-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuTrigger
render={
<Button variant="outline" size="icon" className="rounded-full">
<SunIcon className="size-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" />
<MoonIcon className="absolute size-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" />
<span className="sr-only">Toggle theme</span>
</Button>
}
/>

<DropdownMenuContent align="end">
<DropdownMenuRadioGroup
value={theme ?? 'system'}
Expand Down
24 changes: 12 additions & 12 deletions app/components/navigation/logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ export function Logo() {
tooltip="Home"
aria-label="Logo"
className="cursor-pointer data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
asChild
>
<Link to="/">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<CogIcon aria-hidden className="size-6" />
</div>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">Utilities</span>
<span className="truncate text-xs">Webapp</span>
</div>
</Link>
</SidebarMenuButton>
render={
<Link to="/">
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<CogIcon aria-hidden className="size-6" />
</div>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">Utilities</span>
<span className="truncate text-xs">Webapp</span>
</div>
</Link>
}
/>
</SidebarMenuItem>
</SidebarMenu>
);
Expand Down
207 changes: 127 additions & 80 deletions app/components/navigation/nav-main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
PencilRulerIcon,
RefreshCcwDotIcon,
} from 'lucide-react';
import { Activity } from 'react';
import { Activity, useEffect, useState } from 'react';
import { NavLink, useLocation } from 'react-router';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '~/components/ui/collapsible';
import {
Expand Down Expand Up @@ -78,6 +78,31 @@ export function NavMain() {
},
];

const [openGroups, setOpenGroups] = useState<Record<string, boolean>>(() =>
Object.fromEntries(LINKS.map((item) => [item.title, Boolean(item.isActive)])),
);

useEffect(() => {
setOpenGroups((prev) => {
const next = { ...prev };
let hasChanges = false;

for (const item of LINKS) {
if (next[item.title] === undefined) {
next[item.title] = Boolean(item.isActive);
hasChanges = true;
}

if (item.isActive && !next[item.title]) {
next[item.title] = true;
hasChanges = true;
}
}

return hasChanges ? next : prev;
});
}, [LINKS]);

return (
<SidebarGroup>
<SidebarMenu>
Expand All @@ -86,64 +111,69 @@ export function NavMain() {
aria-current={location.pathname === '/' ? 'page' : undefined}
{...(location.pathname.endsWith('/') && { 'data-current': '' })}
className="cursor-pointer data-current:bg-sidebar-accent data-current:text-sidebar-accent-foreground"
asChild
>
<NavLink to="/" prefetch="render">
<GaugeIcon aria-hidden className="mr-2" />
<span>Home</span>
</NavLink>
</SidebarMenuButton>
render={
<NavLink to="/" prefetch="render">
<GaugeIcon aria-hidden className="mr-2" />
<span>Home</span>
</NavLink>
}
/>

<SidebarMenuButton
tooltip="About"
aria-current={location.pathname.endsWith('/about') ? 'page' : undefined}
{...(location.pathname.endsWith('/about') && { 'data-current': '' })}
className="cursor-pointer data-current:bg-sidebar-accent data-current:text-sidebar-accent-foreground"
asChild
>
<NavLink to="/about" prefetch="render" end>
<NotebookIcon aria-hidden className="mr-2" />
<span>About</span>
</NavLink>
</SidebarMenuButton>
render={
<NavLink to="/about" prefetch="render" end>
<NotebookIcon aria-hidden className="mr-2" />
<span>About</span>
</NavLink>
}
/>

<Activity mode={state === 'collapsed' && !isMobile ? 'visible' : 'hidden'}>
{LINKS.map((item) => (
<DropdownMenu key={item.title}>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
tooltip={item.title}
isActive={item.isActive}
aria-current={item.isActive ? 'page' : undefined}
{...(item.isActive && { 'data-current': '' })}
className="cursor-pointer data-current:bg-sidebar-accent data-current:text-sidebar-accent-foreground"
>
{item.icon && <item.icon />}
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuTrigger
render={
<SidebarMenuButton
tooltip={item.title}
isActive={item.isActive}
aria-current={item.isActive ? 'page' : undefined}
{...(item.isActive && { 'data-current': '' })}
className="cursor-pointer data-current:bg-sidebar-accent data-current:text-sidebar-accent-foreground"
>
{item.icon && <item.icon />}
</SidebarMenuButton>
}
/>

<DropdownMenuContent side="right" align="start" className="w-full">
<DropdownMenuLabel>{item.title}</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuLabel>{item.title}</DropdownMenuLabel>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup className="grid space-y-1">
<DropdownMenuGroup className="grid gap-y-1">
{item.items?.map((subItem) => {
const isActive = location.pathname.endsWith(subItem.url);

return (
<DropdownMenuItem
asChild
{...(isActive && { 'data-current': '' })}
className="inline-flex cursor-pointer items-center gap-x-2 data-current:bg-sidebar-accent data-current:px-2 data-current:font-medium data-current:text-sidebar-accent-foreground"
key={subItem.title}
>
<NavLink
to={subItem.url}
aria-current={isActive ? 'page' : undefined}
prefetch="render"
end
>
<span>{subItem.title}</span>
</NavLink>
</DropdownMenuItem>
render={
<NavLink
to={subItem.url}
aria-current={isActive ? 'page' : undefined}
prefetch="render"
end
>
<span>{subItem.title}</span>
</NavLink>
}
/>
);
})}
</DropdownMenuGroup>
Expand All @@ -154,47 +184,64 @@ export function NavMain() {

<Activity mode={state === 'expanded' || isMobile ? 'visible' : 'hidden'}>
{LINKS.map((item) => (
<Collapsible key={item.title} asChild defaultOpen={item.isActive} className="group/collapsible">
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton
tooltip={item.title}
isActive={item.isActive}
aria-current={item.isActive ? 'page' : undefined}
{...(item.isActive && { 'data-current': '' })}
className="cursor-pointer data-current:bg-sidebar-accent data-current:text-sidebar-accent-foreground"
>
{item.icon && <item.icon />}
<span>{item.title}</span>
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.items?.map((subItem) => {
const isActive = location.pathname.endsWith(subItem.url);

return (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton isActive={isActive} asChild>
<NavLink
to={subItem.url}
{...(isActive && { 'data-current': '' })}
className="inline-flex items-center gap-x-2"
aria-current={isActive ? 'page' : undefined}
prefetch="render"
end
>
<span>{subItem.title}</span>
</NavLink>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
);
})}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
<Collapsible
key={item.title}
open={openGroups[item.title] ?? false}
onOpenChange={(open) =>
setOpenGroups((prev) => ({
...prev,
[item.title]: open,
}))
}
className="group/collapsible"
render={
<SidebarMenuItem>
<CollapsibleTrigger
render={
<SidebarMenuButton
tooltip={item.title}
isActive={item.isActive}
aria-current={item.isActive ? 'page' : undefined}
{...(item.isActive && { 'data-current': '' })}
className="cursor-pointer data-current:bg-sidebar-accent data-current:text-sidebar-accent-foreground"
>
{item.icon && <item.icon />}
<span>{item.title}</span>
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuButton>
}
/>

<CollapsibleContent>
<SidebarMenuSub>
{item.items?.map((subItem) => {
const isActive = location.pathname.endsWith(subItem.url);

return (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton
isActive={isActive}
render={
<NavLink
to={subItem.url}
{...(isActive && { 'data-current': '' })}
className="inline-flex items-center gap-x-2"
aria-current={isActive ? 'page' : undefined}
prefetch="render"
end
>
<span>{subItem.title}</span>
</NavLink>
}
/>
</SidebarMenuSubItem>
);
})}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
}
/>
))}
</Activity>
</SidebarMenu>
Expand Down
Loading
Loading