styled-hairomin 0.2.2 → 0.2.4

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/README.md CHANGED
@@ -1 +1,5 @@
1
- npm install styled-hairomin
1
+ Install package dengan perintah berikut:
2
+ npm install styled-hairomin
3
+
4
+ atau pakai yarn:
5
+ yarn add styled-hairomin
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import styled from "styled-components";
4
+ import Link from "next/link";
4
5
  import {
5
6
  FaHome,
6
7
  FaBed,
@@ -31,6 +32,24 @@ const variantStyles = {
31
32
  },
32
33
  };
33
34
 
35
+ // Default icons mapping
36
+ const defaultIcons = {
37
+ header: <FaHome />,
38
+ card: <FaBed />,
39
+ button: <FaConciergeBell />,
40
+ footer: <FaInfoCircle />,
41
+ sidebar: <FaUser />,
42
+ };
43
+
44
+ // Default items fallback
45
+ const defaultItems = [
46
+ { name: "Header", href: "#", icon: <FaHome /> },
47
+ { name: "Card", href: "#", icon: <FaBed /> },
48
+ { name: "Button", href: "#", icon: <FaConciergeBell /> },
49
+ { name: "Footer", href: "#", icon: <FaInfoCircle /> },
50
+ { name: "Sidebar", href: "#", icon: <FaUser /> },
51
+ ];
52
+
34
53
  const CompactSidebar = styled.aside`
35
54
  font-family: "Inter", sans-serif;
36
55
  background: ${variantStyles.compact.background};
@@ -68,7 +87,65 @@ const CompactTitle = styled.div`
68
87
  }
69
88
  `;
70
89
 
71
- const CompactItem = styled.button`
90
+ const CompactItemLink = styled(Link)`
91
+ width: 50px;
92
+ height: 50px;
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ background: none;
97
+ border: none;
98
+ color: inherit;
99
+ border-radius: 12px;
100
+ cursor: pointer;
101
+ transition: all 0.3s ease;
102
+ position: relative;
103
+ text-decoration: none;
104
+
105
+ svg {
106
+ font-size: 22px;
107
+ }
108
+
109
+ &:hover {
110
+ background: ${variantStyles.compact.hover};
111
+ transform: scale(1.1);
112
+ }
113
+
114
+ &::after {
115
+ content: attr(data-label);
116
+ position: absolute;
117
+ left: 70px;
118
+ background: #2c3e50;
119
+ color: white;
120
+ padding: 0.5rem 1rem;
121
+ border-radius: 6px;
122
+ font-size: 14px;
123
+ white-space: nowrap;
124
+ opacity: 0;
125
+ pointer-events: none;
126
+ transition: opacity 0.3s;
127
+ z-index: 1000;
128
+ }
129
+
130
+ &:hover::after {
131
+ opacity: 1;
132
+ }
133
+
134
+ @media (max-width: 768px) {
135
+ width: 40px;
136
+ height: 40px;
137
+
138
+ svg {
139
+ font-size: 18px;
140
+ }
141
+
142
+ &::after {
143
+ display: none;
144
+ }
145
+ }
146
+ `;
147
+
148
+ const CompactItemButton = styled.button`
72
149
  width: 50px;
73
150
  height: 50px;
74
151
  display: flex;
@@ -169,7 +246,47 @@ const SectionLabel = styled.div`
169
246
  font-weight: 700;
170
247
  `;
171
248
 
172
- const ExpandedItem = styled.button`
249
+ const ExpandedItemLink = styled(Link)`
250
+ width: 100%;
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: space-between;
254
+ padding: 0.9rem 1.2rem;
255
+ background: none;
256
+ border: none;
257
+ color: inherit;
258
+ border-radius: 12px;
259
+ cursor: pointer;
260
+ transition: all 0.3s ease;
261
+ font-size: 15px;
262
+ font-weight: 500;
263
+ position: relative;
264
+ overflow: hidden;
265
+ text-decoration: none;
266
+
267
+ &::before {
268
+ content: "";
269
+ position: absolute;
270
+ left: 0;
271
+ top: 0;
272
+ height: 100%;
273
+ width: 4px;
274
+ background: linear-gradient(135deg, #667eea, #764ba2);
275
+ opacity: 0;
276
+ transition: opacity 0.3s;
277
+ }
278
+
279
+ &:hover::before {
280
+ opacity: 1;
281
+ }
282
+
283
+ &:hover {
284
+ background: ${variantStyles.expanded.hover};
285
+ transform: translateX(5px);
286
+ }
287
+ `;
288
+
289
+ const ExpandedItemButton = styled.button`
173
290
  width: 100%;
174
291
  display: flex;
175
292
  align-items: center;
@@ -248,7 +365,45 @@ const FloatingTitle = styled.h3`
248
365
  color: #2c3e50;
