@xsynaptic/sonic-ui 0.10.4 → 0.13.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 (119) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +39 -15
  3. package/dist/default/define/toggle.js +7 -0
  4. package/dist/default/define.js +1 -0
  5. package/dist/default/elements/button.js +7 -1
  6. package/dist/default/elements/dial.js +7 -1
  7. package/dist/default/elements/display-element.js +5 -1
  8. package/dist/default/elements/envelope.js +6 -1
  9. package/dist/default/elements/meter.js +1 -1
  10. package/dist/default/elements/number.js +7 -1
  11. package/dist/default/elements/position-group.js +163 -0
  12. package/dist/default/elements/radio-group.js +34 -12
  13. package/dist/default/elements/segmented.js +5 -1
  14. package/dist/default/elements/slider.js +7 -1
  15. package/dist/default/elements/sonic-element.js +1 -1
  16. package/dist/default/elements/switch.js +34 -168
  17. package/dist/default/elements/toggle.js +193 -0
  18. package/dist/default/elements/value-element.js +3 -0
  19. package/dist/default/elements/value-gestures.js +7 -0
  20. package/dist/default/elements/wave-element.js +8 -1
  21. package/dist/default/elements/waveform.js +159 -13
  22. package/dist/default/elements/wavestrip.js +4 -0
  23. package/dist/default/elements/xy.js +7 -1
  24. package/dist/default/index.js +2 -1
  25. package/dist/default/lib/key-press.js +27 -0
  26. package/dist/default/lib/toggle-travel.js +19 -0
  27. package/dist/default/lib/zoom-gesture.js +19 -0
  28. package/dist/dev/define/toggle.d.ts +2 -0
  29. package/dist/dev/define/toggle.js +8 -0
  30. package/dist/dev/define/toggle.js.map +1 -0
  31. package/dist/dev/define.d.ts +3 -1
  32. package/dist/dev/define.js +1 -0
  33. package/dist/dev/elements/button.js +7 -1
  34. package/dist/dev/elements/button.js.map +1 -1
  35. package/dist/dev/elements/dial.js +7 -1
  36. package/dist/dev/elements/dial.js.map +1 -1
  37. package/dist/dev/elements/display-element.js +5 -1
  38. package/dist/dev/elements/display-element.js.map +1 -1
  39. package/dist/dev/elements/envelope.js +6 -1
  40. package/dist/dev/elements/envelope.js.map +1 -1
  41. package/dist/dev/elements/meter.js +1 -1
  42. package/dist/dev/elements/meter.js.map +1 -1
  43. package/dist/dev/elements/number.js +7 -1
  44. package/dist/dev/elements/number.js.map +1 -1
  45. package/dist/dev/elements/position-group.d.ts +38 -0
  46. package/dist/dev/elements/position-group.js +164 -0
  47. package/dist/dev/elements/position-group.js.map +1 -0
  48. package/dist/dev/elements/radio-group.d.ts +4 -0
  49. package/dist/dev/elements/radio-group.js +34 -12
  50. package/dist/dev/elements/radio-group.js.map +1 -1
  51. package/dist/dev/elements/segmented.js +5 -1
  52. package/dist/dev/elements/segmented.js.map +1 -1
  53. package/dist/dev/elements/slider.js +7 -1
  54. package/dist/dev/elements/slider.js.map +1 -1
  55. package/dist/dev/elements/sonic-element.d.ts +16 -1
  56. package/dist/dev/elements/sonic-element.js +27 -5
  57. package/dist/dev/elements/sonic-element.js.map +1 -1
  58. package/dist/dev/elements/switch.d.ts +4 -19
  59. package/dist/dev/elements/switch.js +34 -168
  60. package/dist/dev/elements/switch.js.map +1 -1
  61. package/dist/dev/elements/toggle.d.ts +21 -0
  62. package/dist/dev/elements/toggle.js +201 -0
  63. package/dist/dev/elements/toggle.js.map +1 -0
  64. package/dist/dev/elements/value-element.d.ts +1 -0
  65. package/dist/dev/elements/value-element.js +3 -0
  66. package/dist/dev/elements/value-element.js.map +1 -1
  67. package/dist/dev/elements/value-gestures.js +7 -0
  68. package/dist/dev/elements/value-gestures.js.map +1 -1
  69. package/dist/dev/elements/wave-element.js +8 -1
  70. package/dist/dev/elements/wave-element.js.map +1 -1
  71. package/dist/dev/elements/waveform.d.ts +11 -1
  72. package/dist/dev/elements/waveform.js +159 -13
  73. package/dist/dev/elements/waveform.js.map +1 -1
  74. package/dist/dev/elements/wavestrip.d.ts +1 -0
  75. package/dist/dev/elements/wavestrip.js +4 -0
  76. package/dist/dev/elements/wavestrip.js.map +1 -1
  77. package/dist/dev/elements/xy.js +7 -1
  78. package/dist/dev/elements/xy.js.map +1 -1
  79. package/dist/dev/index.d.ts +3 -2
  80. package/dist/dev/index.js +2 -1
  81. package/dist/dev/lib/key-press.js +28 -0
  82. package/dist/dev/lib/key-press.js.map +1 -0
  83. package/dist/dev/lib/toggle-travel.js +20 -0
  84. package/dist/dev/lib/toggle-travel.js.map +1 -0
  85. package/dist/dev/lib/zoom-gesture.js +20 -0
  86. package/dist/dev/lib/zoom-gesture.js.map +1 -0
  87. package/dist/styles/button.css +5 -3
  88. package/dist/styles/controls.css +1 -0
  89. package/dist/styles/dial.css +3 -1
  90. package/dist/styles/envelope.css +3 -1
  91. package/dist/styles/led.css +19 -14
  92. package/dist/styles/material/arc.css +21 -0
  93. package/dist/styles/material/bracket.css +31 -0
  94. package/dist/styles/material/cap.css +179 -0
  95. package/dist/styles/material/core.css +103 -0
  96. package/dist/styles/material/glass.css +62 -0
  97. package/dist/styles/material/groove.css +10 -0
  98. package/dist/styles/material/keycap.css +95 -0
  99. package/dist/styles/material/lens.css +11 -0
  100. package/dist/styles/material/pane.css +97 -0
  101. package/dist/styles/material/readout.css +87 -0
  102. package/dist/styles/material/scale.css +30 -0
  103. package/dist/styles/material/value.css +43 -0
  104. package/dist/styles/material/well.css +24 -0
  105. package/dist/styles/material.css +15 -745
  106. package/dist/styles/meter.css +10 -7
  107. package/dist/styles/number.css +3 -1
  108. package/dist/styles/panel.css +3 -1
  109. package/dist/styles/ring.css +3 -1
  110. package/dist/styles/screen.css +3 -1
  111. package/dist/styles/segmented.css +11 -5
  112. package/dist/styles/slider.css +3 -1
  113. package/dist/styles/spectrum.css +5 -3
  114. package/dist/styles/switch.css +9 -3
  115. package/dist/styles/toggle.css +483 -0
  116. package/dist/styles/waveform.css +3 -1
  117. package/dist/styles/wavestrip.css +3 -1
  118. package/dist/styles/xy.css +3 -1
  119. package/package.json +3 -1
