canny-ui 1.0.0 → 3.0.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.
@@ -31,7 +31,7 @@
31
31
  }
32
32
 
33
33
  .cny-sidebar-section {
34
- margin-bottom: $space-6;
34
+ margin-bottom: $space-5;
35
35
 
36
36
  &:last-child {
37
37
  margin-bottom: 0;
@@ -39,13 +39,26 @@
39
39
  }
40
40
 
41
41
  .cny-sidebar-title {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 8px;
42
45
  font-size: 0.6875rem;
43
46
  font-weight: 650;
44
- letter-spacing: 0.08em;
47
+ letter-spacing: 0.1em;
45
48
  text-transform: uppercase;
46
49
  color: var(--text-muted);
47
- padding: 0 $space-2;
48
- margin: 0 0 $space-3;
50
+ padding: 0 10px;
51
+ margin: 0 0 10px;
52
+
53
+ &::before {
54
+ content: '';
55
+ width: 3px;
56
+ height: 3px;
57
+ border-radius: 50%;
58
+ background: currentColor;
59
+ opacity: 0.55;
60
+ flex-shrink: 0;
61
+ }
49
62
  }
50
63
 
51
64
  .cny-sidebar-nav {
@@ -58,34 +71,44 @@
58
71
  display: flex;
59
72
  align-items: center;
60
73
  gap: $space-2;
61
- padding: 6px $space-2;
74
+ padding: 7px 10px;
62
75
  border-radius: var(--radius-sm);
63
- font-size: 0.84375rem;
76
+ font-size: 0.8125rem;
64
77
  color: var(--text-secondary);
65
78
  text-decoration: none;
66
79
  position: relative;
67
- transition: background-color var(--transition-fast), color var(--transition-fast);
80
+ transition:
81
+ background-color 160ms ease,
82
+ color 160ms ease,
83
+ transform 160ms ease;
68
84
 
69
85
  &:hover {
70
86
  background: var(--bg-surface-low);
71
87
  color: var(--text-primary);
72
88
  }
73
89
 
90
+ &:active { transform: translateX(0.5px); }
91
+
74
92
  &.active {
75
93
  color: var(--color-primary);
76
94
  font-weight: 550;
77
- background: color-mix(in srgb, var(--color-primary) 8%, transparent);
95
+ background: linear-gradient(
96
+ 90deg,
97
+ color-mix(in srgb, var(--color-primary) 13%, transparent),
98
+ color-mix(in srgb, var(--color-primary) 4%, transparent)
99
+ );
78
100
 
79
101
  &::before {
80
102
  content: '';
81
103
  position: absolute;
82
- left: calc(-1 * #{$space-5});
104
+ left: 0;
83
105
  top: 50%;
84
106
  transform: translateY(-50%);
85
- width: 2px;
86
- height: 16px;
107
+ width: 3px;
108
+ height: 14px;
87
109
  background: var(--color-primary);
88
110
  border-radius: 0 2px 2px 0;
111
+ box-shadow: 0 0 8px color-mix(in srgb, var(--color-primary) 50%, transparent);
89
112
  }
90
113
  }
91
114
 
@@ -104,6 +127,28 @@
104
127
 
105
128
  .cny-sidebar-item-badge {
106
129
  margin-left: auto;
130
+ font-size: 9.5px;
131
+ font-weight: 700;
132
+ letter-spacing: 0.04em;
133
+ padding: 1px 6px;
134
+ line-height: 1.4;
135
+ text-transform: lowercase;
136
+ }
137
+ }
138
+
139
+ // Themed scrollbar for sidebar content
140
+ .cny-sidebar {
141
+ scrollbar-width: thin;
142
+ scrollbar-color: var(--border-color) transparent;
143
+
144
+ &::-webkit-scrollbar { width: 6px; }
145
+ &::-webkit-scrollbar-track { background: transparent; }
146
+ &::-webkit-scrollbar-thumb {
147
+ background: var(--border-color);
148
+ border-radius: 3px;
149
+ }
150
+ &::-webkit-scrollbar-thumb:hover {
151
+ background: var(--border-color-strong);
107
152
  }
108
153
  }
109
154
 
@@ -0,0 +1,95 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // Slider — flat track + filled range + circular thumb.
4
+
5
+ .cny-slider {
6
+ --slider-accent: var(--color-primary);
7
+
8
+ position: relative;
9
+ display: flex;
10
+ align-items: center;
11
+ user-select: none;
12
+ touch-action: none;
13
+ width: 100%;
14
+ height: 20px;
15
+
16
+ &-track {
17
+ position: relative;
18
+ flex: 1;
19
+ background: var(--bg-surface-low);
20
+ border-radius: 999px;
21
+ height: 4px;
22
+ overflow: hidden;
23
+ }
24
+
25
+ &-range {
26
+ position: absolute;
27
+ background: var(--slider-accent);
28
+ border-radius: 999px;
29
+ height: 100%;
30
+ }
31
+
32
+ &-thumb {
33
+ display: block;
34
+ width: 16px;
35
+ height: 16px;
36
+ background: var(--bg-surface-lowest);
37
+ border: 2px solid var(--slider-accent);
38
+ border-radius: 50%;
39
+ cursor: grab;
40
+ transition: transform 120ms ease, box-shadow 120ms ease;
41
+
42
+ &:hover { transform: scale(1.08); }
43
+ &:active { cursor: grabbing; }
44
+ &:focus-visible {
45
+ outline: 2px solid var(--slider-accent);
46
+ outline-offset: 2px;
47
+ }
48
+ }
49
+
50
+ &-bubble {
51
+ position: absolute;
52
+ bottom: calc(100% + 6px);
53
+ left: 50%;
54
+ transform: translateX(-50%);
55
+ background: var(--text-primary);
56
+ color: var(--bg-surface-lowest);
57
+ font-size: 11px;
58
+ font-weight: 500;
59
+ padding: 2px 6px;
60
+ border-radius: var(--radius-sm);
61
+ white-space: nowrap;
62
+ pointer-events: none;
63
+ opacity: 0;
64
+ transition: opacity 120ms ease;
65
+ }
66
+
67
+ &-thumb:hover &-bubble,
68
+ &-thumb:focus-visible &-bubble,
69
+ &-thumb[data-state='active'] &-bubble { opacity: 1; }
70
+
71
+ &[data-disabled] {
72
+ opacity: 0.5;
73
+ .cny-slider-thumb { cursor: not-allowed; }
74
+ }
75
+
76
+ // Sizes
77
+ &-sm { height: 16px; .cny-slider-track { height: 3px; } .cny-slider-thumb { width: 12px; height: 12px; } }
78
+ &-lg { height: 24px; .cny-slider-track { height: 6px; } .cny-slider-thumb { width: 20px; height: 20px; } }
79
+
80
+ // Colors
81
+ &-success { --slider-accent: var(--color-success); }
82
+ &-warning { --slider-accent: var(--color-warning); }
83
+ &-danger { --slider-accent: var(--color-danger); }
84
+
85
+ // Vertical orientation
86
+ &[data-orientation='vertical'] {
87
+ flex-direction: column;
88
+ width: 20px;
89
+ height: 100%;
90
+ min-height: 120px;
91
+
92
+ .cny-slider-track { width: 4px; height: 100%; flex: 1; }
93
+ .cny-slider-range { width: 100%; height: auto; }
94
+ }
95
+ }
@@ -0,0 +1,125 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // Stepper — wizard / multi-step progress trail.
4
+
5
+ .cny-stepper {
6
+ list-style: none;
7
+ margin: 0;
8
+ padding: 0;
9
+ font-family: var(--font-body);
10
+
11
+ &-step {
12
+ display: flex;
13
+ align-items: center;
14
+ min-width: 0;
15
+ }
16
+
17
+ &-step-row {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: $space-2;
21
+ padding: 0;
22
+ background: transparent;
23
+ border: 0;
24
+ color: inherit;
25
+ text-align: left;
26
+ cursor: default;
27
+ border-radius: var(--radius-sm);
28
+ min-width: 0;
29
+
30
+ &:not(:disabled) {
31
+ cursor: pointer;
32
+ &:hover .cny-stepper-label { color: var(--text-primary); }
33
+ }
34
+ &:focus-visible {
35
+ outline: 2px solid var(--color-primary);
36
+ outline-offset: 2px;
37
+ }
38
+ }
39
+
40
+ &-marker {
41
+ flex: none;
42
+ display: inline-flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ width: 24px;
46
+ height: 24px;
47
+ border-radius: 50%;
48
+ font-size: 0.75rem;
49
+ font-weight: 600;
50
+ border: 1px solid var(--border-color);
51
+ background: var(--bg-surface-lowest);
52
+ color: var(--text-muted);
53
+ }
54
+
55
+ &-text {
56
+ display: flex;
57
+ flex-direction: column;
58
+ min-width: 0;
59
+ line-height: 1.3;
60
+ }
61
+
62
+ &-label {
63
+ font-size: 0.8125rem;
64
+ font-weight: 500;
65
+ color: var(--text-secondary);
66
+ }
67
+
68
+ &-desc {
69
+ font-size: 0.75rem;
70
+ color: var(--text-muted);
71
+ }
72
+
73
+ &-connector {
74
+ flex: 1 1 auto;
75
+ background: var(--border-color);
76
+ }
77
+
78
+ // States
79
+ &-step.is-active {
80
+ .cny-stepper-marker {
81
+ background: var(--color-primary);
82
+ border-color: var(--color-primary);
83
+ color: var(--color-primary-on);
84
+ }
85
+ .cny-stepper-label { color: var(--text-primary); font-weight: 600; }
86
+ }
87
+ &-step.is-complete {
88
+ .cny-stepper-marker {
89
+ background: var(--color-success);
90
+ border-color: var(--color-success);
91
+ color: var(--color-success-on);
92
+ }
93
+ .cny-stepper-label { color: var(--text-primary); }
94
+ & + .cny-stepper-step .cny-stepper-connector,
95
+ .cny-stepper-connector { background: var(--color-success); }
96
+ }
97
+
98
+ // Horizontal
99
+ &-horizontal {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: $space-2;
103
+
104
+ .cny-stepper-step { flex: 0 1 auto; }
105
+ .cny-stepper-step:not(:last-child) { flex: 1 1 0; }
106
+ .cny-stepper-connector { height: 2px; margin: 0 $space-2; min-width: 12px; }
107
+ }
108
+
109
+ // Vertical
110
+ &-vertical {
111
+ display: flex;
112
+ flex-direction: column;
113
+ gap: $space-2;
114
+
115
+ .cny-stepper-step { flex-direction: column; align-items: flex-start; gap: 4px; }
116
+ .cny-stepper-connector { width: 2px; min-height: 16px; margin-left: 11px; }
117
+ }
118
+
119
+ // Sizes
120
+ &-sm {
121
+ .cny-stepper-marker { width: 20px; height: 20px; font-size: 0.7rem; }
122
+ .cny-stepper-label { font-size: 0.75rem; }
123
+ .cny-stepper-desc { font-size: 0.7rem; }
124
+ }
125
+ }
@@ -0,0 +1,148 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // Tabs — three variants: line (default), pills, segmented.
4
+
5
+ .cny-tabs {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 16px;
9
+
10
+ &[data-orientation='vertical'] {
11
+ flex-direction: row;
12
+ align-items: flex-start;
13
+ gap: 24px;
14
+ }
15
+ }
16
+
17
+ // ── List ──────────────────────────────────────────────────────
18
+ .cny-tabs-list {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ position: relative;
22
+ flex-wrap: wrap;
23
+
24
+ .cny-tabs[data-orientation='vertical'] & {
25
+ flex-direction: column;
26
+ align-items: stretch;
27
+ flex-wrap: nowrap;
28
+ }
29
+ }
30
+
31
+ // ── Trigger ───────────────────────────────────────────────────
32
+ .cny-tabs-trigger {
33
+ display: inline-flex;
34
+ align-items: center;
35
+ gap: 8px;
36
+ background: transparent;
37
+ border: 0;
38
+ font-family: var(--font-body);
39
+ font-size: 0.875rem;
40
+ font-weight: 550;
41
+ color: var(--text-muted);
42
+ cursor: pointer;
43
+ white-space: nowrap;
44
+ transition: color 140ms ease, background-color 140ms ease, box-shadow 140ms ease;
45
+
46
+ &-icon { display: inline-flex; align-items: center; }
47
+ &-badge { display: inline-flex; align-items: center; }
48
+
49
+ &:hover { color: var(--text-secondary); }
50
+ &:focus-visible {
51
+ outline: 2px solid color-mix(in srgb, var(--color-primary) 60%, transparent);
52
+ outline-offset: 2px;
53
+ border-radius: var(--radius-xs);
54
+ }
55
+ &:disabled,
56
+ &[data-disabled] { opacity: 0.5; cursor: not-allowed; }
57
+ }
58
+
59
+ // ── Sizes ─────────────────────────────────────────────────────
60
+ .cny-tabs.size-sm .cny-tabs-trigger { font-size: 0.8125rem; }
61
+ .cny-tabs.size-lg .cny-tabs-trigger { font-size: 0.9375rem; }
62
+
63
+ // ── Variant: line (underline) ─────────────────────────────────
64
+ .cny-tabs.variant-line {
65
+ .cny-tabs-list {
66
+ border-bottom: 1px solid var(--hairline-color);
67
+ gap: 4px;
68
+ }
69
+ .cny-tabs-trigger {
70
+ padding: 10px 14px;
71
+ margin-bottom: -1px;
72
+ border-bottom: 2px solid transparent;
73
+
74
+ &[data-state='active'] {
75
+ color: var(--color-primary);
76
+ border-bottom-color: var(--color-primary);
77
+ }
78
+ }
79
+
80
+ &.size-sm .cny-tabs-trigger { padding: 7px 10px; }
81
+ &.size-lg .cny-tabs-trigger { padding: 13px 18px; }
82
+ }
83
+
84
+ .cny-tabs.variant-line[data-orientation='vertical'] {
85
+ .cny-tabs-list { border-bottom: 0; border-right: 1px solid var(--hairline-color); }
86
+ .cny-tabs-trigger {
87
+ margin-bottom: 0;
88
+ margin-right: -1px;
89
+ border-bottom: 0;
90
+ border-right: 2px solid transparent;
91
+ justify-content: flex-start;
92
+ text-align: left;
93
+ &[data-state='active'] { border-right-color: var(--color-primary); border-bottom: 0; }
94
+ }
95
+ }
96
+
97
+ // ── Variant: pills ────────────────────────────────────────────
98
+ .cny-tabs.variant-pills {
99
+ .cny-tabs-list { gap: 4px; }
100
+ .cny-tabs-trigger {
101
+ padding: 7px 12px;
102
+ border-radius: 999px;
103
+
104
+ &:hover { background: var(--bg-surface-low); }
105
+ &[data-state='active'] {
106
+ color: var(--color-primary);
107
+ background: color-mix(in srgb, var(--color-primary) 12%, transparent);
108
+ }
109
+ }
110
+ &.size-sm .cny-tabs-trigger { padding: 5px 10px; }
111
+ &.size-lg .cny-tabs-trigger { padding: 9px 14px; }
112
+ }
113
+
114
+ // ── Variant: segmented ────────────────────────────────────────
115
+ .cny-tabs.variant-segmented {
116
+ .cny-tabs-list {
117
+ padding: 4px;
118
+ background: var(--bg-surface-low);
119
+ border: 1px solid var(--hairline-color);
120
+ border-radius: 999px;
121
+ gap: 2px;
122
+ }
123
+ .cny-tabs-trigger {
124
+ padding: 6px 14px;
125
+ border-radius: 999px;
126
+
127
+ &:hover { color: var(--text-primary); }
128
+ &[data-state='active'] {
129
+ color: var(--text-primary);
130
+ background: var(--bg-surface-lowest);
131
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), inset 0 0 0 1px var(--hairline-color);
132
+ }
133
+ }
134
+ &.size-sm .cny-tabs-trigger { padding: 4px 10px; }
135
+ &.size-lg .cny-tabs-trigger { padding: 8px 18px; }
136
+ }
137
+
138
+ // ── Content panel ─────────────────────────────────────────────
139
+ .cny-tabs-content {
140
+ outline: none;
141
+ flex: 1 1 auto;
142
+
143
+ &:focus-visible {
144
+ outline: 2px solid var(--color-primary);
145
+ outline-offset: 2px;
146
+ border-radius: var(--radius-xs);
147
+ }
148
+ }