249
366
  `;
250
367
 
251
- const FloatingItem = styled.button`
368
+ const FloatingItemLink = styled(Link)`
369
+ width: 100%;
370
+ display: flex;
371
+ align-items: center;
372
+ gap: 1rem;
373
+ padding: 1rem 1.2rem;
374
+ background: none;
375
+ border: none;
376
+ color: inherit;
377
+ border-radius: 14px;
378
+ cursor: pointer;
379
+ transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
380
+ font-size: 15px;
381
+ font-weight: 600;
382
+ text-decoration: none;
383
+
384
+ svg {
385
+ font-size: 20px;
386
+ padding: 8px;
387
+ background: linear-gradient(135deg, #667eea20, #764ba220);
388
+ border-radius: 10px;
389
+ color: #667eea;
390
+ transition: all 0.3s;
391
+ }
392
+
393
+ &:hover {
394
+ background: ${variantStyles.floating.hover};
395
+ transform: scale(1.05);
396
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
397
+ }
398
+
399
+ &:hover svg {
400
+ background: linear-gradient(135deg, #667eea, #764ba2);
401
+ color: white;
402
+ transform: rotate(10deg);
403
+ }
404
+ `;
405
+
406
+ const FloatingItemButton = styled.button`
252
407
  width: 100%;
253
408
  display: flex;
254
409
  align-items: center;
@@ -285,50 +440,134 @@ const FloatingItem = styled.button`
285
440
  }
