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