canny-ui 3.0.0 → 5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canny-ui",
3
- "version": "3.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Pure CSS foundation for the Canny-UI design system — tokens, layout utilities, and a battery of enterprise components, shipped as one flat stylesheet.",
5
5
  "main": "dist/canny-ui.min.css",
6
6
  "style": "dist/canny-ui.min.css",
package/src/canny-ui.scss CHANGED
@@ -22,11 +22,19 @@
22
22
  @use 'components/command-palette';
23
23
  @use 'components/toast';
24
24
  @use 'components/dialog';
25
+ @use 'components/confirm';
25
26
  @use 'components/drawer';
26
27
  @use 'components/menu';
27
28
  @use 'components/tooltip-radix';
28
29
  @use 'components/popover';
29
30
  @use 'components/chip';
31
+ @use 'components/badge';
32
+ @use 'components/timeline';
33
+ @use 'components/tree';
34
+ @use 'components/uploader';
35
+ @use 'components/panels';
36
+ @use 'components/datatable';
37
+ @use 'components/charts';
30
38
  @use 'components/list';
31
39
  @use 'components/tabs';
32
40
  @use 'components/autocomplete';
@@ -0,0 +1,50 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // Badge — count / dot indicator anchored to a child, or standalone.
4
+
5
+ .cny-badge {
6
+ position: relative;
7
+ display: inline-flex;
8
+ vertical-align: middle;
9
+
10
+ &-standalone { display: inline-flex; }
11
+
12
+ &-indicator {
13
+ --badge-bg: var(--color-danger);
14
+ --badge-fg: var(--color-danger-on);
15
+
16
+ display: inline-flex;
17
+ align-items: center;
18
+ justify-content: center;
19
+ box-sizing: border-box;
20
+ min-width: 18px;
21
+ height: 18px;
22
+ padding: 0 5px;
23
+ border-radius: $radius-full;
24
+ font-family: var(--font-body);
25
+ font-size: 0.6875rem;
26
+ font-weight: 600;
27
+ line-height: 1;
28
+ color: var(--badge-fg);
29
+ background: var(--badge-bg);
30
+ }
31
+
32
+ &-dot {
33
+ min-width: 8px;
34
+ width: 8px;
35
+ height: 8px;
36
+ padding: 0;
37
+ }
38
+
39
+ &-top-right { position: absolute; top: 0; right: 0; transform: translate(50%, -50%); }
40
+ &-top-left { position: absolute; top: 0; left: 0; transform: translate(-50%, -50%); }
41
+ &-bottom-right { position: absolute; bottom: 0; right: 0; transform: translate(50%, 50%); }
42
+ &-bottom-left { position: absolute; bottom: 0; left: 0; transform: translate(-50%, 50%); }
43
+
44
+ &-primary { --badge-bg: var(--color-primary); --badge-fg: var(--color-primary-on); }
45
+ &-success { --badge-bg: var(--color-success); --badge-fg: var(--color-success-on); }
46
+ &-warning { --badge-bg: var(--color-warning); --badge-fg: var(--color-warning-on); }
47
+ &-danger { --badge-bg: var(--color-danger); --badge-fg: var(--color-danger-on); }
48
+ &-info { --badge-bg: var(--color-info); --badge-fg: var(--color-info-on); }
49
+ &-neutral { --badge-bg: var(--color-neutral); --badge-fg: var(--color-neutral-on); }
50
+ }
@@ -0,0 +1,130 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // Charts — from-scratch SVG bar & donut charts.
4
+
5
+ .cny-chart {
6
+ width: 100%;
7
+ font-family: var(--font-body);
8
+ }
9
+
10
+ .cny-chart-responsive {
11
+ display: block;
12
+ }
13
+
14
+ .cny-chart-grid {
15
+ stroke: var(--hairline-color);
16
+ stroke-width: 1;
17
+ }
18
+
19
+ .cny-chart-axis {
20
+ fill: var(--text-muted);
21
+ font-size: 0.6875rem;
22
+ }
23
+
24
+ .cny-chart-bar {
25
+ transition: opacity 120ms ease;
26
+
27
+ &:hover {
28
+ opacity: 0.85;
29
+ }
30
+ }
31
+
32
+ .cny-chart-line {
33
+ stroke-width: 2;
34
+ stroke-linejoin: round;
35
+ stroke-linecap: round;
36
+ }
37
+
38
+ .cny-chart-area {
39
+ opacity: 0.16;
40
+ }
41
+
42
+ .cny-chart-dot {
43
+ stroke: var(--bg-surface-lowest);
44
+ stroke-width: 1.5;
45
+ }
46
+
47
+ .cny-chart-slice {
48
+ stroke: var(--bg-surface-lowest);
49
+ stroke-width: 2;
50
+ transition: opacity 120ms ease;
51
+
52
+ &.is-active {
53
+ opacity: 0.85;
54
+ }
55
+ }
56
+
57
+ .cny-chart-center {
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ width: 100%;
62
+ height: 100%;
63
+ text-align: center;
64
+ font-size: 0.875rem;
65
+ font-weight: 600;
66
+ color: var(--text-primary);
67
+ }
68
+
69
+ // floating tooltip
70
+ .cny-chart-tooltip {
71
+ position: absolute;
72
+ transform: translate(-50%, calc(-100% - 8px));
73
+ min-width: 120px;
74
+ padding: $space-2 $space-3;
75
+ border-radius: $radius-md;
76
+ background: var(--bg-surface-lowest);
77
+ border: 1px solid var(--border-color);
78
+ box-shadow: var(--shadow-md);
79
+ font-size: 0.75rem;
80
+ color: var(--text-primary);
81
+ pointer-events: none;
82
+ z-index: 2;
83
+ }
84
+
85
+ .cny-chart-tooltip-title {
86
+ font-weight: 600;
87
+ margin-bottom: 4px;
88
+ }
89
+
90
+ .cny-chart-tooltip-row {
91
+ display: flex;
92
+ align-items: center;
93
+ gap: 6px;
94
+ line-height: 1.6;
95
+ }
96
+
97
+ .cny-chart-tooltip-label {
98
+ color: var(--text-secondary);
99
+ }
100
+
101
+ .cny-chart-tooltip-value {
102
+ margin-inline-start: auto;
103
+ font-weight: 600;
104
+ font-variant-numeric: tabular-nums;
105
+ }
106
+
107
+ // legend
108
+ .cny-chart-legend {
109
+ display: flex;
110
+ flex-wrap: wrap;
111
+ gap: $space-2 $space-4;
112
+ justify-content: center;
113
+ margin-top: $space-2;
114
+ font-size: 0.75rem;
115
+ color: var(--text-secondary);
116
+ }
117
+
118
+ .cny-chart-legend-item {
119
+ display: inline-flex;
120
+ align-items: center;
121
+ gap: 6px;
122
+ }
123
+
124
+ .cny-chart-swatch {
125
+ display: inline-block;
126
+ width: 10px;
127
+ height: 10px;
128
+ border-radius: 3px;
129
+ flex: none;
130
+ }
@@ -0,0 +1,11 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // ConfirmDialog — preset on Dialog. Inherits dialog chrome; only the body copy is styled.
4
+
5
+ .cny-confirm-message {
6
+ margin: 0;
7
+ font-family: var(--font-body);
8
+ font-size: 0.875rem;
9
+ line-height: 1.5;
10
+ color: var(--text-secondary);
11
+ }
@@ -0,0 +1,176 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // DataTable — server-driven data grid (sorting header, selection, pagination footer).
4
+
5
+ .cny-dt {
6
+ display: flex;
7
+ flex-direction: column;
8
+ width: 100%;
9
+ border: 1px solid var(--border-color);
10
+ border-radius: $radius-lg;
11
+ background: var(--bg-surface-lowest);
12
+ overflow: hidden;
13
+ font-family: var(--font-body);
14
+ }
15
+
16
+ // horizontal scroll keeps the grid responsive on narrow screens
17
+ .cny-dt-scroll {
18
+ width: 100%;
19
+ overflow-x: auto;
20
+ }
21
+
22
+ .cny-dt-table {
23
+ width: 100%;
24
+ border-collapse: collapse;
25
+ font-size: 0.875rem;
26
+ color: var(--text-primary);
27
+
28
+ th,
29
+ td {
30
+ padding: $space-3 $space-4;
31
+ text-align: left;
32
+ vertical-align: middle;
33
+ white-space: nowrap;
34
+ }
35
+
36
+ thead th {
37
+ position: sticky;
38
+ top: 0;
39
+ z-index: 1;
40
+ font-size: 0.75rem;
41
+ font-weight: 600;
42
+ color: var(--text-muted);
43
+ text-transform: uppercase;
44
+ letter-spacing: 0.04em;
45
+ background: var(--bg-surface-low);
46
+ border-bottom: 1px solid var(--border-color);
47
+ }
48
+
49
+ tbody td {
50
+ border-bottom: 1px solid var(--hairline-color);
51
+ }
52
+
53
+ tbody tr:last-child td {
54
+ border-bottom: 0;
55
+ }
56
+ }
57
+
58
+ .cny-dt-left {
59
+ text-align: left;
60
+ }
61
+ .cny-dt-center {
62
+ text-align: center;
63
+ }
64
+ .cny-dt-right {
65
+ text-align: right;
66
+ }
67
+
68
+ .cny-dt-th-inner {
69
+ display: inline-flex;
70
+ align-items: center;
71
+ gap: 4px;
72
+ }
73
+
74
+ // right-aligned headers push the sort affordance to the correct edge
75
+ .cny-dt-right .cny-dt-th-inner {
76
+ flex-direction: row-reverse;
77
+ }
78
+ .cny-dt-center .cny-dt-th-inner {
79
+ justify-content: center;
80
+ }
81
+
82
+ .cny-dt-sortable {
83
+ cursor: pointer;
84
+ user-select: none;
85
+ transition: color 120ms ease;
86
+
87
+ &:hover {
88
+ color: var(--text-primary);
89
+ }
90
+
91
+ &.is-sorted {
92
+ color: var(--color-primary);
93
+ }
94
+ }
95
+
96
+ .cny-dt-sort-icon {
97
+ display: inline-flex;
98
+ align-items: center;
99
+ opacity: 0.5;
100
+ }
101
+
102
+ // drag-to-resize handle on the right edge of each header cell
103
+ .cny-dt-resizer {
104
+ position: absolute;
105
+ top: 0;
106
+ right: 0;
107
+ width: 9px;
108
+ height: 100%;
109
+ cursor: col-resize;
110
+ user-select: none;
111
+ touch-action: none;
112
+
113
+ &::after {
114
+ content: '';
115
+ position: absolute;
116
+ top: 20%;
117
+ right: 4px;
118
+ width: 2px;
119
+ height: 60%;
120
+ border-radius: 2px;
121
+ background: transparent;
122
+ transition: background-color 120ms ease;
123
+ }
124
+
125
+ &:hover::after {
126
+ background: var(--color-primary);
127
+ }
128
+ }
129
+
130
+ .cny-dt-sortable.is-sorted .cny-dt-sort-icon {
131
+ opacity: 1;
132
+ }
133
+
134
+ .cny-dt-row {
135
+ transition: background-color 120ms ease;
136
+
137
+ &.is-clickable {
138
+ cursor: pointer;
139
+ }
140
+
141
+ &:hover {
142
+ background: var(--bg-surface-low);
143
+ }
144
+
145
+ &.is-selected {
146
+ background: var(--color-primary-soft);
147
+ }
148
+ }
149
+
150
+ .cny-dt-checkbox-cell {
151
+ width: 1%;
152
+ white-space: nowrap;
153
+ text-align: center;
154
+ }
155
+
156
+ .cny-dt-empty {
157
+ padding: $space-8 $space-4;
158
+ text-align: center;
159
+ color: var(--text-muted);
160
+ }
161
+
162
+ .cny-dt-footer {
163
+ display: flex;
164
+ flex-wrap: wrap;
165
+ align-items: center;
166
+ justify-content: space-between;
167
+ gap: $space-2;
168
+ padding: $space-2 $space-3;
169
+ border-top: 1px solid var(--border-color);
170
+ background: var(--bg-surface-low);
171
+ }
172
+
173
+ .cny-dt-count {
174
+ font-size: 0.8125rem;
175
+ color: var(--text-muted);
176
+ }
@@ -0,0 +1,63 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // PanelGroup — resizable split panels. Percentage-based, so it fills any container responsively.
4
+
5
+ .cny-panel-group {
6
+ display: flex;
7
+ flex-direction: row;
8
+ width: 100%;
9
+ height: 100%;
10
+ overflow: hidden;
11
+
12
+ &.is-vertical {
13
+ flex-direction: column;
14
+ }
15
+ }
16
+
17
+ .cny-panel {
18
+ position: relative;
19
+ min-width: 0;
20
+ min-height: 0;
21
+ overflow: auto;
22
+ }
23
+
24
+ .cny-panel-handle {
25
+ position: relative;
26
+ flex: none;
27
+ align-self: stretch;
28
+ background: var(--hairline-color);
29
+ transition: background-color 120ms ease;
30
+ touch-action: none;
31
+ z-index: 1;
32
+
33
+ // generous invisible hit area around the thin visible line
34
+ &::before {
35
+ content: '';
36
+ position: absolute;
37
+ inset: -4px;
38
+ }
39
+
40
+ &:hover,
41
+ &:focus-visible {
42
+ background: var(--color-primary);
43
+ outline: none;
44
+ }
45
+
46
+ &-h {
47
+ width: 5px;
48
+ cursor: col-resize;
49
+ }
50
+
51
+ &-v {
52
+ height: 5px;
53
+ cursor: row-resize;
54
+ }
55
+
56
+ &[aria-disabled='true'] {
57
+ cursor: default;
58
+
59
+ &:hover {
60
+ background: var(--hairline-color);
61
+ }
62
+ }
63
+ }