@@ -1,14 +1,15 @@
1
+ @layer sonic.material, sonic.control;
2
+
1
3
  @property --_sonic-led-size {
2
4
  syntax: '<length>';
3
5
  inherits: true;
4
6
  initial-value: 8px;
5
7
  }
6
8
 
7
- @layer sonic {
9
+ @layer sonic.control {
8
10
  .sonic-led {
9
11
  --_sonic-led-size: var(--sonic-led-size, 0.5rem);
10
12
  --_sonic-led-lens-ratio: var(--sonic-led-lens-ratio, calc(0.8 - 0.175 * var(--_sonic-relief)));
11
- --_sonic-lit-alt: var(--sonic-lit-alt, oklch(79% 0.2 150deg));
12
13
  --_sonic-unit: calc(var(--_sonic-led-size) / 8);
13
14
  --_sonic-led-modelled: calc(100% * var(--_sonic-relief));
14
15
  --_sonic-led-bezel: var(
@@ -45,9 +46,9 @@
45
46
  }
46
47
 
47
48
  @media (forced-colors: active) {
48
- --_sonic-lit-alt: Mark;
49
- --_sonic-hot: Highlight;
50
- --_sonic-clip: Mark;
49
+ --_sonic-lit-ok: Mark;
50
+ --_sonic-lit-warning: Highlight;
51
+ --_sonic-lit-danger: Mark;
51
52
 
52
53
  forced-color-adjust: none;
53
54
  background: none;
@@ -59,21 +60,21 @@
59
60
  }
60
61
  }
61
62
 
62
- .sonic-led[data-sonic-lit='alt'] {
63
- --_sonic-lit: var(--_sonic-lit-alt);
63
+ .sonic-led[data-sonic-lit='ok'] {
64
+ --_sonic-lit: var(--_sonic-lit-ok);
64
65
  }
65
66
 
66
- .sonic-led[data-sonic-lit='hot'] {
67
- --_sonic-lit: var(--_sonic-hot);
67
+ .sonic-led[data-sonic-lit='warning'] {
68
+ --_sonic-lit: var(--_sonic-lit-warning);
68
69
  }
69
70
 
70
- .sonic-led[data-sonic-lit='clip'] {
71
- --_sonic-lit: var(--_sonic-clip);
71
+ .sonic-led[data-sonic-lit='danger'] {
72
+ --_sonic-lit: var(--_sonic-lit-danger);
72
73
  }
73
74
 
74
75
  /* Before the lit rule, which a latched button's LED also matches */
75
76
  .sonic-led:is(
76
- [data-sonic-lit='dim'],
77
+ [data-sonic-lit='idle'],
77
78
  :where(:is([armed], [busy]) > .sonic-button:not(:disabled, [aria-disabled='true'])) *
78
79
  ) {
79
80
  &::after {
@@ -91,11 +92,15 @@
91
92
  }
92
93
 
93
94
  .sonic-led:is(
94
- [data-sonic-lit]:where(:not([data-sonic-lit='dim'])),
95
+ [data-sonic-lit]:where(:not([data-sonic-lit='idle'])),
95
96
  :where(
96
97
  .sonic-button[aria-pressed='true'],
97
98
  [momentary]:state(pressed) > .sonic-button,
98
- .sonic-segmented-option[aria-checked='true']
99
+ .sonic-segmented-option[aria-checked='true'],
100
+ .sonic-toggle:has(
101
+ > [role='switch'][aria-checked='true'],
102
+ > [aria-checked='true'] [data-sonic-lit]
103
+ )
99
104
  )
100
105
  *,
101
106
  :where(:state(at-origin):not(:disabled) > .sonic-led)
@@ -0,0 +1,21 @@
1
+ @layer sonic.material {
2
+ /* On the parts, since a recipe's `var()`s resolve where it is declared */
3
+
4
+ .sonic-dial-ring,
5
+ .sonic-dial-modulation,
6
+ .sonic-ring::before {
7
+ --_sonic-arc-mask: radial-gradient(
8
+ closest-side,
9
+ transparent calc(100% - var(--_sonic-arc-width) - 0.5px),
10
+ #000 calc(100% - var(--_sonic-arc-width)),
11
+ #000 calc(100% - var(--_sonic-arc-inset) - 0.5px),
12
+ transparent calc(100% - var(--_sonic-arc-inset))
13
+ );
14
+ --_sonic-arc-shade: radial-gradient(
15
+ closest-side,
16
+ rgb(0 0 0 / calc(0.55 * var(--_sonic-relief))) calc(100% - var(--_sonic-arc-width)),
17
+ transparent calc(100% - var(--_sonic-arc-width) * 0.4),
18
+ rgb(0 0 0 / calc(0.25 * var(--_sonic-relief))) 100%
19
+ );
20
+ }
21
+ }
@@ -0,0 +1,31 @@
1
+ @layer sonic.material {
2
+ .sonic-xy-bracket,
3
+ .sonic-envelope-bracket::before {
4
+ box-sizing: border-box;
5
+ inline-size: var(--_sonic-bracket-size);
6
+ block-size: var(--_sonic-bracket-size);
7
+ pointer-events: none;
8
+ content: '';
9
+ border: max(1px, 0.06 * var(--_sonic-bracket-size)) solid
10
+ color-mix(in oklab, var(--_sonic-glass-text) 45%, transparent);
11
+ border-radius: 50%;
12
+ opacity: 0;
13
+ mask: conic-gradient(
14
+ from 10deg,
15
+ #000 0 70deg,
16
+ transparent 0 180deg,
17
+ #000 0 250deg,
18
+ transparent 0
19
+ );
20
+ scale: 0.6;
21
+ transition:
22
+ opacity 120ms ease-out,
23
+ scale 120ms ease-out;
24
+ }
25
+
26
+ :state(dragging) > * > .sonic-xy-bracket,
27
+ :state(dragging) > * > .sonic-envelope-bracket::before {
28
+ opacity: calc(1 - var(--_sonic-relief));
29
+ scale: 1;
30
+ }
31
+ }
@@ -0,0 +1,179 @@
1
+ @layer sonic.material {
2
+ :is(
3
+ .sonic-dial,
4
+ .sonic-button,
5
+ .sonic-switch,
6
+ .sonic-toggle,
7
+ .sonic-number,
8
+ .sonic-segmented-option,
9
+ .sonic-slider,
10
+ .sonic-waveform,
11
+ .sonic-wavestrip,
12
+ .sonic-xy
13
+ ) {
14
+ --_sonic-cap: var(--sonic-cap, transparent);
15
+ --_sonic-cap-hover: var(--sonic-cap-hover, transparent);
16
+ --_sonic-focus: var(--sonic-focus, oklch(90% 0.23 128deg));
17
+ --_sonic-ink: var(--sonic-ink, currentcolor);
18
+ --_sonic-etch: color-mix(in oklab, var(--_sonic-ink) 30%, transparent);
19
+ --_sonic-ink-lift: var(--sonic-ink-hover, color-mix(in oklab, var(--_sonic-ink) 60%, #fff));
20
+ --_sonic-lit-disabled: color-mix(in oklab, var(--_sonic-ink) 25%, var(--_sonic-unlit));
21
+ --_sonic-skirt: linear-gradient(
22
+ var(--_sonic-light-fall),
23
+ color-mix(in oklab, var(--_sonic-cap) calc(100% - 30% * var(--_sonic-relief)), #fff),
24
+ color-mix(in oklab, var(--_sonic-cap) calc(100% - 45% * var(--_sonic-relief)), #000)
25
+ );
26
+ --_sonic-face: linear-gradient(
27
+ var(--_sonic-light-fall),
28
+ color-mix(in oklab, var(--_sonic-cap) calc(100% - 15% * var(--_sonic-relief)), #000),
29
+ color-mix(in oklab, var(--_sonic-cap) calc(100% - 10% * var(--_sonic-relief)), #fff)
30
+ );
31
+ --_sonic-sheen: linear-gradient(
32
+ 105deg,
33
+ transparent 20%,
34
+ rgb(255 255 255 / calc(0.1 * var(--_sonic-relief))) 45%,
35
+ transparent 55%,
36
+ rgb(0 0 0 / calc(0.06 * var(--_sonic-relief))) 80%
37
+ );
38
+ --_sonic-press-transition:
39
+ scale 60ms cubic-bezier(0.4, 0, 0.2, 1), translate 60ms cubic-bezier(0.4, 0, 0.2, 1),
40
+ box-shadow 60ms cubic-bezier(0.4, 0, 0.2, 1);
41
+ --_sonic-face-shadow:
42
+ inset var(--_sonic-cast-x) var(--_sonic-cast-y) calc(1.5 * var(--_sonic-unit))
43
+ rgb(0 0 0 / calc(0.35 * var(--_sonic-relief))),
44
+ calc(0.5 * var(--_sonic-cast-x)) calc(0.5 * var(--_sonic-cast-y)) var(--_sonic-unit)
45
+ rgb(255 255 255 / calc(0.12 * var(--_sonic-relief)));
46
+ --_sonic-rim-width: max(1px, round(0.75 * var(--_sonic-unit), var(--_sonic-snap)));
47
+ --_sonic-rim: 0 0 0 var(--_sonic-rim-width)
48
+ var(
49
+ --sonic-cap-edge,
50
+ color-mix(in oklab, var(--_sonic-cap) calc(100% - 60% * var(--_sonic-relief)), #000)
51
+ );
52
+ --_sonic-drop-shade: rgb(0 0 0 / calc(0.65 * var(--_sonic-relief)));
53
+ --_sonic-focus-shadow: 0 0 transparent;
54
+ --_sonic-focus-glow: 0 0 max(4px, 3 * var(--_sonic-unit)) max(1px, 0.5 * var(--_sonic-unit))
55
+ color-mix(in oklab, var(--_sonic-focus) 60%, transparent);
56
+ }
57
+
58
+ :is(.sonic-number, .sonic-waveform, .sonic-wavestrip, .sonic-xy) {
59
+ --_sonic-ink: var(--_sonic-glass-text);
60
+ }
61
+
62
+ :is(.sonic-dial, .sonic-slider, .sonic-waveform, .sonic-wavestrip) {
63
+ --_sonic-lit-off: var(
64
+ --sonic-dimmed,
65
+ color-mix(in oklab, var(--_sonic-lit) 50%, var(--_sonic-unlit))
66
+ );
67
+ }
68
+
69
+ :is(.sonic-button, .sonic-segmented-option, .sonic-switch-position, .sonic-toggle-position) {
70
+ --_sonic-target-outset: min(0px, calc((100% - var(--sonic-target-size, 100%)) / 2));
71
+
72
+ &::after {
73
+ position: absolute;
74
+ inset: var(--_sonic-target-outset);
75
+ content: '';
76
+ }
77
+ }
78
+
79
+ @media (hover: hover) {
80
+ :is(.sonic-dial, .sonic-button, .sonic-segmented-option, .sonic-slider):not(
81
+ :disabled,
82
+ [aria-disabled='true']
83
+ ):hover {
84
+ --_sonic-cap: var(--_sonic-cap-hover);
85
+ }
86
+ }
87
+
88
+ :is(
89
+ .sonic-dial,
90
+ .sonic-button,
91
+ .sonic-number,
92
+ .sonic-segmented-option,
93
+ .sonic-slider,
94
+ .sonic-waveform,
95
+ .sonic-wavestrip,
96
+ .sonic-xy-axis
97
+ ):focus-visible {
98
+ outline: 2px solid transparent;
99
+ outline-offset: -2px;
100
+
101
+ &:not([data-sonic-pointer-focus]) {
102
+ --_sonic-cap: var(--_sonic-cap-hover);
103
+ --_sonic-focus-shadow: var(--_sonic-focus-glow);
104
+ }
105
+ }
106
+
107
+ :state(editing)
108
+ > :is(.sonic-dial, .sonic-number, .sonic-slider, .sonic-waveform, .sonic-wavestrip) {
109
+ --_sonic-cap: var(--_sonic-cap-hover);
110
+ --_sonic-focus-shadow: var(--_sonic-focus-glow);
111
+ }
112
+
113
+ @media (forced-colors: active) {
114
+ /* Tokens rather than properties, so a state rule that restates one still paints in system colours */
115
+
116
+ :is(
117
+ .sonic-dial,
118
+ .sonic-button,
119
+ .sonic-number,
120
+ .sonic-segmented-option,
121
+ .sonic-slider,
122
+ .sonic-toggle,
123
+ .sonic-waveform,
124
+ .sonic-wavestrip,
125
+ .sonic-xy
126
+ ) {
127
+ --_sonic-ink: ButtonText;
128
+ --_sonic-etch: ButtonText;
129
+ --_sonic-lit-disabled: GrayText;
130
+ --_sonic-skirt: ButtonFace;
131
+ --_sonic-face: ButtonFace;
132
+ --_sonic-sheen: none;
133
+ --_sonic-face-shadow: none;
134
+ --_sonic-rim: 0 0 0 var(--_sonic-rim-width) var(--_sonic-ink);
135
+ --_sonic-drop-shade: transparent;
136
+ --_sonic-focus-glow: 0 0 transparent;
137
+ }
138
+
139
+ :is(.sonic-dial, .sonic-slider, .sonic-waveform, .sonic-wavestrip) {
140
+ --_sonic-lit-off: Highlight;
141
+ }
142
+
143
+ :is(
144
+ :disabled > :is(.sonic-dial, .sonic-slider, .sonic-waveform, .sonic-wavestrip, .sonic-xy),
145
+ .sonic-button:is(:disabled, [aria-disabled='true']),
146
+ .sonic-segmented-option:disabled
147
+ ) {
148
+ --_sonic-ink: GrayText;
149
+ --_sonic-etch: GrayText;
150
+ }
151
+
152
+ :is(
153
+ .sonic-dial,
154
+ .sonic-button,
155
+ .sonic-number,
156
+ .sonic-segmented-option,
157
+ .sonic-slider,
158
+ .sonic-waveform,
159
+ .sonic-wavestrip
160
+ ):focus-visible {
161
+ outline-offset: 2px;
162
+
163
+ &[data-sonic-pointer-focus] {
164
+ outline-style: none;
165
+ }
166
+ }
167
+
168
+ :is(
169
+ .sonic-dial-cap,
170
+ .sonic-button-cap,
171
+ .sonic-segmented-cap,
172
+ .sonic-slider-cap,
173
+ .sonic-toggle-cap
174
+ ) {
175
+ color: var(--_sonic-ink);
176
+ forced-color-adjust: none;
177
+ }
178
+ }
179
+ }
@@ -0,0 +1,103 @@
1
+ @property --_sonic-reveal-delay {
2
+ syntax: '<time>';
3
+ inherits: true;
4
+ initial-value: 250ms;
5
+ }
6
+
7
+ @layer sonic.material {
8
+ :is(
9
+ .sonic-dial,
10
+ .sonic-dial-readout,
11
+ .sonic-envelope,
12
+ .sonic-envelope-readout,
13
+ .sonic-button,
14
+ .sonic-led,
15
+ .sonic-switch,
16
+ .sonic-toggle,
17
+ .sonic-meter,
18
+ .sonic-number,
19
+ .sonic-panel,
20
+ .sonic-ring,
21
+ .sonic-screen,
22
+ .sonic-segmented,
23
+ .sonic-slider,
24
+ .sonic-slider-readout,
25
+ .sonic-spectrum,
26
+ .sonic-waveform,
27
+ .sonic-waveform-readout,
28
+ .sonic-wavestrip,
29
+ .sonic-wavestrip-readout,
30
+ .sonic-xy,
31
+ .sonic-xy-readout
32
+ ) {
33
+ --_sonic-unlit: var(--sonic-unlit, oklch(27.4% 0.005 286deg));
34
+ --_sonic-relief: var(--sonic-relief, 0);
35
+ --_sonic-light-tilt: var(--sonic-light-tilt, 17deg);
36
+ --_sonic-light-fall: calc(180deg - var(--_sonic-light-tilt));
37
+ --_sonic-cast-x: calc(sin(var(--_sonic-light-tilt)) * var(--_sonic-unit));
38
+ --_sonic-cast-y: calc(cos(var(--_sonic-light-tilt)) * var(--_sonic-unit));
39
+ --_sonic-snap: 1px;
40
+
41
+ @media (resolution >= 2dppx) {
42
+ --_sonic-snap: 0.5px;
43
+ }
44
+
45
+ @media (resolution >= 3dppx) {
46
+ --_sonic-snap: calc(1px / 3);
47
+ }
48
+ }
49
+
50
+ :is(
51
+ .sonic-dial,
52
+ .sonic-envelope,
53
+ .sonic-button,
54
+ .sonic-led,
55
+ .sonic-meter,
56
+ .sonic-number,
57
+ .sonic-ring,
58
+ .sonic-segmented-option,
59
+ .sonic-slider,
60
+ .sonic-spectrum,
61
+ .sonic-toggle,
62
+ .sonic-waveform,
63
+ .sonic-wavestrip,
64
+ .sonic-xy
65
+ ) {
66
+ --_sonic-lit: var(--sonic-lit, oklch(76.9% 0.165 70deg));
67
+ }
68
+
69
+ :is(.sonic-led, .sonic-meter, .sonic-spectrum, .sonic-toggle) {
70
+ --_sonic-lit-ok: var(--sonic-lit-ok, oklch(79% 0.2 150deg));
71
+ --_sonic-lit-warning: var(--sonic-lit-warning, oklch(70.5% 0.187 48deg));
72
+ --_sonic-lit-danger: var(--sonic-lit-danger, oklch(63.7% 0.208 25deg));
73
+ }
74
+
75
+ :is(
76
+ .sonic-dial,
77
+ .sonic-envelope,
78
+ .sonic-number,
79
+ .sonic-slider,
80
+ .sonic-waveform,
81
+ .sonic-wavestrip,
82
+ .sonic-xy
83
+ ) {
84
+ --_sonic-reveal-delay: var(--sonic-reveal-delay, 250ms);
85
+ }
86
+
87
+ @media (forced-colors: active) {
88
+ :is(
89
+ .sonic-dial,
90
+ .sonic-button,
91
+ .sonic-led,
92
+ .sonic-meter,
93
+ .sonic-number,
94
+ .sonic-ring,
95
+ .sonic-segmented-option,
96
+ .sonic-slider,
97
+ .sonic-toggle
98
+ ) {
99
+ --_sonic-lit: Highlight;
100
+ --_sonic-unlit: GrayText;
101
+ }
102
+ }
103
+ }
@@ -0,0 +1,62 @@
1
+ @layer sonic.material {
2
+ :is(
3
+ .sonic-dial-readout,
4
+ .sonic-envelope,
5
+ .sonic-envelope-readout,
6
+ .sonic-number,
7
+ .sonic-screen,
8
+ .sonic-slider-readout,
9
+ .sonic-spectrum,
10
+ .sonic-waveform,
11
+ .sonic-waveform-readout,
12
+ .sonic-wavestrip,
13
+ .sonic-wavestrip-readout,
14
+ .sonic-xy,
15
+ .sonic-xy-readout
16
+ ) {
17
+ --_sonic-glass-slab: color-mix(in oklab, var(--_sonic-unlit) 45%, #000);
18
+ --_sonic-glass-base: var(
19
+ --sonic-glass,
20
+ color-mix(
21
+ in oklab,
22
+ var(--_sonic-glass-slab) calc(100% * var(--_sonic-relief)),
23
+ light-dark(oklch(97% 0.003 286deg), var(--_sonic-glass-slab))
24
+ )
25
+ );
26
+ --_sonic-glass: var(--_sonic-glass-own, var(--_sonic-glass-base));
27
+ --_sonic-glass-fill: radial-gradient(
28
+ closest-side,
29
+ color-mix(
30
+ in oklab,
31
+ var(--_sonic-glass) calc(100% - 12% * var(--_sonic-glass-depth, var(--_sonic-relief))),
32
+ #fff
33
+ ),
34
+ var(--_sonic-glass)
35
+ )
36
+ var(--_sonic-glass);
37
+ --_sonic-glass-text: var(
38
+ --sonic-glass-text,
39
+ color-mix(
40
+ in oklab,
41
+ var(--_sonic-glass) 20%,
42
+ oklch(from var(--_sonic-glass) clamp(0, (0.6 - l) * 1000, 1) 0 0deg / 100%)
43
+ )
44
+ );
45
+
46
+ /* Invalid with the token unset, so the default takes over */
47
+ --_sonic-glass-edge-colour: var(--_sonic-glass-edge-colour-own, var(--sonic-glass-edge));
48
+ --_sonic-glass-edge-width: var(--_sonic-glass-edge-width-own, var(--sonic-glass-edge-width));
49
+ --_sonic-glass-edge-set: var(--_sonic-glass-edge-width, 1px) solid
50
+ var(--_sonic-glass-edge-colour);
51
+ --_sonic-glass-edge: var(
52
+ --_sonic-glass-edge-set,
53
+ var(--_sonic-glass-edge-width, calc(1px * (1 - var(--_sonic-relief)))) solid
54
+ color-mix(in oklab, currentcolor 35%, transparent)
55
+ );
56
+
57
+ /* Glass is forced to Canvas like the page, so only a border shows its edge */
58
+ @media (forced-colors: active) {
59
+ --_sonic-glass-edge: 1px solid CanvasText;
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,10 @@
1
+ @layer sonic.material {
2
+ :is(.sonic-meter, .sonic-slider) {
3
+ --_sonic-groove:
4
+ inset var(--_sonic-cast-x) var(--_sonic-cast-y) calc(0.75 * var(--_sonic-unit))
5
+ rgb(0 0 0 / calc(0.55 * var(--_sonic-relief))),
6
+ inset 0 0 calc(0.5 * var(--_sonic-unit)) rgb(0 0 0 / calc(0.3 * var(--_sonic-relief))),
7
+ calc(0.5 * var(--_sonic-cast-x)) calc(0.5 * var(--_sonic-cast-y)) 0
8
+ rgb(255 255 255 / calc(0.06 * var(--_sonic-relief)));
9
+ }
10
+ }
@@ -0,0 +1,95 @@
1
+ @layer sonic.material {
2
+ :is(.sonic-button, .sonic-segmented, .sonic-toggle) {
3
+ --_sonic-well-floor: var(
4
+ --sonic-well,
5
+ linear-gradient(
6
+ var(--_sonic-light-fall),
7
+ color-mix(
8
+ in oklab,
9
+ color-mix(in oklab, var(--_sonic-unlit) 55%, #000) calc(100% * var(--_sonic-relief)),
10
+ transparent
11
+ ),
12
+ color-mix(
13
+ in oklab,
14
+ color-mix(in oklab, var(--_sonic-unlit) 85%, #000) calc(100% * var(--_sonic-relief)),
15
+ transparent
16
+ )
17
+ )
18
+ );
19
+ --_sonic-engraving: drop-shadow(
20
+ calc(-0.4 * var(--_sonic-cast-x)) calc(-0.4 * var(--_sonic-cast-y))
21
+ calc(0.4 * var(--_sonic-unit)) rgb(0 0 0 / calc(0.3 * var(--_sonic-relief)))
22
+ )
23
+ drop-shadow(
24
+ calc(0.3 * var(--_sonic-cast-x)) calc(0.3 * var(--_sonic-cast-y)) 0
25
+ rgb(255 255 255 / calc(0.07 * var(--_sonic-relief)))
26
+ );
27
+ }
28
+
29
+ /* On the option rather than the strip, where forced colours clear the drop shade */
30
+
31
+ :is(.sonic-button, .sonic-segmented-option, .sonic-toggle) {
32
+ --_sonic-press-drop: calc(0.5 * var(--_sonic-cast-x)) calc(0.5 * var(--_sonic-cast-y))
33
+ var(--_sonic-unit) var(--_sonic-drop-shade);
34
+ --_sonic-keycap-shift: calc(var(--_sonic-keycap-depth) / -2);
35
+ --_sonic-keycap-scale: 1;
36
+ --_sonic-keycap-drop: calc(1.5 * var(--_sonic-cast-x)) calc(1.5 * var(--_sonic-cast-y))
37
+ calc(2 * var(--_sonic-unit)) var(--_sonic-drop-shade);
38
+ --_sonic-keycap-glow: transparent;
39
+ --_sonic-keycap-lit-glow: color-mix(
40
+ in oklab,
41
+ var(--_sonic-lit) calc(15% * var(--_sonic-relief)),
42
+ transparent
43
+ );
44
+ --_sonic-legend-glow: drop-shadow(
45
+ 0 0 var(--_sonic-unit)
46
+ color-mix(in oklab, var(--_sonic-lit) calc(24% * var(--_sonic-relief)), transparent)
47
+ );
48
+ --_sonic-legend-lit-from: var(--_sonic-lit);
49
+ --_sonic-legend-lit: color-mix(
50
+ in oklab,
51
+ var(--sonic-cap) 0%,
52
+ oklch(
53
+ from
54
+ color-mix(
55
+ in oklab,
56
+ oklch(from var(--_sonic-ink) l c h / clamp(0, (0.6 - l) * 1000, 1)),
57
+ oklch(from var(--_sonic-legend-lit-from) l c h / 0.1%)
58
+ )
59
+ l c h / 100%
60
+ )
61
+ );
62
+ }
63
+
64
+ /* Each sheet maps its own depth, corner, bevel and face corner onto the `keycap` tokens */
65
+
66
+ :is(.sonic-button-cap, .sonic-segmented-cap, .sonic-toggle-cap) {
67
+ display: grid;
68
+ place-items: center;
69
+ background: var(--_sonic-skirt);
70
+ border-radius: var(--_sonic-keycap-corner);
71
+ box-shadow:
72
+ var(--_sonic-keycap-drop),
73
+ var(--_sonic-rim),
74
+ 0 0 0 var(--_sonic-rim-width) var(--_sonic-blank-edge, transparent),
75
+ var(--_sonic-focus-shadow);
76
+ scale: var(--_sonic-keycap-scale);
77
+ translate: 0 var(--_sonic-keycap-shift);
78
+ transition: var(--_sonic-press-transition);
79
+
80
+ &::before {
81
+ position: absolute;
82
+ inset: var(--_sonic-keycap-bevel);
83
+ content: '';
84
+ background:
85
+ radial-gradient(closest-side, var(--_sonic-keycap-glow), transparent), var(--_sonic-sheen),
86
+ var(--_sonic-face);
87
+ border-radius: var(--_sonic-keycap-face-corner);
88
+ box-shadow: var(--_sonic-face-shadow);
89
+ }
90
+
91
+ & > * {
92
+ position: relative;
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,11 @@
1
+ @layer sonic.material {
2
+ :is(.sonic-led, .sonic-meter) {
3
+ --_sonic-lens-glint: linear-gradient(
4
+ var(--_sonic-light-fall),
5
+ rgb(255 255 255 / calc(0.1 * var(--_sonic-relief))),
6
+ transparent 60%
7
+ );
8
+ --_sonic-lens-glass: var(--sonic-lens, color-mix(in oklab, var(--_sonic-unlit) 60%, #000));
9
+ --_sonic-lens: var(--_sonic-lens-glint), var(--_sonic-lens-glass);
10
+ }
11
+ }
@@ -0,0 +1,97 @@
1
+ @keyframes sonic-glass-breathe {
2
+ to {
3
+ opacity: calc(0.4 * min(1, var(--_sonic-glass-texture)));
4
+ }
5
+ }
6
+
7
+ @layer sonic.material {
8
+ /* A definite cell, so percentage-sized content fills the glass; a canvas sized to its own box would feed back */
9
+
10
+ :is(
11
+ .sonic-envelope,
12
+ .sonic-number,
13
+ .sonic-screen,
14
+ .sonic-spectrum,
15
+ .sonic-waveform,
16
+ .sonic-wavestrip,
17
+ .sonic-xy
18
+ ) {
19
+ --_sonic-glass-depth: var(--sonic-glass-depth, var(--_sonic-relief));
20
+ --_sonic-glass-texture: var(--sonic-glass-texture, var(--_sonic-relief));
21
+ --_sonic-glass-pitch: max(2px, round(2 * var(--_sonic-unit), 1px));
22
+
23
+ position: relative;
24
+ box-sizing: border-box;
25
+ display: grid;
26
+ flex-shrink: 0;
27
+ grid-template: minmax(0, 1fr) / minmax(0, 1fr);
28
+ place-items: center;
29
+ font-family: var(--sonic-glass-font, inherit);
30
+ color: var(--_sonic-glass-text);
31
+ user-select: none;
32
+ background: var(--_sonic-glass-fill);
33
+ border: var(--_sonic-glass-edge);
34
+
35
+ @media (forced-colors: active) {
36
+ --_sonic-glass-texture: 0;
37
+ }
38
+
39
+ &::after {
40
+ position: absolute;
41
+ inset: 0;
42
+ pointer-events: none;
43
+ content: '';
44
+ background:
45
+ linear-gradient(
46
+ var(--_sonic-light-fall),
47
+ rgb(255 255 255 / calc(0.07 * var(--_sonic-glass-depth))),
48
+ transparent 45%
49
+ ),
50
+ radial-gradient(
51
+ farthest-corner,
52
+ transparent 55%,
53
+ rgb(0 0 0 / calc(0.4 * var(--_sonic-glass-texture)))
54
+ ),
55
+ repeating-linear-gradient(
56
+ to bottom,
57
+ rgb(0 0 0 / calc(0.025 * var(--_sonic-glass-texture))) 0
58
+ calc(var(--_sonic-glass-pitch) / 2),
59
+ transparent 0 var(--_sonic-glass-pitch)
60
+ );
61
+ border-radius: inherit;
62
+ box-shadow:
63
+ var(--_sonic-well),
64
+ inset 0 0 calc(3 * var(--_sonic-glass-depth) * var(--_sonic-unit)) rgb(0 0 0 / 45%);
65
+ }
66
+
67
+ @media (forced-colors: none) {
68
+ /* No var() beside the tile, which would parse the url() again on every style recalculation */
69
+ &::before {
70
+ position: absolute;
71
+ inset: 0;
72
+ color: color-mix(in oklab, var(--_sonic-glass-text) 7.5%, transparent);
73
+ pointer-events: none;
74
+ content: '';
75
+ background:
76
+ radial-gradient(closest-side, currentcolor, transparent) no-repeat,
77
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='128' height='128'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.056 -0.01925'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")
78
+ 0 0 / 128px 128px repeat;
79
+ border-radius: inherit;
80
+ opacity: min(1, var(--_sonic-glass-texture));
81
+ }
82
+
83
+ @media (prefers-reduced-motion: no-preference) {
84
+ &:is(:focus-visible, :focus-within)::before,
85
+ :state(dragging) > &::before {
86
+ animation: sonic-glass-breathe 3s ease-in-out infinite alternate;
87
+ }
88
+
89
+ @media (hover: hover) {
90
+ &:hover::before {
91
+ animation: sonic-glass-breathe 3s ease-in-out infinite alternate;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }