Compare commits
10
Commits
1dde907313
...
fdb2cf3837
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdb2cf3837 | ||
|
|
1d51ece993 | ||
|
|
827dc22729 | ||
|
|
4f7003dde9 | ||
|
|
0ba01cd111 | ||
|
|
ba691d3a0c | ||
|
|
fe258e5895 | ||
|
|
bbdf4a3312 | ||
|
|
e98a1e85f0 | ||
|
|
2232ef0029 |
+4
-2
@@ -26,5 +26,7 @@ yarn-error.log
|
|||||||
# Platform specific
|
# Platform specific
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
/backend/public/
|
/apps/backend/public/
|
||||||
/backend/storage/
|
/apps/backend/storage/
|
||||||
|
/apps/backend/.adonisjs/
|
||||||
|
/apps/backend/database/schema.ts
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Dependencies and generated output
|
||||||
|
**/node_modules/**
|
||||||
|
**/build/**
|
||||||
|
**/dist/**
|
||||||
|
**/coverage/**
|
||||||
|
apps/backend/public/**
|
||||||
|
apps/backend/storage/**
|
||||||
|
|
||||||
|
# Handlebars generator templates contain application syntax that is not valid HTML.
|
||||||
|
apps/backend/app/templates/**
|
||||||
@@ -7,15 +7,51 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `@crux-kit/editor-tiptap`, a free, headless rich-text editor package built on TipTap. The `light` preset covers bold, italic, underline,
|
||||||
|
strikethrough, headings, lists, blockquote, text alignment, links, and undo/redo, reading and
|
||||||
|
writing content as plain HTML so it themes with the shared design-system tokens.
|
||||||
|
- Added the `InputTiptapEditor` composed form field.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
## [1.2.0] - 2026-07-17
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Moved AdonisJS ESLint and Prettier configuration packages and Japa test dependencies from the
|
||||||
|
root package manifest to the backend workspace so workspace-specific dependencies are owned by
|
||||||
|
`apps/backend`.
|
||||||
|
- Updated the Admin frontend architecture so global providers belong to the `app` composition
|
||||||
|
layer under `app/providers` instead of being modeled as a separate architectural layer.
|
||||||
|
|
||||||
|
## [1.1.0] - 2026-07-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added image map editor for creating and editing interactive image map areas in the File Manager.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Migrated TypeScript from `5.8.3` to `7.0.2`
|
||||||
|
- Migrated AdonisJS from `6.x` to `7.3.5`
|
||||||
- Refactored admin module-generator source builders to compose imports and source sections through
|
- Refactored admin module-generator source builders to compose imports and source sections through
|
||||||
shared source-file helpers while preserving the existing generation payload.
|
shared source-file helpers while preserving the existing generation payload.
|
||||||
- Renamed module-generator builder classes and files from template-builder terminology to
|
- Renamed module-generator builder classes and files from template-builder terminology to
|
||||||
source-builder terminology.
|
source-builder terminology.
|
||||||
- Updated module-generator frontend documentation to reference the new source-builder names.
|
- Updated module-generator frontend documentation to reference the new source-builder names.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
- Fix prettier one line import break sorting and class order
|
- Fix prettier one line import break sorting and class order
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
- Removed "prettier-plugin-one-line-imports"
|
- Removed "prettier-plugin-one-line-imports"
|
||||||
|
|
||||||
## [1.0.1] - 2026-06-30
|
## [1.0.1] - 2026-06-30
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
Node.js >= 22.14.0
|
Node.js >= v24.18.0
|
||||||
npm >= 11.6.2
|
npm >= 11.15.0
|
||||||
Database PostgreSQL
|
Database PostgreSQL
|
||||||
|
|
||||||
#### Installation
|
#### Installation
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
FROM node:22-alpine3.20
|
FROM node:24-alpine3.22
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install workspace deps
|
# Copy all workspaces before installation so npm resolves workspace dependencies.
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
|
COPY apps ./apps
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
# Copy project
|
|
||||||
COPY apps/admin ./apps/admin
|
|
||||||
COPY packages ./packages
|
COPY packages ./packages
|
||||||
|
|
||||||
|
RUN npm ci --force
|
||||||
|
|
||||||
WORKDIR /app/apps/admin
|
WORKDIR /app/apps/admin
|
||||||
|
|
||||||
ENV CHOKIDAR_USEPOLLING=true
|
ENV CHOKIDAR_USEPOLLING=true
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@crux-kit/admin-app",
|
"name": "@crux-kit/admin-app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.1",
|
"version": "1.2.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@crux-kit/editor-tiptap": "*",
|
||||||
"@crux-kit/hooks": "*",
|
"@crux-kit/hooks": "*",
|
||||||
"@crux-kit/intl-date": "*",
|
"@crux-kit/intl-date": "*",
|
||||||
"@crux-kit/intl-name": "*",
|
"@crux-kit/intl-name": "*",
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
@plugin "@tailwindcss/typography";
|
@plugin "@tailwindcss/typography";
|
||||||
@plugin "@tailwindcss/typography";
|
@plugin "@tailwindcss/typography";
|
||||||
|
|
||||||
|
/* @crux-kit/editor-tiptap — Tailwind class scanning + editor content styles */
|
||||||
|
@source '../../../../../packages/design-system/editor-tiptap/src';
|
||||||
|
@import '@crux-kit/editor-tiptap/styles.css';
|
||||||
|
|
||||||
/* ReUI Configs */
|
/* ReUI Configs */
|
||||||
@import './config.reui.css';
|
@import './config.reui.css';
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function Breadcrumb() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1.25 text-xs lg:text-sm font-medium mb-2.5 lg:mb-0">
|
<div className="mb-2.5 flex items-center gap-1.25 text-xs font-medium lg:mb-0 lg:text-sm">
|
||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
const last = index === items.length - 1;
|
const last = index === items.length - 1;
|
||||||
const active = item.path ? isActive(item.path) : false;
|
const active = item.path ? isActive(item.path) : false;
|
||||||
@@ -31,7 +31,7 @@ export function Breadcrumb() {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</span>
|
</span>
|
||||||
{!last && (
|
{!last && (
|
||||||
<ChevronRight className="size-3.5 text-muted-foreground" key={`separator-${index}`} />
|
<ChevronRight className="text-muted-foreground size-3.5" key={`separator-${index}`} />
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export function Content() {
|
|||||||
const mobile = useIsMobile();
|
const mobile = useIsMobile();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grow content pt-5" role="content">
|
<div className="content grow pt-5" role="content">
|
||||||
{mobile && (
|
{mobile && (
|
||||||
<Container>
|
<Container>
|
||||||
<Breadcrumb />
|
<Breadcrumb />
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -32,13 +32,13 @@ export function Header() {
|
|||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className={cn(
|
className={cn(
|
||||||
'header fixed top-0 z-10 start-0 flex items-stretch shrink-0 border-b border-transparent bg-background end-0 pe-(--removed-body-scroll-bar-size,0px)',
|
'header bg-background fixed start-0 end-0 top-0 z-10 flex shrink-0 items-stretch border-b border-transparent pe-(--removed-body-scroll-bar-size,0px)',
|
||||||
headerSticky && 'border-b border-border'
|
headerSticky && 'border-border border-b'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Container className="flex justify-between items-stretch lg:gap-4">
|
<Container className="flex items-stretch justify-between lg:gap-4">
|
||||||
{/* HeaderLogo */}
|
{/* HeaderLogo */}
|
||||||
<div className="flex lg:hidden items-center gap-2.5">
|
<div className="flex items-center gap-2.5 lg:hidden">
|
||||||
<Link to="/" className="shrink-0">
|
<Link to="/" className="shrink-0">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo.svg')}
|
||||||
@@ -54,9 +54,9 @@ export function Header() {
|
|||||||
<Menu className="text-muted-foreground/70" />
|
<Menu className="text-muted-foreground/70" />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-68.75" side="left" close={false}>
|
<SheetContent className="w-68.75 gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 overflow-y-auto">
|
<SheetBody className="overflow-y-auto p-0">
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
@@ -69,9 +69,9 @@ export function Header() {
|
|||||||
<SquareChevronRight className="text-muted-foreground/70" />
|
<SquareChevronRight className="text-muted-foreground/70" />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-68.75" side="left" close={false}>
|
<SheetContent className="w-68.75 gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 overflow-y-auto">
|
<SheetBody className="overflow-y-auto p-0">
|
||||||
<MegaMenuMobile />
|
<MegaMenuMobile />
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
@@ -88,7 +88,7 @@ export function Header() {
|
|||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="size-9 rounded-full border-2 border-green-500 shrink-0 cursor-pointer"
|
className="size-9 shrink-0 cursor-pointer rounded-full border-2 border-green-500"
|
||||||
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export function MegaMenuMobile() {
|
|||||||
<AccordionMenuItem key={index} value={item.path || ''} className="text-[13px]">
|
<AccordionMenuItem key={index} value={item.path || ''} className="text-[13px]">
|
||||||
<Link to={item.path || '#'}>
|
<Link to={item.path || '#'}>
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<div className="flex items-center justify-between grow gap-2">
|
<div className="flex grow items-center justify-between gap-2">
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
{item.badge && (
|
{item.badge && (
|
||||||
<Badge variant="secondary" size="sm" className="ms-auto">
|
<Badge variant="secondary" size="sm" className="ms-auto">
|
||||||
@@ -182,7 +182,7 @@ export function MegaMenuMobile() {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex grow shrink-0 py-5 px-5">
|
<div className="flex shrink-0 grow px-5 py-5">
|
||||||
<AccordionMenu
|
<AccordionMenu
|
||||||
selectedValue={pathname}
|
selectedValue={pathname}
|
||||||
matchPath={matchPath}
|
matchPath={matchPath}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { SidebarHeader } from './SidebarHeader';
|
import { SidebarHeader } from './SidebarHeader';
|
||||||
import { SidebarMenu } from './SidebarMenu';
|
import { SidebarMenu } from './SidebarMenu';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ export function Sidebar() {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'sidebar bg-background lg:border-e lg:border-border lg:fixed lg:top-0 lg:bottom-0 lg:z-20 lg:flex flex-col items-stretch shrink-0',
|
'sidebar bg-background lg:border-border shrink-0 flex-col items-stretch lg:fixed lg:top-0 lg:bottom-0 lg:z-20 lg:flex lg:border-e',
|
||||||
(settings.layouts[LayoutNames.DEFAULT].sidebarTheme === 'dark' ||
|
(settings.layouts[LayoutNames.DEFAULT].sidebarTheme === 'dark' ||
|
||||||
pathname.includes('dark-sidebar')) &&
|
pathname.includes('dark-sidebar')) &&
|
||||||
'dark'
|
'dark'
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { ChevronFirst } from 'lucide-react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { toAbsoluteUrl } from '#shared/lib/helpers';
|
import { toAbsoluteUrl } from '#shared/lib/helpers';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
|
|
||||||
export function SidebarHeader() {
|
export function SidebarHeader() {
|
||||||
const { settings, storeOption } = useSettings();
|
const { settings, storeOption } = useSettings();
|
||||||
@@ -17,7 +17,7 @@ export function SidebarHeader() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sidebar-header hidden lg:flex items-center relative justify-between px-3 lg:px-6 shrink-0">
|
<div className="sidebar-header relative hidden shrink-0 items-center justify-between px-3 lg:flex lg:px-6">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<div className="dark:hidden">
|
<div className="dark:hidden">
|
||||||
{/* <img
|
{/* <img
|
||||||
@@ -50,7 +50,7 @@ export function SidebarHeader() {
|
|||||||
mode="icon"
|
mode="icon"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className={cn(
|
className={cn(
|
||||||
'size-7 absolute start-full top-2/4 rtl:translate-x-2/4 -translate-x-2/4 -translate-y-2/4',
|
'absolute start-full top-2/4 size-7 -translate-x-2/4 -translate-y-2/4 rtl:translate-x-2/4',
|
||||||
settings.layouts[LayoutNames.DEFAULT].sidebarCollapse
|
settings.layouts[LayoutNames.DEFAULT].sidebarCollapse
|
||||||
? 'ltr:rotate-180'
|
? 'ltr:rotate-180'
|
||||||
: 'rtl:rotate-180'
|
: 'rtl:rotate-180'
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export function SidebarMenu() {
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm font-medium">
|
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm font-medium">
|
||||||
<Link to={item.path || '#'} className="flex items-center justify-start grow gap-2">
|
<Link to={item.path || '#'} className="flex grow items-center justify-start gap-2">
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<span data-slot="accordion-menu-title">{item.title}</span>
|
<span data-slot="accordion-menu-title">{item.title}</span>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -165,7 +165,7 @@ export function SidebarMenu() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="kt-scrollable-y-hover flex grow shrink-0 py-5 px-5 lg:max-h-[calc(100vh-5.5rem)]">
|
<div className="kt-scrollable-y-hover flex shrink-0 grow px-5 py-5 lg:max-h-[calc(100vh-5.5rem)]">
|
||||||
<AccordionMenu
|
<AccordionMenu
|
||||||
selectedValue={pathname}
|
selectedValue={pathname}
|
||||||
matchPath={matchPath}
|
matchPath={matchPath}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ function ToolbarBreadcrumbs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex [.header_&]:below-lg:hidden items-center gap-1.25 text-xs lg:text-sm font-medium mb-2.5 lg:mb-0">
|
<div className="[.header_&]:below-lg:hidden mb-2.5 flex items-center gap-1.25 text-xs font-medium lg:mb-0 lg:text-sm">
|
||||||
<div className="breadcrumb flex items-center gap-1">
|
<div className="breadcrumb flex items-center gap-1">
|
||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
const isLast = index === items.length - 1;
|
const isLast = index === items.length - 1;
|
||||||
@@ -53,7 +53,7 @@ function ToolbarBreadcrumbs() {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{!isLast && <ChevronRight className="size-3.5 muted-foreground" />}
|
{!isLast && <ChevronRight className="muted-foreground size-3.5" />}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -71,11 +71,11 @@ function ToolbarHeading({ title = '', description }: ToolbarHeadingProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col justify-center gap-2">
|
<div className="flex flex-col justify-center gap-2">
|
||||||
<h1 className="text-xl font-medium leading-none text-mono">
|
<h1 className="text-mono text-xl leading-none font-medium">
|
||||||
{title || item?.title || 'Untitled'}
|
{title || item?.title || 'Untitled'}
|
||||||
</h1>
|
</h1>
|
||||||
{description && (
|
{description && (
|
||||||
<div className="flex items-center gap-2 text-sm font-normal text-muted-foreground">
|
<div className="text-muted-foreground flex items-center gap-2 text-sm font-normal">
|
||||||
{description}
|
{description}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useEffect } from 'react';
|
|||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
import { useIsMobile } from '@crux-kit/hooks';
|
import { useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Sidebar } from './components/Sidebar';
|
import { Sidebar } from './components/Sidebar';
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { useEffect, useState } from 'react'; // Add useState to the imports
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
|
|
||||||
@@ -30,13 +30,13 @@ export function Header() {
|
|||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center transition-[height] shrink-0 h-(--header-height) in-data-[sticky-header=on]:pe-(--removed-body-scroll-bar-size,0px)',
|
'flex h-(--header-height) shrink-0 items-center transition-[height] in-data-[sticky-header=on]:pe-(--removed-body-scroll-bar-size,0px)',
|
||||||
settings.layouts[LayoutNames.HORIZONTAL_MENU].headerSticky &&
|
settings.layouts[LayoutNames.HORIZONTAL_MENU].headerSticky &&
|
||||||
headerStickyOn &&
|
headerStickyOn &&
|
||||||
'transition-[height] fixed z-10 top-0 start-0 end-0 shadow-xs backdrop-blur-md bg-background/70'
|
'bg-background/70 fixed start-0 end-0 top-0 z-10 shadow-xs backdrop-blur-md transition-[height]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Container className="flex justify-between items-center lg:gap-4">
|
<Container className="flex items-center justify-between lg:gap-4">
|
||||||
<HeaderLogo />
|
<HeaderLogo />
|
||||||
<HeaderTopbar />
|
<HeaderTopbar />
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -30,20 +30,20 @@ export function HeaderLogo() {
|
|||||||
<Link to="/" className="shrink-0">
|
<Link to="/" className="shrink-0">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle.svg')}
|
||||||
className="dark:hidden min-h-10.5"
|
className="min-h-10.5 dark:hidden"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle-dark.svg')}
|
||||||
className="hidden dark:inline-block min-h-10.5"
|
className="hidden min-h-10.5 dark:inline-block"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Menu Section */}
|
{/* Menu Section */}
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<h3 className="text-accent-foreground text-base hidden md:block">Metronic Team</h3>
|
<h3 className="text-accent-foreground hidden text-base md:block">Metronic Team</h3>
|
||||||
<span className="text-sm text-muted-foreground font-medium hidden md:inline">/</span>
|
<span className="text-muted-foreground hidden text-sm font-medium md:inline">/</span>
|
||||||
|
|
||||||
{/* <DropdownMenu>
|
{/* <DropdownMenu>
|
||||||
<DropdownMenuTrigger className="cursor-pointer text-mono font-medium flex items-center gap-2">
|
<DropdownMenuTrigger className="cursor-pointer text-mono font-medium flex items-center gap-2">
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export function HeaderTopbar() {
|
|||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="cursor-pointer size-9 rounded-full justify-center border border-gray-500 shrink-0"
|
className="size-9 shrink-0 cursor-pointer justify-center rounded-full border border-gray-500"
|
||||||
src={toAbsoluteUrl('/media/avatars/gray/5.png')}
|
src={toAbsoluteUrl('/media/avatars/gray/5.png')}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { NavbarMenu } from './NavbarMenu';
|
|||||||
|
|
||||||
export function Navbar() {
|
export function Navbar() {
|
||||||
return (
|
return (
|
||||||
<div className="border-b border-border pb-5 lg:pb-0 mb-5 lg:mb-10">
|
<div className="border-border mb-5 border-b pb-5 lg:mb-10 lg:pb-0">
|
||||||
<Container className="flex flex-wrap justify-between items-center gap-2">
|
<Container className="flex flex-wrap items-center justify-between gap-2">
|
||||||
<NavbarMenu />
|
<NavbarMenu />
|
||||||
<NavbarLinks />
|
<NavbarLinks />
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
export function NavbarLinks() {
|
export function NavbarLinks() {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center text-sm gap-5 lg:pb-1">
|
<div className="flex items-center gap-5 text-sm lg:pb-1">
|
||||||
<a className="hover:text-primary" href="https://www.youtube.com/c/KeenThemesTuts/videos">
|
<a className="hover:text-primary" href="https://www.youtube.com/c/KeenThemesTuts/videos">
|
||||||
Videos
|
Videos
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ export function NavbarMenu() {
|
|||||||
<MenubarMenu key={index}>
|
<MenubarMenu key={index}>
|
||||||
<MenubarTrigger
|
<MenubarTrigger
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center gap-1.5 px-3 py-3.5 text-sm text-secondary-foreground text-nowrap',
|
'text-secondary-foreground flex items-center gap-1.5 px-3 py-3.5 text-sm text-nowrap',
|
||||||
'rounded-none border-b-2 border-transparent bg-transparent!',
|
'rounded-none border-b-2 border-transparent bg-transparent!',
|
||||||
'hover:text-mono hover:bg-transparent',
|
'hover:text-mono hover:bg-transparent',
|
||||||
'focus:text-mono focus:bg-transparent',
|
'focus:text-mono focus:bg-transparent',
|
||||||
'data-[state=open]:bg-transparent data-[state=open]:text-mono',
|
'data-[state=open]:text-mono data-[state=open]:bg-transparent',
|
||||||
'data-[here=true]:text-mono data-[here=true]:border-mono'
|
'data-[here=true]:text-mono data-[here=true]:border-mono'
|
||||||
)}
|
)}
|
||||||
data-active={isActive(item.path) || undefined}
|
data-active={isActive(item.path) || undefined}
|
||||||
@@ -57,7 +57,7 @@ export function NavbarMenu() {
|
|||||||
<MenubarTrigger
|
<MenubarTrigger
|
||||||
asChild
|
asChild
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center py-3.5 text-sm text-secondary-foreground px-3 text-nowrap',
|
'text-secondary-foreground flex items-center px-3 py-3.5 text-sm text-nowrap',
|
||||||
'rounded-none border-b-2 border-transparent bg-transparent!',
|
'rounded-none border-b-2 border-transparent bg-transparent!',
|
||||||
'hover:text-mono hover:bg-transparent',
|
'hover:text-mono hover:bg-transparent',
|
||||||
'focus:text-mono focus:bg-transparent',
|
'focus:text-mono focus:bg-transparent',
|
||||||
@@ -112,7 +112,7 @@ export function NavbarMenu() {
|
|||||||
return (
|
return (
|
||||||
<div className="grid">
|
<div className="grid">
|
||||||
<div className="kt-scrollable-x-auto">
|
<div className="kt-scrollable-x-auto">
|
||||||
<Menubar className="flex items-stretch border-none bg-transparent p-0 h-auto">
|
<Menubar className="flex h-auto items-stretch border-none bg-transparent p-0">
|
||||||
{buildMenu(navbarMenu.children as MenuConfig)}
|
{buildMenu(navbarMenu.children as MenuConfig)}
|
||||||
</Menubar>
|
</Menubar>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-5 lg:mb-10">
|
<div className="mb-5 lg:mb-10">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-5">
|
<Container className="flex flex-wrap items-center justify-between gap-5">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,7 +37,7 @@ function ToolbarBreadcrumbs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex [.header_&]:below-lg:hidden items-center gap-1.25 text-xs lg:text-sm font-medium mb-2.5 lg:mb-0">
|
<div className="[.header_&]:below-lg:hidden mb-2.5 flex items-center gap-1.25 text-xs font-medium lg:mb-0 lg:text-sm">
|
||||||
<div className="breadcrumb flex items-center gap-1">
|
<div className="breadcrumb flex items-center gap-1">
|
||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
const isLast = index === items.length - 1;
|
const isLast = index === items.length - 1;
|
||||||
@@ -60,7 +60,7 @@ function ToolbarBreadcrumbs() {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{!isLast && <ChevronRight className="size-3.5 muted-foreground" />}
|
{!isLast && <ChevronRight className="muted-foreground size-3.5" />}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -76,8 +76,8 @@ const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => {
|
|||||||
const item = getCurrentItem(menuConfig);
|
const item = getCurrentItem(menuConfig);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center flex-wrap gap-1 lg:gap-5">
|
<div className="flex flex-wrap items-center gap-1 lg:gap-5">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Outlet, useLocation } from 'react-router-dom';
|
import { Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass } from '@crux-kit/hooks';
|
import { useBodyClass } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { HeaderTopbar } from './HeaderTopbar';
|
|||||||
|
|
||||||
export function Header() {
|
export function Header() {
|
||||||
return (
|
return (
|
||||||
<header className="flex items-center fixed z-10 top-0 left-0 right-0 shrink-0 h-(--header-height) bg-muted">
|
<header className="bg-muted fixed top-0 right-0 left-0 z-10 flex h-(--header-height) shrink-0 items-center">
|
||||||
<Container className="flex justify-between items-stretch px-5 lg:ps-0 lg:gap-4">
|
<Container className="flex items-stretch justify-between px-5 lg:gap-4 lg:ps-0">
|
||||||
<HeaderLogo />
|
<HeaderLogo />
|
||||||
<HeaderTopbar />
|
<HeaderTopbar />
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -27,16 +27,16 @@ export function HeaderLogo() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<div className="flex items-center justify-center lg:w-(--sidebar-width) shrink-0">
|
<div className="flex shrink-0 items-center justify-center lg:w-(--sidebar-width)">
|
||||||
<Sheet>
|
<Sheet>
|
||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button variant="ghost" mode="icon" className="-ms-2 lg:hidden">
|
<Button variant="ghost" mode="icon" className="-ms-2 lg:hidden">
|
||||||
<Menu className="size-4!" />
|
<Menu className="size-4!" />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-(--sidebar-width)" side="left" close={false}>
|
<SheetContent className="w-(--sidebar-width) gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 overflow-y-auto">
|
<SheetBody className="overflow-y-auto p-0">
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
@@ -45,12 +45,12 @@ export function HeaderLogo() {
|
|||||||
<Link to="/" className="mx-1">
|
<Link to="/" className="mx-1">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-primary.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-primary.svg')}
|
||||||
className="dark:hidden min-h-6"
|
className="min-h-6 dark:hidden"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-primary-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-primary-dark.svg')}
|
||||||
className="hidden dark:inline-block min-h-6"
|
className="hidden min-h-6 dark:inline-block"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -58,8 +58,8 @@ export function HeaderLogo() {
|
|||||||
|
|
||||||
{/* Menu Section */}
|
{/* Menu Section */}
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<h3 className="text-accent-foreground text-base hidden md:block">Metronic Team</h3>
|
<h3 className="text-accent-foreground hidden text-base md:block">Metronic Team</h3>
|
||||||
<span className="text-sm text-muted-foreground font-medium hidden md:inline">/</span>
|
<span className="text-muted-foreground hidden text-sm font-medium md:inline">/</span>
|
||||||
|
|
||||||
{/* <DropdownMenu>
|
{/* <DropdownMenu>
|
||||||
<DropdownMenuTrigger className="cursor-pointer text-mono font-medium flex items-center gap-2">
|
<DropdownMenuTrigger className="cursor-pointer text-mono font-medium flex items-center gap-2">
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function HeaderTopbar() {
|
|||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="size-9 rounded-full border-2 border-input shrink-0 cursor-pointer"
|
className="border-input size-9 shrink-0 cursor-pointer rounded-full border-2"
|
||||||
src={toAbsoluteUrl('/media/avatars/gray/5.png')}
|
src={toAbsoluteUrl('/media/avatars/gray/5.png')}
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import { NavbarMenu } from './NavbarMenu';
|
|||||||
|
|
||||||
export function Navbar() {
|
export function Navbar() {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-stretch lg:fixed z-5 top-(--header-height) start-(--sidebar-width) end-5 h-(--navbar-height) mx-5 lg:mx-0 bg-muted">
|
<div className="bg-muted start-(--sidebar-width) end-5 top-(--header-height) z-5 mx-5 flex h-(--navbar-height) items-stretch lg:fixed lg:mx-0">
|
||||||
<div className="rounded-t-xl border border-border bg-background flex items-stretch grow">
|
<div className="border-border bg-background flex grow items-stretch rounded-t-xl border">
|
||||||
<Container className="flex justify-between items-stretch gap-5">
|
<Container className="flex items-stretch justify-between gap-5">
|
||||||
<NavbarMenu />
|
<NavbarMenu />
|
||||||
<NavbarLinks />
|
<NavbarLinks />
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ export function NavbarMenu() {
|
|||||||
<MenubarMenu key={index}>
|
<MenubarMenu key={index}>
|
||||||
<MenubarTrigger
|
<MenubarTrigger
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center gap-1 px-0 py-3.5 text-sm text-secondary-foreground text-nowrap',
|
'text-secondary-foreground flex items-center gap-1 px-0 py-3.5 text-sm text-nowrap',
|
||||||
'rounded-none border-b-2 border-transparent bg-transparent!',
|
'rounded-none border-b-2 border-transparent bg-transparent!',
|
||||||
'hover:text-mono hover:bg-transparent',
|
'hover:text-mono hover:bg-transparent',
|
||||||
'focus:text-mono focus:bg-transparent',
|
'focus:text-mono focus:bg-transparent',
|
||||||
'data-[state=open]:bg-transparent data-[state=open]:text-mono',
|
'data-[state=open]:text-mono data-[state=open]:bg-transparent',
|
||||||
'data-[here=true]:text-mono data-[here=true]:border-mono'
|
'data-[here=true]:text-mono data-[here=true]:border-mono'
|
||||||
)}
|
)}
|
||||||
data-active={isActive(item.path) || undefined}
|
data-active={isActive(item.path) || undefined}
|
||||||
@@ -57,7 +57,7 @@ export function NavbarMenu() {
|
|||||||
<MenubarTrigger
|
<MenubarTrigger
|
||||||
asChild
|
asChild
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center py-3.5 text-sm text-secondary-foreground px-3 text-nowrap',
|
'text-secondary-foreground flex items-center px-3 py-3.5 text-sm text-nowrap',
|
||||||
'rounded-none border-b-2 border-transparent bg-transparent!',
|
'rounded-none border-b-2 border-transparent bg-transparent!',
|
||||||
'hover:text-mono hover:bg-transparent',
|
'hover:text-mono hover:bg-transparent',
|
||||||
'focus:text-mono focus:bg-transparent',
|
'focus:text-mono focus:bg-transparent',
|
||||||
@@ -112,7 +112,7 @@ export function NavbarMenu() {
|
|||||||
return (
|
return (
|
||||||
<div className="grid">
|
<div className="grid">
|
||||||
<div className="kt-scrollable-x-auto flex items-stretch">
|
<div className="kt-scrollable-x-auto flex items-stretch">
|
||||||
<Menubar className="space-x-0 flex items-stretch border-none bg-transparent gap-5 p-0 h-auto">
|
<Menubar className="flex h-auto items-stretch gap-5 space-x-0 border-none bg-transparent p-0">
|
||||||
{buildMenu(navbarMenu.children as MenuConfig)}
|
{buildMenu(navbarMenu.children as MenuConfig)}
|
||||||
</Menubar>
|
</Menubar>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import { SidebarMenu } from './SidebarMenu';
|
|||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<div className="fixed w-(--sidebar-width) lg:top-(--header-height) top-0 bottom-0 z-20 lg:flex flex-col items-stretch shrink-0 group py-3 lg:py-0">
|
<div className="group fixed top-0 bottom-0 z-20 w-(--sidebar-width) shrink-0 flex-col items-stretch py-3 lg:top-(--header-height) lg:flex lg:py-0">
|
||||||
<div className="flex grow shrink-0">
|
<div className="flex shrink-0 grow">
|
||||||
<div className="kt-scrollable-y-auto grow gap-2.5 shrink-0 flex items-center flex-col max-h-[calc(100vh-3rem)]">
|
<div className="kt-scrollable-y-auto flex max-h-[calc(100vh-3rem)] shrink-0 grow flex-col items-center gap-2.5">
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export function SidebarMenu() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<div className="flex flex-col grow items-center py-3.5 lg:py-0 gap-2.5">
|
<div className="flex grow flex-col items-center gap-2.5 py-3.5 lg:py-0">
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<Tooltip key={index}>
|
<Tooltip key={index}>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
@@ -79,8 +79,8 @@ export function SidebarMenu() {
|
|||||||
mode="icon"
|
mode="icon"
|
||||||
{...(item.active ? { 'data-state': 'open' } : {})}
|
{...(item.active ? { 'data-state': 'open' } : {})}
|
||||||
className={cn(
|
className={cn(
|
||||||
'data-[state=open]:bg-background data-[state=open]:border data-[state=open]:border-input data-[state=open]:text-primary',
|
'data-[state=open]:bg-background data-[state=open]:border-input data-[state=open]:text-primary data-[state=open]:border',
|
||||||
'hover:bg-background hover:border hover:border-input hover:text-primary'
|
'hover:bg-background hover:border-input hover:text-primary hover:border'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-5 lg:mb-10">
|
<div className="mb-5 lg:mb-10">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-5">
|
<Container className="flex flex-wrap items-center justify-between gap-5">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,7 +38,7 @@ function ToolbarBreadcrumbs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1.5 text-xs lg:text-sm font-medium mb-2.5 lg:mb-0">
|
<div className="mb-2.5 flex items-center gap-1.5 text-xs font-medium lg:mb-0 lg:text-sm">
|
||||||
<div className="breadcrumb flex items-center gap-1">
|
<div className="breadcrumb flex items-center gap-1">
|
||||||
{items.map((item, index) => {
|
{items.map((item, index) => {
|
||||||
const isLast = index === items.length - 1;
|
const isLast = index === items.length - 1;
|
||||||
@@ -61,7 +61,7 @@ function ToolbarBreadcrumbs() {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{!isLast && <ChevronRight className="size-3.5 muted-foreground" />}
|
{!isLast && <ChevronRight className="muted-foreground size-3.5" />}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -77,8 +77,8 @@ const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => {
|
|||||||
const item = getCurrentItem(menuConfig);
|
const item = getCurrentItem(menuConfig);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center flex-wrap gap-1 lg:gap-5">
|
<div className="flex flex-wrap items-center gap-1 lg:gap-5">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { useEffect } from 'react';
|
|||||||
import { Link, Outlet, useLocation } from 'react-router-dom';
|
import { Link, Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
@@ -37,13 +37,13 @@ export function CompactSidebarLayout() {
|
|||||||
<div className="flex grow">
|
<div className="flex grow">
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row grow pt-(--header-height)">
|
<div className="flex grow flex-col pt-(--header-height) lg:flex-row">
|
||||||
{!isMobileMode && <Sidebar />}
|
{!isMobileMode && <Sidebar />}
|
||||||
|
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="flex grow rounded-b-xl bg-background border-x border-b border-border lg:mt-(--navbar-height) mx-5 lg:ms-(--sidebar-width) mb-5">
|
<div className="bg-background border-border mx-5 mb-5 flex grow rounded-b-xl border-x border-b lg:ms-(--sidebar-width) lg:mt-(--navbar-height)">
|
||||||
<div className="flex flex-col grow kt-scrollable-y lg:[scrollbar-width:auto] pt-7 lg:**:data-[slot=container]:pe-2">
|
<div className="kt-scrollable-y flex grow flex-col pt-7 lg:[scrollbar-width:auto] lg:**:data-[slot=container]:pe-2">
|
||||||
<main className="grow" role="content">
|
<main className="grow" role="content">
|
||||||
{pathname !== '/' && (
|
{pathname !== '/' && (
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -18,17 +18,17 @@ export function Header() {
|
|||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="flex lg:hidden items-center fixed z-10 top-0 start-0 end-0 shrink-0 bg-(--page-bg) dark:bg-(--page-bg-dark) h-(--header-height)">
|
<header className="fixed start-0 end-0 top-0 z-10 flex h-(--header-height) shrink-0 items-center bg-(--page-bg) lg:hidden dark:bg-(--page-bg-dark)">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-3">
|
<Container className="flex flex-wrap items-center justify-between gap-3">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-gray.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-gray.svg')}
|
||||||
className="dark:hidden min-h-7.5"
|
className="min-h-7.5 dark:hidden"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-gray-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-gray-dark.svg')}
|
||||||
className="hidden dark:block min-h-7.5"
|
className="hidden min-h-7.5 dark:block"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -39,9 +39,9 @@ export function Header() {
|
|||||||
<Menu />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-(--sidebar-width)" side="left" close={false}>
|
<SheetContent className="w-(--sidebar-width) gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 flex items-stretch shrink-0 overflow-y-auto">
|
<SheetBody className="flex shrink-0 items-stretch overflow-y-auto p-0">
|
||||||
<SidebarPrimary />
|
<SidebarPrimary />
|
||||||
<SidebarSecondary />
|
<SidebarSecondary />
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { SidebarSecondary } from './SidebarSecondary';
|
|||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<div className="fixed top-0 bottom-0 z-20 flex items-stretch shrink-0 w-(--sidebar-width) bg-muted">
|
<div className="bg-muted fixed top-0 bottom-0 z-20 flex w-(--sidebar-width) shrink-0 items-stretch">
|
||||||
<SidebarPrimary />
|
<SidebarPrimary />
|
||||||
<SidebarSecondary />
|
<SidebarSecondary />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export function SidebarMenuDefault() {
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm">
|
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm">
|
||||||
<Link to={item.path || '#'} className="flex items-center justify-between grow gap-2">
|
<Link to={item.path || '#'} className="flex grow items-center justify-between gap-2">
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<span data-slot="accordion-menu-title">{item.title}</span>
|
<span data-slot="accordion-menu-title">{item.title}</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -101,25 +101,25 @@ export function SidebarPrimary() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<div className="flex flex-col items-stretch shrink-0 gap-5 py-5 w-17.5 border-e border-input">
|
<div className="border-input flex w-17.5 shrink-0 flex-col items-stretch gap-5 border-e py-5">
|
||||||
<div ref={headerRef} className="hidden lg:flex items-center justify-center shrink-0">
|
<div ref={headerRef} className="hidden shrink-0 items-center justify-center lg:flex">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-gray.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-gray.svg')}
|
||||||
className="dark:hidden min-h-7.5"
|
className="min-h-7.5 dark:hidden"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-gray-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-gray-dark.svg')}
|
||||||
className="hidden dark:block min-h-7.5"
|
className="hidden min-h-7.5 dark:block"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex grow shrink-0">
|
<div className="flex shrink-0 grow">
|
||||||
<div
|
<div
|
||||||
className="kt-scrollable-y-hover grow gap-2.5 shrink-0 flex ps-4 flex-col"
|
className="kt-scrollable-y-hover flex shrink-0 grow flex-col gap-2.5 ps-4"
|
||||||
style={{ height: `${scrollableHeight}px` }}
|
style={{ height: `${scrollableHeight}px` }}
|
||||||
>
|
>
|
||||||
{menuItems.map((item, index) => (
|
{menuItems.map((item, index) => (
|
||||||
@@ -131,9 +131,9 @@ export function SidebarPrimary() {
|
|||||||
mode="icon"
|
mode="icon"
|
||||||
{...(item === selectedMenuItem ? { 'data-state': 'open' } : {})}
|
{...(item === selectedMenuItem ? { 'data-state': 'open' } : {})}
|
||||||
className={cn(
|
className={cn(
|
||||||
'shrink-0 rounded-md size-9',
|
'size-9 shrink-0 rounded-md',
|
||||||
'data-[state=open]:bg-background data-[state=open]:border data-[state=open]:border-input data-[state=open]:text-primary',
|
'data-[state=open]:bg-background data-[state=open]:border-input data-[state=open]:text-primary data-[state=open]:border',
|
||||||
'hover:bg-background hover:border hover:border-input hover:text-primary'
|
'hover:bg-background hover:border-input hover:text-primary hover:border'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Link to={item.path}>
|
<Link to={item.path}>
|
||||||
@@ -147,7 +147,7 @@ export function SidebarPrimary() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ref={footerRef} className="flex flex-col gap-4 items-center shrink-0">
|
<div ref={footerRef} className="flex shrink-0 flex-col items-center gap-4">
|
||||||
{/* <ChatSheet
|
{/* <ChatSheet
|
||||||
trigger={
|
trigger={
|
||||||
<Button
|
<Button
|
||||||
@@ -173,7 +173,7 @@ export function SidebarPrimary() {
|
|||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="size-9 rounded-full border border-border shrink-0 cursor-pointer"
|
className="border-border size-9 shrink-0 cursor-pointer rounded-full border"
|
||||||
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export function SidebarSecondary() {
|
|||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grow shrink-0 ps-3.5 kt-scrollable-y-hover max-h-[calc(100vh-2rem)] pe-1 my-5">
|
<div className="kt-scrollable-y-hover my-5 max-h-[calc(100vh-2rem)] shrink-0 grow ps-3.5 pe-1">
|
||||||
{pathname === '/' ? <SidebarMenuDashboard /> : <SidebarMenuDefault />}
|
{pathname === '/' ? <SidebarMenuDashboard /> : <SidebarMenuDefault />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-5">
|
<div className="mb-5">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-5">
|
<Container className="flex flex-wrap items-center justify-between gap-5">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,8 +73,8 @@ const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => {
|
|||||||
const item = getCurrentItem(menuConfig);
|
const item = getCurrentItem(menuConfig);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center flex-wrap gap-1 lg:gap-5">
|
<div className="flex flex-wrap items-center gap-1 lg:gap-5">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { useEffect } from 'react';
|
|||||||
import { Link, Outlet } from 'react-router-dom';
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
||||||
// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet';
|
// import { NotificationsSheet } from '#shared/partials/topbar/notifications-sheet';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
@@ -36,11 +36,11 @@ export function TwoColumnSidebarLayout() {
|
|||||||
<div className="flex grow">
|
<div className="flex grow">
|
||||||
{isMobileMode && <Header />}
|
{isMobileMode && <Header />}
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row grow pt-(--header-height) lg:pt-0">
|
<div className="flex grow flex-col pt-(--header-height) lg:flex-row lg:pt-0">
|
||||||
{!isMobileMode && <Sidebar />}
|
{!isMobileMode && <Sidebar />}
|
||||||
|
|
||||||
<div className="flex grow rounded-xl bg-background border border-input lg:ms-(--sidebar-width) mt-0 lg:mt-5 m-5">
|
<div className="bg-background border-input m-5 mt-0 flex grow rounded-xl border lg:ms-(--sidebar-width) lg:mt-5">
|
||||||
<div className="flex flex-col grow kt-scrollable-y-auto lg:[--kt-scrollbar-width:auto] pt-5">
|
<div className="kt-scrollable-y-auto flex grow flex-col pt-5 lg:[--kt-scrollbar-width:auto]">
|
||||||
<main className="grow" role="content">
|
<main className="grow" role="content">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarHeading />
|
<ToolbarHeading />
|
||||||
@@ -70,7 +70,7 @@ export function TwoColumnSidebarLayout() {
|
|||||||
/> */}
|
/> */}
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="hover:bg-background hover:[&_svg]:text-primary hover:text-primary ms-2.5 "
|
className="hover:bg-background hover:[&_svg]:text-primary hover:text-primary ms-2.5"
|
||||||
asChild
|
asChild
|
||||||
>
|
>
|
||||||
<Link to={'/account/home/get-started'}>
|
<Link to={'/account/home/get-started'}>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@ const Header = () => {
|
|||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center transition-[height] shrink-0 bg-(--header-bg) dark:bg-(--header-bg-dark) h-(--header-height)',
|
'flex h-(--header-height) shrink-0 items-center bg-(--header-bg) transition-[height] dark:bg-(--header-bg-dark)',
|
||||||
headerStickyOn &&
|
headerStickyOn &&
|
||||||
'transition-[height] fixed z-10 top-0 start-0 end-0 shadow-xs backdrop-blur-md bg-white/70'
|
'fixed start-0 end-0 top-0 z-10 bg-white/70 shadow-xs backdrop-blur-md transition-[height]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Container width="fluid" className="flex flex-wrap justify-between items-center lg:gap-4">
|
<Container width="fluid" className="flex flex-wrap items-center justify-between lg:gap-4">
|
||||||
<HeaderLogo />
|
<HeaderLogo />
|
||||||
<HeaderTopbar />
|
<HeaderTopbar />
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -94,12 +94,12 @@ export function HeaderLogo() {
|
|||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle.svg')}
|
||||||
className="dark:hidden min-h-8.5"
|
className="min-h-8.5 dark:hidden"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle-dark.svg')}
|
||||||
className="hidden dark:inline-block min-h-8.5"
|
className="hidden min-h-8.5 dark:inline-block"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -111,9 +111,9 @@ export function HeaderLogo() {
|
|||||||
<Menu />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-62.5" side="left" close={false}>
|
<SheetContent className="w-62.5 gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-3 overflow-y-auto">
|
<SheetBody className="overflow-y-auto p-3">
|
||||||
{pathname === '/' ? <SidebarMenuDashboard /> : <SidebarMenuDefault />}
|
{pathname === '/' ? <SidebarMenuDashboard /> : <SidebarMenuDefault />}
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
@@ -121,12 +121,12 @@ export function HeaderLogo() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<div className="lg:flex items-stretch gap-3">
|
<div className="items-stretch gap-3 lg:flex">
|
||||||
{/* Teams Dropdown */}
|
{/* Teams Dropdown */}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger className="cursor-pointer text-secondary-foreground text-sm font-medium flex items-center gap-2">
|
<DropdownMenuTrigger className="text-secondary-foreground flex cursor-pointer items-center gap-2 text-sm font-medium">
|
||||||
{selectedTeam.title}
|
{selectedTeam.title}
|
||||||
<ChevronDown className="size-3.5 text-muted-foreground" />
|
<ChevronDown className="text-muted-foreground size-3.5" />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent sideOffset={15} side="bottom" align="start">
|
<DropdownMenuContent sideOffset={15} side="bottom" align="start">
|
||||||
{teams.map((team, index) => (
|
{teams.map((team, index) => (
|
||||||
@@ -145,13 +145,13 @@ export function HeaderLogo() {
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
<span className="text-sm text-muted-foreground font-medium px-2.5 md:inline">/</span>
|
<span className="text-muted-foreground px-2.5 text-sm font-medium md:inline">/</span>
|
||||||
|
|
||||||
{/* Items Dropdown */}
|
{/* Items Dropdown */}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger className="cursor-pointer text-secondary-foreground text-sm font-medium flex items-center gap-2">
|
<DropdownMenuTrigger className="text-secondary-foreground flex cursor-pointer items-center gap-2 text-sm font-medium">
|
||||||
{selectedItem.title}
|
{selectedItem.title}
|
||||||
<ChevronDown className="size-3.5 text-muted-foreground" />
|
<ChevronDown className="text-muted-foreground size-3.5" />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent sideOffset={15} side="bottom" align="start">
|
<DropdownMenuContent sideOffset={15} side="bottom" align="start">
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
@@ -170,13 +170,13 @@ export function HeaderLogo() {
|
|||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
<span className="text-sm text-muted-foreground font-medium px-2.5">/</span>
|
<span className="text-muted-foreground px-2.5 text-sm font-medium">/</span>
|
||||||
|
|
||||||
{/* Staging Dropdown */}
|
{/* Staging Dropdown */}
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger className="cursor-pointer text-secondary-foreground text-sm font-medium flex items-center gap-2">
|
<DropdownMenuTrigger className="text-secondary-foreground flex cursor-pointer items-center gap-2 text-sm font-medium">
|
||||||
{selectedStaging.title}
|
{selectedStaging.title}
|
||||||
<ChevronDown className="size-3.5 text-muted-foreground" />
|
<ChevronDown className="text-muted-foreground size-3.5" />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent sideOffset={15} side="bottom" align="start">
|
<DropdownMenuContent sideOffset={15} side="bottom" align="start">
|
||||||
{stagings.map((staging, index) => (
|
{stagings.map((staging, index) => (
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export function HeaderTopbar() {
|
|||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="cursor-pointer size-9 rounded-full border-2 border-mono/25 shrink-0"
|
className="border-mono/25 size-9 shrink-0 cursor-pointer rounded-full border-2"
|
||||||
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { NavbarMenu } from './NavbarMenu';
|
|||||||
|
|
||||||
const Navbar = () => {
|
const Navbar = () => {
|
||||||
return (
|
return (
|
||||||
<div className="bg-bg-background border-y border-border mb-5 lg:mb-8">
|
<div className="bg-bg-background border-border mb-5 border-y lg:mb-8">
|
||||||
<Container className="flex flex-wrap justify-between items-center gap-2">
|
<Container className="flex flex-wrap items-center justify-between gap-2">
|
||||||
<NavbarMenu />
|
<NavbarMenu />
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -54,14 +54,14 @@ export function NavbarMenu() {
|
|||||||
return (
|
return (
|
||||||
<div className="grid">
|
<div className="grid">
|
||||||
<div className="kt-scrollable-x-auto">
|
<div className="kt-scrollable-x-auto">
|
||||||
<div className="flex items-stretch h-12 gap-5 lg:gap-7.5">
|
<div className="flex h-12 items-stretch gap-5 lg:gap-7.5">
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<Link
|
<Link
|
||||||
key={index}
|
key={index}
|
||||||
to={item.path}
|
to={item.path}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center text-nowrap font-medium text-sm text-secondary-foreground',
|
'text-secondary-foreground flex items-center text-sm font-medium text-nowrap',
|
||||||
item.path === selectedItem.path && 'border-b border-mono text-mono'
|
item.path === selectedItem.path && 'border-mono text-mono border-b'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{item.title}
|
{item.title}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export function Sidebar() {
|
|||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-stretch shrink-0 px-2 w-(--sidebar-width) bg-background">
|
<div className="bg-background flex w-(--sidebar-width) shrink-0 items-stretch px-2">
|
||||||
{pathname === '/' ? <SidebarMenuDashboard /> : <SidebarMenuDefault />}
|
{pathname === '/' ? <SidebarMenuDashboard /> : <SidebarMenuDefault />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export function SidebarMenuDefault() {
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm font-medium">
|
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm font-medium">
|
||||||
<Link to={item.path || '#'} className="flex items-center justify-between grow gap-2">
|
<Link to={item.path || '#'} className="flex grow items-center justify-between gap-2">
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<span data-slot="accordion-menu-title">{item.title}</span>
|
<span data-slot="accordion-menu-title">{item.title}</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-5 lg:mb-7.5">
|
<div className="mb-5 lg:mb-7.5">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-5">
|
<Container className="flex flex-wrap items-center justify-between gap-5">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,8 +73,8 @@ const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => {
|
|||||||
const item = getCurrentItem(menuConfig);
|
const item = getCurrentItem(menuConfig);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col md:flex-row md:items-center flex-wrap gap-1 lg:gap-5">
|
<div className="flex flex-col flex-wrap gap-1 md:flex-row md:items-center lg:gap-5">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Outlet, useLocation } from 'react-router';
|
import { Outlet, useLocation } from 'react-router';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
@@ -46,10 +46,10 @@ export const DualRowsHeaderLayout = () => {
|
|||||||
|
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
<div className="w-full flex px-0 lg:ps-4">
|
<div className="flex w-full px-0 lg:ps-4">
|
||||||
{!isMobile && <Sidebar />}
|
{!isMobile && <Sidebar />}
|
||||||
|
|
||||||
<main className="flex flex-col grow">
|
<main className="flex grow flex-col">
|
||||||
{!pathname.includes('/public-profile/') && (
|
{!pathname.includes('/public-profile/') && (
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarHeading />
|
<ToolbarHeading />
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="cursor-pointer flex order-2 md:order-1 gap-2 font-normal text-sm"
|
className="order-2 flex cursor-pointer gap-2 text-sm font-normal md:order-1"
|
||||||
>
|
>
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<p className="text-secondary-foreground hover:text-primary">
|
<p className="text-secondary-foreground hover:text-primary">
|
||||||
@@ -40,7 +40,7 @@ export function Footer() {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground"></nav>
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2"></nav>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -21,17 +21,17 @@ const Header = () => {
|
|||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="flex lg:hidden items-center fixed z-10 top-0 start-0 end-0 shrink-0 bg-muted h-(--header-height)">
|
<header className="bg-muted fixed start-0 end-0 top-0 z-10 flex h-(--header-height) shrink-0 items-center lg:hidden">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-3">
|
<Container className="flex flex-wrap items-center justify-between gap-3">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/logo-light.svg')}
|
src={toAbsoluteUrl('/media/app/logo-light.svg')}
|
||||||
className="dark:hidden h-8.5"
|
className="h-8.5 dark:hidden"
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/logo-dark.svg')}
|
src={toAbsoluteUrl('/media/app/logo-dark.svg')}
|
||||||
className="hidden dark:block h-8.5"
|
className="hidden h-8.5 dark:block"
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -43,9 +43,9 @@ const Header = () => {
|
|||||||
<Menu />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-68.75" side="left" close={false}>
|
<SheetContent className="w-68.75 gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 flex flex-col grow">
|
<SheetBody className="flex grow flex-col p-0">
|
||||||
<SidebarHeader />
|
<SidebarHeader />
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
<SidebarFooter />
|
<SidebarFooter />
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export const RoosterPeek: React.FC = () => {
|
|||||||
<img
|
<img
|
||||||
key={tick}
|
key={tick}
|
||||||
src={toAbsoluteUrl('/media/app/brutal-aggressive-rooster-head-icon.svg')}
|
src={toAbsoluteUrl('/media/app/brutal-aggressive-rooster-head-icon.svg')}
|
||||||
className="size-50 fixed z-1000"
|
className="fixed z-1000 size-50"
|
||||||
style={buildStyle(side)}
|
style={buildStyle(side)}
|
||||||
alt="Brutal rooster"
|
alt="Brutal rooster"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { SidebarMenu } from './SidebarMenu';
|
|||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<div className="fixed top-0 bottom-0 z-50 lg:flex flex-col shrink-0 w-(--sidebar-width) bg-(--page-bg) dark:bg-(--page-bg-dark)">
|
<div className="fixed top-0 bottom-0 z-50 w-(--sidebar-width) shrink-0 flex-col bg-(--page-bg) lg:flex dark:bg-(--page-bg-dark)">
|
||||||
<SidebarHeader />
|
<SidebarHeader />
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
<SidebarFooter />
|
<SidebarFooter />
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export function SidebarFooter() {
|
|||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-center justify-between shrink-0 ps-4 pe-3.5 h-14">
|
<div className="flex-center flex h-14 shrink-0 justify-between ps-4 pe-3.5">
|
||||||
{user && (
|
{user && (
|
||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
|
|||||||
@@ -8,34 +8,34 @@ export function SidebarHeader() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-3.5">
|
<div className="mb-3.5">
|
||||||
<div className="flex items-center justify-between gap-2.5 px-3.5 h-17.5">
|
<div className="flex h-17.5 items-center justify-between gap-2.5 px-3.5">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/logo-light.svg')}
|
src={toAbsoluteUrl('/media/app/logo-light.svg')}
|
||||||
className="dark:hidden h-10.5"
|
className="h-10.5 dark:hidden"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/logo-dark.svg')}
|
src={toAbsoluteUrl('/media/app/logo-dark.svg')}
|
||||||
className="hidden dark:inline-block h-10.5"
|
className="hidden h-10.5 dark:inline-block"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="dark:text-[#c08183] shrink-0">
|
<div className="shrink-0 dark:text-[#c08183]">
|
||||||
C R U X <sub className="text-[50%]">Goat</sub>
|
C R U X <sub className="text-[50%]">Goat</sub>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-2.5 px-3.5 mb-1">
|
<div className="mb-1 px-3.5 pt-2.5">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Search className="text-muted-foreground absolute top-1/2 start-3.5 -translate-y-1/2 size-4" />
|
<Search className="text-muted-foreground absolute start-3.5 top-1/2 size-4 -translate-y-1/2" />
|
||||||
<Input
|
<Input
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="px-9 min-w-0"
|
className="min-w-0 px-9"
|
||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
<span className="text-xs text-muted-foreground absolute end-3.5 top-1/2 -translate-y-1/2">
|
<span className="text-muted-foreground absolute end-3.5 top-1/2 -translate-y-1/2 text-xs">
|
||||||
cmd + /
|
cmd + /
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { SidebarMenuPrimary } from './SidebarMenuPrimary';
|
|||||||
|
|
||||||
export function SidebarMenu() {
|
export function SidebarMenu() {
|
||||||
return (
|
return (
|
||||||
<div className="kt-scrollable-y-auto grow max-h-[calc(100vh-11.5rem)]">
|
<div className="kt-scrollable-y-auto max-h-[calc(100vh-11.5rem)] grow">
|
||||||
<SidebarMenuPrimary />
|
<SidebarMenuPrimary />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="pb-5">
|
<div className="pb-5">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-3">
|
<Container className="flex flex-wrap items-center justify-between gap-3">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
@@ -23,7 +23,7 @@ function Toolbar({ children }: { children?: ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarActions({ children }: { children?: ReactNode }) {
|
function ToolbarActions({ children }: { children?: ReactNode }) {
|
||||||
return <div className="flex items-center flex-wrap gap-1.5 lg:gap-3.5">{children}</div>;
|
return <div className="flex flex-wrap items-center gap-1.5 lg:gap-3.5">{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarBreadcrumbs({ homeVisible = true }: { homeVisible?: boolean }) {
|
function ToolbarBreadcrumbs({ homeVisible = true }: { homeVisible?: boolean }) {
|
||||||
@@ -95,7 +95,7 @@ const ToolbarHeading = ({ title = '' }: ToolbarHeadingProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import React from 'react';
|
|||||||
import { Outlet, useLocation } from 'react-router-dom';
|
import { Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Sidebar } from './components/Sidebar';
|
import { Sidebar } from './components/Sidebar';
|
||||||
@@ -51,9 +51,9 @@ export const MultipleMenusLayout = () => {
|
|||||||
|
|
||||||
{isMobile && <Header />}
|
{isMobile && <Header />}
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row grow pt-(--header-height) lg:pt-0">
|
<div className="flex grow flex-col pt-(--header-height) lg:flex-row lg:pt-0">
|
||||||
<div className="overflow-hidden flex flex-col grow items-stretch rounded-xl bg-background border border-input lg:ms-(--sidebar-width) mt-0 lg:mt-3.75 m-3.75">
|
<div className="bg-background border-input m-3.75 mt-0 flex grow flex-col items-stretch overflow-hidden rounded-xl border lg:ms-(--sidebar-width) lg:mt-3.75">
|
||||||
<div className="flex flex-col grow kt-scrollable-y-auto [--kt-scrollbar-width:auto] pt-5">
|
<div className="kt-scrollable-y-auto flex grow flex-col pt-5 [--kt-scrollbar-width:auto]">
|
||||||
<main className="grow" role="content">
|
<main className="grow" role="content">
|
||||||
{toolbar}
|
{toolbar}
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
|
|
||||||
@@ -29,12 +29,12 @@ const Header = () => {
|
|||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center transition-[height] shrink-0 bg-background py-4 lg:py-0 lg:h-(--header-height)',
|
'bg-background flex shrink-0 items-center py-4 transition-[height] lg:h-(--header-height) lg:py-0',
|
||||||
headerStickyOn &&
|
headerStickyOn &&
|
||||||
'transition-[height] fixed z-10 top-0 left-0 right-0 shadow-xs backdrop-blur-md bg-background/70 pe-(--removed-body-scroll-bar-size,0px)'
|
'bg-background/70 fixed top-0 right-0 left-0 z-10 pe-(--removed-body-scroll-bar-size,0px) shadow-xs backdrop-blur-md transition-[height]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Container className="flex flex-wrap gap-2 items-center lg:gap-4">
|
<Container className="flex flex-wrap items-center gap-2 lg:gap-4">
|
||||||
<HeaderLogo />
|
<HeaderLogo />
|
||||||
<HeaderTopbar />
|
<HeaderTopbar />
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -18,22 +18,22 @@ const HeaderLogo = () => {
|
|||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-stretch gap-1.5 lg:gap-10 grow">
|
<div className="flex grow items-stretch gap-1.5 lg:gap-10">
|
||||||
<div className="flex items-center gap-2.5">
|
<div className="flex items-center gap-2.5">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle-primary.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle-primary.svg')}
|
||||||
className="dark:hidden min-h-8.5"
|
className="min-h-8.5 dark:hidden"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle-primary-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle-primary-dark.svg')}
|
||||||
className="hidden dark:inline-block min-h-8.5"
|
className="hidden min-h-8.5 dark:inline-block"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<h3 className="text-mono text-lg font-medium hidden lg:block">Metronic</h3>
|
<h3 className="text-mono hidden text-lg font-medium lg:block">Metronic</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!isMobile ? (
|
{!isMobile ? (
|
||||||
@@ -45,9 +45,9 @@ const HeaderLogo = () => {
|
|||||||
<Menu />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-68.75" side="left" close={false}>
|
<SheetContent className="w-68.75 gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 flex flex-col grow">
|
<SheetBody className="flex grow flex-col p-0">
|
||||||
<MegaMenuMobile />
|
<MegaMenuMobile />
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu';
|
|||||||
|
|
||||||
const HeaderTopbar = () => {
|
const HeaderTopbar = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center flex-wrap gap-2 lg:gap-3.5">
|
<div className="flex flex-wrap items-center gap-2 lg:gap-3.5">
|
||||||
<div className="flex items-center gap-2.5 lg:gap-3.5">
|
<div className="flex items-center gap-2.5 lg:gap-3.5">
|
||||||
<div className="flex flex-col items-end pt-0.5">
|
<div className="flex flex-col items-end pt-0.5">
|
||||||
<span className="inline-flex gap-0.5 text-foreground font-medium text-xs uppercase">
|
<span className="text-foreground inline-flex gap-0.5 text-xs font-medium uppercase">
|
||||||
<Crown className="size-3.5" />
|
<Crown className="size-3.5" />
|
||||||
free
|
free
|
||||||
</span>
|
</span>
|
||||||
@@ -25,11 +25,11 @@ const HeaderTopbar = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-e border-border h-5 mx-1.5 lg:mx-3"></div>
|
<div className="border-border mx-1.5 h-5 border-e lg:mx-3"></div>
|
||||||
|
|
||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<div className="cursor-pointer size-8.5 rounded-full inline-flex items-center justify-center relative text-lg font-medium border border-input bg-muted">
|
<div className="border-input bg-muted relative inline-flex size-8.5 cursor-pointer items-center justify-center rounded-full border text-lg font-medium">
|
||||||
S
|
S
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -37,7 +37,7 @@ const HeaderTopbar = () => {
|
|||||||
height="16"
|
height="16"
|
||||||
viewBox="0 0 15 16"
|
viewBox="0 0 15 16"
|
||||||
fill="none"
|
fill="none"
|
||||||
className="absolute left-6 -top-0.5 text-primary size-3"
|
className="text-primary absolute -top-0.5 left-6 size-3"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M14.5425 6.89749L13.5 5.83999C13.4273 5.76877 13.3699 5.6835 13.3312 5.58937C13.2925 5.49525 13.2734 5.39424 13.275 5.29249V3.79249C13.274 3.58699 13.2324 3.38371 13.1527 3.19432C13.0729 3.00494 12.9565 2.83318 12.8101 2.68892C12.6638 2.54466 12.4904 2.43073 12.2998 2.35369C12.1093 2.27665 11.9055 2.23801 11.7 2.23999H10.2C10.0982 2.24159 9.99722 2.22247 9.9031 2.18378C9.80898 2.1451 9.72371 2.08767 9.65249 2.01499L8.60249 0.957487C8.30998 0.665289 7.91344 0.50116 7.49999 0.50116C7.08654 0.50116 6.68999 0.665289 6.39749 0.957487L5.33999 1.99999C5.26876 2.07267 5.1835 2.1301 5.08937 2.16879C4.99525 2.20747 4.89424 2.22659 4.79249 2.22499H3.29249C3.08699 2.22597 2.88371 2.26754 2.69432 2.34731C2.50494 2.42709 2.33318 2.54349 2.18892 2.68985C2.04466 2.8362 1.93073 3.00961 1.85369 3.20013C1.77665 3.39064 1.73801 3.5945 1.73999 3.79999V5.29999C1.74159 5.40174 1.72247 5.50275 1.68378 5.59687C1.6451 5.691 1.58767 5.77627 1.51499 5.84749L0.457487 6.89749C0.165289 7.19 0.00115967 7.58654 0.00115967 7.99999C0.00115967 8.41344 0.165289 8.80998 0.457487 9.10249L1.49999 10.16C1.57267 10.2312 1.6301 10.3165 1.66878 10.4106C1.70747 10.5047 1.72659 10.6057 1.72499 10.7075V12.2075C1.72597 12.413 1.76754 12.6163 1.84731 12.8056C1.92709 12.995 2.04349 13.1668 2.18985 13.3111C2.3362 13.4553 2.50961 13.5692 2.70013 13.6463C2.89064 13.7233 3.0945 13.762 3.29999 13.76H4.79999C4.90174 13.7584 5.00275 13.7775 5.09687 13.8162C5.191 13.8549 5.27627 13.9123 5.34749 13.985L6.40499 15.0425C6.69749 15.3347 7.09404 15.4988 7.50749 15.4988C7.92094 15.4988 8.31748 15.3347 8.60999 15.0425L9.65999 14C9.73121 13.9273 9.81647 13.8699 9.9106 13.8312C10.0047 13.7925 10.1057 13.7734 10.2075 13.775H11.7075C12.1212 13.775 12.518 13.6106 12.8106 13.3181C13.1031 13.0255 13.2675 12.6287 13.2675 12.215V10.715C13.2659 10.6132 13.285 10.5122 13.3237 10.4181C13.3624 10.324 13.4198 10.2387 13.4925 10.1675L14.55 9.10999C14.6953 8.96452 14.8104 8.79176 14.8887 8.60164C14.9671 8.41152 15.007 8.20779 15.0063 8.00218C15.0056 7.79656 14.9643 7.59311 14.8847 7.40353C14.8051 7.21394 14.6888 7.04197 14.5425 6.89749ZM10.635 6.64999L6.95249 10.25C6.90055 10.3026 6.83864 10.3443 6.77038 10.3726C6.70212 10.4009 6.62889 10.4153 6.55499 10.415C6.48062 10.4139 6.40719 10.3982 6.33896 10.3685C6.27073 10.3389 6.20905 10.2961 6.15749 10.2425L4.37999 8.44249C4.32532 8.39044 4.28169 8.32793 4.25169 8.25867C4.22169 8.18941 4.20593 8.11482 4.20536 8.03934C4.20479 7.96387 4.21941 7.88905 4.24836 7.81934C4.27731 7.74964 4.31999 7.68647 4.37387 7.63361C4.42774 7.58074 4.4917 7.53926 4.56194 7.51163C4.63218 7.484 4.70726 7.47079 4.78271 7.47278C4.85816 7.47478 4.93244 7.49194 5.00112 7.52324C5.0698 7.55454 5.13148 7.59935 5.18249 7.65499L6.56249 9.05749L9.84749 5.84749C9.95296 5.74215 10.0959 5.68298 10.245 5.68298C10.394 5.68298 10.537 5.74215 10.6425 5.84749C10.6953 5.90034 10.737 5.96318 10.7653 6.03234C10.7935 6.1015 10.8077 6.1756 10.807 6.25031C10.8063 6.32502 10.7908 6.39884 10.7612 6.46746C10.7317 6.53608 10.6888 6.59813 10.635 6.64999Z"
|
d="M14.5425 6.89749L13.5 5.83999C13.4273 5.76877 13.3699 5.6835 13.3312 5.58937C13.2925 5.49525 13.2734 5.39424 13.275 5.29249V3.79249C13.274 3.58699 13.2324 3.38371 13.1527 3.19432C13.0729 3.00494 12.9565 2.83318 12.8101 2.68892C12.6638 2.54466 12.4904 2.43073 12.2998 2.35369C12.1093 2.27665 11.9055 2.23801 11.7 2.23999H10.2C10.0982 2.24159 9.99722 2.22247 9.9031 2.18378C9.80898 2.1451 9.72371 2.08767 9.65249 2.01499L8.60249 0.957487C8.30998 0.665289 7.91344 0.50116 7.49999 0.50116C7.08654 0.50116 6.68999 0.665289 6.39749 0.957487L5.33999 1.99999C5.26876 2.07267 5.1835 2.1301 5.08937 2.16879C4.99525 2.20747 4.89424 2.22659 4.79249 2.22499H3.29249C3.08699 2.22597 2.88371 2.26754 2.69432 2.34731C2.50494 2.42709 2.33318 2.54349 2.18892 2.68985C2.04466 2.8362 1.93073 3.00961 1.85369 3.20013C1.77665 3.39064 1.73801 3.5945 1.73999 3.79999V5.29999C1.74159 5.40174 1.72247 5.50275 1.68378 5.59687C1.6451 5.691 1.58767 5.77627 1.51499 5.84749L0.457487 6.89749C0.165289 7.19 0.00115967 7.58654 0.00115967 7.99999C0.00115967 8.41344 0.165289 8.80998 0.457487 9.10249L1.49999 10.16C1.57267 10.2312 1.6301 10.3165 1.66878 10.4106C1.70747 10.5047 1.72659 10.6057 1.72499 10.7075V12.2075C1.72597 12.413 1.76754 12.6163 1.84731 12.8056C1.92709 12.995 2.04349 13.1668 2.18985 13.3111C2.3362 13.4553 2.50961 13.5692 2.70013 13.6463C2.89064 13.7233 3.0945 13.762 3.29999 13.76H4.79999C4.90174 13.7584 5.00275 13.7775 5.09687 13.8162C5.191 13.8549 5.27627 13.9123 5.34749 13.985L6.40499 15.0425C6.69749 15.3347 7.09404 15.4988 7.50749 15.4988C7.92094 15.4988 8.31748 15.3347 8.60999 15.0425L9.65999 14C9.73121 13.9273 9.81647 13.8699 9.9106 13.8312C10.0047 13.7925 10.1057 13.7734 10.2075 13.775H11.7075C12.1212 13.775 12.518 13.6106 12.8106 13.3181C13.1031 13.0255 13.2675 12.6287 13.2675 12.215V10.715C13.2659 10.6132 13.285 10.5122 13.3237 10.4181C13.3624 10.324 13.4198 10.2387 13.4925 10.1675L14.55 9.10999C14.6953 8.96452 14.8104 8.79176 14.8887 8.60164C14.9671 8.41152 15.007 8.20779 15.0063 8.00218C15.0056 7.79656 14.9643 7.59311 14.8847 7.40353C14.8051 7.21394 14.6888 7.04197 14.5425 6.89749ZM10.635 6.64999L6.95249 10.25C6.90055 10.3026 6.83864 10.3443 6.77038 10.3726C6.70212 10.4009 6.62889 10.4153 6.55499 10.415C6.48062 10.4139 6.40719 10.3982 6.33896 10.3685C6.27073 10.3389 6.20905 10.2961 6.15749 10.2425L4.37999 8.44249C4.32532 8.39044 4.28169 8.32793 4.25169 8.25867C4.22169 8.18941 4.20593 8.11482 4.20536 8.03934C4.20479 7.96387 4.21941 7.88905 4.24836 7.81934C4.27731 7.74964 4.31999 7.68647 4.37387 7.63361C4.42774 7.58074 4.4917 7.53926 4.56194 7.51163C4.63218 7.484 4.70726 7.47079 4.78271 7.47278C4.85816 7.47478 4.93244 7.49194 5.00112 7.52324C5.0698 7.55454 5.13148 7.59935 5.18249 7.65499L6.56249 9.05749L9.84749 5.84749C9.95296 5.74215 10.0959 5.68298 10.245 5.68298C10.394 5.68298 10.537 5.74215 10.6425 5.84749C10.6953 5.90034 10.737 5.96318 10.7653 6.03234C10.7935 6.1015 10.8077 6.1756 10.807 6.25031C10.8063 6.32502 10.7908 6.39884 10.7612 6.46746C10.7317 6.53608 10.6888 6.59813 10.635 6.64999Z"
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export function MegaMenuMobile() {
|
|||||||
<AccordionMenuSub key={index} value={item.path || `root-${index}`}>
|
<AccordionMenuSub key={index} value={item.path || `root-${index}`}>
|
||||||
<AccordionMenuSubTrigger className="text-sm font-medium">
|
<AccordionMenuSubTrigger className="text-sm font-medium">
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<div className="flex items-center justify-between grow gap-2">
|
<div className="flex grow items-center justify-between gap-2">
|
||||||
<span data-slot="accordion-menu-title">{item.title}</span>
|
<span data-slot="accordion-menu-title">{item.title}</span>
|
||||||
{item.badge && (
|
{item.badge && (
|
||||||
<Badge variant="secondary" size="sm" className="ms-auto">
|
<Badge variant="secondary" size="sm" className="ms-auto">
|
||||||
@@ -91,7 +91,7 @@ export function MegaMenuMobile() {
|
|||||||
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm font-medium">
|
<AccordionMenuItem key={index} value={item.path || ''} className="text-sm font-medium">
|
||||||
<Link to={item.path || '#'} className="">
|
<Link to={item.path || '#'} className="">
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<div className="flex items-center justify-between grow gap-2">
|
<div className="flex grow items-center justify-between gap-2">
|
||||||
<span data-slot="accordion-menu-title">{item.title}</span>
|
<span data-slot="accordion-menu-title">{item.title}</span>
|
||||||
{item.badge && (
|
{item.badge && (
|
||||||
<Badge variant="secondary" size="sm" className="ms-auto">
|
<Badge variant="secondary" size="sm" className="ms-auto">
|
||||||
@@ -154,7 +154,7 @@ export function MegaMenuMobile() {
|
|||||||
<AccordionMenuItem key={index} value={item.path || ''} className="text-[13px]">
|
<AccordionMenuItem key={index} value={item.path || ''} className="text-[13px]">
|
||||||
<Link to={item.path || '#'}>
|
<Link to={item.path || '#'}>
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<div className="flex items-center justify-between grow gap-2">
|
<div className="flex grow items-center justify-between gap-2">
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
{item.badge && (
|
{item.badge && (
|
||||||
<Badge variant="secondary" size="sm" className="ms-auto">
|
<Badge variant="secondary" size="sm" className="ms-auto">
|
||||||
@@ -173,7 +173,7 @@ export function MegaMenuMobile() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex grow shrink-0 py-5 px-5">
|
<div className="flex shrink-0 grow px-5 py-5">
|
||||||
<AccordionMenu
|
<AccordionMenu
|
||||||
selectedValue={pathname}
|
selectedValue={pathname}
|
||||||
matchPath={matchPath}
|
matchPath={matchPath}
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<div className="border-t border-border"></div>
|
<div className="border-border border-t"></div>
|
||||||
<div className="flex items-center justify-between flex-wrap gap-2 la:gap-5 my-5">
|
<div className="la:gap-5 my-5 flex flex-wrap items-center justify-between gap-2">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
<div className="border-b border-border mb-5 lg:mb-7.5"></div>
|
<div className="border-border mb-5 border-b lg:mb-7.5"></div>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarActions({ children }: { children?: ReactNode }) {
|
function ToolbarActions({ children }: { children?: ReactNode }) {
|
||||||
return <div className="flex items-center flex-wrap gap-2.5">{children}</div>;
|
return <div className="flex flex-wrap items-center gap-2.5">{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarBreadcrumbs() {
|
function ToolbarBreadcrumbs() {
|
||||||
@@ -78,7 +78,7 @@ function ToolbarHeading({ title = '' }: ToolbarHeadingProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Link, Outlet, useLocation } from 'react-router-dom';
|
import { Link, Outlet, useLocation } from 'react-router-dom';
|
||||||
import { useBodyClass } from '@crux-kit/hooks';
|
import { useBodyClass } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar';
|
import { Toolbar, ToolbarActions, ToolbarHeading } from './components/Toolbar';
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -18,17 +18,17 @@ export function Header() {
|
|||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="flex items-center fixed z-10 top-0 start-0 end-0 shrink-0 bg-muted h-(--header-height)">
|
<header className="bg-muted fixed start-0 end-0 top-0 z-10 flex h-(--header-height) shrink-0 items-center">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-3">
|
<Container className="flex flex-wrap items-center justify-between gap-3">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-gray.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-gray.svg')}
|
||||||
className="dark:hidden h-7.5"
|
className="h-7.5 dark:hidden"
|
||||||
alt="image"
|
alt="image"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-gray-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-gray-dark.svg')}
|
||||||
className="hidden dark:inline-block h-7.5"
|
className="hidden h-7.5 dark:inline-block"
|
||||||
alt="image"
|
alt="image"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -39,9 +39,9 @@ export function Header() {
|
|||||||
<Menu />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-(--sidebar-width)" side="left" close={false}>
|
<SheetContent className="w-(--sidebar-width) gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="px-0 pt-5 flex flex-col grow">
|
<SheetBody className="flex grow flex-col px-0 pt-5">
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
<SidebarFooter />
|
<SidebarFooter />
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { SidebarMenu } from './SidebarMenu';
|
|||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<div className="grow fixed top-0 bottom-0 z-20 flex flex-col items-stretch shrink-0 bg-muted w-(--sidebar-width)">
|
<div className="bg-muted fixed top-0 bottom-0 z-20 flex w-(--sidebar-width) shrink-0 grow flex-col items-stretch">
|
||||||
<SidebarHeader />
|
<SidebarHeader />
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
<SidebarFooter />
|
<SidebarFooter />
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu';
|
|||||||
|
|
||||||
export function SidebarFooter() {
|
export function SidebarFooter() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-5 items-center shrink-0 pb-5">
|
<div className="flex shrink-0 flex-col items-center gap-5 pb-5">
|
||||||
<div className="flex flex-col gap-1.5">
|
<div className="flex flex-col gap-1.5">
|
||||||
{/* <ChatSheet
|
{/* <ChatSheet
|
||||||
trigger={
|
trigger={
|
||||||
@@ -36,7 +36,7 @@ export function SidebarFooter() {
|
|||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="size-8 rounded-lg border-2 border-mono/30 shrink-0 cursor-pointer"
|
className="border-mono/30 size-8 shrink-0 cursor-pointer rounded-lg border-2"
|
||||||
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ import { toAbsoluteUrl } from '#shared/lib/helpers';
|
|||||||
|
|
||||||
export function SidebarHeader() {
|
export function SidebarHeader() {
|
||||||
return (
|
return (
|
||||||
<div className="hidden lg:flex items-center justify-center shrink-0 pt-8 pb-3.5">
|
<div className="hidden shrink-0 items-center justify-center pt-8 pb-3.5 lg:flex">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-square-gray.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-square-gray.svg')}
|
||||||
className="dark:hidden min-h-10.5"
|
className="min-h-10.5 dark:hidden"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-square-gray-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-square-gray-dark.svg')}
|
||||||
className="hidden dark:block min-h-10.5"
|
className="hidden min-h-10.5 dark:block"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ export function SidebarMenu() {
|
|||||||
<Button
|
<Button
|
||||||
data-here={hasActiveChild(item.children) || undefined}
|
data-here={hasActiveChild(item.children) || undefined}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex flex-col items-center justify-center w-15 h-15 gap-1 rounded-lg shadow-none',
|
'flex h-15 w-15 flex-col items-center justify-center gap-1 rounded-lg shadow-none',
|
||||||
'text-xs font-medium text-secondary-foreground bg-transparent',
|
'text-secondary-foreground bg-transparent text-xs font-medium',
|
||||||
'hover:text-primary hover:bg-background hover:border-border',
|
'hover:text-primary hover:bg-background hover:border-border',
|
||||||
'data-[state=open]:text-primary data-[state=open]:bg-background data-[state=open]:border-border',
|
'data-[state=open]:text-primary data-[state=open]:bg-background data-[state=open]:border-border',
|
||||||
'data-[here=true]:text-primary data-[here=true]:bg-background data-[here=true]:border-border'
|
'data-[here=true]:text-primary data-[here=true]:bg-background data-[here=true]:border-border'
|
||||||
@@ -70,8 +70,8 @@ export function SidebarMenu() {
|
|||||||
data-active={isActive(item.path) || undefined}
|
data-active={isActive(item.path) || undefined}
|
||||||
to={item.path || '#'}
|
to={item.path || '#'}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex flex-col items-center justify-center w-15.5 h-15 gap-1 p-2 rounded-lg',
|
'flex h-15 w-15.5 flex-col items-center justify-center gap-1 rounded-lg p-2',
|
||||||
'text-xs font-medium text-muted-foreground bg-transparent',
|
'text-muted-foreground bg-transparent text-xs font-medium',
|
||||||
'hover:text-primary hover:bg-background hover:border-border',
|
'hover:text-primary hover:bg-background hover:border-border',
|
||||||
'data-[active=true]:text-primary data-[active=true]:bg-background data-[active=true]:border-border'
|
'data-[active=true]:text-primary data-[active=true]:bg-background data-[active=true]:border-border'
|
||||||
)}
|
)}
|
||||||
@@ -110,7 +110,7 @@ export function SidebarMenu() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2.5 grow kt-scrollable-y-auto max-h-[calc(100vh-5rem)] lg:max-h-[calc(100vh-6rem)]">
|
<div className="kt-scrollable-y-auto flex max-h-[calc(100vh-5rem)] grow flex-col gap-2.5 lg:max-h-[calc(100vh-6rem)]">
|
||||||
{buildMenu(menuConfig)}
|
{buildMenu(menuConfig)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="pb-5">
|
<div className="pb-5">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-3">
|
<Container className="flex flex-wrap items-center justify-between gap-3">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,7 +21,7 @@ function Toolbar({ children }: { children?: ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarActions({ children }: { children?: ReactNode }) {
|
function ToolbarActions({ children }: { children?: ReactNode }) {
|
||||||
return <div className="flex items-center flex-wrap gap-2.5">{children}</div>;
|
return <div className="flex flex-wrap items-center gap-2.5">{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarBreadcrumbs() {
|
function ToolbarBreadcrumbs() {
|
||||||
@@ -72,8 +72,8 @@ function ToolbarHeading({ title = '' }: ToolbarHeadingProps) {
|
|||||||
const item = getCurrentItem(menuConfig);
|
const item = getCurrentItem(menuConfig);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center flex-wrap gap-1 lg:gap-5">
|
<div className="flex flex-wrap items-center gap-1 lg:gap-5">
|
||||||
<h1 className="font-medium text-base text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-base font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { useEffect } from 'react';
|
|||||||
import { Link, Outlet } from 'react-router-dom';
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
// import { SearchDialog } from '#shared/partials/dialogs/search/search-dialog';
|
||||||
// import { ChatSheet } from '#shared/partials/topbar/chat-sheet';
|
// import { ChatSheet } from '#shared/partials/topbar/chat-sheet';
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
@@ -35,11 +35,11 @@ export function DropdownMenuLayout() {
|
|||||||
<div className="flex grow">
|
<div className="flex grow">
|
||||||
{isMobile && <Header />}
|
{isMobile && <Header />}
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row grow pt-(--header-height) lg:pt-0">
|
<div className="flex grow flex-col pt-(--header-height) lg:flex-row lg:pt-0">
|
||||||
{!isMobile && <Sidebar />}
|
{!isMobile && <Sidebar />}
|
||||||
|
|
||||||
<div className="flex flex-col grow rounded-xl bg-background border border-input lg:ms-(--sidebar-width) mt-0 m-4 lg:m-5">
|
<div className="bg-background border-input m-4 mt-0 flex grow flex-col rounded-xl border lg:m-5 lg:ms-(--sidebar-width)">
|
||||||
<div className="flex flex-col grow kt-scrollable-y-auto lg:[scrollbar-width:auto] pt-5">
|
<div className="kt-scrollable-y-auto flex grow flex-col pt-5 lg:[scrollbar-width:auto]">
|
||||||
<main className="grow" role="content">
|
<main className="grow" role="content">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarHeading />
|
<ToolbarHeading />
|
||||||
@@ -62,7 +62,7 @@ export function DropdownMenuLayout() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
asChild
|
asChild
|
||||||
className="ms-2.5 hover:text-primary hover:[&_svg]:text-primary"
|
className="hover:text-primary hover:[&_svg]:text-primary ms-2.5"
|
||||||
>
|
>
|
||||||
<Link to={'/account/home/get-started'}>
|
<Link to={'/account/home/get-started'}>
|
||||||
<Download />
|
<Download />
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useScrollPosition } from '@crux-kit/hooks';
|
import { useScrollPosition } from '@crux-kit/hooks';
|
||||||
import { cn } from '@crux-kit/utils';
|
import { cn } from '@crux-kit/utils';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Container } from '#shared/widgets/common/Container';
|
import { Container } from '#shared/widgets/common/Container';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { HeaderLogo } from './HeaderLogo';
|
import { HeaderLogo } from './HeaderLogo';
|
||||||
import { HeaderSearch } from './HeaderSearch';
|
import { HeaderSearch } from './HeaderSearch';
|
||||||
import { HeaderTopbar } from './HeaderTopbar';
|
import { HeaderTopbar } from './HeaderTopbar';
|
||||||
@@ -30,12 +30,12 @@ export function Header() {
|
|||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center transition-[height] shrink-0 h-(--header-height)',
|
'flex h-(--header-height) shrink-0 items-center transition-[height]',
|
||||||
headerStickyOn &&
|
headerStickyOn &&
|
||||||
'transition-[height] fixed z-10 top-0 start-0 end-0 shadow-xs backdrop-blur-md bg-background/70'
|
'bg-background/70 fixed start-0 end-0 top-0 z-10 shadow-xs backdrop-blur-md transition-[height]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Container className="flex lg:justify-between items-center gap-2.5">
|
<Container className="flex items-center gap-2.5 lg:justify-between">
|
||||||
<HeaderLogo />
|
<HeaderLogo />
|
||||||
<HeaderSearch />
|
<HeaderSearch />
|
||||||
<HeaderTopbar />
|
<HeaderTopbar />
|
||||||
|
|||||||
@@ -18,21 +18,21 @@ export function HeaderLogo() {
|
|||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1 lg:w-100 grow lg:grow-0">
|
<div className="flex grow items-center gap-1 lg:w-100 lg:grow-0">
|
||||||
<div className="flex items-center gap-2 shrink-0">
|
<div className="flex shrink-0 items-center gap-2">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle.svg')}
|
||||||
className="shrink-0 dark:hidden min-h-8.5"
|
className="min-h-8.5 shrink-0 dark:hidden"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle-dark.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle-dark.svg')}
|
||||||
className="shrink-0 hidden dark:inline-block min-h-8.5"
|
className="hidden min-h-8.5 shrink-0 dark:inline-block"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<h3 className="text-mono text-lg font-medium hidden md:block">Metronic</h3>
|
<h3 className="text-mono hidden text-lg font-medium md:block">Metronic</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isMobile && (
|
{isMobile && (
|
||||||
@@ -42,9 +42,9 @@ export function HeaderLogo() {
|
|||||||
<Menu />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="p-0 gap-0 w-68.75" side="left" close={false}>
|
<SheetContent className="w-68.75 gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 overflow-y-auto">
|
<SheetBody className="overflow-y-auto p-0">
|
||||||
<MegaMenuMobile />
|
<MegaMenuMobile />
|
||||||
</SheetBody>
|
</SheetBody>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ export function HeaderSearch() {
|
|||||||
const handleInputChange = () => {};
|
const handleInputChange = () => {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="hidden md:flex items-center">
|
<div className="hidden items-center md:flex">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Search className="text-muted-foreground absolute top-1/2 start-3.5 -translate-y-1/2 size-4" />
|
<Search className="text-muted-foreground absolute start-3.5 top-1/2 size-4 -translate-y-1/2" />
|
||||||
<Input
|
<Input
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
className="px-9 min-w-0"
|
className="min-w-0 px-9"
|
||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
<span className="text-xs text-muted-foreground absolute end-3.5 top-1/2 -translate-y-1/2">
|
<span className="text-muted-foreground absolute end-3.5 top-1/2 -translate-y-1/2 text-xs">
|
||||||
cmd + /
|
cmd + /
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu';
|
|||||||
|
|
||||||
export function HeaderTopbar() {
|
export function HeaderTopbar() {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-2 lg:gap-3.5 lg:w-100 justify-end">
|
<div className="flex items-center justify-end gap-2 lg:w-100 lg:gap-3.5">
|
||||||
<div className="flex items-center gap-2 me-0.5">
|
<div className="me-0.5 flex items-center gap-2">
|
||||||
{/* <ChatSheet
|
{/* <ChatSheet
|
||||||
trigger={
|
trigger={
|
||||||
<Button
|
<Button
|
||||||
@@ -41,7 +41,7 @@ export function HeaderTopbar() {
|
|||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="ms-2.5 size-9 rounded-full border-2 border-success shrink-0 cursor-pointer"
|
className="border-success ms-2.5 size-9 shrink-0 cursor-pointer rounded-full border-2"
|
||||||
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
/>
|
/>
|
||||||
@@ -49,14 +49,14 @@ export function HeaderTopbar() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-e border-border h-5"></div>
|
<div className="border-border h-5 border-e"></div>
|
||||||
|
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Switch id="auto-update" size="sm" defaultChecked />
|
<Switch id="auto-update" size="sm" defaultChecked />
|
||||||
<Label htmlFor="auto-update">Pro</Label>
|
<Label htmlFor="auto-update">Pro</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-e border-border h-5"></div>
|
<div className="border-border h-5 border-e"></div>
|
||||||
|
|
||||||
{/* <DropdownMenu2
|
{/* <DropdownMenu2
|
||||||
trigger={
|
trigger={
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export function MegaMenuMobile() {
|
|||||||
<AccordionMenuItem key={index} value={item.path || ''} className="text-[13px]">
|
<AccordionMenuItem key={index} value={item.path || ''} className="text-[13px]">
|
||||||
<Link to={item.path || '#'}>
|
<Link to={item.path || '#'}>
|
||||||
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
{item.icon && <item.icon data-slot="accordion-menu-icon" />}
|
||||||
<div className="flex items-center justify-between grow gap-2">
|
<div className="flex grow items-center justify-between gap-2">
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
{item.badge && (
|
{item.badge && (
|
||||||
<Badge variant="secondary" size="sm" className="ms-auto">
|
<Badge variant="secondary" size="sm" className="ms-auto">
|
||||||
@@ -182,7 +182,7 @@ export function MegaMenuMobile() {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex grow shrink-0 py-5 px-5">
|
<div className="flex shrink-0 grow px-5 py-5">
|
||||||
<AccordionMenu
|
<AccordionMenu
|
||||||
selectedValue={pathname}
|
selectedValue={pathname}
|
||||||
matchPath={matchPath}
|
matchPath={matchPath}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { MegaMenu } from './MegaMenu';
|
|||||||
|
|
||||||
export function Navbar() {
|
export function Navbar() {
|
||||||
return (
|
return (
|
||||||
<div className="bg-muted/80 lg:flex lg:items-stretch border-y border-border">
|
<div className="bg-muted/80 border-border border-y lg:flex lg:items-stretch">
|
||||||
<Container className="flex flex-wrap justify-between items-center gap-2 px-0 lg:px-7.5">
|
<Container className="flex flex-wrap items-center justify-between gap-2 px-0 lg:px-7.5">
|
||||||
<MegaMenu />
|
<MegaMenu />
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex items-center justify-between flex-wrap gap-2 la:gap-5 py-7">
|
<div className="la:gap-5 flex flex-wrap items-center justify-between gap-2 py-7">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
@@ -22,7 +22,7 @@ function Toolbar({ children }: { children?: ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarActions({ children }: { children?: ReactNode }) {
|
function ToolbarActions({ children }: { children?: ReactNode }) {
|
||||||
return <div className="flex items-center flex-wrap gap-2.5">{children}</div>;
|
return <div className="flex flex-wrap items-center gap-2.5">{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarBreadcrumbs() {
|
function ToolbarBreadcrumbs() {
|
||||||
@@ -74,7 +74,7 @@ function ToolbarHeading({ title = '' }: ToolbarHeadingProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Link, Outlet, useLocation } from 'react-router';
|
import { Link, Outlet, useLocation } from 'react-router';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Navbar } from './components/Navbar';
|
import { Navbar } from './components/Navbar';
|
||||||
@@ -43,7 +43,7 @@ export function ExtendedHeaderLayout() {
|
|||||||
|
|
||||||
{!isMobile && <Navbar />}
|
{!isMobile && <Navbar />}
|
||||||
|
|
||||||
<main className="flex flex-col grow" role="content">
|
<main className="flex grow flex-col" role="content">
|
||||||
{!pathname.includes('/public-profile/') && (
|
{!pathname.includes('/public-profile/') && (
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarHeading />
|
<ToolbarHeading />
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function Footer() {
|
|||||||
return (
|
return (
|
||||||
<footer className="footer">
|
<footer className="footer">
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-3 py-5">
|
<div className="flex flex-col items-center justify-center gap-3 py-5 md:flex-row md:justify-between">
|
||||||
<div className="flex order-2 md:order-1 gap-2 font-normal text-sm">
|
<div className="order-2 flex gap-2 text-sm font-normal md:order-1">
|
||||||
<span className="text-muted-foreground">{currentYear} ©</span>
|
<span className="text-muted-foreground">{currentYear} ©</span>
|
||||||
<a
|
<a
|
||||||
href="https://keenthemes.com"
|
href="https://keenthemes.com"
|
||||||
@@ -18,7 +18,7 @@ export function Footer() {
|
|||||||
Keenthemes Inc.
|
Keenthemes Inc.
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex order-1 md:order-2 gap-4 font-normal text-sm text-muted-foreground">
|
<nav className="text-muted-foreground order-1 flex gap-4 text-sm font-normal md:order-2">
|
||||||
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
<a href={generalSettings.docsLink} target="_blank" className="hover:text-primary">
|
||||||
Docs
|
Docs
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export function Header() {
|
|||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="flex lg:hidden items-center fixed z-10 top-0 start-0 end-0 shrink-0 bg-mono dark:bg-background h-(--header-height)">
|
<header className="bg-mono dark:bg-background fixed start-0 end-0 top-0 z-10 flex h-(--header-height) shrink-0 items-center lg:hidden">
|
||||||
<Container className="flex items-center justify-between flex-wrap gap-3">
|
<Container className="flex flex-wrap items-center justify-between gap-3">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle-success.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle-success.svg')}
|
||||||
@@ -38,9 +38,9 @@ export function Header() {
|
|||||||
<Menu />
|
<Menu />
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="dark p-0 gap-0 w-62.5" side="left" close={false}>
|
<SheetContent className="dark w-62.5 gap-0 p-0" side="left" close={false}>
|
||||||
<SheetHeader className="p-0 space-y-0" />
|
<SheetHeader className="space-y-0 p-0" />
|
||||||
<SheetBody className="p-0 grow flex flex-col overflow-y-auto">
|
<SheetBody className="flex grow flex-col overflow-y-auto p-0">
|
||||||
<SidebarHeader />
|
<SidebarHeader />
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
<SidebarFooter />
|
<SidebarFooter />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { SidebarMenu } from './SidebarMenu';
|
|||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
return (
|
return (
|
||||||
<div className="flex-col fixed top-0 bottom-0 z-20 lg:flex items-stretch shrink-0 w-(--sidebar-width) dark">
|
<div className="dark fixed top-0 bottom-0 z-20 w-(--sidebar-width) shrink-0 flex-col items-stretch lg:flex">
|
||||||
<SidebarHeader />
|
<SidebarHeader />
|
||||||
<SidebarMenu />
|
<SidebarMenu />
|
||||||
<SidebarFooter />
|
<SidebarFooter />
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import { UserDropdownMenu } from '#shared/widgets/UserDropdownMenu';
|
|||||||
|
|
||||||
export function SidebarFooter() {
|
export function SidebarFooter() {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-center justify-between shrink-0 ps-4 pe-3.5 mb-3.5">
|
<div className="flex-center mb-3.5 flex shrink-0 justify-between ps-4 pe-3.5">
|
||||||
<UserDropdownMenu
|
<UserDropdownMenu
|
||||||
trigger={
|
trigger={
|
||||||
<img
|
<img
|
||||||
className="size-9 rounded-full border-2 border-mono/25 shrink-0 cursor-pointer"
|
className="border-mono/25 size-9 shrink-0 cursor-pointer rounded-full border-2"
|
||||||
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
src={toAbsoluteUrl('/media/avatars/300-2.png')}
|
||||||
alt="User Avatar"
|
alt="User Avatar"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export function SidebarHeader() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2.5">
|
<div className="flex flex-col gap-2.5">
|
||||||
<div className="flex items-center justify-between gap-2.5 px-3.5 h-17.5">
|
<div className="flex h-17.5 items-center justify-between gap-2.5 px-3.5">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl('/media/app/mini-logo-circle-success.svg')}
|
src={toAbsoluteUrl('/media/app/mini-logo-circle-success.svg')}
|
||||||
@@ -38,9 +38,9 @@ export function SidebarHeader() {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger className="cursor-pointer text-mono font-medium flex items-center justify-between gap-2 w-47.5">
|
<DropdownMenuTrigger className="text-mono flex w-47.5 cursor-pointer items-center justify-between gap-2 font-medium">
|
||||||
Metronic
|
Metronic
|
||||||
<ChevronsUpDown className="size-3.5! me-1" />
|
<ChevronsUpDown className="me-1 size-3.5!" />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent
|
<DropdownMenuContent
|
||||||
sideOffset={10}
|
sideOffset={10}
|
||||||
@@ -65,7 +65,7 @@ export function SidebarHeader() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2.5 px-3.5">
|
<div className="flex items-center gap-2.5 px-3.5">
|
||||||
<Button asChild variant="secondary" className="text-white justify-center w-full max-w-49.5">
|
<Button asChild variant="secondary" className="w-full max-w-49.5 justify-center text-white">
|
||||||
<Link to="/public-profile/projects/3-columns">
|
<Link to="/public-profile/projects/3-columns">
|
||||||
<Plus /> Add New
|
<Plus /> Add New
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { SidebarMenuSecondary } from './SidebarMenuSecondary';
|
|||||||
|
|
||||||
export function SidebarMenu() {
|
export function SidebarMenu() {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-5 kt-scrollable-y-auto grow shrink-0 my-5 [--scrollbar-thumb-color:var(--input)] max-h-[calc(100vh-13rem)]">
|
<div className="kt-scrollable-y-auto my-5 max-h-[calc(100vh-13rem)] shrink-0 grow space-y-5 [--scrollbar-thumb-color:var(--input)]">
|
||||||
<SidebarMenuPrimary />
|
<SidebarMenuPrimary />
|
||||||
<SidebarMenuSecondary />
|
<SidebarMenuSecondary />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,18 +22,18 @@ const items = [
|
|||||||
export function SidebarMenuSecondary() {
|
export function SidebarMenuSecondary() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-xs text-muted-foreground uppercase ps-5 inline-block mb-3">Outline</h3>
|
<h3 className="text-muted-foreground mb-3 inline-block ps-5 text-xs uppercase">Outline</h3>
|
||||||
<div className="flex flex-col w-full gap-1.5 px-3.5">
|
<div className="flex w-full flex-col gap-1.5 px-3.5">
|
||||||
{items.map((item, index) => (
|
{items.map((item, index) => (
|
||||||
<Link key={index} to={item.path} className="group flex items-center gap-2.5 py-1 px-1">
|
<Link key={index} to={item.path} className="group flex items-center gap-2.5 px-1 py-1">
|
||||||
<span className="bg-black rounded-md flex items-center justify-center size-7">
|
<span className="flex size-7 items-center justify-center rounded-md bg-black">
|
||||||
<img
|
<img
|
||||||
src={toAbsoluteUrl(`/media/brand-logos/${item.logo}`)}
|
src={toAbsoluteUrl(`/media/brand-logos/${item.logo}`)}
|
||||||
className="size-3.5"
|
className="size-3.5"
|
||||||
alt={item.title}
|
alt={item.title}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span className="text-sm text-secondary-foreground group-hover:text-mono">
|
<span className="text-secondary-foreground group-hover:text-mono text-sm">
|
||||||
{item.title}
|
{item.title}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export interface ToolbarHeadingProps {
|
|||||||
function Toolbar({ children }: { children?: ReactNode }) {
|
function Toolbar({ children }: { children?: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<div className="flex items-center justify-between flex-wrap gap-2 lg:gap-5 pt-3 pb-7">
|
<div className="flex flex-wrap items-center justify-between gap-2 pt-3 pb-7 lg:gap-5">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
@@ -22,7 +22,7 @@ function Toolbar({ children }: { children?: ReactNode }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarActions({ children }: { children?: ReactNode }) {
|
function ToolbarActions({ children }: { children?: ReactNode }) {
|
||||||
return <div className="flex items-center flex-wrap gap-2.5">{children}</div>;
|
return <div className="flex flex-wrap items-center gap-2.5">{children}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToolbarBreadcrumbs() {
|
function ToolbarBreadcrumbs() {
|
||||||
@@ -74,7 +74,7 @@ function ToolbarHeading({ title = '' }: ToolbarHeadingProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
<h1 className="font-medium text-lg text-mono">{title || item?.title}</h1>
|
<h1 className="text-mono text-lg font-medium">{title || item?.title}</h1>
|
||||||
<ToolbarBreadcrumbs />
|
<ToolbarBreadcrumbs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ export function ToolbarMenu() {
|
|||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="outline" size="sm" className="flex items-center gap-1 flex-nowrap">
|
<Button variant="outline" size="sm" className="flex flex-nowrap items-center gap-1">
|
||||||
<Calendar className="h-4 w-4" />
|
<Calendar className="h-4 w-4" />
|
||||||
<span className="hidden md:inline whitespace-nowrap">September, 2024</span>
|
<span className="hidden whitespace-nowrap md:inline">September, 2024</span>
|
||||||
<span className="inline md:hidden whitespace-nowrap">Sep, 2024</span>
|
<span className="inline whitespace-nowrap md:hidden">Sep, 2024</span>
|
||||||
<ChevronDown className="h-3 w-3 ml-1 lg:ml-4" />
|
<ChevronDown className="ml-1 h-3 w-3 lg:ml-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end" className="w-48 max-h-62.5 overflow-y-auto">
|
<DropdownMenuContent align="end" className="max-h-62.5 w-48 overflow-y-auto">
|
||||||
{months.map((item, index) => (
|
{months.map((item, index) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { DateRange } from 'react-day-picker';
|
|||||||
import { Link, Outlet } from 'react-router-dom';
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
import { useBodyClass, useIsMobile } from '@crux-kit/hooks';
|
||||||
import { LayoutNames } from '#app/config/types';
|
import { LayoutNames } from '#app/config/types';
|
||||||
|
import { useSettings } from '#app/providers/SettingsProvider';
|
||||||
import { Button } from '#shared/ui/Button';
|
import { Button } from '#shared/ui/Button';
|
||||||
import { Calendar } from '#shared/ui/Calendar';
|
import { Calendar } from '#shared/ui/Calendar';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '#shared/ui/Popover';
|
||||||
import { useSettings } from '#providers/SettingsProvider';
|
|
||||||
import { Footer } from './components/Footer';
|
import { Footer } from './components/Footer';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
import { Sidebar } from './components/Sidebar';
|
import { Sidebar } from './components/Sidebar';
|
||||||
@@ -41,11 +41,11 @@ export const DarkSidebarLayout = () => {
|
|||||||
<div className="flex grow">
|
<div className="flex grow">
|
||||||
{isMobile && <Header />}
|
{isMobile && <Header />}
|
||||||
|
|
||||||
<div className="flex flex-col lg:flex-row grow pt-(--header-height) lg:pt-0">
|
<div className="flex grow flex-col pt-(--header-height) lg:flex-row lg:pt-0">
|
||||||
{!isMobile && <Sidebar />}
|
{!isMobile && <Sidebar />}
|
||||||
|
|
||||||
<div className="flex flex-col grow lg:rounded-s-xl bg-background border border-input lg:ms-(--sidebar-width)">
|
<div className="bg-background border-input flex grow flex-col border lg:ms-(--sidebar-width) lg:rounded-s-xl">
|
||||||
<div className="flex flex-col grow kt-scrollable-y-auto lg:[scrollbar-width:auto] pt-5">
|
<div className="kt-scrollable-y-auto flex grow flex-col pt-5 lg:[scrollbar-width:auto]">
|
||||||
<main className="grow" role="content">
|
<main className="grow" role="content">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarHeading />
|
<ToolbarHeading />
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user