@oalacea/chaosui 0.4.0 → 0.5.1

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 (178) hide show
  1. package/buttons/cta-brutal/css/cta-brutal.module.css +175 -0
  2. package/buttons/cta-brutal/css/index.tsx +78 -0
  3. package/buttons/cta-brutal/tailwind/index.tsx +85 -0
  4. package/buttons/dead-button/css/dead-button.module.css +216 -0
  5. package/buttons/dead-button/css/index.tsx +47 -0
  6. package/buttons/dead-button/tailwind/index.tsx +90 -0
  7. package/buttons/deeper-button/css/deeper-button.module.css +141 -0
  8. package/buttons/deeper-button/css/index.tsx +62 -0
  9. package/buttons/deeper-button/tailwind/index.tsx +78 -0
  10. package/buttons/dual-choice/css/dual-choice.module.css +176 -0
  11. package/buttons/dual-choice/css/index.tsx +56 -0
  12. package/buttons/dual-choice/tailwind/index.tsx +89 -0
  13. package/buttons/tension-bar/css/index.tsx +96 -0
  14. package/buttons/tension-bar/css/tension-bar.module.css +204 -0
  15. package/buttons/tension-bar/tailwind/index.tsx +122 -0
  16. package/decorative/inscription/css/index.tsx +66 -0
  17. package/decorative/inscription/css/inscription.module.css +160 -0
  18. package/decorative/inscription/tailwind/index.tsx +91 -0
  19. package/decorative/ornaments/css/index.tsx +136 -0
  20. package/decorative/ornaments/css/ornaments.module.css +144 -0
  21. package/decorative/ornaments/tailwind/index.tsx +122 -0
  22. package/decorative/rune-symbols/css/index.tsx +116 -0
  23. package/decorative/rune-symbols/css/rune-symbols.module.css +116 -0
  24. package/decorative/rune-symbols/tailwind/index.tsx +108 -0
  25. package/decorative/sheet-music/css/index.tsx +144 -0
  26. package/decorative/sheet-music/css/sheet-music.module.css +152 -0
  27. package/decorative/sheet-music/tailwind/index.tsx +111 -0
  28. package/layout/horizontal-scroll/css/horizontal-scroll.module.css +93 -0
  29. package/layout/horizontal-scroll/css/index.tsx +114 -0
  30. package/layout/horizontal-scroll/tailwind/index.tsx +108 -0
  31. package/layout/spec-grid/css/index.tsx +103 -0
  32. package/layout/spec-grid/css/spec-grid.module.css +125 -0
  33. package/layout/spec-grid/tailwind/index.tsx +91 -0
  34. package/layout/tower-pricing/css/index.tsx +91 -0
  35. package/layout/tower-pricing/css/tower-pricing.module.css +177 -0
  36. package/layout/tower-pricing/tailwind/index.tsx +106 -0
  37. package/layout/tracklist/css/index.tsx +96 -0
  38. package/layout/tracklist/css/tracklist.module.css +141 -0
  39. package/layout/tracklist/tailwind/index.tsx +92 -0
  40. package/layout/void-frame/css/index.tsx +60 -0
  41. package/layout/void-frame/css/void-frame.module.css +141 -0
  42. package/layout/void-frame/tailwind/index.tsx +64 -0
  43. package/navigation/brutal-nav/css/brutal-nav.module.css +178 -0
  44. package/navigation/brutal-nav/css/index.tsx +80 -0
  45. package/navigation/brutal-nav/tailwind/index.tsx +95 -0
  46. package/navigation/progress-dots/css/index.tsx +60 -0
  47. package/navigation/progress-dots/css/progress-dots.module.css +152 -0
  48. package/navigation/progress-dots/tailwind/index.tsx +105 -0
  49. package/navigation/scattered-nav/css/index.tsx +59 -0
  50. package/navigation/scattered-nav/css/scattered-nav.module.css +121 -0
  51. package/navigation/scattered-nav/tailwind/index.tsx +77 -0
  52. package/navigation/scroll-indicator/css/index.tsx +72 -0
  53. package/navigation/scroll-indicator/css/scroll-indicator.module.css +129 -0
  54. package/navigation/scroll-indicator/tailwind/index.tsx +107 -0
  55. package/navigation/vertical-nav/css/index.tsx +69 -0
  56. package/navigation/vertical-nav/css/vertical-nav.module.css +117 -0
  57. package/navigation/vertical-nav/tailwind/index.tsx +91 -0
  58. package/package.json +8 -33
  59. package/text/ascii-art/css/ascii-art.module.css +173 -0
  60. package/text/ascii-art/css/index.tsx +116 -0
  61. package/text/ascii-art/tailwind/index.tsx +124 -0
  62. package/text/blood-drip/css/blood-drip.module.css +142 -0
  63. package/text/blood-drip/css/index.tsx +113 -0
  64. package/text/blood-drip/tailwind/index.tsx +133 -0
  65. package/text/char-glitch/css/char-glitch.module.css +124 -0
  66. package/text/char-glitch/css/index.tsx +153 -0
  67. package/text/char-glitch/tailwind/index.tsx +126 -0
  68. package/text/countdown-display/css/countdown-display.module.css +179 -0
  69. package/text/countdown-display/css/index.tsx +190 -0
  70. package/text/countdown-display/tailwind/index.tsx +155 -0
  71. package/text/giant-layers/css/giant-layers.module.css +156 -0
  72. package/text/giant-layers/css/index.tsx +97 -0
  73. package/text/giant-layers/tailwind/index.tsx +111 -0
  74. package/text/reveal-text/css/index.tsx +180 -0
  75. package/text/reveal-text/css/reveal-text.module.css +129 -0
  76. package/text/reveal-text/tailwind/index.tsx +135 -0
  77. package/text/rotate-text/css/index.tsx +139 -0
  78. package/text/rotate-text/css/rotate-text.module.css +162 -0
  79. package/text/rotate-text/tailwind/index.tsx +127 -0
  80. package/text/strike-reveal/css/index.tsx +124 -0
  81. package/text/strike-reveal/css/strike-reveal.module.css +139 -0
  82. package/text/strike-reveal/tailwind/index.tsx +138 -0
  83. package/text/terminal-output/css/index.tsx +179 -0
  84. package/text/terminal-output/css/terminal-output.module.css +203 -0
  85. package/text/terminal-output/tailwind/index.tsx +174 -0
  86. package/text/typing-text/css/index.tsx +115 -0
  87. package/text/typing-text/css/typing-text.module.css +84 -0
  88. package/text/typing-text/tailwind/index.tsx +126 -0
  89. package/bin/cli.js +0 -278
  90. package/components/backgrounds/light-beams/index.tsx +0 -80
  91. package/components/backgrounds/light-beams/light-beams.module.css +0 -27
  92. package/components/navigation/hexagon-menu/css/hexagon-menu.module.css +0 -55
  93. package/components/navigation/hexagon-menu/css/index.tsx +0 -35
  94. package/components/navigation/hexagon-menu/tailwind/index.tsx +0 -53
  95. /package/{components/backgrounds → backgrounds}/glow-orbs/glow-orbs.module.css +0 -0
  96. /package/{components/backgrounds → backgrounds}/glow-orbs/index.tsx +0 -0
  97. /package/{components/backgrounds → backgrounds}/noise-canvas/index.tsx +0 -0
  98. /package/{components/backgrounds → backgrounds}/noise-canvas/noise-canvas.module.css +0 -0
  99. /package/{components/backgrounds → backgrounds}/particle-field/index.tsx +0 -0
  100. /package/{components/backgrounds → backgrounds}/particle-field/particle-field.module.css +0 -0
  101. /package/{components/buttons → buttons}/chaos-button/chaos-button.module.css +0 -0
  102. /package/{components/buttons → buttons}/chaos-button/index.tsx +0 -0
  103. /package/{components/buttons → buttons}/glitch-button/glitch-button.module.css +0 -0
  104. /package/{components/buttons → buttons}/glitch-button/index.tsx +0 -0
  105. /package/{components/chaos-vars.css → chaos-vars.css} +0 -0
  106. /package/{components/cyber → cyber}/cyber-avatar/css/cyber-avatar.module.css +0 -0
  107. /package/{components/cyber → cyber}/cyber-avatar/css/index.tsx +0 -0
  108. /package/{components/cyber → cyber}/cyber-avatar/tailwind/index.tsx +0 -0
  109. /package/{components/cyber → cyber}/cyber-input/css/cyber-input.module.css +0 -0
  110. /package/{components/cyber → cyber}/cyber-input/css/index.tsx +0 -0
  111. /package/{components/cyber → cyber}/cyber-input/tailwind/index.tsx +0 -0
  112. /package/{components/cyber → cyber}/cyber-loader/css/cyber-loader.module.css +0 -0
  113. /package/{components/cyber → cyber}/cyber-loader/css/index.tsx +0 -0
  114. /package/{components/cyber → cyber}/cyber-loader/tailwind/index.tsx +0 -0
  115. /package/{components/cyber → cyber}/cyber-modal/css/cyber-modal.module.css +0 -0
  116. /package/{components/cyber → cyber}/cyber-modal/css/index.tsx +0 -0
  117. /package/{components/cyber → cyber}/cyber-modal/tailwind/index.tsx +0 -0
  118. /package/{components/cyber → cyber}/cyber-slider/css/cyber-slider.module.css +0 -0
  119. /package/{components/cyber → cyber}/cyber-slider/css/index.tsx +0 -0
  120. /package/{components/cyber → cyber}/cyber-slider/tailwind/index.tsx +0 -0
  121. /package/{components/cyber → cyber}/cyber-tooltip/css/cyber-tooltip.module.css +0 -0
  122. /package/{components/cyber → cyber}/cyber-tooltip/css/index.tsx +0 -0
  123. /package/{components/cyber → cyber}/cyber-tooltip/tailwind/index.tsx +0 -0
  124. /package/{components/effects → effects}/cursor-follower/cursor-follower.module.css +0 -0
  125. /package/{components/effects → effects}/cursor-follower/index.tsx +0 -0
  126. /package/{components/effects → effects}/glitch-image/css/glitch-image.module.css +0 -0
  127. /package/{components/effects → effects}/glitch-image/css/index.tsx +0 -0
  128. /package/{components/effects → effects}/glitch-image/tailwind/index.tsx +0 -0
  129. /package/{components/effects → effects}/glowing-border/css/glowing-border.module.css +0 -0
  130. /package/{components/effects → effects}/glowing-border/css/index.tsx +0 -0
  131. /package/{components/effects → effects}/glowing-border/tailwind/index.tsx +0 -0
  132. /package/{components/effects → effects}/screen-distortion/index.tsx +0 -0
  133. /package/{components/effects → effects}/screen-distortion/screen-distortion.module.css +0 -0
  134. /package/{components/effects → effects}/warning-tape/index.tsx +0 -0
  135. /package/{components/effects → effects}/warning-tape/warning-tape.module.css +0 -0
  136. /package/{components/layout → layout}/data-grid/css/data-grid.module.css +0 -0
  137. /package/{components/layout → layout}/data-grid/css/index.tsx +0 -0
  138. /package/{components/layout → layout}/data-grid/tailwind/index.tsx +0 -0
  139. /package/{components/layout → layout}/hologram-card/css/hologram-card.module.css +0 -0
  140. /package/{components/layout → layout}/hologram-card/css/index.tsx +0 -0
  141. /package/{components/layout → layout}/hologram-card/tailwind/index.tsx +0 -0
  142. /package/{components/neon → neon}/neon-alert/css/index.tsx +0 -0
  143. /package/{components/neon → neon}/neon-alert/css/neon-alert.module.css +0 -0
  144. /package/{components/neon → neon}/neon-alert/tailwind/index.tsx +0 -0
  145. /package/{components/neon → neon}/neon-badge/css/index.tsx +0 -0
  146. /package/{components/neon → neon}/neon-badge/css/neon-badge.module.css +0 -0
  147. /package/{components/neon → neon}/neon-badge/tailwind/index.tsx +0 -0
  148. /package/{components/neon → neon}/neon-button/css/index.tsx +0 -0
  149. /package/{components/neon → neon}/neon-button/css/neon-button.module.css +0 -0
  150. /package/{components/neon → neon}/neon-button/tailwind/index.tsx +0 -0
  151. /package/{components/neon → neon}/neon-divider/css/index.tsx +0 -0
  152. /package/{components/neon → neon}/neon-divider/css/neon-divider.module.css +0 -0
  153. /package/{components/neon → neon}/neon-divider/tailwind/index.tsx +0 -0
  154. /package/{components/neon → neon}/neon-progress/css/index.tsx +0 -0
  155. /package/{components/neon → neon}/neon-progress/css/neon-progress.module.css +0 -0
  156. /package/{components/neon → neon}/neon-progress/tailwind/index.tsx +0 -0
  157. /package/{components/neon → neon}/neon-tabs/css/index.tsx +0 -0
  158. /package/{components/neon → neon}/neon-tabs/css/neon-tabs.module.css +0 -0
  159. /package/{components/neon → neon}/neon-tabs/tailwind/index.tsx +0 -0
  160. /package/{components/neon → neon}/neon-toggle/css/index.tsx +0 -0
  161. /package/{components/neon → neon}/neon-toggle/css/neon-toggle.module.css +0 -0
  162. /package/{components/neon → neon}/neon-toggle/tailwind/index.tsx +0 -0
  163. /package/{components/overlays → overlays}/noise-overlay/index.tsx +0 -0
  164. /package/{components/overlays → overlays}/noise-overlay/noise-overlay.module.css +0 -0
  165. /package/{components/overlays → overlays}/scanlines/index.tsx +0 -0
  166. /package/{components/overlays → overlays}/scanlines/scanlines.module.css +0 -0
  167. /package/{components/overlays → overlays}/static-flicker/index.tsx +0 -0
  168. /package/{components/overlays → overlays}/static-flicker/static-flicker.module.css +0 -0
  169. /package/{components/overlays → overlays}/vignette/index.tsx +0 -0
  170. /package/{components/overlays → overlays}/vignette/vignette.module.css +0 -0
  171. /package/{components/text → text}/distortion-text/distortion-text.module.css +0 -0
  172. /package/{components/text → text}/distortion-text/index.tsx +0 -0
  173. /package/{components/text → text}/falling-text/falling-text.module.css +0 -0
  174. /package/{components/text → text}/falling-text/index.tsx +0 -0
  175. /package/{components/text → text}/flicker-text/flicker-text.module.css +0 -0
  176. /package/{components/text → text}/flicker-text/index.tsx +0 -0
  177. /package/{components/text → text}/glitch-text/glitch-text.module.css +0 -0
  178. /package/{components/text → text}/glitch-text/index.tsx +0 -0
