tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

_DSCard.scss (16499B)


      1 // Type sizes
      2 /* stylelint-disable-next-line stylelint-plugin-mozilla/no-non-semantic-token-usage */
      3 $header-font-size: var(--font-size-large);
      4 $header-line-height: normal;
      5 /* stylelint-disable-next-line stylelint-plugin-mozilla/no-non-semantic-token-usage */
      6 $excerpt-font-size: var(--font-size-small);
      7 $excerpt-line-height: normal;
      8 $ds-card-image-gradient-fade: rgba(0, 0, 0, 0%);
      9 $ds-card-image-gradient-solid: rgba(0, 0, 0, 100%);
     10 
     11 .ds-card {
     12  display: flex;
     13  flex-direction: column;
     14  position: relative;
     15  // Bug 1914571: Reset the z-index threshold for topic labels
     16  z-index: auto;
     17 
     18  &.placeholder {
     19    display: flex;
     20    flex-direction: column;
     21    gap: var(--space-small);
     22    box-shadow: 0 2px 6px rgba(0, 0, 0, 15%);
     23    border-radius: var(--border-radius-medium);
     24    position: relative;
     25    overflow: hidden;
     26 
     27    .placeholder-fill {
     28      background: var(--newtab-button-active-background);
     29      border-radius: var(--border-radius-small);
     30    }
     31 
     32    .placeholder-image {
     33      width: 100%;
     34      height: 140px;
     35      border-radius: var(--border-radius-medium) var(--border-radius-medium) 0 0;
     36    }
     37 
     38    .placeholder-label {
     39      width: 40%;
     40      height: var(--size-item-small);
     41      margin-block-end: var(--space-small);
     42      margin-inline: var(--space-large);
     43    }
     44 
     45    .placeholder-header {
     46      width: 80%;
     47      height: 20px;
     48      margin-inline: var(--space-large);
     49    }
     50 
     51    .placeholder-description {
     52      height: 60px;
     53      margin-inline: var(--space-large);
     54      margin-block-end: var(--space-large);
     55    }
     56 
     57    &.refined-cards {
     58      .placeholder-image {
     59        height: 150px;
     60      }
     61 
     62      .placeholder-description {
     63        margin-block-end: var(--space-small);
     64      }
     65 
     66      .placeholder-header {
     67        width: initial;
     68        margin-block-end: var(--space-large);
     69      }
     70    }
     71  }
     72 
     73  &.placeholder-seen {
     74    &::before {
     75      content: '';
     76      display: block;
     77      position: absolute;
     78      inset-block-start: 0;
     79      inset-inline-start: -100%;
     80      height: 100%;
     81      width: 100%;
     82      background: linear-gradient(
     83        90deg,
     84        rgba(255, 255, 255, 0%) 0%,
     85        var(--newtab-background-color-secondary) 50%,
     86        rgba(255, 255, 255, 0%) 100%
     87      );
     88      z-index: 2;
     89 
     90      @media (prefers-reduced-motion: no-preference) {
     91        animation: loading 1.5s infinite;
     92      }
     93    }
     94 
     95    @keyframes loading {
     96      0% {
     97        inset-inline-start: -100%;
     98      }
     99 
    100      // We apply the same frame from 50-100% to account for a delay in a repeating animation.
    101      50%,
    102      100% {
    103        inset-inline-start: 100%;
    104      }
    105    }
    106  }
    107 
    108  .img-wrapper {
    109    width: 100%;
    110    position: relative;
    111  }
    112 
    113  .card-stp-button-hover-background {
    114    opacity: 0;
    115    width: 100%;
    116    position: absolute;
    117    inset-block-start: 0;
    118    transition: opacity;
    119    transition-duration: 0s;
    120    padding-block-start: 50%;
    121    pointer-events: none;
    122    background: $black-40;
    123    border-radius: var(--border-radius-medium) var(--border-radius-medium) 0 0;
    124 
    125    .card-stp-button-position-wrapper {
    126      position: absolute;
    127      inset-inline-end: var(--space-small);
    128      inset-block-start: var(--space-small);
    129      display: flex;
    130      justify-content: end;
    131      align-items: center;
    132    }
    133 
    134    .context-menu-position-container {
    135      position: relative;
    136    }
    137 
    138    .context-menu {
    139      margin-inline-start: var(--space-large);
    140      inset-inline-start: auto;
    141      position: absolute;
    142      // Bug 1967304 - Custom number (20px)
    143      inset-block-start: calc(var(--space-xsmall) + var(--space-large));
    144    }
    145 
    146    button,
    147    .context-menu {
    148      pointer-events: auto;
    149    }
    150 
    151    button {
    152      cursor: pointer;
    153    }
    154  }
    155 
    156  // Override note: The colors set here are intentionally static
    157  // due to transparency issues over images.
    158  .context-menu-button {
    159    position: static;
    160    transition: none;
    161    border-radius: var(--border-radius-small);
    162    background-color: var(--newtab-button-static-background);
    163 
    164    &:hover {
    165      background-color: var(--newtab-button-static-hover-background);
    166 
    167      &:active {
    168        background-color: var(--newtab-button-static-active-background);
    169      }
    170    }
    171 
    172    &:focus-visible {
    173      outline: 2px solid var(--newtab-button-focus-border);
    174      background-color: var(--newtab-button-static-focus-background);
    175    }
    176  }
    177 
    178  &.last-item {
    179    .card-stp-button-hover-background {
    180      .context-menu {
    181        margin-inline-start: auto;
    182        margin-inline-end: var(--space-large);
    183      }
    184    }
    185  }
    186 
    187  // The active class is added when the context menu is open.
    188  &.active,
    189  &:focus-within,
    190  &:hover {
    191    .card-stp-button-hover-background {
    192      display: block;
    193      opacity: 1;
    194      transition-duration: 0.3s;
    195 
    196      .context-menu-button {
    197        opacity: 1;
    198        transform: scale(1);
    199      }
    200    }
    201 
    202    h3 {
    203      color: var(--newtab-primary-action-background);
    204    }
    205  }
    206 
    207  &:active {
    208    h3 {
    209      color: var(--newtab-primary-element-active-color);
    210    }
    211  }
    212 
    213  .img {
    214    aspect-ratio: 2/1;
    215 
    216    img {
    217      border-radius: var(--border-radius-small);
    218      box-shadow: $shadow-image-inset;
    219    }
    220  }
    221 
    222  .ds-card-link {
    223    display: flex;
    224    flex-direction: column;
    225    align-items: initial;
    226    text-decoration: none;
    227    grid-template-columns: auto 1fr;
    228    gap: inherit;
    229    flex-grow: 1;
    230 
    231    &:focus {
    232      @include ds-focus;
    233 
    234      transition: none;
    235    }
    236  }
    237 
    238  .ds-card-topic {
    239    position: absolute;
    240    z-index: 1;
    241    background: light-dark(#F0F0F4, var(--newtab-background-color-secondary));
    242    border-radius: var(--border-radius-small);
    243    color: var(--newtab-text-primary-color);
    244    padding: var(--space-small);
    245    margin: var(--space-small);
    246    font-size: var(--font-size-small);
    247  }
    248 
    249  .meta {
    250    display: flex;
    251    justify-content: space-between;
    252    flex-direction: column;
    253    padding: var(--space-medium) var(--space-large);
    254    flex-grow: 1;
    255 
    256    .info-wrap {
    257      flex-grow: 1;
    258    }
    259 
    260    .title {
    261      // show only 3 lines of copy
    262      @include limit-visible-lines(3, $header-line-height, $header-font-size);
    263 
    264      margin-block: 0;
    265      font-weight: var(--heading-font-weight);
    266    }
    267 
    268    .excerpt {
    269      // show only 3 lines of copy
    270      @include limit-visible-lines(3, $excerpt-line-height, $excerpt-font-size);
    271    }
    272 
    273    .source-wrapper {
    274      color: var(--newtab-text-secondary-text);
    275      display: flex;
    276      margin-block-end: var(--space-xxsmall);
    277      align-items: center;
    278 
    279      img {
    280        border-radius: var(--border-radius-small);
    281        margin-inline-end: var(--space-small);
    282      }
    283    }
    284 
    285    .source {
    286      -webkit-line-clamp: 1;
    287      font-size: var(--font-size-small);
    288      color: var(--newtab-text-secondary-color);
    289 
    290      span {
    291        display: inline-block;
    292      }
    293    }
    294 
    295    .new-sponsored-label {
    296      font-size: var(--font-size-small);
    297      margin-block-end: var(--space-xxsmall);
    298    }
    299  }
    300 
    301  &.ds-card-title-lines-2 .meta .title {
    302    // show only 2 lines of copy
    303    @include limit-visible-lines(2, $header-line-height, $header-font-size);
    304  }
    305 
    306  &.ds-card-title-lines-1 .meta .title {
    307    // show only 1 line of copy
    308    @include limit-visible-lines(1, $header-line-height, $header-font-size);
    309  }
    310 
    311  &.ds-card-desc-lines-2 .meta .excerpt {
    312    // show only 2 lines of copy
    313    @include limit-visible-lines(2, $excerpt-line-height, $excerpt-font-size);
    314  }
    315 
    316  &.ds-card-desc-lines-1 .meta .excerpt {
    317    // show only 1 line of copy
    318    @include limit-visible-lines(1, $excerpt-line-height, $excerpt-font-size);
    319  }
    320 
    321  &.ds-card-compact-image .img {
    322    padding-block-start: 47%;
    323  }
    324 
    325  &.ds-card-image-gradient {
    326    img {
    327      mask-image: linear-gradient(
    328        to top,
    329        $ds-card-image-gradient-fade,
    330        $ds-card-image-gradient-solid 40px
    331      );
    332    }
    333 
    334    .meta {
    335      padding: var(--space-xxsmall) var(--space-large) var(--space-medium);
    336    }
    337  }
    338 
    339  &.ds-card-cta-button.variant-a,
    340  &.ds-card-cta-button.variant-b {
    341    .img {
    342      padding-block-start: 52.4%;
    343    }
    344 
    345    .story-sponsored-label {
    346      margin: var(--space-small) 0 0;
    347    }
    348 
    349    .source {
    350      text-decoration: underline;
    351    }
    352 
    353    .story-footer {
    354      display: flex;
    355      flex-wrap: wrap;
    356      justify-content: space-between;
    357      align-items: center;
    358      gap: 0 var(--space-small);
    359      margin-block-start: 0;
    360    }
    361 
    362    .story-cta-button {
    363      cursor: inherit;
    364      background: var(--button-background-color);
    365      border-radius: var(--border-radius-small);
    366      border: none;
    367      padding: var(--space-xsmall) var(--space-large);
    368      font-size: var(--font-size-small);
    369      font-weight: var(--font-weight-semibold);
    370      min-height: var(--size-item-large);
    371      min-width: 97px;
    372      color: var(--newtab-text-primary-color);
    373      margin-block-start: var(--space-small);
    374 
    375      &:hover {
    376        background: var(--button-background-color-hover);
    377      }
    378    }
    379 
    380    .cta-header {
    381      background: var(--button-background-color);
    382      font-size: var(--font-size-root);
    383      font-weight: var(--heading-font-weight);
    384      text-align: end;
    385      padding: var(--space-xsmall) var(--space-large);
    386      color: var(--newtab-text-primary-color);
    387      min-height: var(--size-item-large);
    388    }
    389  }
    390 
    391  h3 {
    392    font-size: $header-font-size;
    393    color: var(--newtab-text-primary-color);
    394  }
    395 
    396  p {
    397    font-size: $excerpt-font-size;
    398    color: var(--newtab-text-primary-color);
    399    margin: 0;
    400  }
    401 }
    402 
    403 // Class is applied to .ds-card element
    404 // See _CardSections.scss for large and small card style mixins
    405 .sections-card-ui {
    406  // Loading Animation
    407  &.placeholder {
    408    box-shadow: 0 2px 6px #15141A24;
    409    border-radius: var(--border-radius-large);
    410  }
    411 
    412  .ds-card-grid & {
    413    @include newtab-card-style;
    414 
    415    &:not(.placeholder) {
    416      box-shadow: 0 1px 2px 0 rgba(58, 57, 68, 20%);
    417      border-radius: var(--border-radius-large);
    418 
    419      &.active,
    420      &:focus-within,
    421      &:hover {
    422        box-shadow: 0 2px 14px 0 var(--newtab-section-card-box-shadow-color);
    423        z-index: 1;
    424      }
    425 
    426      // This is higher to keep the context menu (when open) above any other cards
    427      &.active {
    428        z-index: 2;
    429      }
    430 
    431      .img-wrapper > .ds-image.img > img {
    432        border-radius: var(--border-radius-large) var(--border-radius-large) 0 0;
    433      }
    434    }
    435 
    436    @media (forced-colors: active) {
    437      &:not(.placeholder) {
    438        border: var(--border-width) solid var(--border-color-card);
    439      }
    440 
    441      &:not(.placeholder):hover {
    442        --newtab-background-color-secondary: SelectedItemText;
    443        --newtab-text-secondary-color: SelectedItem;
    444 
    445        color: SelectedItem;
    446        border-color: var(--border-color-interactive-hover);
    447 
    448        .meta .title {
    449          color: var(--link-color-hover);
    450        }
    451      }
    452 
    453      .meta .title {
    454        text-decoration: underline;
    455        color: var(--link-color);
    456      }
    457    }
    458 
    459    .meta {
    460      padding: var(--space-large);
    461 
    462      .title {
    463        // show only 3 lines of copy
    464        -webkit-line-clamp: 3;
    465        font-size: var(--font-size-root);
    466        margin-block-end: var(--space-small);
    467        font-weight: var(--heading-font-weight);
    468      }
    469 
    470      .excerpt {
    471        // show only 3 lines of copy
    472        -webkit-line-clamp: 3;
    473        font-size: var(--font-size-small);
    474      }
    475 
    476      .source {
    477        -webkit-line-clamp: 1;
    478        font-size: var(--font-size-small);
    479      }
    480 
    481      // Sponsored by text
    482      .story-footer {
    483        justify-content: flex-start;
    484        display: grid;
    485        height: 28px;
    486        align-content: center;
    487        margin-block-start: var(--space-small);
    488      }
    489 
    490      .story-sponsored-label {
    491        line-height: unset;
    492        font-size: var(--font-size-small);
    493      }
    494    }
    495 
    496    .sections-card-footer {
    497      margin-block-start: var(--space-small);
    498      position: relative;
    499      min-height: 28px;
    500    }
    501 
    502    .ds-card-topic {
    503      display: grid;
    504      align-content: center;
    505      height: 28px;
    506      font-size: var(--font-size-small);
    507      color: var(--newtab-text-topic-label-color);
    508      margin: initial;
    509      padding: initial;
    510      background-color: initial;
    511    }
    512 
    513    .card-stp-button-hover-background {
    514      border-radius: var(--border-radius-large) var(--border-radius-large) 0 0;
    515      background-color: var(--button-background-color-ghost);
    516    }
    517 
    518    .ds-card-link:focus {
    519      border-radius: var(--border-radius-large);
    520    }
    521  }
    522 }
    523 
    524 .ds-card-grid,
    525 .ds-section-grid {
    526  // Intentionally duplicated classname to increase
    527  // specificity to override .sections-card-ui styles
    528  .ds-card.ds-spoc-rectangle.ds-spoc-rectangle {
    529    box-shadow: none;
    530    background: none;
    531 
    532    .ds-image {
    533      padding-block-start: 83.4%;
    534    }
    535 
    536    .card-stp-button-hover-background {
    537      padding-block-start: 83.4%;
    538    }
    539 
    540    .img-wrapper .ds-image img {
    541      border-radius: var(--border-radius-medium);
    542    }
    543 
    544    .meta {
    545      padding-inline: 0;
    546      padding-block: var(--space-medium);
    547 
    548      .title {
    549        text-transform: uppercase;
    550        font-size: var(--font-size-small);
    551        font-weight: var(--font-weight);
    552        color: var(--newtab-text-secondary-color);
    553      }
    554 
    555      .excerpt {
    556        display: none;
    557      }
    558    }
    559 
    560    .card-stp-button-hover-background {
    561      border-radius: var(--border-radius-medium);
    562    }
    563 
    564    &.sections-card-ui {
    565      .img-wrapper .ds-image img {
    566        border-radius: var(--border-radius-large);
    567      }
    568    }
    569 
    570    &.sections-card-ui:hover {
    571      box-shadow: none;
    572 
    573      .img-wrapper .ds-image img {
    574        box-shadow: 0 2px 14px 0 var(--newtab-section-card-box-shadow-color);
    575      }
    576    }
    577 
    578    &.refined-cards {
    579      @include newtab-card-style;
    580 
    581      .img-wrapper .ds-image img {
    582        border-end-start-radius: 0;
    583        border-end-end-radius: 0;
    584      }
    585 
    586      &:hover .img-wrapper .ds-image img {
    587        box-shadow: none;
    588      }
    589 
    590      .meta {
    591        padding: var(--space-small) var(--space-large);
    592        padding-block-end: 0;
    593 
    594      }
    595 
    596      .info-wrap {
    597        margin-block-start: auto;
    598      }
    599 
    600      .meta .title {
    601        text-transform: none;
    602      }
    603 
    604      .sections-card-footer {
    605        display: none;
    606      }
    607 
    608      .card-stp-button-position-wrapper {
    609        z-index: 10;
    610        inset-block-end: 0;
    611        position: absolute;
    612 
    613      }
    614 
    615      .card-stp-button-position-wrapper .context-menu-position-container {
    616        align-self: flex-start;
    617        padding-block-start: var(--space-medium);
    618      }
    619    }
    620  }
    621 
    622 }
    623 
    624 .ds-card-grid .refined-cards {
    625  .meta {
    626    color: var(--newtab-text-primary-color);
    627    padding: var(--space-small) var(--space-large);
    628 
    629    .excerpt {
    630      display: none;
    631    }
    632  }
    633 
    634  .sections-card-footer {
    635    display: flex;
    636    justify-content: space-between;
    637    pointer-events: none;
    638    max-width: 230px;
    639    margin-block-start: var(--space-xsmall);
    640 
    641    .source-wrapper {
    642      margin-block-end: 0;
    643      margin-inline-end: var(--space-xxsmall);
    644      max-width: 175px;
    645    }
    646  }
    647 
    648  &:has(.story-footer .story-sponsored-label) {
    649    .sections-card-footer {
    650      display: none;
    651    }
    652 
    653    .card-stp-button-position-wrapper {
    654      inset-block-end: var(--space-small);
    655    }
    656  }
    657 
    658  .story-footer {
    659    margin-block: 0 var(--space-xsmall);
    660  }
    661 
    662  .card-stp-button-hover-background {
    663    height: 100%;
    664    padding-block-start: 0;
    665    background: transparent;
    666 
    667    .card-stp-button-position-wrapper {
    668      inset-block-start: unset;
    669      // this value needs to equal the current padding of the card
    670      inset-block-end: var(--space-medium);
    671      inset-inline-end: var(--space-large);
    672      background: var(--button-background-color-ghost);
    673    }
    674  }
    675 
    676  .context-menu-button {
    677    background-color: var(--button-background-color-ghost);
    678 
    679    @media (forced-colors: active) {
    680      border: var(--border-width) solid var(--button-border-color-ghost);
    681    }
    682  }
    683 
    684  &:hover,
    685  &.active {
    686    h3 {
    687      color: var(--color-accent-primary);
    688    }
    689 
    690    .context-menu-button:hover {
    691      background-color: var(--button-background-color-ghost-hover);
    692 
    693      @media (forced-colors: active) {
    694        border-color: var(--button-border-color-ghost-hover);
    695        fill: var(--button-text-color-ghost-hover);
    696      }
    697 
    698      &:active {
    699        background-color: var(--button-background-color-ghost-active);
    700      }
    701    }
    702 
    703    .context-menu-button:focus-visible {
    704      outline: 2px solid var(--newtab-button-focus-border);
    705      background-color: var(--newtab-button-static-focus-background);
    706    }
    707  }
    708 
    709  .sections-card-footer {
    710    .source {
    711      display: block;
    712    }
    713  }
    714 }