@oalacea/chaosui 0.1.0 → 0.5.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 (139) hide show
  1. package/bin/cli.js +105 -13
  2. package/components/backgrounds/glow-orbs/index.tsx +1 -1
  3. package/components/buttons/chaos-button/chaos-button.module.css +3 -2
  4. package/components/buttons/cta-brutal/cta-brutal.module.css +81 -0
  5. package/components/buttons/cta-brutal/index.tsx +56 -0
  6. package/components/buttons/dead-button/dead-button.module.css +111 -0
  7. package/components/buttons/dead-button/index.tsx +47 -0
  8. package/components/buttons/deeper-button/deeper-button.module.css +76 -0
  9. package/components/buttons/deeper-button/index.tsx +51 -0
  10. package/components/buttons/dual-choice/dual-choice.module.css +90 -0
  11. package/components/buttons/dual-choice/index.tsx +54 -0
  12. package/components/buttons/glitch-button/glitch-button.module.css +7 -7
  13. package/components/buttons/tension-bar/index.tsx +79 -0
  14. package/components/buttons/tension-bar/tension-bar.module.css +105 -0
  15. package/components/chaos-vars.css +27 -0
  16. package/components/cyber/cyber-avatar/css/cyber-avatar.module.css +60 -0
  17. package/components/cyber/cyber-avatar/css/index.tsx +28 -0
  18. package/components/cyber/cyber-avatar/tailwind/index.tsx +46 -0
  19. package/components/cyber/cyber-input/css/cyber-input.module.css +87 -0
  20. package/components/cyber/cyber-input/css/index.tsx +49 -0
  21. package/components/cyber/cyber-input/tailwind/index.tsx +55 -0
  22. package/components/cyber/cyber-loader/css/cyber-loader.module.css +102 -0
  23. package/components/cyber/cyber-loader/css/index.tsx +58 -0
  24. package/components/cyber/cyber-loader/tailwind/index.tsx +63 -0
  25. package/components/cyber/cyber-modal/css/cyber-modal.module.css +124 -0
  26. package/components/cyber/cyber-modal/css/index.tsx +75 -0
  27. package/components/cyber/cyber-modal/tailwind/index.tsx +87 -0
  28. package/components/cyber/cyber-slider/css/cyber-slider.module.css +61 -0
  29. package/components/cyber/cyber-slider/css/index.tsx +41 -0
  30. package/components/cyber/cyber-slider/tailwind/index.tsx +51 -0
  31. package/components/cyber/cyber-tooltip/css/cyber-tooltip.module.css +67 -0
  32. package/components/cyber/cyber-tooltip/css/index.tsx +36 -0
  33. package/components/cyber/cyber-tooltip/tailwind/index.tsx +48 -0
  34. package/components/decorative/coffee-stain/coffee-stain.module.css +24 -0
  35. package/components/decorative/coffee-stain/index.tsx +55 -0
  36. package/components/decorative/ornaments/index.tsx +51 -0
  37. package/components/decorative/ornaments/ornaments.module.css +33 -0
  38. package/components/decorative/rune-symbols/index.tsx +55 -0
  39. package/components/decorative/rune-symbols/rune-symbols.module.css +22 -0
  40. package/components/effects/glitch-image/css/glitch-image.module.css +64 -0
  41. package/components/effects/glitch-image/css/index.tsx +25 -0
  42. package/components/effects/glitch-image/tailwind/index.tsx +49 -0
  43. package/components/effects/glowing-border/css/glowing-border.module.css +73 -0
  44. package/components/effects/glowing-border/css/index.tsx +45 -0
  45. package/components/effects/glowing-border/tailwind/index.tsx +40 -0
  46. package/components/effects/screen-distortion/screen-distortion.module.css +2 -2
  47. package/components/effects/warning-tape/index.tsx +4 -4
  48. package/components/effects/warning-tape/warning-tape.module.css +2 -0
  49. package/components/layout/data-grid/css/data-grid.module.css +52 -0
  50. package/components/layout/data-grid/css/index.tsx +76 -0
  51. package/components/layout/data-grid/tailwind/index.tsx +74 -0
  52. package/components/layout/hologram-card/css/hologram-card.module.css +102 -0
  53. package/components/layout/hologram-card/css/index.tsx +46 -0
  54. package/components/layout/hologram-card/tailwind/index.tsx +61 -0
  55. package/components/layout/horizontal-scroll/horizontal-scroll.module.css +30 -0
  56. package/components/layout/horizontal-scroll/index.tsx +78 -0
  57. package/components/layout/spec-grid/index.tsx +56 -0
  58. package/components/layout/spec-grid/spec-grid.module.css +21 -0
  59. package/components/layout/tower-pricing/index.tsx +56 -0
  60. package/components/layout/tower-pricing/tower-pricing.module.css +27 -0
  61. package/components/layout/tracklist/index.tsx +45 -0
  62. package/components/layout/tracklist/tracklist.module.css +24 -0
  63. package/components/layout/void-frame/index.tsx +32 -0
  64. package/components/layout/void-frame/void-frame.module.css +38 -0
  65. package/components/navigation/brutal-nav/brutal-nav.module.css +85 -0
  66. package/components/navigation/brutal-nav/index.tsx +71 -0
  67. package/components/navigation/hexagon-menu/css/hexagon-menu.module.css +55 -0
  68. package/components/navigation/hexagon-menu/css/index.tsx +35 -0
  69. package/components/navigation/hexagon-menu/tailwind/index.tsx +53 -0
  70. package/components/navigation/progress-dots/index.tsx +55 -0
  71. package/components/navigation/progress-dots/progress-dots.module.css +91 -0
  72. package/components/navigation/scattered-nav/index.tsx +59 -0
  73. package/components/navigation/scattered-nav/scattered-nav.module.css +113 -0
  74. package/components/navigation/scroll-indicator/index.tsx +58 -0
  75. package/components/navigation/scroll-indicator/scroll-indicator.module.css +82 -0
  76. package/components/navigation/vertical-nav/index.tsx +59 -0
  77. package/components/navigation/vertical-nav/vertical-nav.module.css +98 -0
  78. package/components/neon/neon-alert/css/index.tsx +53 -0
  79. package/components/neon/neon-alert/css/neon-alert.module.css +60 -0
  80. package/components/neon/neon-alert/tailwind/index.tsx +59 -0
  81. package/components/neon/neon-badge/css/index.tsx +49 -0
  82. package/components/neon/neon-badge/css/neon-badge.module.css +53 -0
  83. package/components/neon/neon-badge/tailwind/index.tsx +50 -0
  84. package/components/neon/neon-button/css/index.tsx +54 -0
  85. package/components/neon/neon-button/css/neon-button.module.css +114 -0
  86. package/components/neon/neon-button/tailwind/index.tsx +51 -0
  87. package/components/neon/neon-divider/css/index.tsx +26 -0
  88. package/components/neon/neon-divider/css/neon-divider.module.css +43 -0
  89. package/components/neon/neon-divider/tailwind/index.tsx +36 -0
  90. package/components/neon/neon-progress/css/index.tsx +65 -0
  91. package/components/neon/neon-progress/css/neon-progress.module.css +88 -0
  92. package/components/neon/neon-progress/tailwind/index.tsx +46 -0
  93. package/components/neon/neon-tabs/css/index.tsx +41 -0
  94. package/components/neon/neon-tabs/css/neon-tabs.module.css +45 -0
  95. package/components/neon/neon-tabs/tailwind/index.tsx +53 -0
  96. package/components/neon/neon-toggle/css/index.tsx +58 -0
  97. package/components/neon/neon-toggle/css/neon-toggle.module.css +79 -0
  98. package/components/neon/neon-toggle/tailwind/index.tsx +57 -0
  99. package/components/text/ascii-art/css/ascii-art.module.css +173 -0
  100. package/components/text/ascii-art/css/index.tsx +116 -0
  101. package/components/text/ascii-art/tailwind/index.tsx +124 -0
  102. package/components/text/blood-drip/css/blood-drip.module.css +142 -0
  103. package/components/text/blood-drip/css/index.tsx +113 -0
  104. package/components/text/blood-drip/tailwind/index.tsx +133 -0
  105. package/components/text/char-glitch/css/char-glitch.module.css +124 -0
  106. package/components/text/char-glitch/css/index.tsx +153 -0
  107. package/components/text/char-glitch/tailwind/index.tsx +126 -0
  108. package/components/text/countdown-display/css/countdown-display.module.css +179 -0
  109. package/components/text/countdown-display/css/index.tsx +190 -0
  110. package/components/text/countdown-display/tailwind/index.tsx +155 -0
  111. package/components/text/giant-layers/css/giant-layers.module.css +156 -0
  112. package/components/text/giant-layers/css/index.tsx +97 -0
  113. package/components/text/giant-layers/tailwind/index.tsx +111 -0
  114. package/components/text/glitch-text/glitch-text.module.css +2 -2
  115. package/components/text/reveal-text/css/index.tsx +180 -0
  116. package/components/text/reveal-text/css/reveal-text.module.css +129 -0
  117. package/components/text/reveal-text/tailwind/index.tsx +135 -0
  118. package/components/text/rotate-text/css/index.tsx +139 -0
  119. package/components/text/rotate-text/css/rotate-text.module.css +162 -0
  120. package/components/text/rotate-text/tailwind/index.tsx +127 -0
  121. package/components/text/strike-reveal/css/index.tsx +124 -0
  122. package/components/text/strike-reveal/css/strike-reveal.module.css +139 -0
  123. package/components/text/strike-reveal/tailwind/index.tsx +138 -0
  124. package/components/text/terminal-output/css/index.tsx +179 -0
  125. package/components/text/terminal-output/css/terminal-output.module.css +203 -0
  126. package/components/text/terminal-output/tailwind/index.tsx +174 -0
  127. package/components/text/typing-text/css/index.tsx +115 -0
  128. package/components/text/typing-text/css/typing-text.module.css +84 -0
  129. package/components/text/typing-text/tailwind/index.tsx +126 -0
  130. package/package.json +1 -1
  131. package/components/glow-orbs/glow-orbs.module.css +0 -31
  132. package/components/glow-orbs/index.tsx +0 -87
  133. package/components/light-beams/index.tsx +0 -80
  134. package/components/light-beams/light-beams.module.css +0 -27
  135. package/components/noise-canvas/index.tsx +0 -113
  136. package/components/noise-canvas/noise-canvas.module.css +0 -8
  137. package/components/package.json +0 -13
  138. package/components/particle-field/index.tsx +0 -81
  139. package/components/particle-field/particle-field.module.css +0 -31
