@ -0,0 +1,27 @@ |
||||
.address-link { |
||||
border: 1px solid $border-color; |
||||
white-space: nowrap; |
||||
display: inline-block; |
||||
|
||||
&__font { |
||||
font-family: $font-family-monospace; |
||||
} |
||||
|
||||
&__type { |
||||
padding: 0 3px; |
||||
} |
||||
|
||||
&__seperator { |
||||
margin: 0 2px; |
||||
} |
||||
|
||||
&__copy-button { |
||||
background-color: $gray-100; |
||||
appearance: none; |
||||
border-color: transparent transparent transparent $border-color; |
||||
|
||||
i { |
||||
color:$gray-500 !important; |
||||
} |
||||
} |
||||
} |
@ -1,67 +0,0 @@ |
||||
.blocks { |
||||
@extend %paper; |
||||
|
||||
&__container { |
||||
padding: explorer-size(-1) explorer-size(0); |
||||
display: flex; |
||||
& + & { padding-top: 0; } |
||||
&--title { padding-top: explorer-size(0); } |
||||
} |
||||
|
||||
&__headline-title, |
||||
&__title { |
||||
@include explorer-typography("title"); |
||||
color: explorer-color("slate", "900"); |
||||
margin: 0; |
||||
width: 90%; |
||||
} |
||||
|
||||
&__headline-title { line-height: 18px; } |
||||
|
||||
&__table { |
||||
@extend %table; |
||||
@include explorer-typography("body1"); |
||||
color: explorer-color("slate", "900"); |
||||
} |
||||
|
||||
&__column-header { |
||||
@include explorer-typography("body1"); |
||||
&--optional { display: none; } |
||||
} |
||||
|
||||
&__column { |
||||
&--optional { display: none; } |
||||
} |
||||
|
||||
&__link { color: explorer-color("blue", "500"); } |
||||
|
||||
&__pagination { |
||||
margin: explorer-size(-1) 0 explorer-size(-2) 0; |
||||
.pagination { text-align: right; } |
||||
} |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-sm) { |
||||
.blocks { |
||||
&__column-header { |
||||
&--optional { display: table-cell; } |
||||
} |
||||
&__column { |
||||
&--optional { display: table-cell; } |
||||
} |
||||
} |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-md) { |
||||
.blocks { |
||||
&__headline { |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
&__headline-title { flex: 1; } |
||||
&__pagination { |
||||
margin: explorer-size(-1) 0 explorer-size(-2) 0; |
||||
} |
||||
} |
||||
} |
@ -1,12 +1,16 @@ |
||||
%dot { |
||||
.transaction { |
||||
|
||||
&__dot { |
||||
display: inline-block; |
||||
height: map-get(map-get($explorer-typography-styles, "body1"), "line-height") / 4; |
||||
width: map-get(map-get($explorer-typography-styles, "body1"), "line-height") / 4; |
||||
line-height: map-get(map-get($explorer-typography-styles, "body1"), "line-height"); |
||||
height: 10px; |
||||
width: 10px ; |
||||
border-radius: 50%; |
||||
} |
||||
margin-left: 5px; |
||||
vertical-align: baseline; |
||||
|
||||
%dot--pending { background-color: explorer-color("gray", "500"); } |
||||
%dot--succeeded { background-color: explorer-color("green", "500"); } |
||||
%dot--failed { background-color: explorer-color("red", "500"); } |
||||
%dot--warned { background-color: explorer-color("yellow", "500"); } |
||||
&--pending { background-color: $gray-500; } |
||||
&--success { background-color: $success; } |
||||
&--failed { background-color: $danger; } |
||||
&--out_of_gas { background-color: $warning; } |
||||
} |
||||
} |
||||
|
@ -1,65 +1,117 @@ |
||||
.header { |
||||
@extend %explorer-header-min-height; |
||||
background: explorer-color("gray", "50"); |
||||
box-shadow: 0 2px 2px 0 rgba(explorer-color("slate", "900"), 0.16), |
||||
0 0px 2px 0 rgba(explorer-color("slate", "900"), 0.12); |
||||
background: $gray-100; |
||||
box-shadow: 0 2px 2px 0 rgba($gray-900, 0.16), |
||||
0 0px 2px 0 rgba($gray-900, 0.12); |
||||
top: 0; |
||||
left: 0; |
||||
right: 0; |
||||
width: 100%; |
||||
|
||||
&__container { |
||||
|
||||
} |
||||
|
||||
&__row { |
||||
vertical-align: middle; |
||||
display: flex; |
||||
|
||||
&--theme { |
||||
display: none; |
||||
} |
||||
|
||||
&--search { |
||||
background-color: $secondary; |
||||
padding: 5px; |
||||
} |
||||
} |
||||
|
||||
&__cell { |
||||
|
||||
&--links { |
||||
display: flex; |
||||
flex-direction: row-reverse; |
||||
padding-right: explorer-size(0); |
||||
padding: 15px 25px; |
||||
|
||||
img { |
||||
height: 20px; |
||||
} |
||||
|
||||
i { |
||||
font-size: 1.55em; |
||||
color: $gray-500; |
||||
|
||||
&--search { |
||||
@include explorer-typography("body1"); |
||||
padding-left: 8px; |
||||
width: 90%; |
||||
margin-top: 7px; |
||||
} |
||||
} |
||||
|
||||
&--search { |
||||
font-size: 12px; |
||||
width: 75%; |
||||
height: 45px; |
||||
margin: 3px; |
||||
|
||||
&--search-form { |
||||
&-form { |
||||
position: relative; |
||||
border: 1px solid darken($secondary, 35%); |
||||
} |
||||
|
||||
&--search-glass { |
||||
height: 16px; |
||||
width: 16px; |
||||
&-glass { |
||||
height: 15px; |
||||
width: 15px; |
||||
position: absolute; |
||||
top: 18px; |
||||
left: 16px; |
||||
opacity: 0.5; |
||||
color: darken($secondary, 45%); |
||||
} |
||||
|
||||
&--search-input { |
||||
&-input { |
||||
width: 100%; |
||||
border: none; |
||||
background-color: transparent; |
||||
height: 50px; |
||||
height: 45px; |
||||
padding-left: 45px; |
||||
|
||||
|
||||
&[placeholder] { |
||||
text-overflow: ellipsis; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
input::-webkit-input-placeholder { |
||||
color: darken($secondary, 75%); |
||||
} |
||||
|
||||
@media (max-width: 768px) { |
||||
width: 90%; |
||||
padding-top: 5px; |
||||
.header { |
||||
&__row { |
||||
|
||||
&--topnav { |
||||
display: none; |
||||
} |
||||
|
||||
&--theme { |
||||
background-color: $primary; |
||||
padding: 5px; |
||||
} |
||||
} |
||||
|
||||
&--search-input[placeholder] { |
||||
text-overflow: ellipsis; |
||||
&__cell { |
||||
|
||||
&--search { |
||||
padding-left: 8px; |
||||
width: 95%; |
||||
height: 50px; |
||||
margin: 3px 0px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.topnav-dropdown { |
||||
background: $gray-100; |
||||
width: 85px; |
||||
border: none; |
||||
transform: translate3d(48px, 35px, 0px) !important; |
||||
} |
||||
|
||||
.topnav-dropdown-items { |
||||
padding-left: 12px; |
||||
} |
||||
|
@ -1,42 +0,0 @@ |
||||
.internal-transaction { |
||||
@extend %paper; |
||||
|
||||
&__container { |
||||
padding: explorer-size(-1) explorer-size(0); |
||||
& + & { padding-top: 0; } |
||||
&--title { padding-top: explorer-size(0); } |
||||
} |
||||
|
||||
&__header { @extend %section-header; } |
||||
&__heading { @extend %section-header__heading; } |
||||
&__subheading { @extend %section-header__subheading; } |
||||
&__tabs { @extend %section-tabs; } |
||||
|
||||
&__tab { |
||||
@extend %section-tabs__tab; |
||||
&--active { @extend %section-tabs__tab--active; } |
||||
} |
||||
|
||||
&__attributes { padding: explorer-size(-1) explorer-size(1); } |
||||
&__link { color: explorer-color("blue", "500"); } |
||||
|
||||
&__table { |
||||
@extend %table; |
||||
@include explorer-typography("body1"); |
||||
color: explorer-color("slate", "900"); |
||||
} |
||||
|
||||
&__to-address, &__from-address { |
||||
max-width: explorer-size(1); |
||||
text-overflow: ellipsis; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
&__column-header { @include explorer-typography("body1"); } |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-lg) { |
||||
&__to-address, &__from-address { |
||||
max-width: explorer-size(6); |
||||
} |
||||
} |
@ -0,0 +1,8 @@ |
||||
.nav-tabs { |
||||
border-bottom: none; |
||||
|
||||
.nav-link { |
||||
border-color: $border-color $border-color $border-color; |
||||
margin-right: 5px; |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
.panels { |
||||
@extend %paper; |
||||
|
||||
&__container { |
||||
padding: 20px; |
||||
} |
||||
} |
||||
|
||||
.pagination { |
||||
text-align: right; |
||||
margin: 10px; |
||||
} |
||||
|
||||
.monospace { |
||||
font-family: $font-family-monospace; |
||||
} |
@ -1,49 +0,0 @@ |
||||
.transaction { |
||||
&__container { @extend %paper; } |
||||
&__header { @extend %section-header; } |
||||
&__heading { @extend %section-header__heading; } |
||||
&__subheading { @extend %section-header__subheading; } |
||||
&__tabs { @extend %section-tabs; } |
||||
|
||||
&__tab { |
||||
@extend %section-tabs__tab; |
||||
&--active { @extend %section-tabs__tab--active; } |
||||
} |
||||
|
||||
&__attributes { padding: explorer-size(-1) explorer-size(1); } |
||||
&__column { @include explorer-typography("body1"); } |
||||
&__item { @extend %section-list__item; } |
||||
&__item-key { @extend %section-list__item-key; } |
||||
&__item-value { @extend %section-list__item-value; } |
||||
&__link { color: explorer-color("blue", "500"); } |
||||
|
||||
&__dot { |
||||
@extend %dot; |
||||
margin-left: explorer-size(-2); |
||||
vertical-align: baseline; |
||||
|
||||
&--pending { @extend %dot--pending; } |
||||
&--success { @extend %dot--succeeded; } |
||||
&--failed { @extend %dot--failed; } |
||||
&--out_of_gas { @extend %dot--warned; } |
||||
} |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-lg) { |
||||
.transaction { |
||||
&__attributes { |
||||
display: flex; |
||||
align-items: top; |
||||
justify-content: top; |
||||
} |
||||
|
||||
&__column { |
||||
width: explorer-size(1); |
||||
flex: 1; |
||||
margin-right: explorer-size(1); |
||||
& + & { margin-left: explorer-size(1); } |
||||
} |
||||
|
||||
&__dot { margin-left: explorer-size(-1); } |
||||
} |
||||
} |
@ -1,156 +0,0 @@ |
||||
.transactions { |
||||
@extend %paper; |
||||
|
||||
&__container { |
||||
padding: explorer-size(-1) explorer-size(0); |
||||
|
||||
&__flex { |
||||
display: flex; |
||||
} |
||||
|
||||
& + & { |
||||
padding-top: 0; |
||||
} |
||||
|
||||
&--title { |
||||
padding-top: explorer-size(0); |
||||
} |
||||
} |
||||
|
||||
&__headline-title, |
||||
&__title { |
||||
@include explorer-typography("title"); |
||||
color: explorer-color("slate", "900"); |
||||
width: 90%; |
||||
} |
||||
|
||||
&__title { margin: 0; } |
||||
|
||||
&__table { |
||||
@extend %table; |
||||
@include explorer-typography("body1"); |
||||
color: explorer-color("slate", "900"); |
||||
|
||||
& > thead > tr > th.transactions__column-header--status { |
||||
border-bottom: 0 none; |
||||
} |
||||
} |
||||
|
||||
&__column-header { @include explorer-typography("body1"); } |
||||
&__column-title { |
||||
&--status { display: none; } |
||||
} |
||||
&__link { |
||||
color: explorer-color("blue", "500"); |
||||
|
||||
&--truncated { |
||||
display: inline-block; |
||||
text-overflow: ellipsis; |
||||
white-space: nowrap; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
&--next-page { |
||||
@include explorer-typography("body1"); |
||||
display: block; |
||||
text-align: center; |
||||
padding: explorer-size(-1) 0; |
||||
border-top: 1px solid explorer-color("slate", "50"); |
||||
} |
||||
|
||||
&--long-hash { max-width: explorer-size(2); } |
||||
&--hash { max-width: explorer-size(2); } |
||||
} |
||||
|
||||
&__pagination { |
||||
margin: explorer-size(-1) 0 explorer-size(-2) 0; |
||||
.pagination { text-align: right; } |
||||
} |
||||
|
||||
&__column-header { |
||||
&--optional { display: none; } |
||||
} |
||||
|
||||
&__column { |
||||
&--status { |
||||
width: explorer-size(-1); |
||||
text-align: center; |
||||
} |
||||
&--optional { display: none; } |
||||
} |
||||
|
||||
&__tabs { @extend %section-tabs; } |
||||
|
||||
&__tab { |
||||
@extend %section-tabs__tab; |
||||
&--active { @extend %section-tabs__tab--active; } |
||||
} |
||||
|
||||
&__tab-link { |
||||
color: explorer-color("blue", "500"); |
||||
text-decoration: none; |
||||
&--active { color: explorer-color("slate", "900"); } |
||||
} |
||||
|
||||
&__hash-container { height: 1rem; } |
||||
|
||||
&__dot { |
||||
@extend %dot; |
||||
vertical-align: baseline; |
||||
&--pending { @extend %dot--pending; } |
||||
&--success { @extend %dot--succeeded; } |
||||
&--failed { @extend %dot--failed; } |
||||
&--out_of_gas { @extend %dot--warned; } |
||||
} |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-sm) { |
||||
.transactions { |
||||
&__link { |
||||
&--long-hash { max-width: explorer-size(3); } |
||||
&--hash { max-width: explorer-size(1); } |
||||
} |
||||
} |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-md) { |
||||
.transactions { |
||||
&__headline { |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
&__headline-title { flex: 1; } |
||||
&__pagination { |
||||
margin: explorer-size(-1) 0 explorer-size(-2) 0; |
||||
} |
||||
&__link { |
||||
&--long-hash { max-width: explorer-size(4); } |
||||
&--hash { max-width: explorer-size(3); } |
||||
} |
||||
} |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-lg) { |
||||
.transactions { |
||||
&__link { |
||||
&--long-hash { max-width: explorer-size(5); } |
||||
&--hash { max-width: explorer-size(4); } |
||||
} |
||||
} |
||||
} |
||||
|
||||
@media (min-width: $explorer-breakpoint-xl) { |
||||
.transactions { |
||||
&__column-header { |
||||
&--optional { display: table-cell; } |
||||
} |
||||
&__column { |
||||
&--optional { display: table-cell; } |
||||
} |
||||
&__link { |
||||
&--long-hash { max-width: explorer-size(5); } |
||||
&--hash { max-width: explorer-size(4); } |
||||
} |
||||
} |
||||
} |
@ -1,23 +1,25 @@ |
||||
%table { |
||||
width: 100%; |
||||
max-width: 100%; |
||||
margin-bottom: 1rem; |
||||
.table-font { |
||||
|
||||
> thead, |
||||
> tbody, |
||||
> tfoot { |
||||
> tr { |
||||
> th { text-align: left; } |
||||
thead th, td, th { |
||||
border-top: none; |
||||
border-bottom: none; |
||||
} |
||||
|
||||
> th, |
||||
> td { |
||||
padding: explorer-size(-2) 0; |
||||
line-height: 1rem; |
||||
i { |
||||
color: $gray-500; |
||||
} |
||||
|
||||
img { |
||||
width: 12px; |
||||
} |
||||
} |
||||
|
||||
> thead > tr > th { |
||||
border-bottom: 2px solid explorer-color("slate", "50"); |
||||
.table-horizontal { |
||||
th { |
||||
width: 35%; |
||||
} |
||||
} |
||||
|
||||
.address-cell { |
||||
width: 150px; |
||||
} |
||||
|
@ -1,37 +1,2 @@ |
||||
|
||||
@font-face { |
||||
font-family: 'Roboto'; |
||||
src: url("/fonts/Roboto/Roboto-Light.ttf"); |
||||
font-weight: 200; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: 'Roboto'; |
||||
src: url("/fonts/Roboto/Roboto-Regular.ttf"); |
||||
font-weight: 400; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: 'Roboto'; |
||||
src: url("/fonts/Roboto/Roboto-MediumItalic.ttf"); |
||||
font-weight: 400; |
||||
font-style: italic; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: 'Roboto'; |
||||
src: url("/fonts/Roboto/Roboto-Medium.ttf"); |
||||
font-weight: 600; |
||||
} |
||||
|
||||
|
||||
@font-face { |
||||
font-family: 'Roboto'; |
||||
src: url("/fonts/Roboto/Roboto-Bold.ttf"); |
||||
font-weight: 700; |
||||
} |
||||
|
||||
@font-face { |
||||
font-family: 'Boxed Bold'; |
||||
src: url("/fonts/boxed-bold.otf"); |
||||
} |
||||
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono'); |
||||
@import url('https://fonts.googleapis.com/css?family=Roboto'); |
||||
|
@ -0,0 +1,928 @@ |
||||
// Variables |
||||
// |
||||
// Variables should follow the `$component-state-property-size` formula for |
||||
// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs. |
||||
|
||||
|
||||
// |
||||
// Color system |
||||
// |
||||
|
||||
// stylelint-disable |
||||
$white: #fff !default; |
||||
$gray-100: #f8f9fa !default; |
||||
$gray-200: #e9ecef !default; |
||||
$gray-300: #dee2e6 !default; |
||||
$gray-400: #ced4da !default; |
||||
$gray-500: #adb5bd !default; |
||||
$gray-600: #cdcdcc !default; |
||||
$gray-700: #495057 !default; |
||||
$gray-800: #343a40 !default; |
||||
$gray-900: #212529 !default; |
||||
$black: #000 !default; |
||||
|
||||
$grays: () !default; |
||||
$grays: map-merge(( |
||||
"100": $gray-100, |
||||
"200": $gray-200, |
||||
"300": $gray-300, |
||||
"400": $gray-400, |
||||
"500": $gray-500, |
||||
"600": $gray-600, |
||||
"700": $gray-700, |
||||
"800": $gray-800, |
||||
"900": $gray-900 |
||||
), $grays); |
||||
|
||||
$blue: #4786ff !default; |
||||
$indigo: #5b33a1 !default; |
||||
$purple: #9987fc !default; |
||||
$pink: #e83e8c !default; |
||||
$red: #dc3545 !default; |
||||
$orange: #fd7e14 !default; |
||||
$yellow: #ffc107 !default; |
||||
$green: #61db97 !default; |
||||
$teal: !default; |
||||
$cyan: #90e1d8 !default; |
||||
|
||||
$colors: () !default; |
||||
$colors: map-merge(( |
||||
"blue": $blue, |
||||
"indigo": $indigo, |
||||
"purple": $purple, |
||||
"pink": $pink, |
||||
"red": $red, |
||||
"orange": $orange, |
||||
"yellow": $yellow, |
||||
"green": $green, |
||||
"teal": $teal, |
||||
"cyan": $cyan, |
||||
"white": $white, |
||||
"gray": $gray-600, |
||||
"gray-dark": $gray-800 |
||||
), $colors); |
||||
|
||||
$primary: $indigo !default; |
||||
$secondary: $cyan !default; |
||||
$success: $green !default; |
||||
$info: $cyan !default; |
||||
$warning: $orange !default; |
||||
$danger: $red !default; |
||||
$light: $gray-100 !default; |
||||
$dark: $gray-800 !default; |
||||
|
||||
$theme-colors: () !default; |
||||
$theme-colors: map-merge(( |
||||
"primary": $primary, |
||||
"secondary": $cyan, |
||||
"success": $success, |
||||
"info": $info, |
||||
"warning": $warning, |
||||
"danger": $danger, |
||||
"light": $light, |
||||
"dark": $dark |
||||
), $theme-colors); |
||||
// stylelint-enable |
||||
|
||||
// Set a specific jump point for requesting color jumps |
||||
$theme-color-interval: 8% !default; |
||||
|
||||
// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255. |
||||
$yiq-contrasted-threshold: 150 !default; |
||||
|
||||
// Customize the light and dark text colors for use in our YIQ color contrast function. |
||||
$yiq-text-dark: $gray-900 !default; |
||||
$yiq-text-light: $white !default; |
||||
|
||||
// Options |
||||
// |
||||
// Quickly modify global styling by enabling or disabling optional features. |
||||
|
||||
$enable-caret: true !default; |
||||
$enable-rounded: true !default; |
||||
$enable-shadows: false !default; |
||||
$enable-gradients: false !default; |
||||
$enable-transitions: true !default; |
||||
$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS |
||||
$enable-grid-classes: true !default; |
||||
$enable-print-styles: true !default; |
||||
|
||||
|
||||
// Spacing |
||||
// |
||||
// Control the default styling of most Bootstrap elements by modifying these |
||||
// variables. Mostly focused on spacing. |
||||
// You can add more entries to the $spacers map, should you need more variation. |
||||
|
||||
// stylelint-disable |
||||
$spacer: 1rem !default; |
||||
$spacers: () !default; |
||||
$spacers: map-merge(( |
||||
0: 0, |
||||
1: ($spacer * .25), |
||||
2: ($spacer * .5), |
||||
3: $spacer, |
||||
4: ($spacer * 1.5), |
||||
5: ($spacer * 3) |
||||
), $spacers); |
||||
|
||||
// This variable affects the `.h-*` and `.w-*` classes. |
||||
$sizes: () !default; |
||||
$sizes: map-merge(( |
||||
25: 25%, |
||||
50: 50%, |
||||
75: 75%, |
||||
100: 100%, |
||||
auto: auto |
||||
), $sizes); |
||||
// stylelint-enable |
||||
|
||||
// Body |
||||
// |
||||
// Settings for the `<body>` element. |
||||
|
||||
$body-bg: $white !default; |
||||
$body-color: $gray-900 !default; |
||||
|
||||
// Links |
||||
// |
||||
// Style anchor elements. |
||||
|
||||
$link-color: theme-color("primary") !default; |
||||
$link-decoration: none !default; |
||||
$link-hover-color: darken(map-get($theme-colors, primary), 15%) !default; |
||||
$link-hover-decoration: underline !default; |
||||
|
||||
// Paragraphs |
||||
// |
||||
// Style p element. |
||||
|
||||
$paragraph-margin-bottom: 1rem !default; |
||||
|
||||
|
||||
// Grid breakpoints |
||||
// |
||||
// Define the minimum dimensions at which your layout will change, |
||||
// adapting to different screen sizes, for use in media queries. |
||||
|
||||
$grid-breakpoints: ( |
||||
xs: 0, |
||||
sm: 576px, |
||||
md: 768px, |
||||
lg: 992px, |
||||
xl: 1200px |
||||
) !default; |
||||
|
||||
@include _assert-ascending($grid-breakpoints, "$grid-breakpoints"); |
||||
@include _assert-starts-at-zero($grid-breakpoints); |
||||
|
||||
|
||||
// Grid containers |
||||
// |
||||
// Define the maximum width of `.container` for different screen sizes. |
||||
|
||||
$container-max-widths: ( |
||||
sm: 540px, |
||||
md: 720px, |
||||
lg: 960px, |
||||
xl: 1140px |
||||
) !default; |
||||
|
||||
@include _assert-ascending($container-max-widths, "$container-max-widths"); |
||||
|
||||
|
||||
// Grid columns |
||||
// |
||||
// Set the number of columns and specify the width of the gutters. |
||||
|
||||
$grid-columns: 12 !default; |
||||
$grid-gutter-width: 30px !default; |
||||
|
||||
// Components |
||||
// |
||||
// Define common padding and border radius sizes and more. |
||||
|
||||
$line-height-lg: 1.5 !default; |
||||
$line-height-sm: 1.5 !default; |
||||
|
||||
$border-width: 1px !default; |
||||
$border-color: $gray-300 !default; |
||||
|
||||
$border-radius: .25rem !default; |
||||
$border-radius-lg: .3rem !default; |
||||
$border-radius-sm: .2rem !default; |
||||
|
||||
$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default; |
||||
$box-shadow: 0 .5rem 1rem rgba($black, .15) !default; |
||||
$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default; |
||||
|
||||
$component-active-color: $white !default; |
||||
$component-active-bg: theme-color("primary") !default; |
||||
|
||||
$caret-width: .3em !default; |
||||
|
||||
$transition-base: all .2s ease-in-out !default; |
||||
$transition-fade: opacity .15s linear !default; |
||||
$transition-collapse: height .35s ease !default; |
||||
|
||||
|
||||
// Fonts |
||||
// |
||||
// Font, line-height, and color for body text, headings, and more. |
||||
|
||||
// stylelint-disable value-keyword-case |
||||
$font-family-sans-serif: Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default; |
||||
$font-family-monospace: "Roboto Mono", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default; |
||||
$font-family-base: $font-family-sans-serif !default; |
||||
// stylelint-enable value-keyword-case |
||||
|
||||
$font-size-base: 1rem !default; // Assumes the browser default, typically `16px` |
||||
$font-size-lg: ($font-size-base * 1.25) !default; |
||||
$font-size-sm: ($font-size-base * .875) !default; |
||||
|
||||
$font-weight-light: 300 !default; |
||||
$font-weight-normal: 400 !default; |
||||
$font-weight-bold: 700 !default; |
||||
|
||||
$font-weight-base: $font-weight-normal !default; |
||||
$line-height-base: 1.5 !default; |
||||
|
||||
$h1-font-size: $font-size-base * 2.5 !default; |
||||
$h2-font-size: $font-size-base * 2 !default; |
||||
$h3-font-size: $font-size-base * 1.75 !default; |
||||
$h4-font-size: $font-size-base * 1.5 !default; |
||||
$h5-font-size: $font-size-base * 1.25 !default; |
||||
$h6-font-size: $font-size-base !default; |
||||
|
||||
$headings-margin-bottom: ($spacer / 2) !default; |
||||
$headings-font-family: inherit !default; |
||||
$headings-font-weight: 500 !default; |
||||
$headings-line-height: 1.2 !default; |
||||
$headings-color: inherit !default; |
||||
|
||||
$display1-size: 6rem !default; |
||||
$display2-size: 5.5rem !default; |
||||
$display3-size: 4.5rem !default; |
||||
$display4-size: 3.5rem !default; |
||||
|
||||
$display1-weight: 300 !default; |
||||
$display2-weight: 300 !default; |
||||
$display3-weight: 300 !default; |
||||
$display4-weight: 300 !default; |
||||
$display-line-height: $headings-line-height !default; |
||||
|
||||
$lead-font-size: ($font-size-base * 1.25) !default; |
||||
$lead-font-weight: 300 !default; |
||||
|
||||
$small-font-size: 80% !default; |
||||
|
||||
$text-muted: $gray-600 !default; |
||||
|
||||
$blockquote-small-color: $gray-600 !default; |
||||
$blockquote-font-size: ($font-size-base * 1.25) !default; |
||||
|
||||
$hr-border-color: rgba($black, .1) !default; |
||||
$hr-border-width: $border-width !default; |
||||
|
||||
$mark-padding: .2em !default; |
||||
|
||||
$dt-font-weight: $font-weight-bold !default; |
||||
|
||||
$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default; |
||||
$nested-kbd-font-weight: $font-weight-bold !default; |
||||
|
||||
$list-inline-padding: .5rem !default; |
||||
|
||||
$mark-bg: #fcf8e3 !default; |
||||
|
||||
$hr-margin-y: $spacer !default; |
||||
|
||||
|
||||
// Tables |
||||
// |
||||
// Customizes the `.table` component with basic values, each used across all table variations. |
||||
|
||||
$table-cell-padding: .75rem !default; |
||||
$table-cell-padding-sm: .3rem !default; |
||||
|
||||
$table-bg: transparent !default; |
||||
$table-accent-bg: rgba($black, .05) !default; |
||||
$table-hover-bg: rgba($black, .075) !default; |
||||
$table-active-bg: $table-hover-bg !default; |
||||
|
||||
$table-border-width: $border-width !default; |
||||
$table-border-color: $gray-300 !default; |
||||
|
||||
$table-head-bg: $gray-200 !default; |
||||
$table-head-color: $gray-700 !default; |
||||
|
||||
$table-dark-bg: $gray-900 !default; |
||||
$table-dark-accent-bg: rgba($white, .05) !default; |
||||
$table-dark-hover-bg: rgba($white, .075) !default; |
||||
$table-dark-border-color: lighten($gray-900, 7.5%) !default; |
||||
$table-dark-color: $body-bg !default; |
||||
|
||||
$table-striped-order: odd !default; |
||||
|
||||
$table-caption-color: $text-muted !default; |
||||
|
||||
// Buttons + Forms |
||||
// |
||||
// Shared variables that are reassigned to `$input-` and `$btn-` specific variables. |
||||
|
||||
$input-btn-padding-y: .375rem !default; |
||||
$input-btn-padding-x: .75rem !default; |
||||
$input-btn-line-height: $line-height-base !default; |
||||
|
||||
$input-btn-focus-width: .2rem !default; |
||||
$input-btn-focus-color: rgba($component-active-bg, .25) !default; |
||||
$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default; |
||||
|
||||
$input-btn-padding-y-sm: .25rem !default; |
||||
$input-btn-padding-x-sm: .5rem !default; |
||||
$input-btn-line-height-sm: $line-height-sm !default; |
||||
|
||||
$input-btn-padding-y-lg: .5rem !default; |
||||
$input-btn-padding-x-lg: 1rem !default; |
||||
$input-btn-line-height-lg: $line-height-lg !default; |
||||
|
||||
$input-btn-border-width: $border-width !default; |
||||
|
||||
|
||||
// Buttons |
||||
// |
||||
// For each of Bootstrap's buttons, define text, background, and border color. |
||||
|
||||
$btn-padding-y: $input-btn-padding-y !default; |
||||
$btn-padding-x: $input-btn-padding-x !default; |
||||
$btn-line-height: $input-btn-line-height !default; |
||||
|
||||
$btn-padding-y-sm: $input-btn-padding-y-sm !default; |
||||
$btn-padding-x-sm: $input-btn-padding-x-sm !default; |
||||
$btn-line-height-sm: $input-btn-line-height-sm !default; |
||||
|
||||
$btn-padding-y-lg: $input-btn-padding-y-lg !default; |
||||
$btn-padding-x-lg: $input-btn-padding-x-lg !default; |
||||
$btn-line-height-lg: $input-btn-line-height-lg !default; |
||||
|
||||
$btn-border-width: $input-btn-border-width !default; |
||||
|
||||
$btn-font-weight: $font-weight-normal !default; |
||||
$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default; |
||||
$btn-focus-width: $input-btn-focus-width !default; |
||||
$btn-focus-box-shadow: $input-btn-focus-box-shadow !default; |
||||
$btn-disabled-opacity: .65 !default; |
||||
$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default; |
||||
|
||||
$btn-link-disabled-color: $gray-600 !default; |
||||
|
||||
$btn-block-spacing-y: .5rem !default; |
||||
|
||||
// Allows for customizing button radius independently from global border radius |
||||
$btn-border-radius: $border-radius !default; |
||||
$btn-border-radius-lg: $border-radius-lg !default; |
||||
$btn-border-radius-sm: $border-radius-sm !default; |
||||
|
||||
$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; |
||||
|
||||
|
||||
// Forms |
||||
|
||||
$label-margin-bottom: .5rem !default; |
||||
|
||||
$input-padding-y: $input-btn-padding-y !default; |
||||
$input-padding-x: $input-btn-padding-x !default; |
||||
$input-line-height: $input-btn-line-height !default; |
||||
|
||||
$input-padding-y-sm: $input-btn-padding-y-sm !default; |
||||
$input-padding-x-sm: $input-btn-padding-x-sm !default; |
||||
$input-line-height-sm: $input-btn-line-height-sm !default; |
||||
|
||||
$input-padding-y-lg: $input-btn-padding-y-lg !default; |
||||
$input-padding-x-lg: $input-btn-padding-x-lg !default; |
||||
$input-line-height-lg: $input-btn-line-height-lg !default; |
||||
|
||||
$input-bg: $white !default; |
||||
$input-disabled-bg: $gray-200 !default; |
||||
|
||||
$input-color: $gray-700 !default; |
||||
$input-border-color: $gray-400 !default; |
||||
$input-border-width: $input-btn-border-width !default; |
||||
$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default; |
||||
|
||||
$input-border-radius: $border-radius !default; |
||||
$input-border-radius-lg: $border-radius-lg !default; |
||||
$input-border-radius-sm: $border-radius-sm !default; |
||||
|
||||
$input-focus-bg: $input-bg !default; |
||||
$input-focus-border-color: lighten($component-active-bg, 25%) !default; |
||||
$input-focus-color: $input-color !default; |
||||
$input-focus-width: $input-btn-focus-width !default; |
||||
$input-focus-box-shadow: $input-btn-focus-box-shadow !default; |
||||
|
||||
$input-placeholder-color: $gray-600 !default; |
||||
$input-plaintext-color: $body-color !default; |
||||
|
||||
$input-height-border: $input-border-width * 2 !default; |
||||
|
||||
$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default; |
||||
$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default; |
||||
|
||||
$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default; |
||||
$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default; |
||||
|
||||
$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default; |
||||
$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default; |
||||
|
||||
$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default; |
||||
|
||||
$form-text-margin-top: .25rem !default; |
||||
|
||||
$form-check-input-gutter: 1.25rem !default; |
||||
$form-check-input-margin-y: .3rem !default; |
||||
$form-check-input-margin-x: .25rem !default; |
||||
|
||||
$form-check-inline-margin-x: .75rem !default; |
||||
$form-check-inline-input-margin-x: .3125rem !default; |
||||
|
||||
$form-group-margin-bottom: 1rem !default; |
||||
|
||||
$input-group-addon-color: $input-color !default; |
||||
$input-group-addon-bg: $gray-200 !default; |
||||
$input-group-addon-border-color: $input-border-color !default; |
||||
|
||||
$custom-control-gutter: 1.5rem !default; |
||||
$custom-control-spacer-x: 1rem !default; |
||||
|
||||
$custom-control-indicator-size: 1rem !default; |
||||
$custom-control-indicator-bg: $gray-300 !default; |
||||
$custom-control-indicator-bg-size: 50% 50% !default; |
||||
$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default; |
||||
|
||||
$custom-control-indicator-disabled-bg: $gray-200 !default; |
||||
$custom-control-label-disabled-color: $gray-600 !default; |
||||
|
||||
$custom-control-indicator-checked-color: $component-active-color !default; |
||||
$custom-control-indicator-checked-bg: $component-active-bg !default; |
||||
$custom-control-indicator-checked-disabled-bg: rgba(theme-color("primary"), .5) !default; |
||||
$custom-control-indicator-checked-box-shadow: none !default; |
||||
|
||||
$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default; |
||||
|
||||
$custom-control-indicator-active-color: $component-active-color !default; |
||||
$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default; |
||||
$custom-control-indicator-active-box-shadow: none !default; |
||||
|
||||
$custom-checkbox-indicator-border-radius: $border-radius !default; |
||||
$custom-checkbox-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
|
||||
$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default; |
||||
$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default; |
||||
$custom-checkbox-indicator-icon-indeterminate: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
$custom-checkbox-indicator-indeterminate-box-shadow: none !default; |
||||
|
||||
$custom-radio-indicator-border-radius: 50% !default; |
||||
$custom-radio-indicator-icon-checked: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
|
||||
$custom-select-padding-y: .375rem !default; |
||||
$custom-select-padding-x: .75rem !default; |
||||
$custom-select-height: $input-height !default; |
||||
$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator |
||||
$custom-select-line-height: $input-btn-line-height !default; |
||||
$custom-select-color: $input-color !default; |
||||
$custom-select-disabled-color: $gray-600 !default; |
||||
$custom-select-bg: $input-bg !default; |
||||
$custom-select-disabled-bg: $gray-200 !default; |
||||
$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions |
||||
$custom-select-indicator-color: $gray-800 !default; |
||||
$custom-select-indicator: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
$custom-select-border-width: $input-btn-border-width !default; |
||||
$custom-select-border-color: $input-border-color !default; |
||||
$custom-select-border-radius: $border-radius !default; |
||||
|
||||
$custom-select-focus-border-color: $input-focus-border-color !default; |
||||
$custom-select-focus-box-shadow: inset 0 1px 2px rgba($black, .075), 0 0 5px rgba($custom-select-focus-border-color, .5) !default; |
||||
|
||||
$custom-select-font-size-sm: 75% !default; |
||||
$custom-select-height-sm: $input-height-sm !default; |
||||
|
||||
$custom-select-font-size-lg: 125% !default; |
||||
$custom-select-height-lg: $input-height-lg !default; |
||||
|
||||
$custom-range-track-width: 100% !default; |
||||
$custom-range-track-height: .5rem !default; |
||||
$custom-range-track-cursor: pointer !default; |
||||
$custom-range-track-bg: $gray-300 !default; |
||||
$custom-range-track-border-radius: 1rem !default; |
||||
$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default; |
||||
|
||||
$custom-range-thumb-width: 1rem !default; |
||||
$custom-range-thumb-height: $custom-range-thumb-width !default; |
||||
$custom-range-thumb-bg: $component-active-bg !default; |
||||
$custom-range-thumb-border: 0 !default; |
||||
$custom-range-thumb-border-radius: 1rem !default; |
||||
$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default; |
||||
$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default; |
||||
$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default; |
||||
|
||||
$custom-file-height: $input-height !default; |
||||
$custom-file-focus-border-color: $input-focus-border-color !default; |
||||
$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default; |
||||
|
||||
$custom-file-padding-y: $input-btn-padding-y !default; |
||||
$custom-file-padding-x: $input-btn-padding-x !default; |
||||
$custom-file-line-height: $input-btn-line-height !default; |
||||
$custom-file-color: $input-color !default; |
||||
$custom-file-bg: $input-bg !default; |
||||
$custom-file-border-width: $input-btn-border-width !default; |
||||
$custom-file-border-color: $input-border-color !default; |
||||
$custom-file-border-radius: $input-border-radius !default; |
||||
$custom-file-box-shadow: $input-box-shadow !default; |
||||
$custom-file-button-color: $custom-file-color !default; |
||||
$custom-file-button-bg: $input-group-addon-bg !default; |
||||
$custom-file-text: ( |
||||
en: "Browse" |
||||
) !default; |
||||
|
||||
|
||||
// Form validation |
||||
$form-feedback-margin-top: $form-text-margin-top !default; |
||||
$form-feedback-font-size: $small-font-size !default; |
||||
$form-feedback-valid-color: theme-color("success") !default; |
||||
$form-feedback-invalid-color: theme-color("danger") !default; |
||||
|
||||
|
||||
// Dropdowns |
||||
// |
||||
// Dropdown menu container and contents. |
||||
|
||||
$dropdown-min-width: 10rem !default; |
||||
$dropdown-padding-y: .5rem !default; |
||||
$dropdown-spacer: .125rem !default; |
||||
$dropdown-bg: $white !default; |
||||
$dropdown-border-color: rgba($black, .15) !default; |
||||
$dropdown-border-radius: $border-radius !default; |
||||
$dropdown-border-width: $border-width !default; |
||||
$dropdown-divider-bg: $gray-200 !default; |
||||
$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default; |
||||
|
||||
$dropdown-link-color: $gray-900 !default; |
||||
$dropdown-link-hover-color: darken($gray-900, 5%) !default; |
||||
$dropdown-link-hover-bg: $gray-100 !default; |
||||
|
||||
$dropdown-link-active-color: $component-active-color !default; |
||||
$dropdown-link-active-bg: $component-active-bg !default; |
||||
|
||||
$dropdown-link-disabled-color: $gray-600 !default; |
||||
|
||||
$dropdown-item-padding-y: .25rem !default; |
||||
$dropdown-item-padding-x: 1.5rem !default; |
||||
|
||||
$dropdown-header-color: $gray-600 !default; |
||||
|
||||
|
||||
// Z-index master list |
||||
// |
||||
// Warning: Avoid customizing these values. They're used for a bird's eye view |
||||
// of components dependent on the z-axis and are designed to all work together. |
||||
|
||||
$zindex-dropdown: 1000 !default; |
||||
$zindex-sticky: 1020 !default; |
||||
$zindex-fixed: 1030 !default; |
||||
$zindex-modal-backdrop: 1040 !default; |
||||
$zindex-modal: 1050 !default; |
||||
$zindex-popover: 1060 !default; |
||||
$zindex-tooltip: 1070 !default; |
||||
|
||||
// Navs |
||||
|
||||
$nav-link-padding-y: .5rem !default; |
||||
$nav-link-padding-x: 1rem !default; |
||||
$nav-link-disabled-color: $gray-600 !default; |
||||
|
||||
$nav-tabs-border-color: $gray-300 !default; |
||||
$nav-tabs-border-width: $border-width !default; |
||||
$nav-tabs-border-radius: $border-radius !default; |
||||
$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default; |
||||
$nav-tabs-link-active-color: $gray-700 !default; |
||||
$nav-tabs-link-active-bg: $body-bg !default; |
||||
$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default; |
||||
|
||||
$nav-pills-border-radius: $border-radius !default; |
||||
$nav-pills-link-active-color: $component-active-color !default; |
||||
$nav-pills-link-active-bg: $component-active-bg !default; |
||||
|
||||
$nav-divider-color: $gray-200 !default; |
||||
$nav-divider-margin-y: ($spacer / 2) !default; |
||||
|
||||
// Navbar |
||||
|
||||
$navbar-padding-y: ($spacer / 2) !default; |
||||
$navbar-padding-x: $spacer !default; |
||||
|
||||
$navbar-nav-link-padding-x: .5rem !default; |
||||
|
||||
$navbar-brand-font-size: $font-size-lg !default; |
||||
// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link |
||||
$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default; |
||||
$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default; |
||||
$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default; |
||||
|
||||
$navbar-toggler-padding-y: .25rem !default; |
||||
$navbar-toggler-padding-x: .75rem !default; |
||||
$navbar-toggler-font-size: $font-size-lg !default; |
||||
$navbar-toggler-border-radius: $btn-border-radius !default; |
||||
|
||||
$navbar-dark-color: rgba($white, .5) !default; |
||||
$navbar-dark-hover-color: rgba($white, .75) !default; |
||||
$navbar-dark-active-color: $white !default; |
||||
$navbar-dark-disabled-color: rgba($white, .25) !default; |
||||
$navbar-dark-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
$navbar-dark-toggler-border-color: rgba($white, .1) !default; |
||||
|
||||
$navbar-light-color: $gray-200 !default; |
||||
$navbar-light-hover-color: rgba($black, .7) !default; |
||||
$navbar-light-active-color: rgba($black, .9) !default; |
||||
$navbar-light-disabled-color: rgba($black, .3) !default; |
||||
$navbar-light-toggler-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
$navbar-light-toggler-border-color: rgba($black, .1) !default; |
||||
|
||||
// Pagination |
||||
|
||||
$pagination-padding-y: .5rem !default; |
||||
$pagination-padding-x: .75rem !default; |
||||
$pagination-padding-y-sm: .25rem !default; |
||||
$pagination-padding-x-sm: .5rem !default; |
||||
$pagination-padding-y-lg: .75rem !default; |
||||
$pagination-padding-x-lg: 1.5rem !default; |
||||
$pagination-line-height: 1.25 !default; |
||||
|
||||
$pagination-color: $link-color !default; |
||||
$pagination-bg: $white !default; |
||||
$pagination-border-width: $border-width !default; |
||||
$pagination-border-color: $gray-300 !default; |
||||
|
||||
$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default; |
||||
$pagination-focus-outline: 0 !default; |
||||
|
||||
$pagination-hover-color: $link-hover-color !default; |
||||
$pagination-hover-bg: $gray-200 !default; |
||||
$pagination-hover-border-color: $gray-300 !default; |
||||
|
||||
$pagination-active-color: $component-active-color !default; |
||||
$pagination-active-bg: $component-active-bg !default; |
||||
$pagination-active-border-color: $pagination-active-bg !default; |
||||
|
||||
$pagination-disabled-color: $gray-600 !default; |
||||
$pagination-disabled-bg: $white !default; |
||||
$pagination-disabled-border-color: $gray-300 !default; |
||||
|
||||
|
||||
// Jumbotron |
||||
|
||||
$jumbotron-padding: 2rem !default; |
||||
$jumbotron-bg: $gray-200 !default; |
||||
|
||||
|
||||
// Cards |
||||
|
||||
$card-spacer-y: .75rem !default; |
||||
$card-spacer-x: 1.25rem !default; |
||||
$card-border-width: $border-width !default; |
||||
$card-border-radius: $border-radius !default; |
||||
$card-border-color: rgba($black, .125) !default; |
||||
$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default; |
||||
$card-cap-bg: rgba($black, .03) !default; |
||||
$card-bg: $white !default; |
||||
|
||||
$card-img-overlay-padding: 1.25rem !default; |
||||
|
||||
$card-group-margin: ($grid-gutter-width / 2) !default; |
||||
$card-deck-margin: $card-group-margin !default; |
||||
|
||||
$card-columns-count: 3 !default; |
||||
$card-columns-gap: 1.25rem !default; |
||||
$card-columns-margin: $card-spacer-y !default; |
||||
|
||||
|
||||
// Tooltips |
||||
|
||||
$tooltip-font-size: $font-size-sm !default; |
||||
$tooltip-max-width: 70ch !default; |
||||
$tooltip-color: $white !default; |
||||
$tooltip-bg: darken($secondary, 25%) !default; |
||||
$tooltip-border-radius: $border-radius !default; |
||||
$tooltip-opacity: 1 !default; |
||||
$tooltip-padding-y: .30rem !default; |
||||
$tooltip-padding-x: .6rem !default; |
||||
$tooltip-margin: 0 !default; |
||||
|
||||
$tooltip-arrow-width: .8rem !default; |
||||
$tooltip-arrow-height: .4rem !default; |
||||
$tooltip-arrow-color: $tooltip-bg !default; |
||||
|
||||
|
||||
// Popovers |
||||
|
||||
$popover-font-size: $font-size-sm !default; |
||||
$popover-bg: $white !default; |
||||
$popover-max-width: 276px !default; |
||||
$popover-border-width: $border-width !default; |
||||
$popover-border-color: rgba($black, .2) !default; |
||||
$popover-border-radius: $border-radius-lg !default; |
||||
$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default; |
||||
|
||||
$popover-header-bg: darken($popover-bg, 3%) !default; |
||||
$popover-header-color: $headings-color !default; |
||||
$popover-header-padding-y: .5rem !default; |
||||
$popover-header-padding-x: .75rem !default; |
||||
|
||||
$popover-body-color: $body-color !default; |
||||
$popover-body-padding-y: $popover-header-padding-y !default; |
||||
$popover-body-padding-x: $popover-header-padding-x !default; |
||||
|
||||
$popover-arrow-width: 1rem !default; |
||||
$popover-arrow-height: .5rem !default; |
||||
$popover-arrow-color: $popover-bg !default; |
||||
|
||||
$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default; |
||||
|
||||
|
||||
// Badges |
||||
|
||||
$badge-font-size: 75% !default; |
||||
$badge-font-weight: $font-weight-bold !default; |
||||
$badge-padding-y: .25em !default; |
||||
$badge-padding-x: .4em !default; |
||||
$badge-border-radius: $border-radius !default; |
||||
|
||||
$badge-pill-padding-x: .6em !default; |
||||
// Use a higher than normal value to ensure completely rounded edges when |
||||
// customizing padding or font-size on labels. |
||||
$badge-pill-border-radius: 10rem !default; |
||||
|
||||
|
||||
// Modals |
||||
|
||||
// Padding applied to the modal body |
||||
$modal-inner-padding: 1rem !default; |
||||
|
||||
$modal-dialog-margin: .5rem !default; |
||||
$modal-dialog-margin-y-sm-up: 1.75rem !default; |
||||
|
||||
$modal-title-line-height: $line-height-base !default; |
||||
|
||||
$modal-content-bg: $white !default; |
||||
$modal-content-border-color: rgba($black, .2) !default; |
||||
$modal-content-border-width: $border-width !default; |
||||
$modal-content-border-radius: $border-radius-lg !default; |
||||
$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default; |
||||
$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default; |
||||
|
||||
$modal-backdrop-bg: $black !default; |
||||
$modal-backdrop-opacity: .5 !default; |
||||
$modal-header-border-color: $gray-200 !default; |
||||
$modal-footer-border-color: $modal-header-border-color !default; |
||||
$modal-header-border-width: $modal-content-border-width !default; |
||||
$modal-footer-border-width: $modal-header-border-width !default; |
||||
$modal-header-padding: 1rem !default; |
||||
|
||||
$modal-lg: 800px !default; |
||||
$modal-md: 500px !default; |
||||
$modal-sm: 300px !default; |
||||
|
||||
$modal-transition: transform .3s ease-out !default; |
||||
|
||||
|
||||
// Alerts |
||||
// |
||||
// Define alert colors, border radius, and padding. |
||||
|
||||
$alert-padding-y: .75rem !default; |
||||
$alert-padding-x: 1.25rem !default; |
||||
$alert-margin-bottom: 1rem !default; |
||||
$alert-border-radius: $border-radius !default; |
||||
$alert-link-font-weight: $font-weight-bold !default; |
||||
$alert-border-width: $border-width !default; |
||||
|
||||
$alert-bg-level: -10 !default; |
||||
$alert-border-level: -9 !default; |
||||
$alert-color-level: 6 !default; |
||||
|
||||
|
||||
// Progress bars |
||||
|
||||
$progress-height: 1rem !default; |
||||
$progress-font-size: ($font-size-base * .75) !default; |
||||
$progress-bg: $gray-200 !default; |
||||
$progress-border-radius: $border-radius !default; |
||||
$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default; |
||||
$progress-bar-color: $white !default; |
||||
$progress-bar-bg: theme-color("primary") !default; |
||||
$progress-bar-animation-timing: 1s linear infinite !default; |
||||
$progress-bar-transition: width .6s ease !default; |
||||
|
||||
// List group |
||||
|
||||
$list-group-bg: $white !default; |
||||
$list-group-border-color: rgba($black, .125) !default; |
||||
$list-group-border-width: $border-width !default; |
||||
$list-group-border-radius: $border-radius !default; |
||||
|
||||
$list-group-item-padding-y: .75rem !default; |
||||
$list-group-item-padding-x: 1.25rem !default; |
||||
|
||||
$list-group-hover-bg: $gray-100 !default; |
||||
$list-group-active-color: $component-active-color !default; |
||||
$list-group-active-bg: $component-active-bg !default; |
||||
$list-group-active-border-color: $list-group-active-bg !default; |
||||
|
||||
$list-group-disabled-color: $gray-600 !default; |
||||
$list-group-disabled-bg: $list-group-bg !default; |
||||
|
||||
$list-group-action-color: $gray-700 !default; |
||||
$list-group-action-hover-color: $list-group-action-color !default; |
||||
|
||||
$list-group-action-active-color: $body-color !default; |
||||
$list-group-action-active-bg: $gray-200 !default; |
||||
|
||||
|
||||
// Image thumbnails |
||||
|
||||
$thumbnail-padding: .25rem !default; |
||||
$thumbnail-bg: $body-bg !default; |
||||
$thumbnail-border-width: $border-width !default; |
||||
$thumbnail-border-color: $gray-300 !default; |
||||
$thumbnail-border-radius: $border-radius !default; |
||||
$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default; |
||||
|
||||
|
||||
// Figures |
||||
|
||||
$figure-caption-font-size: 90% !default; |
||||
$figure-caption-color: $gray-600 !default; |
||||
|
||||
|
||||
// Breadcrumbs |
||||
|
||||
$breadcrumb-padding-y: .75rem !default; |
||||
$breadcrumb-padding-x: 1rem !default; |
||||
$breadcrumb-item-padding: .5rem !default; |
||||
|
||||
$breadcrumb-margin-bottom: 1rem !default; |
||||
|
||||
$breadcrumb-bg: $gray-200 !default; |
||||
$breadcrumb-divider-color: $gray-600 !default; |
||||
$breadcrumb-active-color: $gray-600 !default; |
||||
$breadcrumb-divider: quote("/") !default; |
||||
|
||||
$breadcrumb-border-radius: $border-radius !default; |
||||
|
||||
|
||||
// Carousel |
||||
|
||||
$carousel-control-color: $white !default; |
||||
$carousel-control-width: 15% !default; |
||||
$carousel-control-opacity: .5 !default; |
||||
|
||||
$carousel-indicator-width: 30px !default; |
||||
$carousel-indicator-height: 3px !default; |
||||
$carousel-indicator-spacer: 3px !default; |
||||
$carousel-indicator-active-bg: $white !default; |
||||
|
||||
$carousel-caption-width: 70% !default; |
||||
$carousel-caption-color: $white !default; |
||||
|
||||
$carousel-control-icon-width: 20px !default; |
||||
|
||||
$carousel-control-prev-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
$carousel-control-next-icon-bg: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"), "#", "%23") !default; |
||||
|
||||
$carousel-transition: transform .6s ease !default; // Define transform transition first if using multiple transitons (e.g., `transform 2s ease, opacity .5s ease-out`) |
||||
|
||||
|
||||
// Close |
||||
|
||||
$close-font-size: $font-size-base * 1.5 !default; |
||||
$close-font-weight: $font-weight-bold !default; |
||||
$close-color: $black !default; |
||||
$close-text-shadow: 0 1px 0 $white !default; |
||||
|
||||
// Code |
||||
|
||||
$code-font-size: 87.5% !default; |
||||
$code-color: $pink !default; |
||||
|
||||
$kbd-padding-y: .2rem !default; |
||||
$kbd-padding-x: .4rem !default; |
||||
$kbd-font-size: $code-font-size !default; |
||||
$kbd-color: $white !default; |
||||
$kbd-bg: $gray-900 !default; |
||||
|
||||
$pre-color: $gray-900 !default; |
||||
$pre-scrollable-max-height: 340px !default; |
||||
|
||||
|
||||
// Printing |
||||
$print-page-size: a3 !default; |
||||
$print-body-min-width: map-get($grid-breakpoints, "lg") !default; |
@ -0,0 +1,145 @@ |
||||
.theme__ribbon { |
||||
width: 155px; |
||||
height: 160px; |
||||
position: absolute; |
||||
right: 8%; |
||||
color: white; |
||||
padding: 10px; |
||||
z-index: 9999; |
||||
perspective: 800px; |
||||
backface-visibility: hidden; |
||||
outline: 1px solid transparent; |
||||
|
||||
@media (max-width: 890px) { |
||||
right: 1%; |
||||
} |
||||
|
||||
@media (max-width: 768px) { |
||||
display: none; |
||||
} |
||||
|
||||
&--logo { |
||||
width: 100%; |
||||
padding: 35px 15px; |
||||
} |
||||
|
||||
&--social { |
||||
display: flex; |
||||
position: absolute; |
||||
bottom: 0; |
||||
margin-bottom: 2px; |
||||
justify-content: center; |
||||
width: 100%; |
||||
|
||||
&-icons { |
||||
display: flex; |
||||
font-size: 15px; |
||||
padding: 8px; |
||||
color: lighten($primary, 25%); |
||||
justify-content: space-between; |
||||
} |
||||
|
||||
&-divider { |
||||
width: 1px; |
||||
padding: 0px !important; |
||||
background: lighten($primary, 25%); |
||||
} |
||||
} |
||||
} |
||||
|
||||
.flex { |
||||
display: flex; |
||||
justify-content: center; |
||||
position: absolute; |
||||
bottom: 5px; |
||||
left: 1px; |
||||
margin-left: 8px; |
||||
} |
||||
|
||||
|
||||
//Ribbon FLip Syles |
||||
|
||||
.card { |
||||
width: 100%; |
||||
height: 100%; |
||||
transition: all .5s; |
||||
backface-visibility: hidden; |
||||
position: absolute; |
||||
top: 0px; |
||||
left: 0px; |
||||
outline: 1px solid transparent; |
||||
|
||||
} |
||||
|
||||
.front { |
||||
z-index: 2; |
||||
background-color: $primary; |
||||
outline: 1px solid transparent; |
||||
box-shadow: 0 2px 2px 0 rgba(#212529, 0.16), |
||||
0 0px 2px 0 rgba(#212529, 0.12); |
||||
} |
||||
|
||||
.back { |
||||
z-index: 1; |
||||
transform: rotateY(-180deg); |
||||
background-color: $primary; |
||||
outline: 1px solid transparent; |
||||
box-shadow: 0 2px 2px 0 rgba(#212529, 0.16), |
||||
0 0px 2px 0 rgba(#212529, 0.12); |
||||
|
||||
& .switch-network { |
||||
font-size: 12px; |
||||
padding: 3px; |
||||
background-color: lighten($primary, 25%); |
||||
width: 115px; |
||||
} |
||||
|
||||
& .switch-network-menu { |
||||
width: 115px; |
||||
} |
||||
|
||||
& .switch-network-item { |
||||
padding: 3px 5px; |
||||
} |
||||
|
||||
& .back-arrow { |
||||
position: absolute; |
||||
bottom: 0; |
||||
margin: 0px 0px 10px -10px; |
||||
} |
||||
} |
||||
|
||||
.rotatecard, .rotatecardback{ |
||||
z-index: 3; |
||||
cursor: pointer; |
||||
background: none; |
||||
border: none; |
||||
padding: 0px; |
||||
|
||||
&:focus { |
||||
outline: none; |
||||
} |
||||
} |
||||
|
||||
.flipped{ |
||||
z-index: 1; |
||||
transform: rotateY(180deg); |
||||
backface-visibility: hidden; |
||||
outline: 1px solid transparent; |
||||
} |
||||
|
||||
.backflip { |
||||
z-index: 2; |
||||
transform: rotateY(0deg); |
||||
transition: all .5s; |
||||
outline: 1px solid transparent; |
||||
} |
||||
|
||||
.change-color svg { |
||||
width: 20px; |
||||
height: 20px; |
||||
|
||||
path { |
||||
fill: $primary; |
||||
} |
||||
} |
@ -1 +1 @@ |
||||
@import "neutral-variables"; |
||||
@import "poa_variables"; |
||||
|
@ -0,0 +1,115 @@ |
||||
// Base class |
||||
.tooltip { |
||||
position: absolute; |
||||
z-index: $zindex-tooltip; |
||||
display: block; |
||||
margin: $tooltip-margin; |
||||
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. |
||||
// So reset our font and text properties to avoid inheriting weird values. |
||||
@include reset-text(); |
||||
font-size: $tooltip-font-size; |
||||
// Allow breaking very long words so they don't overflow the tooltip's bounds |
||||
word-wrap: break-word; |
||||
opacity: 0; |
||||
|
||||
&.show { opacity: $tooltip-opacity; } |
||||
|
||||
.arrow { |
||||
position: absolute; |
||||
display: block; |
||||
width: $tooltip-arrow-width; |
||||
height: $tooltip-arrow-height; |
||||
|
||||
&::before { |
||||
position: absolute; |
||||
content: ""; |
||||
border-color: transparent; |
||||
border-style: solid; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.bs-tooltip-top { |
||||
padding: $tooltip-arrow-height 0; |
||||
|
||||
.arrow { |
||||
bottom: 0; |
||||
|
||||
&::before { |
||||
top: 0; |
||||
border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0; |
||||
border-top-color: $tooltip-arrow-color; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.bs-tooltip-right { |
||||
padding: 0 $tooltip-arrow-height; |
||||
|
||||
.arrow { |
||||
left: 0; |
||||
width: $tooltip-arrow-height; |
||||
height: $tooltip-arrow-width; |
||||
|
||||
&::before { |
||||
right: 0; |
||||
border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0; |
||||
border-right-color: $tooltip-arrow-color; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.bs-tooltip-bottom { |
||||
padding: $tooltip-arrow-height 0; |
||||
|
||||
.arrow { |
||||
top: 0; |
||||
|
||||
&::before { |
||||
bottom: 0; |
||||
border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height; |
||||
border-bottom-color: $tooltip-arrow-color; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.bs-tooltip-left { |
||||
padding: 0 $tooltip-arrow-height; |
||||
|
||||
.arrow { |
||||
right: 0; |
||||
width: $tooltip-arrow-height; |
||||
height: $tooltip-arrow-width; |
||||
|
||||
&::before { |
||||
left: 0; |
||||
border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height; |
||||
border-left-color: $tooltip-arrow-color; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.bs-tooltip-auto { |
||||
&[x-placement^="top"] { |
||||
@extend .bs-tooltip-top; |
||||
} |
||||
&[x-placement^="right"] { |
||||
@extend .bs-tooltip-right; |
||||
} |
||||
&[x-placement^="bottom"] { |
||||
@extend .bs-tooltip-bottom; |
||||
} |
||||
&[x-placement^="left"] { |
||||
@extend .bs-tooltip-left; |
||||
} |
||||
} |
||||
|
||||
// Wrapper for the tooltip content |
||||
.tooltip-inner { |
||||
max-width: $tooltip-max-width; |
||||
padding: $tooltip-padding-y $tooltip-padding-x; |
||||
color: $tooltip-color; |
||||
text-align: center; |
||||
background-color: $tooltip-bg; |
||||
@include border-radius($tooltip-border-radius); |
||||
} |
@ -0,0 +1,11 @@ |
||||
import $ from 'jquery' |
||||
|
||||
$('.rotatecard').click(function () { |
||||
$(this).parents('.front').toggleClass('flipped') |
||||
$(this).parentsUntil('.theme__ribbon').next('.back').toggleClass('backflip') |
||||
}) |
||||
|
||||
$('.rotatecardback').click(function () { |
||||
$(this).parentsUntil('.panel').prev('.front').toggleClass('flipped') |
||||
$(this).parents('.back').toggleClass('backflip') |
||||
}) |
@ -0,0 +1,16 @@ |
||||
import ClipboardJS from 'clipboard' |
||||
import $ from 'jquery' |
||||
|
||||
const clipboard = new ClipboardJS('[data-clipboard-text]') |
||||
|
||||
clipboard.on('success', ({trigger}) => { |
||||
const copyButton = $(trigger) |
||||
copyButton.tooltip({ |
||||
title: 'Copied!', |
||||
trigger: 'click', |
||||
placement: 'top' |
||||
}).tooltip('show') |
||||
setTimeout(() => { |
||||
copyButton.tooltip('dispose') |
||||
}, 1000) |
||||
}) |
@ -0,0 +1,5 @@ |
||||
import $ from 'jquery' |
||||
|
||||
$(function () { |
||||
$('[data-toggle="tooltip"]').tooltip() |
||||
}) |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1014 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 256 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,15 @@ |
||||
<div class="address-link"> |
||||
<%= if @address do %> |
||||
<%= link to: address_path(@conn, :show, @conn.assigns.locale, @address), |
||||
"data-toggle": "tooltip", |
||||
"data-placement": "top", |
||||
class: "address-link__font", |
||||
title: @address do %> |
||||
<i class="address-link__type fas fa-address-card"></i> |
||||
<%= @address |> hash |> String.slice(0..3) %><i class="fas fa-ellipsis-v address-link__seperator"></i><%= @address |> hash |> String.slice(-4..-1) %> |
||||
<% end %> |
||||
<button class="address-link__copy-button" data-clipboard-text="<%= @address %>" aria-label="copy address"> |
||||
<i class="fa fa-copy"></i> |
||||
</button> |
||||
<% end %> |
||||
</div> |
@ -0,0 +1,31 @@ |
||||
<div class="panels container__subsection container__subsection-chain"> |
||||
<div class="panels__container panels__container--title"> |
||||
<%= link(gettext("View All"), to: block_path(@conn, :index, Gettext.get_locale), class: "button button--secondary button--xsmall u-float-right") %> |
||||
<h2 class="panels__title"><%= gettext "Blocks" %></h2> |
||||
</div> |
||||
<table class="table table-font table-responsive-sm"> |
||||
<thead> |
||||
<th><%= gettext "Height" %></th> |
||||
<th><%= gettext "Age" %></th> |
||||
<th><%= gettext "TXNs" %></th> |
||||
<th><%= gettext "Gas" %></th> |
||||
<th><%= gettext "Validator" %></th> |
||||
</thead> |
||||
<tbody> |
||||
<%= for block <- @chain.blocks do %> |
||||
<tr data-test="chain_block"> |
||||
<td> |
||||
<img src="<%= static_path(@conn, "/images/block.svg") %>" /> |
||||
<%= link(block, to: block_path(@conn, :show, @conn.assigns.locale, block)) %> |
||||
</td> |
||||
<td><%= block.timestamp |> Timex.from_now %></td> |
||||
<td><%= block.transactions |> Enum.count %></td> |
||||
<td><%= block.gas_used |> Cldr.Number.to_string! %></td> |
||||
<td> |
||||
<%= render ExplorerWeb.AddressView, "_link.html", conn: @conn, address: block.miner %> |
||||
</td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
</div> |
@ -0,0 +1,32 @@ |
||||
<div class="panels container__subsection container__subsection-chain"> |
||||
<div class="panels__container panels__container--title"> |
||||
<%= link(gettext("View All"), to: transaction_path(@conn, :index, Gettext.get_locale), class: "button button--secondary button--xsmall u-float-right") %> |
||||
<h2 class="panels__title"><%= gettext "Transactions" %></h2> |
||||
</div> |
||||
<table class="table table-font table-responsive-sm"> |
||||
<thead> |
||||
<th><%= gettext "TX Hash" %></th> |
||||
<th><%= gettext "From" %></th> |
||||
<th><%= gettext "To" %></th> |
||||
<th><%= gettext "Value" %> (<%= gettext "Ether" %>)</th> |
||||
<th><%= gettext "Age" %></th> |
||||
</thead> |
||||
<tbody> |
||||
<%= for transaction <- @chain.transactions do %> |
||||
<tr data-test="chain_transaction"> |
||||
<td> |
||||
<%= render ExplorerWeb.TransactionView, "_link.html", conn: @conn, transaction: transaction %> |
||||
</td> |
||||
<td> |
||||
<%= render ExplorerWeb.AddressView, "_link.html", conn: @conn, address: transaction.from_address %> |
||||
</td> |
||||
<td> |
||||
<%= render ExplorerWeb.AddressView, "_link.html", conn: @conn, address: transaction.to_address %> |
||||
</td> |
||||
<td><%= ExplorerWeb.TransactionView.value(transaction, include_label: false) %> </td> |
||||
<td><%= transaction.block.timestamp |> Timex.from_now() %></td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
</div> |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 494 B |
@ -0,0 +1,61 @@ |
||||
<div class="theme__ribbon"> |
||||
<div class="front card"> |
||||
<%= link to: chain_path(@conn, :show), "data-test": "header_logo" do %> |
||||
<img class="theme__ribbon--logo" src="<%= static_path(@conn, "/images/poa_logo.svg") %>" /> |
||||
<% end %> |
||||
<div class="theme__ribbon--social" align="right"> |
||||
<a href="https://www.facebook.com/PoaNetwork/" target="_blank"> |
||||
<div class="theme__ribbon--social-icons"> |
||||
<i class="fab fa-facebook-f"></i> |
||||
</div> |
||||
</a> |
||||
<a href="https://www.instagram.com/PoaNetwork/" target="_blank"> |
||||
<div class="theme__ribbon--social-icons"> |
||||
<i class="fab fa-instagram"></i> |
||||
</div> |
||||
</a> |
||||
<a href="https://www.twitter.com/PoaNetwork/" target="_blank"> |
||||
<div class="theme__ribbon--social-icons"> |
||||
<i class="fab fa-twitter"></i> |
||||
</div> |
||||
</a> |
||||
<a href="https://www.twitter.com/PoaNetwork/" target="_blank"> |
||||
<div class="theme__ribbon--social-icons"> |
||||
<i class="fab fa-telegram-plane"></i> |
||||
</div> |
||||
</a> |
||||
<div class="theme__ribbon--social-icons u-padding-none"> |
||||
<i class="theme__ribbon--social-divider"></i> |
||||
</div> |
||||
<button class="rotatecard header__link"> |
||||
<div class="theme__ribbon--social-icons "> |
||||
<i class="fa fa-sitemap"></i> |
||||
</div> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
<div class="back card"> |
||||
<%= link to: chain_path(@conn, :show) do %> |
||||
<img class="theme__ribbon--logo" src="<%= static_path(@conn, "/images/poa_logo.svg") %>" /> |
||||
<% end %> |
||||
<div class="flex"> |
||||
<div class="dropdown"> |
||||
<button class="switch-network dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
||||
Switch Network |
||||
</button> |
||||
<div class="dropdown-menu switch-network-menu" aria-labelledby="dropdownMenuButton"> |
||||
<a class="dropdown-item switch-network-item" href="https://explorer-core.poanetwork/">POA Core</a> |
||||
<a class="dropdown-item switch-network-item" href="https://explorer-sokol.poanetwork/">POA Sokol</a> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="header__cell header__cell--social" align="right"> |
||||
<button class="rotatecardback"> |
||||
<div class="theme__ribbon--social-icons"> |
||||
<i class="fa fa-arrow-left "></i> |
||||
</div> |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
@ -0,0 +1,60 @@ |
||||
<div id="sidebar--container"> |
||||
<nav id="sidebar"> |
||||
<div class="sidebar-header"> |
||||
<%= link to: chain_path(@conn, :show) do %> |
||||
<img class="" src="<%= static_path(@conn, "/images/poa_logo.svg") %>" /> |
||||
<% end %> |
||||
</div> |
||||
<div class="menu-items"> |
||||
<div tabindex="0" class="icon-locate"> |
||||
<a href="#pageSubmenu" data-toggle="collapse" aria-expanded="false"> |
||||
<i class="fa fa-sitemap fa-2x u-nudge-right u-nudge-top"></i> |
||||
<%= gettext("Switch Network ") %> |
||||
<i class="fa fa-caret-down"></i> |
||||
</a> |
||||
<ul class="collapse list-unstyled" id="pageSubmenu"> |
||||
<li><a href="#">Explorer</a></li> |
||||
<li><a href="#">Sokol (Testnet)</a></li> |
||||
<li><a href="#">Mainnet</a></li> |
||||
</ul> |
||||
</div> |
||||
<%= link to: block_path(@conn, :index, Gettext.get_locale), class: "header__link" do %> |
||||
<div tabindex="0" class="icon-locate"> |
||||
<i class="fas fa-home fa-2x u-nudge-right u-nudge-top"></i> |
||||
<%= gettext("Dashboard") %> |
||||
</div> |
||||
<% end %> |
||||
<%= link to: block_path(@conn, :index, Gettext.get_locale), class: "header__link" do %> |
||||
<div tabindex="0" class="icon-locate"> |
||||
<img class="" src="<%= static_path(@conn, "/images/block.svg") %>" /> |
||||
<%= gettext("Blocks") %> |
||||
</div> |
||||
<% end %> |
||||
<div tabindex="0" class="icon-locate"> |
||||
<a href="#pageSubmenu-tx" data-toggle="collapse" aria-expanded="false"> |
||||
<img class="" src="<%= static_path(@conn, "/images/transaction.svg") %>" /> |
||||
<%= gettext("Transactions") %> |
||||
<i class="fa fa-caret-down"></i> |
||||
</a> |
||||
<ul class="collapse list-unstyled" id="pageSubmenu-tx"> |
||||
<li><%= link(gettext("Validated"), to: transaction_path(@conn, :index, Gettext.get_locale)) %></li> |
||||
<li><%= link(gettext("Pending"), to: pending_transaction_path(@conn, :index, Gettext.get_locale)) %></li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
<div class="social-media"> |
||||
<a href="https://www.facebook.com/PoaNetwork/" target="_blank"> |
||||
<i class="fab fa-facebook-f"></i> |
||||
</a> |
||||
<a href="https://www.instagram.com/PoaNetwork/" target="_blank"> |
||||
<i class="fab fa-instagram"></i> |
||||
</a> |
||||
<a href="https://www.twitter.com/PoaNetwork/" target="_blank"> |
||||
<i class="fab fa-twitter"></i> |
||||
</a> |
||||
<a href="https://www.twitter.com/PoaNetwork/" target="_blank"> |
||||
<i class="fab fa-telegram-plane"></i> |
||||
</a> |
||||
</div> |
||||
</nav> |
||||
</div> |
@ -0,0 +1,37 @@ |
||||
<header class="header"> |
||||
<div class="header__row header__row--search"> |
||||
<div class="header__cell header__cell--search"> |
||||
<%= form_for @conn, chain_path(@conn, :search, Gettext.get_locale), [class: "header__cell--search-form", method: :get, enforce_utf8: false], fn f -> %> |
||||
<i class="header__cell--search-glass fa fa-search"></i> |
||||
<%= search_input f, :q, class: 'header__cell--search-input', placeholder: gettext("Search by address, transaction hash, or block number"), "data-test": "search_input" %> |
||||
<% end %> |
||||
</div> |
||||
</div> |
||||
<div class="header__row header__row--topnav"> |
||||
<div class="header__cell header__cell--links" align="right"> |
||||
<%= link to: chain_path(@conn, :show) do %> |
||||
<div tabindex="0"> |
||||
<i class="fas fa-home fa-2x"></i> |
||||
</div> |
||||
<% end %> |
||||
</div> |
||||
<div class="header__cell header__cell--links" align="right"> |
||||
<%= link to: block_path(@conn, :index, Gettext.get_locale) do %> |
||||
<div tabindex="0"> |
||||
<img src="<%= static_path(@conn, "/images/block.svg") %>" /> |
||||
<%= gettext("Blocks") %> |
||||
</div> |
||||
<% end %> |
||||
</div> |
||||
<div class="header__cell header__cell--links dropdown"> |
||||
<a class="dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
||||
<img src="<%= static_path(@conn, "/images/transaction.svg") %>" /> |
||||
<%= gettext("Transactions") %> |
||||
</a> |
||||
<div class="dropdown-menu topnav-dropdown" aria-labelledby="navbarDropdown"> |
||||
<%= link(gettext("Validated"), to: transaction_path(@conn, :index, Gettext.get_locale), class: "dropdown-item topnav-dropdown-items") %> |
||||
<%= link(gettext("Pending"), to: pending_transaction_path(@conn, :index, Gettext.get_locale), class: "dropdown-item topnav-dropdown-items") %> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</header> |
@ -0,0 +1,8 @@ |
||||
<%= link(@transaction |> hash |> String.slice(2..7), |
||||
to: transaction_path(@conn, :show, @conn.assigns.locale, @transaction), |
||||
"data-toggle": "tooltip", |
||||
"data-placement": "top", |
||||
"data-test": "transaction_hash", |
||||
"data-transaction-hash": @transaction.hash, |
||||
class: "monospace", |
||||
title: @transaction) %> |
@ -0,0 +1,3 @@ |
||||
defmodule ExplorerWeb.IconsView do |
||||
use ExplorerWeb, :view |
||||
end |
@ -1,280 +0,0 @@ |
||||
defmodule ExplorerWeb.ContributorBrowsingTest do |
||||
use ExplorerWeb.FeatureCase, async: true |
||||
|
||||
import Wallaby.Query, only: [css: 1, css: 2, link: 1] |
||||
|
||||
alias Explorer.Chain.{Credit, Debit} |
||||
|
||||
@logo css("[data-test='header_logo']") |
||||
|
||||
test "browses the home page", %{session: session} do |
||||
session |> visit("/") |
||||
assert current_path(session) == "/en" |
||||
|
||||
session |
||||
|> click(@logo) |
||||
|> assert_has(css("main", text: "Blocks")) |
||||
end |
||||
|
||||
test "search for blocks", %{session: session} do |
||||
block = insert(:block, number: 42) |
||||
|
||||
refute block.miner_hash == nil |
||||
|
||||
session |
||||
|> visit("/") |
||||
|> fill_in(css(".header__cell--search-input"), with: to_string(block.number)) |
||||
|> send_keys([:enter]) |
||||
|> assert_has(css(".block__item", text: to_string(block.miner_hash))) |
||||
end |
||||
|
||||
test "search for transactions", %{session: session} do |
||||
transaction = insert(:transaction, input: "0x736f636b73") |
||||
|
||||
session |
||||
|> visit("/") |
||||
|> fill_in( |
||||
css(".header__cell--search-input"), |
||||
with: to_string(transaction.hash) |
||||
) |
||||
|> send_keys([:enter]) |
||||
|> assert_has(css(".transaction__item", text: to_string(transaction.input))) |
||||
end |
||||
|
||||
test "search for address", %{session: session} do |
||||
address = insert(:address) |
||||
|
||||
session |
||||
|> visit("/") |
||||
|> fill_in( |
||||
css(".header__cell--search-input"), |
||||
with: to_string(address.hash) |
||||
) |
||||
|> send_keys([:enter]) |
||||
|> assert_has(css(".address__subheading", text: to_string(address.hash))) |
||||
end |
||||
|
||||
test "views blocks", %{session: session} do |
||||
timestamp = Timex.now() |> Timex.shift(hours: -1) |
||||
Enum.map(307..310, &insert(:block, number: &1, timestamp: timestamp, gas_used: 10)) |
||||
|
||||
fifth_block = |
||||
insert(:block, %{ |
||||
gas_limit: 5_030_101, |
||||
gas_used: 1_010_101, |
||||
nonce: 123_456_789, |
||||
number: 311, |
||||
size: 9_999_999, |
||||
timestamp: timestamp |
||||
}) |
||||
|
||||
transaction = insert(:transaction, block_hash: fifth_block.hash, index: 0) |
||||
|
||||
insert(:transaction, block_hash: fifth_block.hash, index: 1) |
||||
insert(:transaction, block_hash: fifth_block.hash, index: 2) |
||||
insert(:receipt, transaction_hash: transaction.hash, transaction_index: transaction.index) |
||||
|
||||
Credit.refresh() |
||||
Debit.refresh() |
||||
|
||||
session |
||||
|> visit("/en") |
||||
|> assert_has(css(".blocks__title", text: "Blocks")) |
||||
|> assert_has(css(".blocks__column--height", count: 2, text: "1")) |
||||
|> assert_has(css(".blocks__column--transactions-count", count: 5)) |
||||
|> assert_has(css(".blocks__column--transactions-count", count: 1, text: "3")) |
||||
|> assert_has(css(".blocks__column--age", count: 5, text: "1 hour ago")) |
||||
|> assert_has(css(".blocks__column--gas-used", count: 5, text: "10")) |
||||
|
||||
session |
||||
|> click(link("Blocks")) |
||||
|> assert_has(css(".blocks__column--height", text: "311")) |
||||
|> click(link("311")) |
||||
|> assert_has(css(".block__item", text: to_string(fifth_block.hash))) |
||||
|> assert_has(css(".block__item", text: to_string(fifth_block.miner_hash))) |
||||
|> assert_has(css(".block__item", text: "9,999,999")) |
||||
|> assert_has(css(".block__item", text: "1 hour ago")) |
||||
|> assert_has(css(".block__item", text: "5,030,101")) |
||||
|> assert_has(css(".block__item", text: to_string(fifth_block.nonce))) |
||||
|> assert_has(css(".block__item", text: "1,010,101")) |
||||
|> click(css(".block__link", text: "Transactions")) |
||||
|> assert_has(css(".transactions__link--long-hash", text: to_string(transaction.hash))) |
||||
end |
||||
|
||||
describe "transactions and address pages" do |
||||
setup do |
||||
block = |
||||
insert(:block, %{ |
||||
number: 555, |
||||
timestamp: Timex.now() |> Timex.shift(hours: -2), |
||||
gas_used: 123_987 |
||||
}) |
||||
|
||||
for index <- 0..3, do: insert(:transaction, block_hash: block.hash, index: index) |
||||
pending = insert(:transaction, block_hash: nil, gas: 5891, index: nil) |
||||
|
||||
lincoln = insert(:address) |
||||
taft = insert(:address) |
||||
|
||||
transaction = |
||||
insert( |
||||
:transaction, |
||||
block_hash: block.hash, |
||||
value: Explorer.Chain.Wei.from(Decimal.new(5656), :ether), |
||||
gas: Decimal.new(1_230_000_000_000_123_123), |
||||
gas_price: Decimal.new(7_890_000_000_898_912_300_045), |
||||
index: 4, |
||||
input: "0x000012", |
||||
nonce: 99045, |
||||
inserted_at: Timex.parse!("1970-01-01T00:00:18-00:00", "{ISO:Extended}"), |
||||
updated_at: Timex.parse!("1980-01-01T00:00:18-00:00", "{ISO:Extended}"), |
||||
from_address_hash: taft.hash, |
||||
to_address_hash: lincoln.hash |
||||
) |
||||
|
||||
receipt = insert(:receipt, status: :ok, transaction_hash: transaction.hash, transaction_index: transaction.index) |
||||
insert(:log, address_hash: lincoln.hash, index: 0, transaction_hash: receipt.transaction_hash) |
||||
|
||||
# From Lincoln to Taft. |
||||
txn_from_lincoln = |
||||
insert( |
||||
:transaction, |
||||
block_hash: block.hash, |
||||
index: 5, |
||||
from_address_hash: lincoln.hash, |
||||
to_address_hash: taft.hash |
||||
) |
||||
|
||||
internal_receipt = |
||||
insert(:receipt, transaction_hash: txn_from_lincoln.hash, transaction_index: txn_from_lincoln.index) |
||||
|
||||
internal = insert(:internal_transaction, transaction_hash: internal_receipt.transaction_hash) |
||||
|
||||
Credit.refresh() |
||||
Debit.refresh() |
||||
|
||||
{:ok, |
||||
%{ |
||||
pending: pending, |
||||
internal: internal, |
||||
lincoln: lincoln, |
||||
taft: taft, |
||||
transaction: transaction, |
||||
txn_from_lincoln: txn_from_lincoln |
||||
}} |
||||
end |
||||
|
||||
test "views transactions", %{session: session} do |
||||
session |
||||
|> visit("/en") |
||||
|> assert_has(css(".transactions__title", text: "Transactions")) |
||||
|> assert_has(css(".transactions__column--hash", count: 5)) |
||||
|> assert_has(css(".transactions__column--value", count: 5)) |
||||
|> assert_has(css(".transactions__column--age", count: 5)) |
||||
end |
||||
|
||||
test "can see pending transactions", %{pending: pending, session: session} do |
||||
session |
||||
|> visit("/transactions") |
||||
|> click(css(".transactions__tab-link", text: "Pending")) |
||||
|> click(css(".transactions__link", text: to_string(pending.hash))) |
||||
|> assert_has(css(".transaction__item-value--status", text: "Pending")) |
||||
end |
||||
|
||||
test "don't see pending transactions by default", %{session: session} do |
||||
session |
||||
|> visit("/transactions") |
||||
|> refute_has(css(".transactions__column--block", text: "Pending")) |
||||
end |
||||
|
||||
test "can see a transaction's details", %{lincoln: lincoln, session: session, taft: taft, transaction: transaction} do |
||||
session |
||||
|> visit("/transactions") |
||||
|> click(link(to_string(transaction.hash))) |
||||
|> assert_has(css(".transaction__subheading", text: to_string(transaction.hash))) |
||||
|> assert_has(css(".transaction__item", text: "123,987")) |
||||
|> assert_has(css(".transaction__item", text: "5,656 POA")) |
||||
|> assert_has(css(".transaction__item", text: "Success")) |
||||
|> assert_has( |
||||
css( |
||||
".transaction__item", |
||||
text: "7,890,000,000,898,912,300,045 Wei (7,890,000,000,898.912 Gwei)" |
||||
) |
||||
) |
||||
|> assert_has(css(".transaction__item", text: "1,230,000,000,000,123,123 Gas")) |
||||
|> assert_has(css(".transaction__item", text: to_string(transaction.input))) |
||||
|> assert_has(css(".transaction__item", text: "99045")) |
||||
|> assert_has(css(".transaction__item", text: "123,987")) |
||||
|> assert_has(css(".transaction__item", text: to_string(lincoln.hash))) |
||||
|> assert_has(css(".transaction__item", text: to_string(taft.hash))) |
||||
|> assert_has(css(".transaction__item", text: "49 years ago")) |
||||
|> assert_has(css(".transaction__item", text: "38 years ago")) |
||||
end |
||||
|
||||
test "can view a transaction's logs", %{lincoln: lincoln, session: session, transaction: transaction} do |
||||
session |
||||
|> visit("/en/transactions/#{Phoenix.Param.to_param(transaction)}") |
||||
|> click(link("Logs")) |
||||
|> assert_has(css(".transaction-log__link", text: to_string(lincoln.hash))) |
||||
end |
||||
|
||||
test "can visit an address from the transaction logs page", %{ |
||||
lincoln: lincoln, |
||||
session: session, |
||||
transaction: transaction |
||||
} do |
||||
session |
||||
|> visit("/en/transactions/#{Phoenix.Param.to_param(transaction)}/logs") |
||||
|> click(css(".transaction-log__link", text: to_string(lincoln.hash))) |
||||
|> assert_has(css(".address__subheading", text: to_string(lincoln.hash))) |
||||
end |
||||
|
||||
test "see's all addresses transactions by default", %{ |
||||
lincoln: lincoln, |
||||
session: session, |
||||
transaction: transaction, |
||||
txn_from_lincoln: txn_from_lincoln |
||||
} do |
||||
session |
||||
|> visit("/en/addresses/#{Phoenix.Param.to_param(lincoln)}") |
||||
|> assert_has(css(".transactions__link--long-hash", text: to_string(transaction.hash))) |
||||
|> assert_has(css(".transactions__link--long-hash", text: to_string(txn_from_lincoln.hash))) |
||||
end |
||||
|
||||
test "can filter to only see transactions to an address", %{ |
||||
lincoln: lincoln, |
||||
session: session, |
||||
transaction: transaction, |
||||
txn_from_lincoln: txn_from_lincoln |
||||
} do |
||||
session |
||||
|> visit("/en/addresses/#{Phoenix.Param.to_param(lincoln)}") |
||||
|> click(css("[data-test='filter_dropdown']", text: "Filter: All")) |
||||
|> click(css(".address__link", text: "To")) |
||||
|> assert_has(css(".transactions__link--long-hash", text: to_string(transaction.hash))) |
||||
|> refute_has(css(".transactions__link--long-hash", text: to_string(txn_from_lincoln.hash))) |
||||
end |
||||
|
||||
test "can filter to only see transactions from an address", %{ |
||||
lincoln: lincoln, |
||||
session: session, |
||||
transaction: transaction, |
||||
txn_from_lincoln: txn_from_lincoln |
||||
} do |
||||
session |
||||
|> visit("/en/addresses/#{Phoenix.Param.to_param(lincoln)}") |
||||
|> click(css("[data-test='filter_dropdown']", text: "Filter: All")) |
||||
|> click(css(".address__link", text: "From")) |
||||
|> assert_has(css(".transactions__link--long-hash", text: to_string(txn_from_lincoln.hash))) |
||||
|> refute_has(css(".transactions__link--long-hash", text: to_string(transaction.hash))) |
||||
end |
||||
end |
||||
|
||||
test "views addresses", %{session: session} do |
||||
address = insert(:address, fetched_balance: 500) |
||||
|
||||
session |
||||
|> visit("/en/addresses/#{Phoenix.Param.to_param(address)}") |
||||
|> assert_has(css(".address__balance", text: "0.000,000,000,000,000,500 POA")) |
||||
end |
||||
end |
@ -0,0 +1,17 @@ |
||||
defmodule ExplorerWeb.BlockListPage do |
||||
@moduledoc false |
||||
|
||||
use Wallaby.DSL |
||||
|
||||
import Wallaby.Query, only: [css: 1] |
||||
|
||||
alias Explorer.Chain.Block |
||||
|
||||
def visit_page(session) do |
||||
visit(session, "/en/blocks") |
||||
end |
||||
|
||||
def block(%Block{number: block_number}) do |
||||
css("[data-test='block_number'][data-block-number='#{block_number}']") |
||||
end |
||||
end |
@ -0,0 +1,13 @@ |
||||
defmodule ExplorerWeb.BlockPage do |
||||
@moduledoc false |
||||
|
||||
use Wallaby.DSL |
||||
|
||||
import Wallaby.Query, only: [css: 2] |
||||
|
||||
alias Explorer.Chain.Block |
||||
|
||||
def detail_number(%Block{number: block_number}) do |
||||
css("[data-test='block_detail_number']", text: to_string(block_number)) |
||||
end |
||||
end |
@ -0,0 +1,25 @@ |
||||
defmodule ExplorerWeb.HomePage do |
||||
@moduledoc false |
||||
|
||||
use Wallaby.DSL |
||||
|
||||
import Wallaby.Query, only: [css: 1, css: 2] |
||||
|
||||
def blocks(count: count) do |
||||
css("[data-test='chain_block']", count: count) |
||||
end |
||||
|
||||
def search(session, text) do |
||||
session |
||||
|> fill_in(css("[data-test='search_input']"), with: text) |
||||
|> send_keys([:enter]) |
||||
end |
||||
|
||||
def visit_page(session) do |
||||
visit(session, "/") |
||||
end |
||||
|
||||
def transactions(count: count) do |
||||
css("[data-test='chain_transaction']", count: count) |
||||
end |
||||
end |
@ -0,0 +1,25 @@ |
||||
defmodule ExplorerWeb.TransactionListPage do |
||||
@moduledoc false |
||||
|
||||
use Wallaby.DSL |
||||
|
||||
import Wallaby.Query, only: [css: 1] |
||||
|
||||
alias Explorer.Chain.Transaction |
||||
|
||||
def click_transaction(session, %Transaction{hash: transaction_hash}) do |
||||
click(session, css("[data-test='transaction_hash'][data-transaction-hash='#{transaction_hash}']")) |
||||
end |
||||
|
||||
def visit_page(session) do |
||||
visit(session, "/en/transactions") |
||||
end |
||||
|
||||
def click_pending(session) do |
||||
click(session, css("[data-test='pending_transactions_link']")) |
||||
end |
||||
|
||||
def transaction(%Transaction{hash: transaction_hash}) do |
||||
css("[data-test='transaction_hash'][data-transaction-hash='#{transaction_hash}']") |
||||
end |
||||
end |
@ -0,0 +1,23 @@ |
||||
defmodule ExplorerWeb.TransactionLogsPage do |
||||
@moduledoc false |
||||
|
||||
use Wallaby.DSL |
||||
|
||||
import Wallaby.Query, only: [css: 1, css: 2] |
||||
import ExplorerWeb.Router.Helpers, only: [transaction_log_path: 4] |
||||
|
||||
alias Explorer.Chain.{Address, Transaction} |
||||
alias ExplorerWeb.Endpoint |
||||
|
||||
def logs(count: count) do |
||||
css("[data-test='transaction_log']", count: count) |
||||
end |
||||
|
||||
def visit_page(session, %Transaction{} = transaction) do |
||||
visit(session, transaction_log_path(Endpoint, :index, :en, transaction)) |
||||
end |
||||
|
||||
def click_address(session, %Address{hash: address_hash}) do |
||||
click(session, css("[data-test='log_address_link'][data-address-hash='#{address_hash}']")) |
||||
end |
||||
end |
@ -0,0 +1,21 @@ |
||||
defmodule ExplorerWeb.TransactionPage do |
||||
@moduledoc false |
||||
|
||||
use Wallaby.DSL |
||||
|
||||
import Wallaby.Query, only: [css: 1, css: 2] |
||||
|
||||
alias Explorer.Chain.{Transaction, Hash} |
||||
|
||||
def click_logs(session) do |
||||
click(session, css("[data-test='transaction_logs_link']")) |
||||
end |
||||
|
||||
def detail_hash(%Transaction{hash: transaction_hash}) do |
||||
css("[data-test='transaction_detail_hash']", text: Hash.to_string(transaction_hash)) |
||||
end |
||||
|
||||
def visit_page(session, %Transaction{hash: transaction_hash}) do |
||||
visit(session, "/en/transactions/#{transaction_hash}") |
||||
end |
||||
end |
@ -0,0 +1,43 @@ |
||||
defmodule ExplorerWeb.ViewingBlocksTest do |
||||
use ExplorerWeb.FeatureCase, async: true |
||||
|
||||
alias ExplorerWeb.{BlockListPage, BlockPage, HomePage} |
||||
|
||||
setup do |
||||
timestamp = Timex.now() |> Timex.shift(hours: -1) |
||||
Enum.map(307..310, &insert(:block, number: &1, timestamp: timestamp, gas_used: 10)) |
||||
|
||||
block = |
||||
insert(:block, %{ |
||||
gas_limit: 5_030_101, |
||||
gas_used: 1_010_101, |
||||
nonce: 123_456_789, |
||||
number: 311, |
||||
size: 9_999_999, |
||||
timestamp: timestamp |
||||
}) |
||||
|
||||
{:ok, block: block} |
||||
end |
||||
|
||||
test "search for blocks", %{session: session} do |
||||
block = insert(:block, number: 42) |
||||
|
||||
session |
||||
|> HomePage.visit_page() |
||||
|> HomePage.search(to_string(block.number)) |
||||
|> assert_has(BlockPage.detail_number(block)) |
||||
end |
||||
|
||||
test "viewing blocks on the home page", %{session: session} do |
||||
session |
||||
|> HomePage.visit_page() |
||||
|> assert_has(HomePage.blocks(count: 5)) |
||||
end |
||||
|
||||
test "viewing the blocks index page", %{block: block, session: session} do |
||||
session |
||||
|> BlockListPage.visit_page() |
||||
|> assert_has(BlockListPage.block(block)) |
||||
end |
||||
end |
@ -0,0 +1,136 @@ |
||||
defmodule ExplorerWeb.ViewingTransactionsTest do |
||||
@moduledoc false |
||||
|
||||
use ExplorerWeb.FeatureCase, async: true |
||||
|
||||
alias Explorer.Chain.{Credit, Debit, Wei} |
||||
alias ExplorerWeb.{AddressPage, HomePage, TransactionListPage, TransactionLogsPage, TransactionPage} |
||||
|
||||
setup do |
||||
block = |
||||
insert(:block, %{ |
||||
number: 555, |
||||
timestamp: Timex.now() |> Timex.shift(hours: -2), |
||||
gas_used: 123_987 |
||||
}) |
||||
|
||||
for index <- 0..3, do: insert(:transaction, block_hash: block.hash, index: index) |
||||
pending = insert(:transaction, block_hash: nil, gas: 5891, index: nil) |
||||
|
||||
lincoln = insert(:address) |
||||
taft = insert(:address) |
||||
|
||||
transaction = |
||||
insert( |
||||
:transaction, |
||||
block_hash: block.hash, |
||||
value: Wei.from(Decimal.new(5656), :ether), |
||||
gas: Decimal.new(1_230_000_000_000_123_123), |
||||
gas_price: Decimal.new(7_890_000_000_898_912_300_045), |
||||
index: 4, |
||||
input: "0x000012", |
||||
nonce: 99045, |
||||
inserted_at: Timex.parse!("1970-01-01T00:00:18-00:00", "{ISO:Extended}"), |
||||
updated_at: Timex.parse!("1980-01-01T00:00:18-00:00", "{ISO:Extended}"), |
||||
from_address_hash: taft.hash, |
||||
to_address_hash: lincoln.hash |
||||
) |
||||
|
||||
receipt = insert(:receipt, status: :ok, transaction_hash: transaction.hash, transaction_index: transaction.index) |
||||
insert(:log, address_hash: lincoln.hash, index: 0, transaction_hash: receipt.transaction_hash) |
||||
|
||||
# From Lincoln to Taft. |
||||
txn_from_lincoln = |
||||
insert( |
||||
:transaction, |
||||
block_hash: block.hash, |
||||
index: 5, |
||||
from_address_hash: lincoln.hash, |
||||
to_address_hash: taft.hash |
||||
) |
||||
|
||||
internal_receipt = |
||||
insert(:receipt, transaction_hash: txn_from_lincoln.hash, transaction_index: txn_from_lincoln.index) |
||||
|
||||
internal = insert(:internal_transaction, transaction_hash: internal_receipt.transaction_hash) |
||||
|
||||
Credit.refresh() |
||||
Debit.refresh() |
||||
|
||||
{:ok, |
||||
%{ |
||||
pending: pending, |
||||
internal: internal, |
||||
lincoln: lincoln, |
||||
taft: taft, |
||||
transaction: transaction, |
||||
txn_from_lincoln: txn_from_lincoln |
||||
}} |
||||
end |
||||
|
||||
test "search for transactions", %{session: session} do |
||||
transaction = insert(:transaction, input: "0x736f636b73") |
||||
|
||||
session |
||||
|> HomePage.visit_page() |
||||
|> HomePage.search(to_string(transaction.hash)) |
||||
|> assert_has(TransactionPage.detail_hash(transaction)) |
||||
end |
||||
|
||||
describe "viewing transaction lists" do |
||||
test "transactions on the home page", %{session: session} do |
||||
session |
||||
|> HomePage.visit_page() |
||||
|> assert_has(HomePage.transactions(count: 5)) |
||||
end |
||||
|
||||
test "viewing the default transactions tab", %{session: session, transaction: transaction, pending: pending} do |
||||
session |
||||
|> TransactionListPage.visit_page() |
||||
|> assert_has(TransactionListPage.transaction(transaction)) |
||||
|> refute_has(TransactionListPage.transaction(pending)) |
||||
end |
||||
|
||||
test "viewing the pending tab", %{pending: pending, session: session} do |
||||
session |
||||
|> TransactionListPage.visit_page() |
||||
|> TransactionListPage.click_pending() |
||||
|> assert_has(TransactionListPage.transaction(pending)) |
||||
|
||||
# |> click(css(".transactions__link", text: to_string(pending.hash))) |
||||
end |
||||
end |
||||
|
||||
describe "viewing a transaction page" do |
||||
test "can navigate to transaction show from list page", %{session: session, transaction: transaction} do |
||||
session |
||||
|> TransactionListPage.visit_page() |
||||
|> TransactionListPage.click_transaction(transaction) |
||||
|> assert_has(TransactionPage.detail_hash(transaction)) |
||||
end |
||||
|
||||
test "can see a transaction's details", %{session: session, transaction: transaction} do |
||||
session |
||||
|> TransactionPage.visit_page(transaction) |
||||
|> assert_has(TransactionPage.detail_hash(transaction)) |
||||
end |
||||
|
||||
test "can view a transaction's logs", %{session: session, transaction: transaction} do |
||||
session |
||||
|> TransactionPage.visit_page(transaction) |
||||
|> TransactionPage.click_logs() |
||||
|> assert_has(TransactionLogsPage.logs(count: 1)) |
||||
end |
||||
|
||||
test "can visit an address from the transaction logs page", %{ |
||||
lincoln: lincoln, |
||||
session: session, |
||||
transaction: transaction |
||||
} do |
||||
session |
||||
|> TransactionLogsPage.visit_page(transaction) |
||||
|> TransactionLogsPage.click_address(lincoln) |
||||
|> assert_has(AddressPage.detail_hash(lincoln)) |
||||
end |
||||
end |
||||
end |