286
441
  `;
287
442
 
288
- export default function SidebarVariant({ variant = "compact", onSelect }) {
289
- const items = [
290
- { name: "Header", icon: <FaHome /> },
291
- { name: "Card", icon: <FaBed /> },
292
- { name: "Button", icon: <FaConciergeBell /> },
293
- { name: "Footer", icon: <FaInfoCircle /> },
294
- { name: "Sidebar", icon: <FaUser /> },
295
- ];
443
+ // Helper function to get icon for an item
444
+ const getItemIcon = (item) => {
445
+ if (item.icon) return item.icon;
446
+ const name = (item.name || item.label || "").toLowerCase();
447
+ return defaultIcons[name] || <FaHome />;
448
+ };
449
+
450
+ // Helper function to get item display name
451
+ const getItemName = (item) => {
452
+ return item.name || item.label || "Menu";
453
+ };
454
+
455
+ export default function SidebarVariant({ variant = "compact", items, onSelect, title }) {
456
+ // Use provided items or fallback to defaults
457
+ const menuItems = items && items.length > 0 ? items : defaultItems;
458
+
459
+ // Get title based on variant or use custom title
460
+ const sidebarTitle = title || variantStyles[variant]?.title || "Menu";
461
+
462
+ const renderCompactItem = (item, index) => {
463
+ const icon = getItemIcon(item);
464
+ const name = getItemName(item);
465
+ const hasHref = item.href && item.href !== "";
466
+
467
+ if (hasHref) {
468
+ return (
469
+ <CompactItemLink
470
+ key={item.name || item.label || index}
471
+ href={item.href}
472
+ data-label={name}
473
+ onClick={() => onSelect?.(name.toLowerCase())}
474
+ >
475
+ {icon}
476
+ </CompactItemLink>
477
+ );
478
+ }
479
+
480
+ return (
481
+ <CompactItemButton
482
+ key={item.name || item.label || index}
483
+ data-label={name}
484
+ onClick={() => onSelect?.(name.toLowerCase())}
485
+ >
486
+ {icon}
487
+ </CompactItemButton>
488
+ );
489
+ };
490
+
491
+ const renderExpandedItem = (item, index) => {
492
+ const icon = getItemIcon(item);
493
+ const name = getItemName(item);
494
+ const hasHref = item.href && item.href !== "";
495
+
496
+ if (hasHref) {
497
+ return (
498
+ <ExpandedItemLink
499
+ key={item.name || item.label || index}
500
+ href={item.href}
501
+ onClick={() => onSelect?.(name.toLowerCase())}
502
+ >
503
+ <ItemLeft>
504
+ {icon}
505
+ <span>{name}</span>
506
+ </ItemLeft>
507
+ <FaChevronRight size={14} style={{ opacity: 0.5 }} />
508
+ </ExpandedItemLink>
509
+ );
510
+ }
511
+
512
+ return (
513
+ <ExpandedItemButton
514
+ key={item.name || item.label || index}
515
+ onClick={() => onSelect?.(name.toLowerCase())}
516
+ >
517
+ <ItemLeft>
518
+ {icon}
519
+ <span>{name}</span>
520
+ </ItemLeft>
521
+ <FaChevronRight size={14} style={{ opacity: 0.5 }} />
522
+ </ExpandedItemButton>
523
+ );
524
+ };
525
+
526
+ const renderFloatingItem = (item, index) => {
527
+ const icon = getItemIcon(item);
528
+ const name = getItemName(item);
529
+ const hasHref = item.href && item.href !== "";
530
+
531
+ if (hasHref) {
532
+ return (
533
+ <FloatingItemLink
534
+ key={item.name || item.label || index}
535
+ href={item.href}
536
+ onClick={() => onSelect?.(name.toLowerCase())}
537
+ >
538
+ {icon}
539
+ <span>{name}</span>
540
+ </FloatingItemLink>
541
+ );
542
+ }
543
+
544
+ return (
545
+ <FloatingItemButton
546
+ key={item.name || item.label || index}
547
+ onClick={() => onSelect?.(name.toLowerCase())}
548
+ >
549
+ {icon}
550
+ <span>{name}</span>
551
+ </FloatingItemButton>
552
+ );
553
+ };
296
554
 
297
555
  switch (variant) {
298
556
  case "compact":
299
557
  return (
300
558
  <CompactSidebar>
301
- <CompactTitle>{variantStyles.compact.title}</CompactTitle>
302
- {items.map((item) => (
303
- <CompactItem
304
- key={item.name}
305
- data-label={item.name}
306
- onClick={() => onSelect?.(item.name.toLowerCase())}
307
- >
308
- {item.icon}
309
- </CompactItem>
310
- ))}
559
+ <CompactTitle>{sidebarTitle}</CompactTitle>
560
+ {menuItems.map((item, index) => renderCompactItem(item, index))}
311
561
  </CompactSidebar>
312
562
  );
313
563
 
314
564
  case "expanded":
315
565
  return (
316
566
  <ExpandedSidebar>
317
- <ExpandedTitle>{variantStyles.expanded.title}</ExpandedTitle>
567
+ <ExpandedTitle>{sidebarTitle}</ExpandedTitle>
318
568
  <ExpandedSection>
319
569
  <SectionLabel>Components</SectionLabel>
320
- {items.map((item) => (
321
- <ExpandedItem
322
- key={item.name}
323
- onClick={() => onSelect?.(item.name.toLowerCase())}
324
- >
325
- <ItemLeft>
326
- {item.icon}
327
- <span>{item.name}</span>
328
- </ItemLeft>
329
- <FaChevronRight size={14} style={{ opacity: 0.5 }} />
330
- </ExpandedItem>
331
- ))}
570
+ {menuItems.map((item, index) => renderExpandedItem(item, index))}
332
571
  </ExpandedSection>
333
572
  </ExpandedSidebar>
334
573
  );
@@ -336,16 +575,8 @@ export default function SidebarVariant({ variant = "compact", onSelect }) {
336
575
  case "floating":
337
576
  return (
338
577
  <FloatingSidebar>
339
- <FloatingTitle>{variantStyles.floating.title}</FloatingTitle>
340
- {items.map((item) => (
341
- <FloatingItem
342
- key={item.name}
343
- onClick={() => onSelect?.(item.name.toLowerCase())}
344
- >
345
- {item.icon}
346
- <span>{item.name}</span>
347
- </FloatingItem>
348
- ))}
578
+ <FloatingTitle>{sidebarTitle}</FloatingTitle>
579
+ {menuItems.map((item, index) => renderFloatingItem(item, index))}
349
580
  </FloatingSidebar>
350
581
  );
351
582
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "styled-hairomin",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  ".": {