@@ -0,0 +1,141 @@
1
+ .frame {
2
+ --frame-color: #c9a227;
3
+ --frame-bg: rgba(0, 0, 0, 0.5);
4
+
5
+ position: relative;
6
+ padding: 2rem;
7
+ background: var(--frame-bg);
8
+ border: 1px solid var(--frame-color);
9
+ }
10
+
11
+ /* Corner ornaments */
12
+ .corner {
13
+ position: absolute;
14
+ width: 20px;
15
+ height: 20px;
16
+ border-color: var(--frame-color);
17
+ border-style: solid;
18
+ }
19
+
20
+ .cornerTopLeft {
21
+ top: -1px;
22
+ left: -1px;
23
+ border-width: 2px 0 0 2px;
24
+ }
25
+
26
+ .cornerTopRight {
27
+ top: -1px;
28
+ right: -1px;
29
+ border-width: 2px 2px 0 0;
30
+ }
31
+
32
+ .cornerBottomLeft {
33
+ bottom: -1px;
34
+ left: -1px;
35
+ border-width: 0 0 2px 2px;
36
+ }
37
+
38
+ .cornerBottomRight {
39
+ bottom: -1px;
40
+ right: -1px;
41
+ border-width: 0 2px 2px 0;
42
+ }
43
+
44
+ /* Extended corners */
45
+ .extended .corner {
46
+ width: 30px;
47
+ height: 30px;
48
+ }
49
+
50
+ .extended .corner::before,
51
+ .extended .corner::after {
52
+ content: '';
53
+ position: absolute;
54
+ background: var(--frame-color);
55
+ }
56
+
57
+ .extended .cornerTopLeft::before,
58
+ .extended .cornerBottomLeft::before {
59
+ left: 5px;
60
+ width: 1px;
61
+ height: 15px;
62
+ }
63
+
64
+ .extended .cornerTopLeft::before { top: 5px; }
65
+ .extended .cornerBottomLeft::before { bottom: 5px; }
66
+
67
+ .extended .cornerTopRight::before,
68
+ .extended .cornerBottomRight::before {
69
+ right: 5px;
70
+ width: 1px;
71
+ height: 15px;
72
+ }
73
+
74
+ .extended .cornerTopRight::before { top: 5px; }
75
+ .extended .cornerBottomRight::before { bottom: 5px; }
76
+
77
+ .extended .cornerTopLeft::after,
78
+ .extended .cornerTopRight::after {
79
+ top: 5px;
80
+ height: 1px;
81
+ width: 15px;
82
+ }
83
+
84
+ .extended .cornerTopLeft::after { left: 5px; }
85
+ .extended .cornerTopRight::after { right: 5px; }
86
+
87
+ .extended .cornerBottomLeft::after,
88
+ .extended .cornerBottomRight::after {
89
+ bottom: 5px;
90
+ height: 1px;
91
+ width: 15px;
92
+ }
93
+
94
+ .extended .cornerBottomLeft::after { left: 5px; }
95
+ .extended .cornerBottomRight::after { right: 5px; }
96
+
97
+ /* Ornate style - with decorative elements */
98
+ .ornate .corner {
99
+ width: 40px;
100
+ height: 40px;
101
+ }
102
+
103
+ .ornate::before {
104
+ content: '✦';
105
+ position: absolute;
106
+ top: -0.5em;
107
+ left: 50%;
108
+ transform: translateX(-50%);
109
+ color: var(--frame-color);
110
+ font-size: 1rem;
111
+ }
112
+
113
+ .ornate::after {
114
+ content: '✦';
115
+ position: absolute;
116
+ bottom: -0.5em;
117
+ left: 50%;
118
+ transform: translateX(-50%);
119
+ color: var(--frame-color);
120
+ font-size: 1rem;
121
+ }
122
+
123
+ /* Variants */
124
+ .gold { --frame-color: #c9a227; }
125
+ .bone { --frame-color: #d4c5a9; }
126
+ .blood { --frame-color: #8b1a1a; }
127
+ .iron { --frame-color: #4a4a4a; }
128
+ .cyan { --frame-color: #00f0ff; }
129
+
130
+ /* Glow effect */
131
+ .glow {
132
+ box-shadow: 0 0 20px rgba(201, 162, 39, 0.2);
133
+ }
134
+
135
+ .glow.cyan {
136
+ box-shadow: 0 0 20px rgba(0, 240, 255, 0.2);
137
+ }
138
+
139
+ .glow.blood {
140
+ box-shadow: 0 0 20px rgba(139, 26, 26, 0.3);
141
+ }
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, HTMLAttributes, ReactNode } from 'react';
4
+
5
+ export interface VoidFrameProps extends HTMLAttributes<HTMLDivElement> {
6
+ children: ReactNode;
7
+ variant?: 'gold' | 'bone' | 'blood' | 'iron' | 'cyan';
8
+ cornerStyle?: 'simple' | 'extended' | 'ornate';
9
+ glow?: boolean;
10
+ padding?: 'sm' | 'md' | 'lg' | 'xl';
11
+ }
12
+
13
+ const variantStyles = {
14
+ gold: { border: 'border-amber-600', corner: 'border-amber-600', glow: 'shadow-[0_0_20px_rgba(201,162,39,0.2)]', ornament: 'text-amber-600' },
15
+ bone: { border: 'border-stone-400', corner: 'border-stone-400', glow: 'shadow-[0_0_20px_rgba(212,197,169,0.2)]', ornament: 'text-stone-400' },
16
+ blood: { border: 'border-red-800', corner: 'border-red-800', glow: 'shadow-[0_0_20px_rgba(139,26,26,0.3)]', ornament: 'text-red-800' },
17
+ iron: { border: 'border-zinc-600', corner: 'border-zinc-600', glow: 'shadow-[0_0_20px_rgba(74,74,74,0.2)]', ornament: 'text-zinc-600' },
18
+ cyan: { border: 'border-cyan-400', corner: 'border-cyan-400', glow: 'shadow-[0_0_20px_rgba(0,240,255,0.2)]', ornament: 'text-cyan-400' },
19
+ };
20
+
21
+ const paddingClasses = {
22
+ sm: 'p-4',
23
+ md: 'p-8',
24
+ lg: 'p-12',
25
+ xl: 'p-16',
26
+ };
27
+
28
+ export const VoidFrame = forwardRef<HTMLDivElement, VoidFrameProps>(
29
+ ({ children, variant = 'gold', cornerStyle = 'simple', glow = false, padding = 'md', className = '', ...props }, ref) => {
30
+ const colors = variantStyles[variant];
31
+ const cornerSize = cornerStyle === 'ornate' ? 'w-10 h-10' : cornerStyle === 'extended' ? 'w-[30px] h-[30px]' : 'w-5 h-5';
32
+
33
+ return (
34
+ <div
35
+ ref={ref}
36
+ className={`
37
+ relative bg-black/50 border ${colors.border} ${paddingClasses[padding]}
38
+ ${glow ? colors.glow : ''}
39
+ ${className}
40
+ `}
41
+ {...props}
42
+ >
43
+ {/* Corners */}
44
+ <span className={`absolute -top-px -left-px ${cornerSize} border-t-2 border-l-2 ${colors.corner}`} />
45
+ <span className={`absolute -top-px -right-px ${cornerSize} border-t-2 border-r-2 ${colors.corner}`} />
46
+ <span className={`absolute -bottom-px -left-px ${cornerSize} border-b-2 border-l-2 ${colors.corner}`} />
47
+ <span className={`absolute -bottom-px -right-px ${cornerSize} border-b-2 border-r-2 ${colors.corner}`} />
48
+
49
+ {/* Ornate decorations */}
50
+ {cornerStyle === 'ornate' && (
51
+ <>
52
+ <span className={`absolute -top-[0.5em] left-1/2 -translate-x-1/2 ${colors.ornament}`}>✦</span>
53
+ <span className={`absolute -bottom-[0.5em] left-1/2 -translate-x-1/2 ${colors.ornament}`}>✦</span>
54
+ </>
55
+ )}
56
+
57
+ {children}
58
+ </div>
59
+ );
60
+ }
61
+ );
62
+
63
+ VoidFrame.displayName = 'VoidFrame';
64
+ export default VoidFrame;
@@ -0,0 +1,178 @@
1
+ /* brutal-nav - Nav brutaliste chaotique avec status */
2
+ .nav {
3
+ position: fixed;
4
+ top: 0;
5
+ left: 0;
6
+ right: 0;
7
+ z-index: 1000;
8
+ background: var(--chaos-void, #0a0a0a);
9
+ border-bottom: 3px solid var(--chaos-blood, #ff0040);
10
+ font-family: var(--chaos-font-mono, 'Space Mono', monospace);
11
+ }
12
+
13
+ .inner {
14
+ display: flex;
15
+ align-items: stretch;
16
+ height: 60px;
17
+ }
18
+
19
+ .brand {
20
+ background: var(--chaos-blood, #ff0040);
21
+ color: var(--chaos-void, #0a0a0a);
22
+ font-family: var(--chaos-font-display, 'Bebas Neue', sans-serif);
23
+ font-size: 1.5rem;
24
+ padding: 0 2rem;
25
+ display: flex;
26
+ align-items: center;
27
+ letter-spacing: 0.1em;
28
+ text-transform: uppercase;
29
+ }
30
+
31
+ .links {
32
+ display: flex;
33
+ flex: 1;
34
+ }
35
+
36
+ .link {
37
+ display: flex;
38
+ align-items: center;
39
+ padding: 0 1.5rem;
40
+ font-size: 0.75rem;
41
+ letter-spacing: 0.15em;
42
+ text-transform: uppercase;
43
+ color: var(--chaos-bone-dark, #888);
44
+ text-decoration: none;
45
+ border-right: 1px solid rgba(255, 255, 255, 0.1);
46
+ position: relative;
47
+ transition: all 0.15s;
48
+ }
49
+
50
+ .link:hover {
51
+ background: var(--chaos-blood, #ff0040);
52
+ color: var(--chaos-void, #0a0a0a);
53
+ }
54
+
55
+ .linkActive {
56
+ background: rgba(255, 0, 64, 0.1);
57
+ color: var(--chaos-blood, #ff0040);
58
+ }
59
+
60
+ .linkActive::after {
61
+ content: '';
62
+ position: absolute;
63
+ bottom: 0;
64
+ left: 0;
65
+ right: 0;
66
+ height: 3px;
67
+ background: var(--chaos-blood, #ff0040);
68
+ }
69
+
70
+ /* Status section */
71
+ .status {
72
+ margin-left: auto;
73
+ display: flex;
74
+ align-items: center;
75
+ gap: 2rem;
76
+ padding: 0 2rem;
77
+ background: rgba(0, 0, 0, 0.5);
78
+ border-left: 1px solid rgba(255, 255, 255, 0.1);
79
+ }
80
+
81
+ .statusItem {
82
+ display: flex;
83
+ flex-direction: column;
84
+ gap: 0.2rem;
85
+ }
86
+
87
+ .statusLabel {
88
+ font-size: 0.5rem;
89
+ color: var(--chaos-bone-dark, #666);
90
+ letter-spacing: 0.2em;
91
+ text-transform: uppercase;
92
+ }
93
+
94
+ .statusValue {
95
+ font-size: 0.7rem;
96
+ color: var(--chaos-blood, #ff0040);
97
+ font-weight: bold;
98
+ }
99
+
100
+ .statusOnline {
101
+ display: flex;
102
+ align-items: center;
103
+ gap: 0.5rem;
104
+ }
105
+
106
+ .dot {
107
+ width: 8px;
108
+ height: 8px;
109
+ border-radius: 50%;
110
+ animation: pulse 2s ease-in-out infinite;
111
+ }
112
+
113
+ .dotOnline { background: #00ff00; box-shadow: 0 0 10px #00ff00; }
114
+ .dotOffline { background: #ff0040; }
115
+ .dotWarning { background: #ffaa00; animation: blink 0.5s infinite; }
116
+
117
+ @keyframes pulse {
118
+ 0%, 100% { opacity: 1; }
119
+ 50% { opacity: 0.5; }
120
+ }
121
+
122
+ @keyframes blink {
123
+ 50% { opacity: 0; }
124
+ }
125
+
126
+ /* Glitch brand effect */
127
+ .brandGlitch {
128
+ position: relative;
129
+ }
130
+
131
+ .brandGlitch::before,
132
+ .brandGlitch::after {
133
+ content: attr(data-text);
134
+ position: absolute;
135
+ left: 0;
136
+ top: 0;
137
+ }
138
+
139
+ .brandGlitch::before {
140
+ animation: glitch1 0.3s infinite;
141
+ color: cyan;
142
+ clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%);
143
+ z-index: -1;
144
+ }
145
+
146
+ .brandGlitch::after {
147
+ animation: glitch2 0.3s infinite;
148
+ color: yellow;
149
+ clip-path: polygon(0 55%, 100% 55%, 100% 100%, 0 100%);
150
+ z-index: -1;
151
+ }
152
+
153
+ @keyframes glitch1 {
154
+ 0%, 100% { transform: translate(0); }
155
+ 20% { transform: translate(-2px, 2px); }
156
+ 40% { transform: translate(2px, -2px); }
157
+ }
158
+
159
+ @keyframes glitch2 {
160
+ 0%, 100% { transform: translate(0); }
161
+ 20% { transform: translate(2px, -2px); }
162
+ 40% { transform: translate(-2px, 2px); }
163
+ }
164
+
165
+ /* Brutal border variants */
166
+ .variantHeavy {
167
+ border-bottom-width: 5px;
168
+ }
169
+
170
+ .variantHeavy .brand {
171
+ clip-path: polygon(0 0, 100% 0, 90% 100%, 0 100%);
172
+ padding-right: 3rem;
173
+ }
174
+
175
+ .variantDouble {
176
+ border-bottom: 2px solid var(--chaos-blood, #ff0040);
177
+ box-shadow: 0 4px 0 0 var(--chaos-blood, #ff0040);
178
+ }
@@ -0,0 +1,80 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, HTMLAttributes, ReactNode } from 'react';
4
+ import styles from './brutal-nav.module.css';
5
+
6
+ export interface BrutalNavLinkProps {
7
+ href: string;
8
+ children: ReactNode;
9
+ active?: boolean;
10
+ }
11
+
12
+ export interface BrutalNavStatusProps {
13
+ label: string;
14
+ value: string;
15
+ status?: 'online' | 'offline' | 'warning';
16
+ }
17
+
18
+ export interface BrutalNavProps extends HTMLAttributes<HTMLElement> {
19
+ brand: string;
20
+ brandGlitch?: boolean;
21
+ links?: BrutalNavLinkProps[];
22
+ statusItems?: BrutalNavStatusProps[];
23
+ variant?: 'default' | 'heavy' | 'double';
24
+ children?: ReactNode;
25
+ }
26
+
27
+ export const BrutalNav = forwardRef<HTMLElement, BrutalNavProps>(
28
+ ({ brand, brandGlitch, links, statusItems, variant = 'default', children, className, ...props }, ref) => {
29
+ const navClasses = [
30
+ styles.nav,
31
+ variant === 'heavy' && styles.variantHeavy,
32
+ variant === 'double' && styles.variantDouble,
33
+ className,
34
+ ].filter(Boolean).join(' ');
35
+
36
+ return (
37
+ <nav ref={ref} className={navClasses} {...props}>
38
+ <div className={styles.inner}>
39
+ <div className={styles.brand}>
40
+ {brandGlitch ? (
41
+ <span className={styles.brandGlitch} data-text={brand}>{brand}</span>
42
+ ) : brand}
43
+ </div>
44
+
45
+ <div className={styles.links}>
46
+ {links?.map((link, i) => (
47
+ <a
48
+ key={i}
49
+ href={link.href}
50
+ className={`${styles.link} ${link.active ? styles.linkActive : ''}`}
51
+ >
52
+ {link.children}
53
+ </a>
54
+ ))}
55
+ {children}
56
+ </div>
57
+
58
+ {statusItems && statusItems.length > 0 && (
59
+ <div className={styles.status}>
60
+ {statusItems.map((item, i) => (
61
+ <div key={i} className={styles.statusItem}>
62
+ <span className={styles.statusLabel}>{item.label}</span>
63
+ <span className={styles.statusOnline}>
64
+ {item.status && (
65
+ <span className={`${styles.dot} ${styles[`dot${item.status.charAt(0).toUpperCase() + item.status.slice(1)}`]}`} />
66
+ )}
67
+ <span className={styles.statusValue}>{item.value}</span>
68
+ </span>
69
+ </div>
70
+ ))}
71
+ </div>
72
+ )}
73
+ </div>
74
+ </nav>
75
+ );
76
+ }
77
+ );
78
+
79
+ BrutalNav.displayName = 'BrutalNav';
80
+ export default BrutalNav;
@@ -0,0 +1,95 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, HTMLAttributes, ReactNode } from 'react';
4
+
5
+ export interface BrutalNavLinkProps {
6
+ href: string;
7
+ children: ReactNode;
8
+ active?: boolean;
9
+ }
10
+
11
+ export interface BrutalNavStatusProps {
12
+ label: string;
13
+ value: string;
14
+ status?: 'online' | 'offline' | 'warning';
15
+ }
16
+
17
+ export interface BrutalNavProps extends HTMLAttributes<HTMLElement> {
18
+ brand: string;
19
+ brandGlitch?: boolean;
20
+ links?: BrutalNavLinkProps[];
21
+ statusItems?: BrutalNavStatusProps[];
22
+ variant?: 'default' | 'heavy' | 'double';
23
+ children?: ReactNode;
24
+ }
25
+
26
+ const dotClasses: Record<string, string> = {
27
+ online: 'bg-green-500 shadow-[0_0_10px_#00ff00]',
28
+ offline: 'bg-red-500',
29
+ warning: 'bg-amber-500 animate-pulse',
30
+ };
31
+
32
+ export const BrutalNav = forwardRef<HTMLElement, BrutalNavProps>(
33
+ ({ brand, brandGlitch, links, statusItems, variant = 'default', children, className, ...props }, ref) => {
34
+ const navClasses = `
35
+ fixed top-0 left-0 right-0 z-50 bg-black font-mono
36
+ ${variant === 'heavy' ? 'border-b-[5px] border-red-500' : ''}
37
+ ${variant === 'double' ? 'border-b-2 border-red-500 shadow-[0_4px_0_0_#ff0040]' : ''}
38
+ ${variant === 'default' ? 'border-b-[3px] border-red-500' : ''}
39
+ ${className || ''}
40
+ `;
41
+
42
+ return (
43
+ <nav ref={ref} className={navClasses} {...props}>
44
+ <div className="flex items-stretch h-[60px]">
45
+ <div className={`
46
+ bg-red-500 text-black font-display text-2xl px-8 flex items-center
47
+ tracking-wider uppercase
48
+ ${variant === 'heavy' ? 'clip-path-[polygon(0_0,100%_0,90%_100%,0_100%)] pr-12' : ''}
49
+ `}>
50
+ {brand}
51
+ </div>
52
+
53
+ <div className="flex flex-1">
54
+ {links?.map((link, i) => (
55
+ <a
56
+ key={i}
57
+ href={link.href}
58
+ className={`
59
+ flex items-center px-6 text-xs tracking-[0.15em] uppercase
60
+ border-r border-white/10 transition-all
61
+ ${link.active
62
+ ? 'bg-red-500/10 text-red-500 relative after:absolute after:bottom-0 after:left-0 after:right-0 after:h-[3px] after:bg-red-500'
63
+ : 'text-gray-500 hover:bg-red-500 hover:text-black'
64
+ }
65
+ `}
66
+ >
67
+ {link.children}
68
+ </a>
69
+ ))}
70
+ {children}
71
+ </div>
72
+
73
+ {statusItems && statusItems.length > 0 && (
74
+ <div className="ml-auto flex items-center gap-8 px-8 bg-black/50 border-l border-white/10">
75
+ {statusItems.map((item, i) => (
76
+ <div key={i} className="flex flex-col gap-0.5">
77
+ <span className="text-[0.5rem] text-gray-600 tracking-[0.2em] uppercase">{item.label}</span>
78
+ <span className="flex items-center gap-2">
79
+ {item.status && (
80
+ <span className={`w-2 h-2 rounded-full ${dotClasses[item.status]} animate-pulse`} />
81
+ )}
82
+ <span className="text-xs text-red-500 font-bold">{item.value}</span>
83
+ </span>
84
+ </div>
85
+ ))}
86
+ </div>
87
+ )}
88
+ </div>
89
+ </nav>
90
+ );
91
+ }
92
+ );
93
+
94
+ BrutalNav.displayName = 'BrutalNav';
95
+ export default BrutalNav;
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, HTMLAttributes } from 'react';
4
+ import styles from './progress-dots.module.css';
5
+
6
+ export interface ProgressDotItem {
7
+ id: string;
8
+ label?: string;
9
+ href?: string;
10
+ }
11
+
12
+ export interface ProgressDotsProps extends HTMLAttributes<HTMLDivElement> {
13
+ items: ProgressDotItem[];
14
+ activeId?: string;
15
+ variant?: 'default' | 'gold' | 'minimal';
16
+ direction?: 'vertical' | 'horizontal';
17
+ showConnector?: boolean;
18
+ onDotClick?: (id: string) => void;
19
+ }
20
+
21
+ export const ProgressDots = forwardRef<HTMLDivElement, ProgressDotsProps>(
22
+ ({ items, activeId, variant = 'default', direction = 'vertical', showConnector = false, onDotClick, className, ...props }, ref) => {
23
+ const containerClasses = [
24
+ styles.container,
25
+ variant === 'gold' && styles.variantGold,
26
+ variant === 'minimal' && styles.variantMinimal,
27
+ direction === 'horizontal' && styles.horizontal,
28
+ showConnector && styles.withConnector,
29
+ className,
30
+ ].filter(Boolean).join(' ');
31
+
32
+ const handleClick = (id: string, href?: string) => {
33
+ if (onDotClick) {
34
+ onDotClick(id);
35
+ }
36
+ if (href) {
37
+ const el = document.querySelector(href);
38
+ el?.scrollIntoView({ behavior: 'smooth' });
39
+ }
40
+ };
41
+
42
+ return (
43
+ <div ref={ref} className={containerClasses} {...props}>
44
+ {items.map((item) => (
45
+ <button
46
+ key={item.id}
47
+ className={`${styles.dot} ${item.label ? styles.dotWithLabel : ''} ${activeId === item.id ? styles.dotActive : ''}`}
48
+ onClick={() => handleClick(item.id, item.href)}
49
+ aria-label={item.label || `Go to section ${item.id}`}
50
+ >
51
+ {item.label && <span className={styles.label}>{item.label}</span>}
52
+ </button>
53
+ ))}
54
+ </div>
55
+ );
56
+ }
57
+ );
58
+
59
+ ProgressDots.displayName = 'ProgressDots';
60
+ export default ProgressDots;