_drawing.scss 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. // Drawing mixins
  2. // generic drawing of more complex things
  3. @function _widget_edge($c:$borders_edge) {
  4. // outer highlight "used" on most widgets
  5. @if $c == none { @return none; }
  6. @else { @return 0 1px $c; }
  7. }
  8. @mixin _shadows($list...) {
  9. //
  10. // Helper mixin to stack up to box-shadows;
  11. //
  12. $shadows: null;
  13. @each $shadow in $list {
  14. @if $shadow!=none { $shadows: $shadows, $shadow; }
  15. }
  16. box-shadow: $shadows;
  17. }
  18. // entries
  19. @function entry_focus_border($fc:$selected_bg_color) {
  20. @if $variant == 'light' { @return $fc; }
  21. @else { @return if($fc==$selected_bg_color, $selected_borders_color, darken($fc, 35%)); }
  22. }
  23. @function entry_focus_shadow($fc:$selected_bg_color) { @return inset 0 0 0 1px $fc; }
  24. @mixin entry($t, $fc:$selected_bg_color, $edge: none) {
  25. //
  26. // Entries drawing function
  27. //
  28. // $t: entry type
  29. // $fc: focus color
  30. // $edge: set to none to not draw the bottom edge or specify a color to not
  31. // use the default one
  32. //
  33. // possible $t values:
  34. // normal, focus, insensitive, backdrop, backdrop-insensitive, osd, osd-focus, osd-backdrop;
  35. //
  36. $_blank_edge: if($edge == none, none, 0 1px transparentize($edge, 1));
  37. $_entry_edge: if($edge == none, none, _widget_edge($edge));
  38. @if $t==normal {
  39. color: $text_color;
  40. border-color: $borders_color;
  41. background-color: $base_color;
  42. @include _shadows(entry_focus_shadow(transparentize($fc, 1)), $_entry_edge);
  43. // for the transition to work the number of shadows in different states needs to match, hence the transparent shadow here.
  44. }
  45. @if $t==focus {
  46. @include _shadows(entry_focus_shadow($fc), $_entry_edge);
  47. border-color: entry_focus_border($fc);
  48. }
  49. @if $t==insensitive {
  50. color: $insensitive_fg_color;
  51. border-color: $borders_color;
  52. background-color: $insensitive_bg_color;
  53. box-shadow: $_entry_edge;
  54. }
  55. @if $t==backdrop {
  56. color: $backdrop_text_color;
  57. border-color: $backdrop_borders_color;
  58. background-color: $backdrop_base_color;
  59. box-shadow: $_blank_edge;
  60. }
  61. @if $t==backdrop-insensitive {
  62. color: $backdrop_insensitive_color;
  63. border-color: $backdrop_borders_color;
  64. background-color: $insensitive_bg_color;
  65. box-shadow: $_blank_edge;
  66. }
  67. @if $t==osd {
  68. color: $osd_text_color;
  69. border-color: $osd_borders_color;
  70. background-color: transparentize(opacify($osd_borders_color, 1), 0.5);
  71. background-clip: padding-box;
  72. box-shadow: none;
  73. text-shadow: 0 1px black;
  74. -gtk-icon-shadow: 0 1px black;
  75. }
  76. @if $t==osd-focus {
  77. color: $osd_text_color;
  78. border-color: $selected_bg_color;
  79. background-color: transparentize(opacify($osd_borders_color, 1), 0.5);
  80. background-clip: padding-box;
  81. box-shadow: entry_focus_shadow($fc);
  82. text-shadow: 0 1px black;
  83. -gtk-icon-shadow: 0 1px black;
  84. }
  85. @if $t==osd-insensitive {
  86. color: $osd_insensitive_fg_color;
  87. border-color: $osd_borders_color;
  88. background-color: $osd_insensitive_bg_color;
  89. background-clip: padding-box;
  90. box-shadow: none;
  91. text-shadow: none;
  92. -gtk-icon-shadow: none;
  93. }
  94. @if $t==osd-backdrop {
  95. color: $osd_text_color;
  96. border-color: $osd_borders_color;
  97. background-color: transparentize(opacify($osd_borders_color, 1), 0.5);
  98. background-clip: padding-box;
  99. box-shadow: none;
  100. text-shadow: none;
  101. -gtk-icon-shadow: none;
  102. }
  103. }
  104. // buttons
  105. @function _border_color($c, $darker: false) {
  106. @if $darker == true { @return darken($c, 20%); }
  107. @else { @return darken($c, 10%); }
  108. }
  109. @function _text_shadow_color ($tc: $fg_color, $bg: $bg_color) {
  110. //
  111. // calculate the color of text shadows
  112. //
  113. // $tc is the text color
  114. // $bg is the background color
  115. //
  116. $_lbg: lightness($bg)/100%;
  117. @if lightness($tc)<50% { @return transparentize(white, 1-$_lbg/($_lbg*1.3)); }
  118. @else { @return transparentize(black, $_lbg*0.8); }
  119. }
  120. @function _button_hilight_color($c) {
  121. //
  122. // calculate the right top hilight color for buttons
  123. //
  124. // $c: base color;
  125. //
  126. @if lightness($c)>95% { @return white; }
  127. @else if lightness($c)>90% { @return transparentize(white, 0.2); }
  128. @else if lightness($c)>80% { @return transparentize(white, 0.5); }
  129. @else if lightness($c)>50% { @return transparentize(white, 0.8); }
  130. @else if lightness($c)>40% { @return transparentize(white, 0.9); }
  131. @else { @return transparentize(white, 0.98); }
  132. }
  133. @mixin _button_text_shadow ($tc:$fg_color, $bg:$bg_color) {
  134. //
  135. // helper function for the text emboss effect
  136. //
  137. // $tc is the optional text color, not the shadow color
  138. //
  139. // TODO: this functions needs a way to deal with special cases
  140. //
  141. $_shadow: _text_shadow_color($tc, $bg);
  142. @if lightness($tc)<50% {
  143. text-shadow: 0 1px $_shadow;
  144. -gtk-icon-shadow: 0 1px $_shadow;
  145. }
  146. @else {
  147. text-shadow: 0 -1px $_shadow;
  148. -gtk-icon-shadow: 0 -1px $_shadow;
  149. }
  150. }
  151. @mixin button($t, $c:$bg_color, $tc:$fg_color, $edge: none, $backimage: null) {
  152. //
  153. // Button drawing function
  154. //
  155. // $t: button type,
  156. // $c: base button color for colored* types
  157. // $tc: optional text color for colored* types
  158. // $edge: set to none to not draw the bottom edge or specify a color to not
  159. // use the default one
  160. // $backimage: additional background-image behind the default one
  161. // (for the button.circular hack)
  162. //
  163. // possible $t values:
  164. // normal, hover, active, insensitive, insensitive-active,
  165. // backdrop, backdrop-active, backdrop-insensitive, backdrop-insensitive-active,
  166. // osd, osd-hover, osd-active, osd-insensitive, osd-backdrop, undecorated
  167. //
  168. $_hilight_color: _button_hilight_color($c);
  169. $_button_edge: if($edge == none, none, _widget_edge($edge));
  170. $_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
  171. $_button_shadow: 0 1px 2px transparentize($shadow_color, 0.03);
  172. @if $t==normal {
  173. //
  174. // normal button
  175. //
  176. color: $tc;
  177. outline-color: transparentize($tc, 0.7);
  178. border-color: if($c != $bg_color, _border_color($c), $borders_color);
  179. border-bottom-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
  180. background-image: if($variant == 'light', linear-gradient(to top, darken($c, 4%) 2px, $c),
  181. linear-gradient(to top, darken($c,1%) 2px, $c)),
  182. $backimage;
  183. @include _button_text_shadow($tc, $c);
  184. @include _shadows(inset 0 1px $_hilight_color, $_button_edge, $_button_shadow);
  185. }
  186. @else if $t==hover {
  187. //
  188. // hovered button
  189. //
  190. color: $tc;
  191. outline-color: transparentize($tc, 0.7);
  192. border-color: if($c != $bg_color, _border_color($c), $borders_color);
  193. border-bottom-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
  194. @if $variant == 'light' {
  195. background-image: linear-gradient(to top, $c, lighten($c, 1%) 1px),
  196. $backimage;
  197. @include _button_text_shadow($tc, lighten($c, 6%));
  198. @include _shadows(inset 0 1px _button_hilight_color(lighten($c, 6%)), $_button_edge, $_button_shadow);
  199. }
  200. @else {
  201. background-image: linear-gradient(to top, darken($c,1%), lighten($c, 1%) 1px),
  202. $backimage;
  203. @include _button_text_shadow($tc,lighten($c, 6%));
  204. @include _shadows(inset 0 1px _button_hilight_color(darken($c, 2%)), $_button_edge, $_button_shadow);
  205. }
  206. }
  207. @if $t==normal-alt {
  208. //
  209. // normal button alternative look
  210. //
  211. color: $tc;
  212. outline-color: transparentize($tc, 0.7);
  213. border-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
  214. @include _button_text_shadow($tc, $c);
  215. @if $variant == 'light' {
  216. background-image: linear-gradient(to bottom, lighten($c, 5%) 20%, $c 90%);
  217. @include _shadows(inset 0 1px _button_hilight_color(lighten($c, 6%)),
  218. $_button_edge, $_button_shadow);
  219. }
  220. @else {
  221. background-image: linear-gradient(to bottom, darken($c, 3%) 20%, darken($c, 6%) 90%);
  222. @include _shadows(inset 0 1px $_hilight_color,
  223. $_button_edge, $_button_shadow);
  224. }
  225. }
  226. @else if $t==hover-alt {
  227. //
  228. // hovered button alternative look
  229. //
  230. color: $tc;
  231. outline-color: transparentize($tc, 0.7);
  232. border-color: if($c != $bg_color, _border_color($c, true), $alt_borders_color);
  233. @if $variant == 'light' {
  234. background-image: linear-gradient(to bottom, lighten($c, 9%) 10%, lighten($c, 4%) 90%);
  235. @include _shadows(inset 0 1px _button_hilight_color(lighten($c, 6%)),
  236. $_button_edge, $_button_shadow);
  237. }
  238. @else {
  239. background-image: linear-gradient(to bottom, $c 20%, darken($c, 4%) 90%);
  240. @include _shadows(inset 0 1px $_hilight_color,
  241. $_button_edge, $_button_shadow);
  242. }
  243. }
  244. @else if $t==active {
  245. //
  246. // pushed button
  247. //
  248. color: $tc;
  249. outline-color: transparentize($tc, 0.7);
  250. border-color: if($c != $bg_color, _border_color($c), $borders_color);
  251. background-image: if($variant == 'light', image(darken($c, 14%)), image(darken($c, 9%)));
  252. @include _shadows(inset 0 1px transparentize($_hilight_color, 1), $_button_edge);
  253. text-shadow: none;
  254. -gtk-icon-shadow: none;
  255. }
  256. @else if $t==insensitive {
  257. //
  258. // insensitive button
  259. //
  260. $_bg: if($c != $bg_color, mix($c, $base_color, 85%), $insensitive_bg_color);
  261. color: if($tc != $fg_color, mix($tc, $_bg, 50%), $insensitive_fg_color);
  262. border-color: if($c != $bg_color, _border_color($c), $insensitive_borders_color);
  263. background-image: image($_bg);
  264. text-shadow: none;
  265. -gtk-icon-shadow: none;
  266. // white with 0 alpha to avoid an ugly transition, since no color means
  267. // black with 0 alpha
  268. @include _shadows(inset 0 1px transparentize(white, 1), $_button_edge);
  269. }
  270. @else if $t==insensitive-active {
  271. //
  272. // insensitive pushed button
  273. //
  274. $_bg: if($variant == 'light', darken(mix($c, $base_color, 85%), 8%), darken(mix($c, $base_color, 85%), 6%));
  275. $_bc: if($c != $bg_color, _border_color($c), $insensitive_borders_color);
  276. color: if($c != $bg_color, mix($tc, $_bg, 60%), $insensitive_fg_color);
  277. border-color: $_bc;
  278. background-image: image($_bg);
  279. // white with 0 alpha to avoid an ugly transition, since no color means
  280. // black with 0 alpha
  281. @include _shadows(inset 0 1px transparentize(white, 1), $_button_edge);
  282. }
  283. @else if $t==backdrop {
  284. //
  285. // backdrop button
  286. //
  287. $_bg: if($c != $bg_color, $c, $backdrop_bg_color);
  288. $_bc: if($variant == 'light', $c, _border_color($c));
  289. color: if($tc != $fg_color, mix($tc, $_bg, 80%), $backdrop_fg_color);
  290. border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
  291. background-image: image($_bg);
  292. text-shadow: none;
  293. -gtk-icon-shadow: none;
  294. @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
  295. }
  296. @else if $t==backdrop-active {
  297. //
  298. // backdrop pushed button
  299. //
  300. $_bg: if($variant == 'light', darken(mix($c, $base_color, 85%), 8%), darken(mix($c, $base_color, 85%), 4%));
  301. $_bc: if($variant == 'light', $_bg ,_border_color($c));
  302. color: if($tc != $fg_color, mix($tc, $_bg, 80%), $backdrop_fg_color);
  303. border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
  304. background-image: image($_bg);
  305. @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
  306. }
  307. @else if $t==backdrop-insensitive {
  308. //
  309. // backdrop insensitive button
  310. //
  311. $_bg: if($c != $bg_color, mix($c, $base_color, 85%), $insensitive_bg_color);
  312. $_bc: if($variant == 'light', $_bg,_border_color($c));
  313. color: if($c != $bg_color, mix($tc, $_bg, 35%), $backdrop_insensitive_color);
  314. border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
  315. background-image: image($_bg);
  316. text-shadow: none;
  317. -gtk-icon-shadow: none;
  318. // white with 0 alpha to avoid an ugly transition, since no color means
  319. // black with 0 alpha
  320. @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
  321. }
  322. @else if $t==backdrop-insensitive-active {
  323. //
  324. // backdrop insensitive pushed button
  325. //
  326. $_bg: if($variant == 'light', darken(mix($c, $base_color, 85%), 8%), darken(mix($c, $base_color, 85%), 4%));
  327. $_bc: if($variant == 'light', $_bg, _border_color($c));
  328. color: if($c != $bg_color, mix($tc, $_bg, 35%), $backdrop_insensitive_color);
  329. border-color: if($c != $bg_color, $_bc, $backdrop_borders_color);
  330. background-image: image($_bg);
  331. @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
  332. }
  333. @else if $t==osd {
  334. //
  335. // normal osd button
  336. //
  337. $_bg: if($c != $bg_color, transparentize($c, 0.5), $osd_bg_color);
  338. color: $osd_fg_color;
  339. border-color: $osd_borders_color;
  340. background-color: transparent;
  341. background-image: image($_bg);
  342. background-clip: padding-box;
  343. box-shadow: inset 0 1px transparentize(white, 0.9);
  344. text-shadow: 0 1px black;
  345. -gtk-icon-shadow: 0 1px black;
  346. outline-color: transparentize($osd_fg_color, 0.7);
  347. }
  348. @else if $t==osd-hover {
  349. //
  350. // active osd button
  351. //
  352. $_bg: if($c != $bg_color, transparentize($c, 0.3), lighten($osd_bg_color, 12%));
  353. color: white;
  354. border-color: $osd_borders_color;
  355. background-color: transparent;
  356. background-image: image($_bg);
  357. background-clip: padding-box;
  358. box-shadow: inset 0 1px transparentize(white, 0.9);
  359. text-shadow: 0 1px black;
  360. -gtk-icon-shadow: 0 1px black;
  361. outline-color: transparentize($osd_fg_color, 0.7);
  362. }
  363. @else if $t==osd-active {
  364. //
  365. // active osd button
  366. //
  367. $_bg: if($c != $bg_color, $c, $osd_borders_color);
  368. color: white;
  369. border-color: $osd_borders_color;
  370. background-color: transparent;
  371. background-image: image($_bg);
  372. background-clip: padding-box;
  373. box-shadow: none;
  374. text-shadow: none;
  375. -gtk-icon-shadow: none;
  376. outline-color: transparentize($osd_fg_color, 0.7);
  377. }
  378. @else if $t==osd-insensitive {
  379. //
  380. // insensitive osd button
  381. //
  382. color: $osd_insensitive_fg_color;
  383. border-color: $osd_borders_color;
  384. background-color: transparent;
  385. background-image: image($osd_insensitive_bg_color);
  386. background-clip: padding-box;
  387. box-shadow: none;
  388. text-shadow: none;
  389. -gtk-icon-shadow: none;
  390. }
  391. @else if $t==osd-backdrop {
  392. //
  393. // backdrop osd button
  394. //
  395. $_bg: if($c != $bg_color, transparentize($c, 0.5), $osd_bg_color);
  396. color: $osd_fg_color;
  397. border-color: $osd_borders_color;
  398. background-color: transparent;
  399. background-image: image($_bg);
  400. background-clip: padding-box;
  401. box-shadow: none;
  402. text-shadow: none;
  403. -gtk-icon-shadow: none;
  404. }
  405. @else if $t==undecorated {
  406. //
  407. // reset
  408. //
  409. border-color: transparent;
  410. background-color: transparent;
  411. background-image: none;
  412. @include _shadows(inset 0 1px transparentize(white, 1), $_blank_edge);
  413. text-shadow: none;
  414. -gtk-icon-shadow: none;
  415. }
  416. }
  417. @mixin headerbar_fill($c:$headerbar_color, $hc:$top_hilight, $ov: none) {
  418. //
  419. // headerbar fill
  420. //
  421. // $c: base color
  422. // $hc: top highlight color
  423. // $ov: a background layer for background shorthand (hence no commas!)
  424. //
  425. $gradient: linear-gradient(to top, darken($c, 2%), lighten($c, 1%));
  426. @if $variant == 'dark' { $gradient: linear-gradient(to top, lighten($c, 4%), lighten($c, 6%)); }
  427. @if $ov != none { background: $c $ov, $gradient; }
  428. @else { background: $c $gradient; }
  429. box-shadow: inset 0 1px $hc; // top highlight
  430. }
  431. @mixin overshoot($p, $t:normal, $c:$fg_color) {
  432. //
  433. // overshoot
  434. //
  435. // $p: position
  436. // $t: type
  437. // $c: base color
  438. //
  439. // possible $p values:
  440. // top, bottom, right, left
  441. //
  442. // possible $t values:
  443. // normal, backdrop
  444. //
  445. $_small_gradient_length: 5%;
  446. $_big_gradient_length: 100%;
  447. $_position: center top;
  448. $_small_gradient_size: 100% $_small_gradient_length;
  449. $_big_gradient_size: 100% $_big_gradient_length;
  450. @if $p==bottom {
  451. $_position: center bottom;
  452. $_linear_gradient_direction: to top;
  453. }
  454. @else if $p==right {
  455. $_position: right center;
  456. $_small_gradient_size: $_small_gradient_length 100%;
  457. $_big_gradient_size: $_big_gradient_length 100%;
  458. }
  459. @else if $p==left {
  460. $_position: left center;
  461. $_small_gradient_size: $_small_gradient_length 100%;
  462. $_big_gradient_size: $_big_gradient_length 100%;
  463. }
  464. $_small_gradient_color: $c;
  465. $_big_gradient_color: $c;
  466. @if $c==$fg_color {
  467. $_small_gradient_color: darken($borders_color, 10%);
  468. $_big_gradient_color: $fg_color;
  469. @if $t==backdrop { $_small_gradient_color: $backdrop_borders_color; }
  470. }
  471. $_small_gradient: -gtk-gradient(radial,
  472. $_position, 0,
  473. $_position, 0.5,
  474. to($_small_gradient_color),
  475. to(transparentize($_small_gradient_color, 1)));
  476. $_big_gradient: -gtk-gradient(radial,
  477. $_position, 0,
  478. $_position, 0.6,
  479. from(transparentize($_big_gradient_color, 0.93)),
  480. to(transparentize($_big_gradient_color, 1)));
  481. @if $t==normal {
  482. background-image: $_small_gradient, $_big_gradient;
  483. background-size: $_small_gradient_size, $_big_gradient_size;
  484. }
  485. @else if $t==backdrop {
  486. background-image: $_small_gradient;
  487. background-size: $_small_gradient_size;
  488. }
  489. background-repeat: no-repeat;
  490. background-position: $_position;
  491. background-color: transparent; // reset some properties to be sure to not inherit them somehow
  492. border: none; //
  493. box-shadow: none; //
  494. }
  495. /***************************
  496. * Check and Radio buttons *
  497. ***************************/
  498. @mixin check($t, $c:$bg_color, $tc:$fg_color, $checked: false) {
  499. // Check/Radio drawing function
  500. //
  501. // $t: check/radio type,
  502. // $c: base button color for colored* types
  503. // $tc: optional text color for colored* types
  504. // $checked: bool to chose between checked/unchecked
  505. //
  506. // possible $t values:
  507. // normal, hover, active, insensitive, backdrop, backdrop-insensitive
  508. $_border_color: if($c==$checkradio_bg_color, $c, $alt_borders_color);
  509. $_dim_border_color: transparentize($_border_color, if($variant == 'light', 0.3, 0.7));
  510. @if $t==normal {
  511. background-clip: if($checked, border-box, padding-box);
  512. background-image: linear-gradient(to bottom, lighten($c, 5%) 20%, $c 90%);
  513. border-color: $_border_color;
  514. box-shadow: 0 1px transparentize(black, 0.95);
  515. color: $tc;
  516. }
  517. @if $t==hover {
  518. background-image: if($c == white, image(darken($c, 5%)), linear-gradient(to bottom, lighten($c, 9%) 10%, lighten($c, 4%) 90%));
  519. }
  520. @if $t==active {
  521. box-shadow: inset 0 1px 1px 0px if($variant == 'light', rgba(0, 0, 0, 0.2), black);
  522. }
  523. @if $t==insensitive {
  524. box-shadow: none;
  525. color: transparentize($tc, 0.3);
  526. }
  527. @if $t==backdrop {
  528. background-image: image($c);
  529. box-shadow: none;
  530. color: $tc;
  531. }
  532. @if $t==backdrop-insensitive {
  533. box-shadow: none;
  534. color: transparentize($tc, 0.3);
  535. }
  536. }