@akinon/ui-shell-dev 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/akinon-favicon.png +0 -0
  2. package/dist/akinon-logo.png +0 -0
  3. package/dist/akinon-logo.svg +10 -0
  4. package/dist/assets/index-BFs1gfY5.css +1 -0
  5. package/dist/assets/index-Dk6Gr15i.js +408 -0
  6. package/dist/assets/jost-cyrillic-wght-normal-B0_vFdaS.woff2 +0 -0
  7. package/dist/assets/jost-latin-ext-wght-normal-B4kqP43q.woff2 +0 -0
  8. package/dist/assets/jost-latin-wght-normal-CfFW3YMY.woff2 +0 -0
  9. package/dist/index.html +2 -2
  10. package/dist/logo.png +0 -0
  11. package/dist/symbol.png +0 -0
  12. package/package.json +9 -9
  13. package/public/akinon-favicon.png +0 -0
  14. package/public/akinon-logo.png +0 -0
  15. package/public/akinon-logo.svg +10 -0
  16. package/public/logo.png +0 -0
  17. package/public/symbol.png +0 -0
  18. package/src/components/AppLayout.tsx +44 -48
  19. package/src/components/Header.tsx +33 -48
  20. package/src/components/HeaderSearch.tsx +12 -0
  21. package/src/components/HeaderUser.tsx +23 -0
  22. package/src/components/Navigation.tsx +55 -0
  23. package/src/components/PageContent.tsx +9 -0
  24. package/src/components/PageHeading.tsx +61 -0
  25. package/src/components/PluginTestPage.scss +26 -0
  26. package/src/components/PluginTestPage.tsx +105 -0
  27. package/src/components/WelcomePage.tsx +117 -0
  28. package/src/components/layout.scss +48 -0
  29. package/src/global.scss +33 -0
  30. package/src/main.tsx +8 -2
  31. package/src/pages/Dashboard.tsx +25 -0
  32. package/src/pages/External.tsx +15 -0
  33. package/src/pages/PluginTest.tsx +7 -0
  34. package/src/pages/pages.scss +9 -0
  35. package/src/providers.tsx +108 -0
  36. package/src/routes.tsx +44 -0
  37. package/src/server/dev-server.mjs +18 -15
  38. package/src/shell-app.tsx +13 -4
  39. package/src/types.ts +4 -0
  40. package/src/utils/navigation.tsx +65 -0
  41. package/dist/assets/index-CuIRnKVE.css +0 -1
  42. package/dist/assets/index-DUUd718F.js +0 -193
  43. package/src/components/Sidebar.tsx +0 -74
