ab-nextjs-components 0.1.2 → 0.1.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.
Files changed (112) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +60 -14
  3. package/ab-avatar/index.tsx +90 -0
  4. package/ab-avatar/styles.module.css +62 -0
  5. package/ab-balloon/index.tsx +55 -0
  6. package/ab-balloon/styles.module.css +12 -0
  7. package/ab-brand/index.tsx +88 -0
  8. package/ab-brand/styles.module.css +54 -0
  9. package/ab-button/index.tsx +164 -0
  10. package/ab-button/styles.module.css +63 -0
  11. package/ab-collapsible/index.tsx +188 -0
  12. package/ab-collapsible/styles.module.css +98 -0
  13. package/ab-color/index.tsx +84 -0
  14. package/ab-color/styles.module.css +51 -0
  15. package/ab-demo-box/index.tsx +38 -0
  16. package/ab-demo-box/styles.module.css +13 -0
  17. package/ab-demo-code/index.tsx +62 -0
  18. package/ab-demo-code/styles.module.css +41 -0
  19. package/ab-icon/index.tsx +63 -0
  20. package/ab-icon/styles.module.css +27 -0
  21. package/ab-icon-button/index.tsx +107 -0
  22. package/ab-icon-button/styles.module.css +64 -0
  23. package/ab-image/index.tsx +83 -0
  24. package/ab-image/styles.module.css +27 -0
  25. package/ab-info/index.tsx +89 -0
  26. package/ab-info/styles.module.css +87 -0
  27. package/ab-input/index.tsx +277 -0
  28. package/ab-input/styles.module.css +101 -0
  29. package/ab-key-feature/index.tsx +60 -0
  30. package/ab-key-feature/styles.module.css +47 -0
  31. package/ab-like-button/index.tsx +116 -0
  32. package/ab-like-button/styles.module.css +60 -0
  33. package/ab-logo/index.tsx +94 -0
  34. package/ab-logo/styles.module.css +30 -0
  35. package/ab-main-headline/index.tsx +57 -0
  36. package/ab-main-headline/styles.module.css +24 -0
  37. package/ab-menu/index.tsx +119 -0
  38. package/ab-menu/styles.module.css +99 -0
  39. package/ab-name/index.tsx +49 -0
  40. package/ab-name/styles.module.css +14 -0
  41. package/ab-navbar/index.tsx +68 -0
  42. package/ab-navbar/styles.module.css +35 -0
  43. package/ab-page-paginator/index.tsx +130 -0
  44. package/ab-page-paginator/styles.module.css +47 -0
  45. package/ab-page-switcher/index.tsx +121 -0
  46. package/ab-page-switcher/styles.module.css +37 -0
  47. package/ab-preview/index.tsx +78 -0
  48. package/ab-preview/styles.module.css +26 -0
  49. package/ab-price/index.tsx +109 -0
  50. package/ab-price/styles.module.css +36 -0
  51. package/ab-price-tag/index.tsx +70 -0
  52. package/ab-price-tag/styles.module.css +81 -0
  53. package/ab-product/index.tsx +128 -0
  54. package/ab-product/styles.module.css +44 -0
  55. package/ab-product-item/index.tsx +78 -0
  56. package/ab-product-item/styles.module.css +21 -0
  57. package/ab-progress-chips/index.tsx +105 -0
  58. package/ab-progress-chips/styles.module.css +43 -0
  59. package/ab-search-result/index.tsx +79 -0
  60. package/ab-search-result/styles.module.css +48 -0
  61. package/ab-searchbar/index.tsx +150 -0
  62. package/ab-searchbar/styles.module.css +77 -0
  63. package/ab-sidebar/index.tsx +72 -0
  64. package/ab-sidebar/styles.module.css +41 -0
  65. package/ab-switch-back/index.tsx +72 -0
  66. package/ab-switch-back/styles.module.css +45 -0
  67. package/ab-tab/index.tsx +101 -0
  68. package/ab-tab/styles.module.css +65 -0
  69. package/ab-tabs/index.tsx +45 -0
  70. package/ab-tabs/styles.module.css +17 -0
  71. package/ab-test-hello/index.tsx +37 -0
  72. package/ab-test-hello/styles.module.css +25 -0
  73. package/ab-text/index.tsx +36 -0
  74. package/ab-text/styles.module.css +3 -0
  75. package/index.ts +117 -0
  76. package/package.json +152 -7
  77. package/server/ab-avatar/index.tsx +85 -0
  78. package/server/ab-avatar/styles.module.css +62 -0
  79. package/server/ab-badge/index.tsx +66 -0
  80. package/server/ab-badge/styles.module.css +39 -0
  81. package/server/ab-brand/index.tsx +87 -0
  82. package/server/ab-brand/styles.module.css +54 -0
  83. package/server/ab-button/index.tsx +144 -0
  84. package/server/ab-button/styles.module.css +63 -0
  85. package/server/ab-icon/index.tsx +61 -0
  86. package/server/ab-icon/styles.module.css +27 -0
  87. package/server/ab-key-feature/index.tsx +59 -0
  88. package/server/ab-key-feature/styles.module.css +47 -0
  89. package/server/ab-logo/index.tsx +93 -0
  90. package/server/ab-logo/styles.module.css +30 -0
  91. package/server/ab-name/index.tsx +48 -0
  92. package/server/ab-name/styles.module.css +14 -0
  93. package/server/ab-nav-link/index.tsx +60 -0
  94. package/server/ab-nav-link/styles.module.css +32 -0
  95. package/server/ab-navbar/index.tsx +64 -0
  96. package/server/ab-navbar/styles.module.css +35 -0
  97. package/server/ab-polygon/index.tsx +45 -0
  98. package/server/ab-polygon/styles.module.css +11 -0
  99. package/server/ab-sidebar/index.tsx +68 -0
  100. package/server/ab-sidebar/styles.module.css +41 -0
  101. package/server/ab-switch-back/index.tsx +71 -0
  102. package/server/ab-switch-back/styles.module.css +45 -0
  103. package/server/ab-test-hello/index.tsx +35 -0
  104. package/server/ab-test-hello/styles.module.css +22 -0
  105. package/server/ab-text/index.tsx +33 -0
  106. package/server/ab-text/styles.module.css +3 -0
  107. package/server/index.ts +27 -0
  108. package/types/index.d.ts +54 -0
  109. package/.github/ab-logo-dark.svg +0 -12
  110. package/.github/ab-logo-light.svg +0 -9
  111. package/.github/nextjs-logoname-dark.svg +0 -28
  112. package/.github/nextjs-logoname-light.svg +0 -25
