@manafishrov/ui 1.1.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@manafishrov/ui",
4
- "version": "1.1.0",
4
+ "version": "1.2.0",
5
5
  "description": "Styled component library for Manafish interfaces ",
6
6
  "license": "AGPL-3.0-or-later",
7
7
  "repository": {
@@ -6,7 +6,7 @@ import { useSidebar } from './context';
6
6
  import { SidebarDesktop } from './SidebarDesktop';
7
7
  import { SidebarMobile } from './SidebarMobile';
8
8
 
9
- export type SidebarProps = ComponentProps<'div'> & {
9
+ export type SidebarProps = ComponentProps<'aside'> & {
10
10
  side?: 'left' | 'right';
11
11
  variant?: 'sidebar' | 'floating' | 'inset';
12
12
  collapsible?: 'offcanvas' | 'icon' | 'none';
@@ -1,24 +1,57 @@
1
- import type { Component, ComponentProps, JSXElement } from 'solid-js';
2
-
1
+ import {
2
+ createMemo,
3
+ type Component,
4
+ type ComponentProps,
5
+ type JSX,
6
+ type JSXElement,
7
+ } from 'solid-js';
3
8
  import { cn } from 'tailwind-variants';
4
9
 
5
10
  import type { SidebarProps } from './Sidebar';
6
11
 
12
+ import { SIDEBAR_WIDTH, SIDEBAR_WIDTH_ICON } from './constants';
7
13
  import { useSidebar } from './context';
8
14
 
9
- type SidebarDesktopContainerProps = ComponentProps<'div'> & {
15
+ type SidebarDesktopContainerProps = ComponentProps<'aside'> & {
10
16
  variant: string;
11
17
  side: string;
12
18
  children: JSXElement;
13
19
  };
14
20
 
21
+ const getSidebarDesktopRootClass = (
22
+ disableMobileSidebar: boolean | undefined,
23
+ ): ComponentProps<'div'>['class'] =>
24
+ cn(
25
+ disableMobileSidebar === true
26
+ ? 'group peer min-h-0 relative block self-stretch text-sidebar-foreground'
27
+ : 'group peer md:block min-h-0 relative hidden self-stretch text-sidebar-foreground',
28
+ );
29
+
30
+ const getSidebarGapClass = (variant: SidebarProps['variant']): ComponentProps<'div'>['class'] =>
31
+ cn(
32
+ 'relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',
33
+ 'group-data-[collapsible=offcanvas]:w-0',
34
+ 'group-data-[side=right]:rotate-180',
35
+ variant === 'floating' || variant === 'inset'
36
+ ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+1rem)]'
37
+ : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
38
+ );
39
+
40
+ const getSidebarStyle = (style: SidebarProps['style']): JSX.CSSProperties => {
41
+ const base: JSX.CSSProperties = {
42
+ '--sidebar-width': SIDEBAR_WIDTH,
43
+ '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
44
+ };
45
+ return typeof style === 'object' && style !== null ? { ...base, ...style } : base;
46
+ };
47
+
15
48
  const SidebarDesktopContainer: Component<SidebarDesktopContainerProps> = (props) => {
16
49
  const [local, others] = splitProps(props, ['variant', 'side', 'class', 'children']);
17
50
  return (
18
- <div
51
+ <aside
19
52
  data-slot='sidebar-container'
20
53
  class={cn(
21
- 'inset-y-0 md:flex fixed z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear',
54
+ 'top-0 bottom-0 md:flex absolute z-10 hidden w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear',
22
55
  local.side === 'left'
23
56
  ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
24
57
  : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
@@ -36,7 +69,7 @@ const SidebarDesktopContainer: Component<SidebarDesktopContainerProps> = (props)
36
69
  >
37
70
  {local.children}
38
71
  </div>
39
- </div>
72
+ </aside>
40
73
  );
41
74
  };
42
75
 
@@ -47,34 +80,24 @@ export const SidebarDesktop: Component<SidebarProps> = (props) => {
47
80
  'variant',
48
81
  'collapsible',
49
82
  'disableMobileSidebar',
83
+ 'style',
50
84
  'class',
51
85
  'children',
52
86
  ]);
53
87
 
88
+ const style = createMemo(() => getSidebarStyle(local.style));
89
+
54
90
  return (
55
91
  <div
56
- class={cn(
57
- local.disableMobileSidebar === true
58
- ? 'group peer block text-sidebar-foreground'
59
- : 'group peer md:block hidden text-sidebar-foreground',
60
- )}
92
+ style={style()}
93
+ class={getSidebarDesktopRootClass(local.disableMobileSidebar)}
61
94
  data-state={state()}
62
95
  data-collapsible={state() === 'collapsed' ? (local.collapsible ?? 'offcanvas') : ''}
63
96
  data-variant={local.variant ?? 'sidebar'}
64
97
  data-side={local.side ?? 'left'}
65
98
  data-slot='sidebar'
66
99
  >
67
- <div
68
- data-slot='sidebar-gap'
69
- class={cn(
70
- 'relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',
71
- 'group-data-[collapsible=offcanvas]:w-0',
72
- 'group-data-[side=right]:rotate-180',
73
- local.variant === 'floating' || local.variant === 'inset'
74
- ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+1rem)]'
75
- : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
76
- )}
77
- />
100
+ <div data-slot='sidebar-gap' class={getSidebarGapClass(local.variant)} />
78
101
  <SidebarDesktopContainer
79
102
  variant={local.variant ?? 'sidebar'}
80
103
  side={local.side ?? 'left'}
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  type Component,
3
3
  type ComponentProps,
4
- createMemo,
5
4
  createSignal,
6
5
  onCleanup,
7
6
  onMount,
@@ -12,14 +11,31 @@ import { cn } from 'tailwind-variants';
12
11
 
13
12
  import { createMediaQuery } from '@/primitives/createMediaQuery';
14
13
 
15
- import { SIDEBAR_KEYBOARD_SHORTCUT, SIDEBAR_WIDTH, SIDEBAR_WIDTH_ICON } from './constants';
14
+ import { SIDEBAR_KEYBOARD_SHORTCUT } from './constants';
16
15
  import { SidebarContext, type SidebarContextProps } from './context';
17
16
  import { setSidebarCookie } from './utils';
18
17
 
19
- export type SidebarProviderProps = ComponentProps<'div'> & {
18
+ export type SidebarProviderProps = {
20
19
  defaultOpen?: boolean;
21
20
  open?: boolean;
22
21
  onOpenChange?: (openValue: boolean) => void;
22
+ children?: JSX.Element;
23
+ };
24
+
25
+ export type SidebarLayoutProps = ComponentProps<'div'>;
26
+
27
+ export const SidebarLayout: Component<SidebarLayoutProps> = (props) => {
28
+ const [local, others] = splitProps(props, ['class']);
29
+ return (
30
+ <div
31
+ data-slot='sidebar-wrapper'
32
+ class={cn(
33
+ 'relative flex h-full min-h-full w-full has-data-[variant=inset]:bg-sidebar',
34
+ local.class,
35
+ )}
36
+ {...others}
37
+ />
38
+ );
23
39
  };
24
40
 
25
41
  const useSidebarState = (
@@ -105,40 +121,12 @@ const createSidebarContextValue = (
105
121
  });
106
122
 
107
123
  export const SidebarProvider: Component<SidebarProviderProps> = (props) => {
108
- const [local, others] = splitProps(props, [
109
- 'defaultOpen',
110
- 'open',
111
- 'onOpenChange',
112
- 'class',
113
- 'style',
114
- 'children',
115
- ]);
116
- const stateSet = useSidebarState(local);
124
+ const stateSet = useSidebarState(props);
117
125
  const { toggle } = useSidebarEvents(stateSet);
118
126
 
119
- const style = createMemo((): JSX.CSSProperties => {
120
- const base: JSX.CSSProperties = {
121
- '--sidebar-width': SIDEBAR_WIDTH,
122
- '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,
123
- };
124
- return typeof local.style === 'object' && local.style !== null
125
- ? { ...base, ...local.style }
126
- : base;
127
- });
128
-
129
127
  return (
130
128
  <SidebarContext.Provider value={createSidebarContextValue(stateSet, toggle)}>
131
- <div
132
- data-slot='sidebar-wrapper'
133
- style={style()}
134
- class={cn(
135
- 'group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar',
136
- local.class,
137
- )}
138
- {...others}
139
- >
140
- {local.children}
141
- </div>
129
+ {props.children}
142
130
  </SidebarContext.Provider>
143
131
  );
144
132
  };
@@ -4,7 +4,13 @@ import { cn } from 'tailwind-variants';
4
4
  import ViewSidebarIcon from '~icons/material-symbols/side-navigation';
5
5
 
6
6
  import { Button } from '@/components/Button';
7
- import { ScrollArea } from '@/components/ScrollArea';
7
+ import {
8
+ ScrollArea,
9
+ ScrollAreaContent,
10
+ ScrollAreaScrollbar,
11
+ ScrollAreaThumb,
12
+ ScrollAreaViewport,
13
+ } from '@/components/ScrollArea';
8
14
  import { Separator } from '@/components/Separator';
9
15
  import * as messages from '@/paraglide/messages';
10
16
 
@@ -140,13 +146,17 @@ export const SidebarContent: Component<ComponentProps<'div'>> = (props) => {
140
146
  data-slot='sidebar-content'
141
147
  data-sidebar='content'
142
148
  id={typeof local.id === 'string' ? local.id : 'sidebar-content'}
143
- class={cn(
144
- 'gap-0 min-h-0 flex flex-1 flex-col group-data-[collapsible=icon]:overflow-hidden',
145
- local.class,
146
- )}
149
+ class={cn('min-h-0 flex flex-1 flex-col', local.class)}
147
150
  {...others}
148
151
  >
149
- {local.children}
152
+ <ScrollAreaViewport class='h-full'>
153
+ <ScrollAreaContent class='gap-0 flex min-h-full flex-col group-data-[collapsible=icon]:overflow-hidden'>
154
+ {local.children}
155
+ </ScrollAreaContent>
156
+ </ScrollAreaViewport>
157
+ <ScrollAreaScrollbar orientation='vertical'>
158
+ <ScrollAreaThumb />
159
+ </ScrollAreaScrollbar>
150
160
  </ScrollArea>
151
161
  );
152
162
  };
@@ -170,7 +180,7 @@ export const SidebarGroupLabel: Component<ComponentProps<'div'>> = (props) => {
170
180
  data-slot='sidebar-group-label'
171
181
  data-sidebar='group-label'
172
182
  class={cn(
173
- 'h-8 px-2 text-xs font-medium group-data-[collapsible=icon]:-mt-8 [&>svg]:size-4 flex shrink-0 items-center rounded-md font-heading text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:shrink-0',
183
+ 'h-8 px-2 text-xs group-data-[collapsible=icon]:-mt-8 [&>svg]:size-4 flex shrink-0 items-center rounded-md text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:shrink-0',
174
184
  local.class,
175
185
  )}
176
186
  {...others}
package/src/theme.css CHANGED
@@ -1,7 +1,10 @@
1
1
  @import 'tw-animate-css';
2
- @import '@fontsource/rajdhani';
3
- @import '@fontsource-variable/google-sans-flex/index.css';
4
2
  @import '@fontsource/chakra-petch/500';
3
+ @import '@fontsource/rajdhani/400';
4
+ @import '@fontsource/rajdhani/500';
5
+ @import '@fontsource/rajdhani/600';
6
+ @import '@fontsource/rajdhani/700';
7
+ @import '@fontsource-variable/google-sans-flex';
5
8
  @import './components/marquee/marquee.css';
6
9
  @import './components/toaster/toaster.css';
7
10
 
@@ -82,8 +85,8 @@
82
85
  'Google Sans Flex Variable', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji',
83
86
  'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
84
87
  --font-heading:
85
- 'Rajdhani', 'Google Sans Flex Variable', ui-sans-serif, system-ui, sans-serif,
86
- 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
88
+ 'Rajdhani', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
89
+ 'Segoe UI Symbol', 'Noto Color Emoji';
87
90
  --font-branding:
88
91
  'Chakra Petch', 'Google Sans Flex Variable', ui-sans-serif, system-ui, sans-serif,
89
92
  'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';