@@ -0,0 +1,117 @@
1
+ import { useAppShell } from '@akinon/app-shell';
2
+ import { Button, Card, Divider, Tag } from '@akinon/ui-react';
3
+ import React from 'react';
4
+ import { useNavigate } from 'react-router-dom';
5
+
6
+ export const WelcomePage: React.FC = () => {
7
+ const navigate = useNavigate();
8
+ const { apps } = useAppShell();
9
+ const app = apps[0]; // Get the first (and likely only) app
10
+
11
+ return (
12
+ <div>
13
+ <Card title="Application Configuration" style={{ marginBottom: '24px' }}>
14
+ <div
15
+ style={{
16
+ display: 'grid',
17
+ gridTemplateColumns: '1fr 1fr',
18
+ gap: '16px'
19
+ }}
20
+ >
21
+ <div>
22
+ <strong>Application Name:</strong>
23
+ <p style={{ margin: '12px 0 4px 0' }}>
24
+ {app?.name || 'Development App'}
25
+ </p>
26
+ </div>
27
+ <div>
28
+ <strong>Application Type:</strong>
29
+ <p style={{ margin: '12px 0 4px 0' }}>
30
+ <Tag color={app?.type === 'full_page' ? 'blue' : 'green'}>
31
+ {app?.type === 'full_page' ? 'fullpage' : 'plugin'}
32
+ </Tag>
33
+ </p>
34
+ </div>
35
+ <div>
36
+ <strong>Development URL:</strong>
37
+ <p
38
+ style={{
39
+ margin: '12px 0 4px 0',
40
+ color: '#999',
41
+ fontFamily: 'monospace',
42
+ fontSize: '13px'
43
+ }}
44
+ >
45
+ {app?.url || 'http://localhost:4001'}
46
+ </p>
47
+ </div>
48
+ <div>
49
+ <strong>Shell Theme:</strong>
50
+ <p style={{ margin: '12px 0 4px 0', color: '#999' }}>omnitron</p>
51
+ </div>
52
+ </div>
53
+ </Card>
54
+
55
+ <Card title="Quick Actions" style={{ marginBottom: '24px' }}>
56
+ <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>
57
+ <Button
58
+ type="primary"
59
+ onClick={() => navigate(`/external/${app?.slug}`)}
60
+ >
61
+ Launch Application
62
+ </Button>
63
+ {app?.type === 'plugin' && (
64
+ <Button onClick={() => navigate('/plugin-test')}>
65
+ Test Plugin Integration
66
+ </Button>
67
+ )}
68
+ </div>
69
+ </Card>
70
+
71
+ <Card title="Development Instructions">
72
+ <div style={{ lineHeight: '1.6' }}>
73
+ <h4 style={{ margin: '0 0 8px 0' }}>Getting Started:</h4>
74
+ <ol style={{ paddingLeft: '20px' }}>
75
+ <li>
76
+ Make sure your application is running at{' '}
77
+ <code>{app?.url || 'http://localhost:4001'}</code>
78
+ </li>
79
+ <li>
80
+ Click &quot;Launch Application&quot; to load your app in the shell
81
+ environment
82
+ </li>
83
+ {app?.type === 'plugin' && (
84
+ <li>
85
+ Use &quot;Test Plugin Integration&quot; to test your plugin in
86
+ different placeholder configurations
87
+ </li>
88
+ )}
89
+ <li>
90
+ The shell provides a realistic integration environment for testing
91
+ </li>
92
+ </ol>
93
+
94
+ <Divider />
95
+
96
+ <h4 style={{ margin: '16px 0 8px 0' }}>
97
+ Application Type:{' '}
98
+ {app?.type === 'full_page' ? 'fullpage' : 'plugin'}
99
+ </h4>
100
+ {app?.type === 'full_page' ? (
101
+ <p style={{ margin: 0, color: '#666' }}>
102
+ Your fullpage application will render as complete pages within the
103
+ shell environment, providing full control over the content area
104
+ and routing.
105
+ </p>
106
+ ) : (
107
+ <p style={{ margin: 0, color: '#666' }}>
108
+ Your plugin application will render within designated placeholders
109
+ in the host application, providing component-level integration
110
+ capabilities.
111
+ </p>
112
+ )}
113
+ </div>
114
+ </Card>
115
+ </div>
116
+ );
117
+ };
@@ -0,0 +1,48 @@
1
+ .akinon-layout {
2
+ height: 100vh;
3
+ }
4
+
5
+ .akinon-layout-sider {
6
+ overflow-x: hidden;
7
+ }
8
+
9
+ .akinon-layout-content {
10
+ height: calc(100vh - 64px - 40px); // Subtract header and footer
11
+ overflow-y: auto;
12
+ overflow-x: hidden;
13
+ }
14
+
15
+ .akinon-menu-item.akinon-menu-item-disabled {
16
+ opacity: 0.6;
17
+ }
18
+
19
+ .akinon-menu-item {
20
+ font-weight: 500 !important;
21
+ }
22
+
23
+ .akinon-menu-item-selected {
24
+ font-weight: 600 !important;
25
+ }
26
+
27
+ .log-messages {
28
+ display: flex;
29
+ flex-direction: column;
30
+ padding: 0.75rem;
31
+
32
+ .akinon-space-item {
33
+ width: 100%;
34
+ }
35
+
36
+ &-item {
37
+ border-radius: 10px;
38
+ border: 1px solid #fff;
39
+ padding: 0.75rem;
40
+ display: flex;
41
+ flex-direction: column;
42
+ margin-bottom: 0.25rem;
43
+
44
+ & > div {
45
+ width: 100%;
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,33 @@
1
+ *,
2
+ *::before,
3
+ *::after {
4
+ font-family: 'Jost Variable', sans-serif;
5
+ }
6
+
7
+ html,
8
+ body,
9
+ #root {
10
+ height: 100%;
11
+ margin: 0;
12
+ padding: 0;
13
+ }
14
+
15
+ main {
16
+ padding: 4px 0;
17
+ }
18
+
19
+ ::-webkit-scrollbar {
20
+ width: 8px;
21
+ }
22
+
23
+ ::-webkit-scrollbar-track {
24
+ background-color: var(--color-ebonyClay-400);
25
+ border: none;
26
+ padding: 1px;
27
+ }
28
+
29
+ ::-webkit-scrollbar-thumb {
30
+ background-color: var(--color-ebonyClay-700);
31
+ border-radius: 3px;
32
+ border: none;
33
+ }
package/src/main.tsx CHANGED
@@ -1,3 +1,7 @@
1
+ import '@akinon/fonts-jost-variable';
2
+ import '@akinon/ui-utils';
3
+ import './global.scss';
4
+
1
5
  import React from 'react';
2
6
  import ReactDOM from 'react-dom/client';
3
7
 
@@ -9,8 +13,10 @@ const config: ShellConfig = (
9
13
  window as unknown as { __SHELL_CONFIG__?: ShellConfig }
10
14
  ).__SHELL_CONFIG__ || {
11
15
  plugin: {
12
- url: 'http://localhost:4002',
13
- path: './src'
16
+ url: 'http://localhost:4001',
17
+ path: './src',
18
+ name: 'Development App',
19
+ type: 'fullpage'
14
20
  },
15
21
  shell: {
16
22
  port: 4000,
@@ -0,0 +1,25 @@
1
+ import './pages.scss';
2
+
3
+ import React from 'react';
4
+
5
+ import { PageContent } from '../components/PageContent';
6
+ import { PageHeading } from '../components/PageHeading';
7
+ import { WelcomePage } from '../components/WelcomePage';
8
+
9
+ export const PageDashboard: React.FC = () => {
10
+ return (
11
+ <div className="page-dashboard">
12
+ <div className="page-heading-container">
13
+ <PageHeading
14
+ title="Welcome"
15
+ description="Development environment for testing and integrating your applications"
16
+ />
17
+ </div>
18
+ <div className="page-content-container">
19
+ <PageContent>
20
+ <WelcomePage />
21
+ </PageContent>
22
+ </div>
23
+ </div>
24
+ );
25
+ };
@@ -0,0 +1,15 @@
1
+ import './pages.scss';
2
+
3
+ import { AppRenderer } from '@akinon/app-shell';
4
+ import React from 'react';
5
+
6
+ export const PageExternal: React.FC<{ id: number; path?: string }> = ({
7
+ id,
8
+ path
9
+ }) => {
10
+ return (
11
+ <div className="page-plugin-external">
12
+ <AppRenderer id={id} path={path} />
13
+ </div>
14
+ );
15
+ };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+
3
+ import { PluginTestPage } from '../components/PluginTestPage';
4
+
5
+ export const PagePluginTest: React.FC = () => {
6
+ return <PluginTestPage />;
7
+ };
@@ -0,0 +1,9 @@
1
+ // Common page styling
2
+ .page-dashboard,
3
+ .page-plugin-external {
4
+ height: 100%;
5
+ }
6
+
7
+ .page-content-container {
8
+ // Additional content styling if needed
9
+ }
@@ -0,0 +1,108 @@
1
+ import type { ApplicationActions, RegisteredApp } from '@akinon/app-shell';
2
+ import { AppShellProvider, type ShellNavigation } from '@akinon/app-shell';
3
+ import { notification } from '@akinon/ui-react';
4
+ import React from 'react';
5
+ import { useNavigate, useSearchParams } from 'react-router-dom';
6
+
7
+ import type { ShellConfig } from './types';
8
+
9
+ interface ProvidersProps {
10
+ config: ShellConfig;
11
+ children: React.ReactNode;
12
+ }
13
+
14
+ export const Providers: React.FC<ProvidersProps> = ({ config, children }) => {
15
+ const [api, contextHolder] = notification.useNotification();
16
+ const [searchParams] = useSearchParams();
17
+ const navigate = useNavigate();
18
+
19
+ // Convert shell config to apps format for AppShellProvider
20
+ const apps: RegisteredApp[] = [
21
+ {
22
+ id: 1,
23
+ url: config.plugin.url,
24
+ slug: config.plugin.name.toLowerCase().replace(/\s+/g, '-'),
25
+ path: '', // Empty path for development like playground
26
+ type: config.plugin.type === 'fullpage' ? 'full_page' : 'plugin',
27
+ name: config.plugin.name
28
+ }
29
+ ];
30
+
31
+ const navigation: ShellNavigation = {
32
+ navigate: ({ id, path, external }: any) => {
33
+ const app = apps.find(app => app.id === id);
34
+ if (!app) return;
35
+
36
+ const uri = external ? path : `/external/${app.slug}${path || ''}`;
37
+ navigate(uri);
38
+ }
39
+ };
40
+
41
+ const data = {
42
+ lng: 'en',
43
+ username: 'Developer',
44
+ searchParams: Object.fromEntries([...searchParams])
45
+ };
46
+
47
+ const defaultActions = {
48
+ showModalDialog: () => {
49
+ // Implementation for showing a modal dialog
50
+ },
51
+ showToast: (
52
+ content: string,
53
+ type: 'success' | 'error' | 'info' | 'warning' | 'loading' | 'destroy'
54
+ ) => {
55
+ if (type === 'loading' || type === 'destroy') {
56
+ return;
57
+ }
58
+ api[type]({
59
+ message: content,
60
+ placement: 'top'
61
+ });
62
+ },
63
+ showErrorMessage: (title: string, content: string) => {
64
+ api.error({
65
+ message: title,
66
+ description: content,
67
+ placement: 'top'
68
+ });
69
+ },
70
+ showRichModal: () => {
71
+ // Rich modal implementation
72
+ }
73
+ };
74
+
75
+ const customActions = {
76
+ reloadPage: () => window.location.reload(),
77
+ logMessage: (newItem: Object) => {
78
+ try {
79
+ const prevItems = JSON.parse(
80
+ localStorage.getItem('logMessages') || '[]'
81
+ );
82
+ localStorage.setItem(
83
+ 'logMessages',
84
+ JSON.stringify([...prevItems, newItem])
85
+ );
86
+ } catch {}
87
+ }
88
+ };
89
+
90
+ const actions: ApplicationActions = {
91
+ ...defaultActions,
92
+ actions: {
93
+ ...customActions
94
+ }
95
+ };
96
+
97
+ return (
98
+ <AppShellProvider
99
+ apps={apps}
100
+ navigation={navigation}
101
+ data={data}
102
+ actions={actions}
103
+ >
104
+ {children}
105
+ {contextHolder}
106
+ </AppShellProvider>
107
+ );
108
+ };
package/src/routes.tsx ADDED
@@ -0,0 +1,44 @@
1
+ import { useAppShell } from '@akinon/app-shell';
2
+ import React from 'react';
3
+ import { Route, Routes as ReactRouterRoutes } from 'react-router-dom';
4
+
5
+ import { PageDashboard } from './pages/Dashboard';
6
+ import { PageExternal } from './pages/External';
7
+ import { PagePluginTest } from './pages/PluginTest';
8
+
9
+ export const Routes = () => {
10
+ const { apps, configs } = useAppShell();
11
+ const fullpageApps = apps.filter(app => app.type === 'full_page');
12
+
13
+ return (
14
+ <ReactRouterRoutes>
15
+ {fullpageApps.map(app => (
16
+ <Route key={app.id} path={`/external/${app.slug}`}>
17
+ <Route index element={<PageExternal id={app.id} path={app.path} />} />
18
+
19
+ {(configs.get(app.id) as any)?.menu?.map((sub: any) => {
20
+ return (
21
+ sub.path !== '/' && (
22
+ <Route
23
+ key={sub.path}
24
+ path={`/external/${app.slug}${sub.path}`}
25
+ element={
26
+ <PageExternal
27
+ id={app.id}
28
+ path={
29
+ app.subSlug ? `${app.subSlug}${sub.path}` : sub.path
30
+ }
31
+ />
32
+ }
33
+ />
34
+ )
35
+ );
36
+ })}
37
+ </Route>
38
+ ))}
39
+
40
+ <Route path="/plugin-test" element={<PagePluginTest />} />
41
+ <Route path="/" element={<PageDashboard />} />
42
+ </ReactRouterRoutes>
43
+ );
44
+ };
@@ -35,12 +35,13 @@ export class ShellDevServer {
35
35
  async start() {
36
36
  try {
37
37
  console.log('🔧 Starting shell server initialization...');
38
-
38
+
39
39
  const shellRoot = path.resolve(__dirname, '../..');
40
40
  const distPath = path.resolve(shellRoot, 'dist');
41
41
  // Only use production mode if explicitly set via env var
42
- const isProduction = process.env.NODE_ENV === 'production' && fs.existsSync(distPath);
43
-
42
+ const isProduction =
43
+ process.env.NODE_ENV === 'production' && fs.existsSync(distPath);
44
+
44
45
  console.log(`📁 Shell root: ${shellRoot}`);
45
46
  console.log(`🏭 Production mode: ${isProduction}`);
46
47
 
@@ -50,14 +51,14 @@ export class ShellDevServer {
50
51
  if (isProduction) {
51
52
  // Production: serve built assets
52
53
  this.app.use('/assets', express.static(path.join(distPath, 'assets')));
53
-
54
+
54
55
  this.app.get('*', (req, res, next) => {
55
56
  if (req.path.startsWith('/api')) {
56
57
  return next();
57
58
  }
58
59
 
59
60
  console.log(`📄 Serving production HTML for: ${req.url}`);
60
-
61
+
61
62
  let template = fs.readFileSync(
62
63
  path.resolve(distPath, 'index.html'),
63
64
  'utf-8'
@@ -85,20 +86,18 @@ export class ShellDevServer {
85
86
 
86
87
  console.log('✅ Vite server created successfully');
87
88
 
88
- // Use Vite middleware for assets and HMR
89
- this.app.use(this.viteServer.middlewares);
90
-
91
- console.log('✅ Vite middleware configured');
92
-
93
- // Serve the shell app (only for HTML requests)
89
+ // Serve the shell app (only for HTML requests) - MUST be before Vite middleware
94
90
  this.app.get('*', async (req, res, next) => {
95
- if (req.path.startsWith('/api') || req.path.startsWith('/src') || req.path.includes('.')) {
91
+ if (
92
+ req.path.startsWith('/api') ||
93
+ req.path.startsWith('/src') ||
94
+ req.path.startsWith('/@') ||
95
+ req.path.includes('.')
96
+ ) {
96
97
  return next();
97
98
  }
98
99
 
99
100
  try {
100
- console.log(`📄 Serving development HTML for: ${req.url}`);
101
-
102
101
  let template = fs.readFileSync(
103
102
  path.resolve(__dirname, '../../index.html'),
104
103
  'utf-8'
@@ -115,7 +114,6 @@ export class ShellDevServer {
115
114
  `<script>window.__SHELL_CONFIG__ = ${JSON.stringify(this.config)};</script>`
116
115
  );
117
116
 
118
- console.log(`✅ HTML processed successfully for ${req.url}`);
119
117
  res.status(200).set({ 'Content-Type': 'text/html' }).end(template);
120
118
  } catch (error) {
121
119
  console.error(`❌ Error serving ${req.url}:`, error);
@@ -123,6 +121,11 @@ export class ShellDevServer {
123
121
  next(error);
124
122
  }
125
123
  });
124
+
125
+ // Use Vite middleware for assets and HMR - MUST be after our route handler
126
+ this.app.use(this.viteServer.middlewares);
127
+
128
+ console.log('✅ Vite middleware configured');
126
129
  }
127
130
 
128
131
  // Start server
package/src/shell-app.tsx CHANGED
@@ -1,7 +1,10 @@
1
- import { AkinonUiProvider } from '@akinon/ui-system';
1
+ import { AkinonUiProvider } from '@akinon/ui-react';
2
2
  import React from 'react';
3
+ import { BrowserRouter } from 'react-router-dom';
3
4
 
4
5
  import { AppLayout } from './components/AppLayout';
6
+ import { Providers } from './providers';
7
+ import { Routes } from './routes';
5
8
  import type { ShellConfig } from './types';
6
9
 
7
10
  interface ShellAppProps {
@@ -10,8 +13,14 @@ interface ShellAppProps {
10
13
 
11
14
  export const ShellApp: React.FC<ShellAppProps> = ({ config }) => {
12
15
  return (
13
- <AkinonUiProvider>
14
- <AppLayout config={config} />
15
- </AkinonUiProvider>
16
+ <BrowserRouter>
17
+ <AkinonUiProvider>
18
+ <Providers config={config}>
19
+ <AppLayout>
20
+ <Routes />
21
+ </AppLayout>
22
+ </Providers>
23
+ </AkinonUiProvider>
24
+ </BrowserRouter>
16
25
  );
17
26
  };
package/src/types.ts CHANGED
@@ -2,6 +2,8 @@ export interface ShellConfig {
2
2
  plugin: {
3
3
  url: string;
4
4
  path: string;
5
+ name: string;
6
+ type: 'fullpage' | 'plugin';
5
7
  };
6
8
  shell: {
7
9
  port: number;
@@ -38,3 +40,5 @@ export interface ThemeConfig {
38
40
  height: number;
39
41
  };
40
42
  }
43
+
44
+ export type ViewType = 'welcome' | 'app' | 'plugin-test';
@@ -0,0 +1,65 @@
1
+ import type { RegisteredApp } from '@akinon/app-shell';
2
+ import type { TMenuItemType } from '@akinon/ui-react';
3
+
4
+ const STATIC_NAVIGATION_ITEMS: TMenuItemType[] = [
5
+ {
6
+ key: '/',
7
+ label: 'Welcome',
8
+ icon: 'dashboard'
9
+ },
10
+ {
11
+ key: '/placeholder-1',
12
+ label: 'Settings',
13
+ icon: 'ayarlar',
14
+ disabled: true
15
+ },
16
+ {
17
+ key: '/placeholder-2',
18
+ label: 'Help & Support',
19
+ icon: 'bilgilendirme_servis',
20
+ disabled: true
21
+ }
22
+ ];
23
+
24
+ const PLUGIN_NAVIGATION_ITEMS: TMenuItemType[] = [
25
+ {
26
+ key: '/plugin-test',
27
+ label: 'Plugin Test',
28
+ icon: 'box'
29
+ }
30
+ ];
31
+
32
+ export const getStaticNavigationItems = () => {
33
+ return STATIC_NAVIGATION_ITEMS;
34
+ };
35
+
36
+ export const getFullpageNavigationItems = (
37
+ apps: RegisteredApp[],
38
+ configs: Map<number, any>
39
+ ): TMenuItemType[] => {
40
+ return apps
41
+ .filter(app => app.type === 'full_page')
42
+ .map((app): TMenuItemType => {
43
+ return {
44
+ key: `/external/${app.slug}`,
45
+ label: app.name,
46
+ icon: 'stoklistesi',
47
+ children: configs
48
+ .get(app.id)
49
+ ?.menu?.map((sub: any): TMenuItemType | false => {
50
+ if (sub?.child) return false;
51
+
52
+ return {
53
+ key: `/external/${app.slug}${sub.path}`,
54
+ label: sub.label,
55
+ icon: 'eksi'
56
+ };
57
+ })
58
+ .filter(Boolean)
59
+ };
60
+ });
61
+ };
62
+
63
+ export const getPluginNavigationItems = () => {
64
+ return PLUGIN_NAVIGATION_ITEMS;
65
+ };
@@ -1 +0,0 @@
1
- .akinon-layout-footer{text-align:center}.akinon-layout-header{padding-inline:1rem;height:3.5rem;border-bottom:1px solid var(--color-gray-900);display:flex;align-items:center;justify-content:space-between;line-height:unset;position:sticky;top:0;z-index:999}.akinon-layout-sider{position:sticky;top:0;height:100svh;overflow-y:auto}.akinon-layout-sider.left{inset-inline-start:0}.akinon-layout-sider.right{inset-inline-end:0}.akinon-layout-sider .logo-container{display:flex;flex-direction:row;align-items:center;height:3.5rem;gap:.8rem;background-color:var(--color-ebonyClay-600);padding-inline:1.5rem}.akinon-layout-sider .logo-container.collapsed{justify-content:center;padding-inline:1rem}.akinon-layout-sider .logo-container.collapsed .brand-image{display:none}