@@ -0,0 +1,27 @@
1
+ /*
2
+ * @license MIT
3
+ * ~~~~~~~~~~~~
4
+ * ab-nextjs-components
5
+ * ~~~~~~~~~~~~
6
+ * Copyright (c) 2026 Abraham Ukachi. The abElements Project.
7
+ * Plain CSS modules — no Tailwind Tailwind apply (Turbopack-safe).
8
+ */
9
+
10
+ /*
11
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12
+ * MOTTO: We'll always do more 😜!!!
13
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
14
+ */
15
+
16
+ .abIcon {
17
+ display: inline-flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
21
+ line-height: 1;
22
+ user-select: none;
23
+ }
24
+
25
+ .abIcon[data-filled='true'] {
26
+ font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
27
+ }
@@ -0,0 +1,107 @@
1
+ /*
2
+ * @license MIT
3
+ * ~~~~~~~~~~~~
4
+ * ab-nextjs-components
5
+ * ~~~~~~~~~~~~
6
+ * Copyright (c) 2026 Abraham Ukachi. The abElements Project.
7
+ *
8
+ * @project: ab-nextjs-components
9
+ * @name: AbIconButton - Client
10
+ * @file: ab-icon-button/index.tsx
11
+ */
12
+
13
+ 'use client';
14
+
15
+ import type { CSSProperties, MouseEvent } from 'react';
16
+ import { forwardRef } from 'react';
17
+ import clsx from 'clsx';
18
+ import styles from './styles.module.css';
19
+
20
+ export interface AbIconButtonProps {
21
+ className?: string;
22
+ style?: CSSProperties;
23
+ hidden?: boolean;
24
+ icon: string;
25
+ disabled?: boolean;
26
+ expands?: boolean;
27
+ shrinks?: boolean;
28
+ tabIndex?: number;
29
+ onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
30
+ href?: string;
31
+ active?: boolean;
32
+ naked?: boolean;
33
+ isLoading?: boolean;
34
+ title?: string;
35
+ type?: 'button' | 'submit' | 'reset';
36
+ }
37
+
38
+ const AbIconButton = forwardRef<HTMLButtonElement, AbIconButtonProps>(function AbIconButton(props, ref) {
39
+ const {
40
+ className,
41
+ style,
42
+ hidden = false,
43
+ icon,
44
+ disabled = false,
45
+ expands = false,
46
+ shrinks = false,
47
+ tabIndex,
48
+ onClick,
49
+ href,
50
+ active = false,
51
+ naked = false,
52
+ isLoading = false,
53
+ title,
54
+ type = 'button',
55
+ } = props;
56
+
57
+ const classNames = clsx('AbIconButton', 'icon-button', styles.abIconButton, className);
58
+
59
+ if (href && !isLoading) {
60
+ return (
61
+ <span hidden={hidden} className={styles.wrap} title={title}>
62
+ <a
63
+ href={disabled ? undefined : href}
64
+ role="button"
65
+ className={classNames}
66
+ style={style}
67
+ data-active={String(active)}
68
+ data-naked={String(naked)}
69
+ data-expands={String(expands)}
70
+ data-shrinks={String(shrinks)}
71
+ tabIndex={tabIndex ?? 0}
72
+ aria-disabled={disabled}
73
+ >
74
+ <span className={clsx('material-symbols-rounded', 'icon')}>{icon}</span>
75
+ </a>
76
+ </span>
77
+ );
78
+ }
79
+
80
+ return (
81
+ <span hidden={hidden} className={styles.wrap} title={title}>
82
+ <button
83
+ ref={ref}
84
+ type={type}
85
+ className={classNames}
86
+ style={style}
87
+ disabled={disabled || isLoading}
88
+ data-active={String(active)}
89
+ data-naked={String(naked)}
90
+ data-expands={String(expands)}
91
+ data-shrinks={String(shrinks)}
92
+ onClick={onClick}
93
+ tabIndex={tabIndex ?? 0}
94
+ aria-label={title}
95
+ >
96
+ {isLoading ? (
97
+ <span className={clsx('spinner', 'dots-12', styles.spinner)} />
98
+ ) : (
99
+ <span className={clsx('material-symbols-rounded', 'icon')}>{icon}</span>
100
+ )}
101
+ </button>
102
+ </span>
103
+ );
104
+ });
105
+
106
+ export default AbIconButton;
107
+ export { AbIconButton };
@@ -0,0 +1,64 @@
1
+ /*
2
+ * @license MIT
3
+ * ~~~~~~~~~~~~
4
+ * ab-nextjs-components
5
+ * Plain CSS modules — no Tailwind Tailwind apply (Turbopack-safe).
6
+ */
7
+
8
+ /*
9
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10
+ * MOTTO: We'll always do more 😜!!!
11
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12
+ */
13
+
14
+ .wrap {
15
+ display: inline-block;
16
+ width: fit-content;
17
+ height: fit-content;
18
+ }
19
+
20
+ .abIconButton {
21
+ position: relative;
22
+ display: inline-flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ width: fit-content;
26
+ height: fit-content;
27
+ padding: 0.5rem;
28
+ margin: 0;
29
+ border: none;
30
+ border-radius: 9999px;
31
+ overflow: hidden;
32
+ text-decoration: none;
33
+ cursor: pointer;
34
+ background: transparent;
35
+ color: inherit;
36
+ transition: background-color 0.2s ease, transform 0.2s ease;
37
+ }
38
+
39
+ .abIconButton:hover {
40
+ background-color: color-mix(in srgb, currentColor 10%, transparent);
41
+ }
42
+
43
+ .abIconButton[data-naked='true']:hover {
44
+ background-color: transparent;
45
+ }
46
+
47
+ .abIconButton[data-expands='true']:hover {
48
+ transform: scale(1.06);
49
+ }
50
+
51
+ .abIconButton[data-shrinks='true']:active {
52
+ transform: scale(0.94);
53
+ }
54
+
55
+ .abIconButton:disabled {
56
+ opacity: 0.5;
57
+ cursor: not-allowed;
58
+ }
59
+
60
+ .spinner {
61
+ display: inline-block;
62
+ width: 1.25rem;
63
+ height: 1.25rem;
64
+ }
@@ -0,0 +1,83 @@
1
+ /*
2
+ * @license MIT
3
+ * ~~~~~~~~~~~~
4
+ * ab-nextjs-components
5
+ * ~~~~~~~~~~~~
6
+ * Copyright (c) 2026 Abraham Ukachi. The abElements Project.
7
+ *
8
+ * @project: ab-nextjs-components
9
+ * @name: AbImage - Client (Adapt of lyd-image — Dexie/offline stripped)
10
+ * @file: ab-image/index.tsx
11
+ */
12
+
13
+ 'use client';
14
+
15
+ import type { CSSProperties, ReactElement } from 'react';
16
+ import { useState } from 'react';
17
+ import Image from 'next/image';
18
+ import clsx from 'clsx';
19
+ import styles from './styles.module.css';
20
+
21
+ export interface AbImageProps {
22
+ className?: string;
23
+ style?: CSSProperties;
24
+ hidden?: boolean;
25
+ src: string;
26
+ alt?: string;
27
+ width?: number;
28
+ height?: number;
29
+ fill?: boolean;
30
+ priority?: boolean;
31
+ sizes?: string;
32
+ fallbackSrc?: string | null;
33
+ unoptimized?: boolean;
34
+ }
35
+
36
+ const AbImage = ({
37
+ className,
38
+ style,
39
+ hidden = false,
40
+ src,
41
+ alt = '',
42
+ width = 320,
43
+ height = 320,
44
+ fill = false,
45
+ priority = false,
46
+ sizes,
47
+ fallbackSrc = null,
48
+ unoptimized = false,
49
+ }: AbImageProps): ReactElement => {
50
+ const [failed, setFailed] = useState(false);
51
+ const activeSrc = failed && fallbackSrc ? fallbackSrc : src;
52
+
53
+ if (failed && !fallbackSrc) {
54
+ return (
55
+ <div hidden={hidden} style={style} className={clsx('AbImage', styles.abImage, className)}>
56
+ <div className={styles.abImageFallback} role="img" aria-label={alt || 'Image unavailable'}>
57
+ <span className="material-symbols-rounded" aria-hidden>broken_image</span>
58
+ </div>
59
+ </div>
60
+ );
61
+ }
62
+
63
+ return (
64
+ <div hidden={hidden} style={style} className={clsx('AbImage', styles.abImage, className)}>
65
+ <Image
66
+ className={styles.abImageImg}
67
+ src={activeSrc}
68
+ alt={alt}
69
+ width={fill ? undefined : width}
70
+ height={fill ? undefined : height}
71
+ fill={fill}
72
+ priority={priority}
73
+ sizes={sizes}
74
+ unoptimized={unoptimized}
75
+ onError={() => setFailed(true)}
76
+ />
77
+ </div>
78
+ );
79
+ };
80
+
81
+ export default AbImage;
82
+ export { AbImage };
83
+
@@ -0,0 +1,27 @@
1
+ .abImage {
2
+ position: relative;
3
+ display: flex;
4
+ width: 100%;
5
+ height: 100%;
6
+ align-items: center;
7
+ justify-content: center;
8
+ background-repeat: no-repeat;
9
+ background-size: contain;
10
+ background-position: center;
11
+ overflow: hidden;
12
+ }
13
+ .abImageImg {
14
+ object-fit: contain;
15
+ max-width: 100%;
16
+ max-height: 100%;
17
+ }
18
+ .abImageFallback {
19
+ width: 100%;
20
+ height: 100%;
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ opacity: 0.45;
25
+ font-size: 0.875rem;
26
+ }
27
+
@@ -0,0 +1,89 @@
1
+ /*
2
+ * @license MIT
3
+ * ~~~~~~~~~~~~
4
+ * ab-nextjs-components
5
+ * ~~~~~~~~~~~~
6
+ * Copyright (c) 2026 Abraham Ukachi. The abElements Project.
7
+ *
8
+ * @project: ab-nextjs-components
9
+ * @name: AbInfo - Client (port of lyd-info)
10
+ * @file: ab-info/index.tsx
11
+ */
12
+
13
+ 'use client';
14
+
15
+ import type { ReactElement } from 'react';
16
+ import Link from 'next/link';
17
+ import clsx from 'clsx';
18
+ import styles from './styles.module.css';
19
+
20
+ export interface AbInfoProps {
21
+ className?: string;
22
+ hidden?: boolean;
23
+ color?: 'primary' | 'secondary' | 'tertiary' | 'white' | 'black';
24
+ icon: string;
25
+ title: string;
26
+ message: string;
27
+ closeLabel?: string;
28
+ actionLabel?: string;
29
+ actionHref?: string | null;
30
+ onActionClick?: () => void;
31
+ onCloseClick?: () => void;
32
+ }
33
+
34
+ const AbInfo = ({
35
+ className,
36
+ hidden = false,
37
+ color = 'primary',
38
+ icon,
39
+ title,
40
+ message,
41
+ closeLabel = 'Close',
42
+ actionLabel,
43
+ actionHref = null,
44
+ onActionClick,
45
+ onCloseClick,
46
+ }: AbInfoProps): ReactElement => {
47
+ return (
48
+ <div
49
+ hidden={hidden}
50
+ data-color={color}
51
+ className={clsx('AbInfo', styles.abInfo, styles[`color_${color}`], className)}
52
+ role="status"
53
+ >
54
+ <span className={styles.abInfoIconWrap} aria-hidden>
55
+ <span className={clsx('material-symbols-rounded', styles.abInfoIcon)}>{icon}</span>
56
+ </span>
57
+ <div className={styles.abInfoContent}>
58
+ <p className={styles.abInfoTitle}>{title}</p>
59
+ <p className={styles.abInfoMessage}>{message}</p>
60
+ {actionLabel ? (
61
+ actionHref ? (
62
+ <Link href={actionHref} className={styles.abInfoAction} onClick={onActionClick}>
63
+ {actionLabel}
64
+ </Link>
65
+ ) : (
66
+ <button type="button" className={styles.abInfoAction} onClick={onActionClick}>
67
+ {actionLabel}
68
+ </button>
69
+ )
70
+ ) : null}
71
+ </div>
72
+ {onCloseClick ? (
73
+ <button
74
+ type="button"
75
+ className={styles.abInfoClose}
76
+ aria-label={closeLabel}
77
+ onClick={onCloseClick}
78
+ >
79
+ <span className="material-symbols-rounded" aria-hidden>
80
+ close
81
+ </span>
82
+ </button>
83
+ ) : null}
84
+ </div>
85
+ );
86
+ };
87
+
88
+ export default AbInfo;
89
+ export { AbInfo };
@@ -0,0 +1,87 @@
1
+ .abInfo {
2
+ position: relative;
3
+ display: flex;
4
+ flex-direction: row;
5
+ align-items: flex-start;
6
+ gap: 0.75rem;
7
+ width: 100%;
8
+ padding: 1rem;
9
+ border-radius: 0.75rem;
10
+ background: var(--ab-surface-container-high, #ece6f0);
11
+ color: var(--ab-on-surface, #1c1b1f);
12
+ }
13
+
14
+ .abInfoIconWrap {
15
+ display: flex;
16
+ flex-shrink: 0;
17
+ align-items: center;
18
+ justify-content: center;
19
+ width: 3rem;
20
+ height: 3rem;
21
+ border-radius: 9999px;
22
+ }
23
+
24
+ .abInfoIcon {
25
+ font-size: 1.5rem;
26
+ line-height: 1;
27
+ }
28
+
29
+ .color_primary .abInfoIconWrap {
30
+ background: color-mix(in srgb, var(--ab-primary, #a67c52) 24%, transparent);
31
+ color: var(--ab-primary, #a67c52);
32
+ }
33
+ .color_secondary .abInfoIconWrap {
34
+ background: color-mix(in srgb, #625b71 24%, transparent);
35
+ color: #625b71;
36
+ }
37
+ .color_tertiary .abInfoIconWrap {
38
+ background: color-mix(in srgb, #7d5260 24%, transparent);
39
+ color: #7d5260;
40
+ }
41
+ .color_white .abInfoIconWrap { background: #fff; color: #1c1b1f; }
42
+ .color_black .abInfoIconWrap { background: #1c1b1f; color: #fff; }
43
+
44
+ .abInfoContent {
45
+ display: flex;
46
+ flex: 1;
47
+ flex-direction: column;
48
+ gap: 0.25rem;
49
+ min-width: 0;
50
+ }
51
+
52
+ .abInfoTitle {
53
+ margin: 0;
54
+ font-weight: 700;
55
+ }
56
+
57
+ .abInfoMessage {
58
+ margin: 0;
59
+ font-size: 0.875rem;
60
+ opacity: 0.85;
61
+ }
62
+
63
+ .abInfoAction {
64
+ align-self: flex-start;
65
+ margin-top: 0.5rem;
66
+ padding: 0;
67
+ border: none;
68
+ background: none;
69
+ color: var(--ab-primary, #a67c52);
70
+ font: inherit;
71
+ font-weight: 600;
72
+ text-decoration: none;
73
+ cursor: pointer;
74
+ }
75
+
76
+ .abInfoClose {
77
+ display: inline-flex;
78
+ flex-shrink: 0;
79
+ align-items: center;
80
+ justify-content: center;
81
+ padding: 0.25rem;
82
+ border: none;
83
+ border-radius: 9999px;
84
+ background: transparent;
85
+ color: inherit;
86
+ cursor: pointer;
87
+ }