@@ -0,0 +1,90 @@
1
+ /* dual-choice - Deux boutons OUI/NON côte à côte */
2
+ .container {
3
+ display: flex;
4
+ gap: 0;
5
+ font-family: var(--chaos-font-display, 'Bebas Neue', sans-serif);
6
+ }
7
+
8
+ .button {
9
+ flex: 1;
10
+ padding: 1.5rem 3rem;
11
+ font-size: 1.5rem;
12
+ letter-spacing: 0.15em;
13
+ text-transform: uppercase;
14
+ border: 2px solid var(--chaos-iron, #333);
15
+ background: transparent;
16
+ cursor: pointer;
17
+ transition: all 0.2s;
18
+ position: relative;
19
+ overflow: hidden;
20
+ }
21
+
22
+ .button::before {
23
+ content: '';
24
+ position: absolute;
25
+ top: 0;
26
+ left: -100%;
27
+ width: 100%;
28
+ height: 100%;
29
+ transition: left 0.3s;
30
+ z-index: -1;
31
+ }
32
+
33
+ .button:hover::before { left: 0; }
34
+
35
+ .yes { color: var(--chaos-bone, #e8e8e8); border-color: var(--chaos-bone-dark, #666); }
36
+ .yes::before { background: var(--chaos-bone, #e8e8e8); }
37
+ .yes:hover { color: var(--chaos-void, #0a0a0a); border-color: var(--chaos-bone, #e8e8e8); }
38
+
39
+ .no { color: var(--chaos-blood, #ff0040); border-color: var(--chaos-blood, #ff0040); border-left: none; }
40
+ .no::before { background: var(--chaos-blood, #ff0040); }
41
+ .no:hover { color: var(--chaos-void, #0a0a0a); }
42
+
43
+ .divider {
44
+ width: 2px;
45
+ background: var(--chaos-iron, #333);
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ position: relative;
50
+ }
51
+
52
+ .divider::before {
53
+ content: 'OU';
54
+ position: absolute;
55
+ font-size: 0.6rem;
56
+ color: var(--chaos-bone-dark, #666);
57
+ background: var(--chaos-void, #0a0a0a);
58
+ padding: 0.3rem;
59
+ letter-spacing: 0.1em;
60
+ }
61
+
62
+ .variantDramatic .yes { color: var(--chaos-gold, #c9a227); border-color: var(--chaos-gold, #c9a227); }
63
+ .variantDramatic .yes::before { background: var(--chaos-gold, #c9a227); }
64
+
65
+ .variantMinimal .button { border: none; padding: 1rem 2rem; font-size: 1rem; }
66
+ .variantMinimal .button::after {
67
+ content: '';
68
+ position: absolute;
69
+ bottom: 0;
70
+ left: 0;
71
+ right: 0;
72
+ height: 2px;
73
+ background: currentColor;
74
+ transform: scaleX(0);
75
+ transition: transform 0.3s;
76
+ }
77
+ .variantMinimal .button:hover::after { transform: scaleX(1); }
78
+ .variantMinimal .button::before { display: none; }
79
+ .variantMinimal .button:hover { color: inherit; }
80
+ .variantMinimal .divider { display: none; }
81
+
82
+ .variantStacked { flex-direction: column; }
83
+ .variantStacked .no { border-left: 2px solid var(--chaos-blood, #ff0040); border-top: none; }
84
+ .variantStacked .divider { width: 100%; height: 2px; }
85
+
86
+ .sizeSm .button { padding: 0.8rem 1.5rem; font-size: 1rem; }
87
+ .sizeLg .button { padding: 2rem 4rem; font-size: 2rem; }
88
+
89
+ .disabled { opacity: 0.5; pointer-events: none; }
90
+ .selected { background: currentColor; color: var(--chaos-void, #0a0a0a) !important; }
@@ -0,0 +1,54 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, HTMLAttributes } from 'react';
4
+ import styles from './dual-choice.module.css';
5
+
6
+ export interface DualChoiceProps extends HTMLAttributes<HTMLDivElement> {
7
+ yesLabel?: string;
8
+ noLabel?: string;
9
+ onYes?: () => void;
10
+ onNo?: () => void;
11
+ variant?: 'default' | 'dramatic' | 'minimal' | 'stacked';
12
+ size?: 'sm' | 'md' | 'lg';
13
+ showDivider?: boolean;
14
+ disabled?: boolean;
15
+ selectedValue?: 'yes' | 'no' | null;
16
+ }
17
+
18
+ export const DualChoice = forwardRef<HTMLDivElement, DualChoiceProps>(
19
+ ({ yesLabel = 'OUI', noLabel = 'NON', onYes, onNo, variant = 'default', size = 'md', showDivider = true, disabled = false, selectedValue = null, className, ...props }, ref) => {
20
+ const containerClasses = [
21
+ styles.container,
22
+ variant === 'dramatic' && styles.variantDramatic,
23
+ variant === 'minimal' && styles.variantMinimal,
24
+ variant === 'stacked' && styles.variantStacked,
25
+ size === 'sm' && styles.sizeSm,
26
+ size === 'lg' && styles.sizeLg,
27
+ disabled && styles.disabled,
28
+ className,
29
+ ].filter(Boolean).join(' ');
30
+
31
+ return (
32
+ <div ref={ref} className={containerClasses} {...props}>
33
+ <button
34
+ className={`${styles.button} ${styles.yes} ${selectedValue === 'yes' ? styles.selected : ''}`}
35
+ onClick={onYes}
36
+ disabled={disabled}
37
+ >
38
+ {yesLabel}
39
+ </button>
40
+ {showDivider && variant !== 'minimal' && <div className={styles.divider} />}
41
+ <button
42
+ className={`${styles.button} ${styles.no} ${selectedValue === 'no' ? styles.selected : ''}`}
43
+ onClick={onNo}
44
+ disabled={disabled}
45
+ >
46
+ {noLabel}
47
+ </button>
48
+ </div>
49
+ );
50
+ }
51
+ );
52
+
53
+ DualChoice.displayName = 'DualChoice';
54
+ export default DualChoice;
@@ -13,8 +13,8 @@
13
13
  cursor: pointer;
14
14
  overflow: hidden;
15
15
  transition: transform 0.1s;
16
- --glitch-color: #ff0040;
17
- --glitch-color-alt: #00ffff;
16
+ --glitch-color: hsl(var(--primary, 347 100% 50%));
17
+ --glitch-color-alt: hsl(var(--secondary, 180 100% 50%));
18
18
  }
19
19
 
20
20
  .button:active {
@@ -23,20 +23,20 @@
23
23
 
24
24
  /* Variants */
25
25
  .default {
26
- background: #0a0a0a;
27
- color: #fafafa;
28
- border: 1px solid #333;
26
+ background: hsl(var(--background, 0 0% 4%));
27
+ color: hsl(var(--foreground, 0 0% 98%));
28
+ border: 1px solid hsl(var(--border, 0 0% 20%));
29
29
  }
30
30
 
31
31
  .outline {
32
32
  background: transparent;
33
- color: #fafafa;
33
+ color: hsl(var(--foreground, 0 0% 98%));
34
34
  border: 2px solid currentColor;
35
35
  }
36
36
 
37
37
  .ghost {
38
38
  background: transparent;
39
- color: #fafafa;
39
+ color: hsl(var(--foreground, 0 0% 98%));
40
40
  border: none;
41
41
  }
42
42
 
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, HTMLAttributes } from 'react';
4
+ import styles from './tension-bar.module.css';
5
+
6
+ export interface TensionBarProps extends HTMLAttributes<HTMLDivElement> {
7
+ value: number;
8
+ max?: number;
9
+ labelLeft?: string;
10
+ labelRight?: string;
11
+ showPercentage?: boolean;
12
+ showMarkers?: boolean;
13
+ markerCount?: number;
14
+ variant?: 'default' | 'gold' | 'danger' | 'segmented';
15
+ size?: 'sm' | 'md' | 'lg';
16
+ innerText?: string;
17
+ animated?: boolean;
18
+ dangerThreshold?: number;
19
+ }
20
+
21
+ export const TensionBar = forwardRef<HTMLDivElement, TensionBarProps>(
22
+ ({ value, max = 100, labelLeft, labelRight, showPercentage = false, showMarkers = false, markerCount = 10, variant = 'default', size = 'md', innerText, animated = false, dangerThreshold = 80, className, ...props }, ref) => {
23
+ const percentage = Math.min(100, Math.max(0, (value / max) * 100));
24
+ const isHigh = variant === 'danger' && percentage >= dangerThreshold;
25
+
26
+ const containerClasses = [
27
+ styles.container,
28
+ variant === 'gold' && styles.variantGold,
29
+ variant === 'danger' && styles.variantDanger,
30
+ variant === 'segmented' && styles.variantSegmented,
31
+ size === 'sm' && styles.sizeSm,
32
+ size === 'lg' && styles.sizeLg,
33
+ innerText && styles.withText,
34
+ animated && styles.animated,
35
+ isHigh && styles.high,
36
+ className,
37
+ ].filter(Boolean).join(' ');
38
+
39
+ const renderSegmented = () => {
40
+ const segments = [];
41
+ const filledCount = Math.floor((percentage / 100) * markerCount);
42
+ for (let i = 0; i < markerCount; i++) {
43
+ segments.push(
44
+ <div key={i} className={`${styles.segment} ${i < filledCount ? styles.segmentFilled : ''}`} />
45
+ );
46
+ }
47
+ return segments;
48
+ };
49
+
50
+ return (
51
+ <div ref={ref} className={containerClasses} {...props}>
52
+ {(labelLeft || labelRight) && (
53
+ <div className={styles.labels}>
54
+ <span className={styles.labelLeft}>{labelLeft}</span>
55
+ <span className={styles.labelRight}>{labelRight}</span>
56
+ </div>
57
+ )}
58
+
59
+ <div className={styles.track}>
60
+ {innerText && <span className={styles.innerText}>{innerText}</span>}
61
+ {variant === 'segmented' ? renderSegmented() : <div className={styles.fill} style={{ width: `${percentage}%` }} />}
62
+ {showPercentage && <span className={styles.percentage}>{Math.round(percentage)}%</span>}
63
+ </div>
64
+
65
+ {showMarkers && variant !== 'segmented' && (
66
+ <div className={styles.markers}>
67
+ {Array.from({ length: markerCount + 1 }).map((_, i) => {
68
+ const markerPercent = (i / markerCount) * 100;
69
+ return <div key={i} className={`${styles.marker} ${markerPercent <= percentage ? styles.markerActive : ''}`} />;
70
+ })}
71
+ </div>
72
+ )}
73
+ </div>
74
+ );
75
+ }
76
+ );
77
+
78
+ TensionBar.displayName = 'TensionBar';
79
+ export default TensionBar;
@@ -0,0 +1,105 @@
1
+ /* tension-bar - Barre de tension/progression dramatique */
2
+ .container {
3
+ width: 100%;
4
+ position: relative;
5
+ font-family: var(--chaos-font-mono, 'Space Mono', monospace);
6
+ }
7
+
8
+ .labels {
9
+ display: flex;
10
+ justify-content: space-between;
11
+ margin-bottom: 0.5rem;
12
+ font-size: 0.65rem;
13
+ letter-spacing: 0.2em;
14
+ text-transform: uppercase;
15
+ }
16
+
17
+ .labelLeft { color: var(--chaos-bone-dark, #666); }
18
+ .labelRight { color: var(--chaos-blood, #ff0040); }
19
+
20
+ .track {
21
+ height: 8px;
22
+ background: var(--chaos-iron, #222);
23
+ position: relative;
24
+ overflow: hidden;
25
+ }
26
+
27
+ .fill {
28
+ height: 100%;
29
+ background: var(--chaos-blood, #ff0040);
30
+ transition: width 0.5s ease-out;
31
+ position: relative;
32
+ }
33
+
34
+ .fill::after {
35
+ content: '';
36
+ position: absolute;
37
+ right: 0;
38
+ top: 0;
39
+ bottom: 0;
40
+ width: 20px;
41
+ background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.3));
42
+ animation: shimmer 1.5s infinite;
43
+ }
44
+
45
+ @keyframes shimmer {
46
+ 0% { opacity: 0; }
47
+ 50% { opacity: 1; }
48
+ 100% { opacity: 0; }
49
+ }
50
+
51
+ .percentage {
52
+ position: absolute;
53
+ right: 0;
54
+ top: -1.5rem;
55
+ font-size: 0.7rem;
56
+ color: var(--chaos-blood, #ff0040);
57
+ font-weight: bold;
58
+ }
59
+
60
+ .markers { display: flex; justify-content: space-between; margin-top: 0.3rem; }
61
+ .marker { width: 1px; height: 6px; background: var(--chaos-iron, #333); }
62
+ .markerActive { background: var(--chaos-blood, #ff0040); }
63
+
64
+ .variantGold .fill { background: linear-gradient(to right, var(--chaos-gold-dark, #8b7017), var(--chaos-gold, #c9a227)); }
65
+ .variantGold .labelRight, .variantGold .percentage { color: var(--chaos-gold, #c9a227); }
66
+ .variantGold .markerActive { background: var(--chaos-gold, #c9a227); }
67
+
68
+ .variantDanger .fill { background: var(--chaos-blood, #ff0040); }
69
+ .variantDanger.high .fill { animation: dangerPulse 0.5s ease-in-out infinite; }
70
+ .variantDanger.high .track { animation: dangerGlow 0.5s ease-in-out infinite; }
71
+
72
+ @keyframes dangerPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } }
73
+ @keyframes dangerGlow {
74
+ 0%, 100% { box-shadow: 0 0 5px var(--chaos-blood, #ff0040); }
75
+ 50% { box-shadow: 0 0 15px var(--chaos-blood, #ff0040); }
76
+ }
77
+
78
+ .variantSegmented .track { display: flex; gap: 2px; background: transparent; }
79
+ .segment { flex: 1; height: 8px; background: var(--chaos-iron, #222); transition: background 0.3s; }
80
+ .segmentFilled { background: var(--chaos-blood, #ff0040); }
81
+
82
+ .sizeSm .track, .sizeSm .segment { height: 4px; }
83
+ .sizeLg .track, .sizeLg .segment { height: 16px; }
84
+
85
+ .withText .track { height: 30px; display: flex; align-items: center; padding: 0 1rem; }
86
+ .innerText {
87
+ position: absolute;
88
+ left: 1rem;
89
+ font-size: 0.7rem;
90
+ color: var(--chaos-bone, #e8e8e8);
91
+ z-index: 1;
92
+ text-transform: uppercase;
93
+ letter-spacing: 0.1em;
94
+ }
95
+
96
+ .animated .fill {
97
+ background: repeating-linear-gradient(45deg, var(--chaos-blood, #ff0040), var(--chaos-blood, #ff0040) 10px, #cc0033 10px, #cc0033 20px);
98
+ background-size: 200% 100%;
99
+ animation: stripeMove 1s linear infinite;
100
+ }
101
+
102
+ @keyframes stripeMove {
103
+ 0% { background-position: 0 0; }
104
+ 100% { background-position: 28px 0; }
105
+ }
@@ -0,0 +1,27 @@
1
+ /* Chaos UI - CSS Variables */
2
+ /* These are the DEFAULT values - they will be overridden by your project's globals.css */
3
+ /* Only add this if you don't have these variables defined yet */
4
+
5
+ :root {
6
+ /* Standard variables (same as shadcn/ui) */
7
+ --primary: 347 100% 50%; /* #ff0040 */
8
+ --primary-foreground: 0 0% 100%;
9
+
10
+ --secondary: 180 100% 50%; /* #00ffff */
11
+ --secondary-foreground: 0 0% 0%;
12
+
13
+ --accent: 300 100% 50%; /* #ff00ff */
14
+ --accent-foreground: 0 0% 100%;
15
+
16
+ --background: 0 0% 4%; /* #0a0a0a */
17
+ --foreground: 0 0% 98%; /* #fafafa */
18
+
19
+ --muted: 0 0% 9%; /* #171717 */
20
+ --muted-foreground: 0 0% 63%; /* #a1a1a1 */
21
+
22
+ --border: 0 0% 20%; /* #333333 */
23
+
24
+ /* Chaos-specific (optional, for fine-tuning effects) */
25
+ --destructive: 0 84% 60%;
26
+ --destructive-foreground: 0 0% 98%;
27
+ }
@@ -0,0 +1,60 @@
1
+ .avatar {
2
+ --avatar-color: #00f0ff;
3
+ --avatar-size: 3rem;
4
+ position: relative;
5
+ width: var(--avatar-size);
6
+ height: var(--avatar-size);
7
+ }
8
+
9
+ .sm { --avatar-size: 2rem; }
10
+ .md { --avatar-size: 3rem; }
11
+ .lg { --avatar-size: 4rem; }
12
+ .xl { --avatar-size: 6rem; }
13
+
14
+ .cyan { --avatar-color: #00f0ff; }
15
+ .pink { --avatar-color: #ff00ff; }
16
+ .green { --avatar-color: #00ff88; }
17
+ .purple { --avatar-color: #a855f7; }
18
+
19
+ .image {
20
+ width: 100%;
21
+ height: 100%;
22
+ object-fit: cover;
23
+ border-radius: 50%;
24
+ }
25
+
26
+ .border {
27
+ position: absolute;
28
+ top: -2px;
29
+ left: -2px;
30
+ width: calc(100% + 4px);
31
+ height: calc(100% + 4px);
32
+ border: 2px solid var(--avatar-color);
33
+ border-radius: 50%;
34
+ pointer-events: none;
35
+ }
36
+
37
+ .glowing .border {
38
+ box-shadow: 0 0 10px var(--avatar-color), 0 0 20px var(--avatar-color);
39
+ animation: avatar-glow 2s ease-in-out infinite;
40
+ }
41
+
42
+ @keyframes avatar-glow {
43
+ 0%, 100% { box-shadow: 0 0 5px var(--avatar-color); }
44
+ 50% { box-shadow: 0 0 15px var(--avatar-color), 0 0 30px var(--avatar-color); }
45
+ }
46
+
47
+ .status {
48
+ position: absolute;
49
+ bottom: 2px;
50
+ right: 2px;
51
+ width: 0.75rem;
52
+ height: 0.75rem;
53
+ border-radius: 50%;
54
+ border: 2px solid hsl(var(--background, 0 0% 4%));
55
+ }
56
+
57
+ .online { background: #00ff88; box-shadow: 0 0 6px #00ff88; }
58
+ .offline { background: #666; }
59
+ .busy { background: #ff0040; box-shadow: 0 0 6px #ff0040; }
60
+ .away { background: #ffaa00; box-shadow: 0 0 6px #ffaa00; }
@@ -0,0 +1,28 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, ImgHTMLAttributes } from 'react';
4
+ import styles from './cyber-avatar.module.css';
5
+
6
+ export interface CyberAvatarProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src'> {
7
+ src: string;
8
+ size?: 'sm' | 'md' | 'lg' | 'xl';
9
+ variant?: 'cyan' | 'pink' | 'green' | 'purple';
10
+ status?: 'online' | 'offline' | 'busy' | 'away';
11
+ glowing?: boolean;
12
+ }
13
+
14
+ export const CyberAvatar = forwardRef<HTMLDivElement, CyberAvatarProps>(
15
+ ({ src, alt = 'Avatar', size = 'md', variant = 'cyan', status, glowing = false, className, ...props }, ref) => {
16
+ const classes = [styles.avatar, styles[size], styles[variant], glowing && styles.glowing, className].filter(Boolean).join(' ');
17
+ return (
18
+ <div ref={ref} className={classes}>
19
+ <img src={src} alt={alt} className={styles.image} {...props} />
20
+ <div className={styles.border} />
21
+ {status && <span className={`${styles.status} ${styles[status]}`} />}
22
+ </div>
23
+ );
24
+ }
25
+ );
26
+
27
+ CyberAvatar.displayName = 'CyberAvatar';
28
+ export default CyberAvatar;
@@ -0,0 +1,46 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, ImgHTMLAttributes } from 'react';
4
+
5
+ export interface CyberAvatarProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src'> {
6
+ src: string;
7
+ size?: 'sm' | 'md' | 'lg' | 'xl';
8
+ variant?: 'cyan' | 'pink' | 'green' | 'purple';
9
+ status?: 'online' | 'offline' | 'busy' | 'away';
10
+ glowing?: boolean;
11
+ }
12
+
13
+ const sizeStyles = { sm: 'w-8 h-8', md: 'w-12 h-12', lg: 'w-16 h-16', xl: 'w-24 h-24' };
14
+ const variantStyles = {
15
+ cyan: 'border-cyan-400 shadow-[0_0_10px_#00f0ff]',
16
+ pink: 'border-fuchsia-500 shadow-[0_0_10px_#ff00ff]',
17
+ green: 'border-emerald-400 shadow-[0_0_10px_#00ff88]',
18
+ purple: 'border-purple-500 shadow-[0_0_10px_#a855f7]',
19
+ };
20
+ const statusStyles = {
21
+ online: 'bg-emerald-400 shadow-[0_0_6px_#00ff88]',
22
+ offline: 'bg-gray-500',
23
+ busy: 'bg-rose-500 shadow-[0_0_6px_#ff0040]',
24
+ away: 'bg-amber-500 shadow-[0_0_6px_#ffaa00]',
25
+ };
26
+
27
+ export const CyberAvatar = forwardRef<HTMLDivElement, CyberAvatarProps>(
28
+ ({ src, alt = 'Avatar', size = 'md', variant = 'cyan', status, glowing = false, className = '', ...props }, ref) => {
29
+ return (
30
+ <div ref={ref} className={`relative ${sizeStyles[size]} ${className}`}>
31
+ <img
32
+ src={src}
33
+ alt={alt}
34
+ className={`w-full h-full object-cover rounded-full border-2 ${variantStyles[variant]} ${glowing ? 'animate-pulse' : ''}`}
35
+ {...props}
36
+ />
37
+ {status && (
38
+ <span className={`absolute bottom-0.5 right-0.5 w-3 h-3 rounded-full border-2 border-[#0a0a0f] ${statusStyles[status]}`} />
39
+ )}
40
+ </div>
41
+ );
42
+ }
43
+ );
44
+
45
+ CyberAvatar.displayName = 'CyberAvatar';
46
+ export default CyberAvatar;
@@ -0,0 +1,87 @@
1
+ .wrapper {
2
+ --input-color: #00f0ff;
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 0.5rem;
6
+ }
7
+
8
+ .cyan { --input-color: #00f0ff; }
9
+ .pink { --input-color: #ff00ff; }
10
+ .green { --input-color: #00ff88; }
11
+ .purple { --input-color: #a855f7; }
12
+ .hasError { --input-color: #ff0040; }
13
+
14
+ .label {
15
+ font-family: var(--font-display, 'Rajdhani', sans-serif);
16
+ font-size: 0.75rem;
17
+ font-weight: 600;
18
+ text-transform: uppercase;
19
+ letter-spacing: 0.125em;
20
+ color: var(--input-color);
21
+ }
22
+
23
+ .inputWrapper {
24
+ position: relative;
25
+ display: flex;
26
+ align-items: center;
27
+ }
28
+
29
+ .input {
30
+ width: 100%;
31
+ padding: 0.75rem 1rem;
32
+ font-family: var(--font-mono, 'Share Tech Mono', monospace);
33
+ font-size: 0.875rem;
34
+ color: hsl(var(--foreground, 0 0% 98%));
35
+ background: rgba(0, 0, 0, 0.5);
36
+ border: 1px solid rgba(255, 255, 255, 0.1);
37
+ border-radius: 0;
38
+ outline: none;
39
+ transition: all 0.3s ease;
40
+ }
41
+
42
+ .input::placeholder {
43
+ color: rgba(255, 255, 255, 0.3);
44
+ }
45
+
46
+ .input:focus {
47
+ border-color: var(--input-color);
48
+ box-shadow: 0 0 10px rgba(0, 240, 255, 0.3);
49
+ }
50
+
51
+ .border {
52
+ position: absolute;
53
+ bottom: 0;
54
+ left: 0;
55
+ width: 0;
56
+ height: 2px;
57
+ background: var(--input-color);
58
+ transition: width 0.3s ease;
59
+ }
60
+
61
+ .input:focus ~ .border {
62
+ width: 100%;
63
+ }
64
+
65
+ .glow {
66
+ position: absolute;
67
+ bottom: 0;
68
+ left: 50%;
69
+ width: 0;
70
+ height: 1.25rem;
71
+ background: radial-gradient(ellipse, var(--input-color), transparent);
72
+ opacity: 0;
73
+ transform: translateX(-50%);
74
+ transition: all 0.3s ease;
75
+ pointer-events: none;
76
+ }
77
+
78
+ .input:focus ~ .glow {
79
+ width: 80%;
80
+ opacity: 0.3;
81
+ }
82
+
83
+ .error {
84
+ font-family: var(--font-mono, 'Share Tech Mono', monospace);
85
+ font-size: 0.75rem;
86
+ color: #ff0040;
87
+ }
@@ -0,0 +1,49 @@
1
+ 'use client';
2
+
3
+ import { forwardRef, InputHTMLAttributes } from 'react';
4
+ import styles from './cyber-input.module.css';
5
+
6
+ export interface CyberInputProps extends InputHTMLAttributes<HTMLInputElement> {
7
+ /** Neon color variant */
8
+ variant?: 'cyan' | 'pink' | 'green' | 'purple';
9
+ /** Label above input */
10
+ label?: string;
11
+ /** Error message */
12
+ error?: string;
13
+ }
14
+
15
+ export const CyberInput = forwardRef<HTMLInputElement, CyberInputProps>(
16
+ (
17
+ {
18
+ variant = 'cyan',
19
+ label,
20
+ error,
21
+ className,
22
+ ...props
23
+ },
24
+ ref
25
+ ) => {
26
+ const wrapperClasses = [
27
+ styles.wrapper,
28
+ styles[variant],
29
+ error && styles.hasError,
30
+ className,
31
+ ].filter(Boolean).join(' ');
32
+
33
+ return (
34
+ <div className={wrapperClasses}>
35
+ {label && <label className={styles.label}>{label}</label>}
36
+ <div className={styles.inputWrapper}>
37
+ <input ref={ref} className={styles.input} {...props} />
38
+ <span className={styles.border} />
39
+ <span className={styles.glow} />
40
+ </div>
41
+ {error && <span className={styles.error}>{error}</span>}
42
+ </div>
43
+ );
44
+ }
45
+ );
46
+
47
+ CyberInput.displayName = 'CyberInput';
48
+
49
+ export default CyberInput;