netbox.scss 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. // Netbox-specific Styles and Overrides.
  2. @use 'sass:map';
  3. :root {
  4. --nbx-sidebar-bg: #{$gray-200};
  5. --nbx-sidebar-link-color: #{$gray-800};
  6. --nbx-sidebar-link-hover-bg: #{$blue-100};
  7. --nbx-sidebar-title-color: #{$text-muted};
  8. --nbx-sidebar-shadow: inset 0px -25px 20px -25px rgba(0, 0, 0, 0.25);
  9. --nbx-breadcrumb-bg: #{$light};
  10. --nbx-body-bg: #{$white};
  11. --nbx-body-color: #{$gray-800};
  12. --nbx-pre-bg: #{$gray-100};
  13. --nbx-pre-border-color: #{$gray-600};
  14. --nbx-change-added: #{rgba($green, 0.4)};
  15. --nbx-change-removed: #{rgba($red, 0.4)};
  16. --nbx-cable-node-bg: #{$gray-100};
  17. --nbx-cable-node-border-color: #{$gray-200};
  18. --nbx-cable-termination-bg: #{$gray-200};
  19. --nbx-cable-termination-border-color: #{$gray-300};
  20. --nbx-search-filter-border-left-color: #{$gray-300};
  21. --nbx-color-mode-toggle-color: #{$primary};
  22. &[data-netbox-color-mode='dark'] {
  23. --nbx-sidebar-bg: #{$gray-900};
  24. --nbx-sidebar-link-color: #{$gray-100};
  25. --nbx-sidebar-link-hover-bg: #{rgba($blue-300, 0.15)};
  26. --nbx-sidebar-title-color: #{$gray-600};
  27. --nbx-sidebar-shadow: inset 0px -25px 20px -25px rgba(255, 255, 255, 0.05);
  28. --nbx-breadcrumb-bg: #{$gray-800};
  29. --nbx-body-bg: #{$darker};
  30. --nbx-body-color: #{$gray-100};
  31. --nbx-pre-bg: #{$gray-700};
  32. --nbx-pre-border-color: #{$gray-600};
  33. --nbx-change-added: #{rgba($green-300, 0.4)};
  34. --nbx-change-removed: #{rgba($red-300, 0.4)};
  35. --nbx-cable-node-bg: #{$gray-700};
  36. --nbx-cable-node-border-color: #{$gray-600};
  37. --nbx-cable-termination-bg: #{$gray-800};
  38. --nbx-cable-termination-border-color: #{$gray-700};
  39. --nbx-search-filter-border-left-color: #{$gray-600};
  40. --nbx-color-mode-toggle-color: #{$yellow-300};
  41. }
  42. }
  43. * {
  44. transition: background-color, color 0.15s ease-in-out;
  45. }
  46. .mw-25 {
  47. max-width: 25% !important;
  48. }
  49. .mw-33 {
  50. max-width: 33.33% !important;
  51. }
  52. .mw-50 {
  53. max-width: 50% !important;
  54. }
  55. .mw-66 {
  56. max-width: 66.66% !important;
  57. }
  58. .mw-75 {
  59. max-width: 75% !important;
  60. }
  61. .text-xs {
  62. font-size: $font-size-xs;
  63. line-height: $line-height-sm;
  64. }
  65. .opacity-0 {
  66. opacity: 0 !important;
  67. }
  68. .opacity-25 {
  69. opacity: 0.25 !important;
  70. }
  71. .opacity-50 {
  72. opacity: 0.5 !important;
  73. }
  74. .opacity-75 {
  75. opacity: 0.75 !important;
  76. }
  77. .opacity-100 {
  78. opacity: 1 !important;
  79. }
  80. // Force <small/> elements to make text smaller.
  81. small {
  82. font-size: smaller !important;
  83. }
  84. // Automatically space out adjacent columns.
  85. .col:not(:last-child):not(:only-child) {
  86. margin-bottom: $spacer;
  87. }
  88. // Ensure elements with data-href set show the correct cursor.
  89. // data-href is set on non non-anchor elements that need to redirect the user to a URL when
  90. // clicked, but where an anchor element does not suffice or is not supported.
  91. *[data-href] {
  92. cursor: pointer;
  93. }
  94. @each $color, $value in $theme-colors {
  95. // Override CSS values on each theme color.
  96. // Use Bootstrap's method of coloring alert links to appropriately color close buttons within
  97. // another colored element.
  98. // See: https://github.com/twbs/bootstrap/blob/2bdbb42dcf6bfb99b5e9e5444d9e64589eb8c08f/scss/_alert.scss#L50-L52
  99. // See: https://github.com/twbs/bootstrap/blob/2bdbb42dcf6bfb99b5e9e5444d9e64589eb8c08f/scss/_close.scss#L12
  100. $shaded-color: shade-color(mix($value, color-contrast($value), abs($alert-color-scale)), 5%);
  101. $btn-close-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$shaded-color}'><path d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/></svg>");
  102. .bg-#{$color} button.btn-close {
  103. background: transparent escape-svg($btn-close-bg) center / $btn-close-width auto no-repeat;
  104. }
  105. // Use Bootstrap's method of coloring the .alert-link class automatically.
  106. // See: https://github.com/twbs/bootstrap/blob/2bdbb42dcf6bfb99b5e9e5444d9e64589eb8c08f/scss/_alert.scss#L50-L52
  107. .toast.bg-#{$color},
  108. .alert.alert-#{$color} {
  109. a {
  110. color: $shaded-color;
  111. font-weight: $font-weight-bold;
  112. }
  113. }
  114. // Use proper contrasting color foreground color for special components.
  115. .badge,
  116. .toast,
  117. .progress-bar {
  118. &.bg-#{$color} {
  119. color: color-contrast($value);
  120. }
  121. }
  122. // Use proper foreground color in the alert body. Note: this is applied to p, & small because
  123. // we *don't* want to override the h1-h6 colors for alerts, since those are set to a color
  124. // similar to the alert color.
  125. .alert.alert-#{$color} {
  126. p,
  127. small {
  128. color: color-contrast($value);
  129. }
  130. }
  131. }
  132. // Fix the hideous way Safari shows button anchor elements.
  133. a[type='button'] {
  134. -webkit-appearance: unset !important;
  135. }
  136. // Ensure progress bars (utilization graph) in tables aren't too narrow to display the percentage.
  137. table td > .progress {
  138. min-width: 6rem;
  139. }
  140. .card > .table.table-flush {
  141. margin-bottom: 0;
  142. overflow: hidden;
  143. border-bottom-right-radius: $card-border-radius;
  144. border-bottom-left-radius: $card-border-radius;
  145. thead th[scope='col'] {
  146. background-color: $table-flush-header-bg;
  147. vertical-align: middle;
  148. text-transform: uppercase;
  149. padding-top: map.get($spacers, 3);
  150. padding-bottom: map.get($spacers, 3);
  151. border-bottom-color: $card-border-color;
  152. border-top: 1px solid $card-border-color;
  153. }
  154. th,
  155. td {
  156. border-left: 0;
  157. border-right: 0;
  158. padding-left: map.get($spacers, 4) !important;
  159. padding-right: map.get($spacers, 4) !important;
  160. }
  161. tr[class] {
  162. border-color: $card-border-color !important;
  163. &:last-of-type {
  164. border-bottom-color: transparent !important;
  165. border-bottom-right-radius: $card-border-radius;
  166. border-bottom-left-radius: $card-border-radius;
  167. }
  168. }
  169. }
  170. // Primarily used for the new release notification, but could be used for other alerts as needed.
  171. // Wrap any alerts in .header-alert-container to ensure the layout is consistent.
  172. .header-alert-container {
  173. // Center-align the alert(s).
  174. display: flex;
  175. justify-content: center;
  176. align-items: center;
  177. // Apply the same spacing that's applied to the #content div's first child (.px-3).
  178. padding: 0 $spacer;
  179. // By default, alerts inside .header-alert-container should take up the full width.
  180. .alert {
  181. width: 100%;
  182. // Adjust the max-width for larger screens so there's not a big ugly blue blob taking up the
  183. // entire screen.
  184. @include media-breakpoint-up(md) {
  185. max-width: 75%;
  186. }
  187. @include media-breakpoint-up(lg) {
  188. max-width: 50%;
  189. }
  190. }
  191. }
  192. span.profile-button .dropdown-menu {
  193. transition: opacity 0.2s ease-in-out;
  194. display: block !important;
  195. right: 0;
  196. left: auto;
  197. margin-top: 0.5rem;
  198. box-shadow: $box-shadow;
  199. &:not(.show) {
  200. opacity: 0;
  201. pointer-events: none;
  202. }
  203. &.show {
  204. opacity: 1;
  205. pointer-events: auto;
  206. }
  207. }
  208. div#advanced-search-content div.card div.card-body div.col:not(:last-child) {
  209. margin-right: 1rem;
  210. }
  211. body {
  212. background-color: var(--nbx-body-bg);
  213. color: var(--nbx-body-color);
  214. g#netbox-logo-1 {
  215. fill: #9cc8f8;
  216. stroke: #9cc8f8;
  217. }
  218. g#netbox-logo-2 {
  219. fill: #1685fc;
  220. stroke: #1685fc;
  221. }
  222. &[data-netbox-color-mode='light'] {
  223. .btn.btn-primary,
  224. .progress-bar.bg-primary,
  225. .badge.bg-primary,
  226. .nav.nav-pills .nav-item.nav-link.active,
  227. .nav.nav-pills .nav-item .nav-link.active,
  228. .nav.nav-pills .nav-item .show > .nav-link {
  229. color: $gray-100;
  230. }
  231. }
  232. &[data-netbox-color-mode='dark'] {
  233. & {
  234. .btn.btn-primary,
  235. .progress-bar.bg-primary,
  236. .badge.bg-primary,
  237. .nav.nav-pills .nav-item.nav-link.active,
  238. .nav.nav-pills .nav-item .nav-link.active,
  239. .nav.nav-pills .nav-item .show > .nav-link {
  240. color: $black;
  241. }
  242. }
  243. .card table caption {
  244. color: $gray-300;
  245. }
  246. .breadcrumb .breadcrumb-item > a {
  247. color: $blue-200;
  248. &:hover {
  249. color: $blue-100;
  250. }
  251. }
  252. .card,
  253. .sidebar {
  254. .text-muted {
  255. color: $gray-400 !important;
  256. }
  257. }
  258. .text-body[class] {
  259. color: var(--nbx-body-color) !important;
  260. }
  261. g#netbox-logo-1 {
  262. fill: $white;
  263. stroke: $white;
  264. }
  265. g#netbox-logo-2 {
  266. fill: $gray-200;
  267. stroke: $gray-200;
  268. }
  269. }
  270. & table,
  271. &[data-netbox-color-mode] table {
  272. a {
  273. text-decoration: none;
  274. &:hover {
  275. text-decoration: underline;
  276. }
  277. }
  278. &.table > :not(caption) > * > * {
  279. padding-left: $table-cell-padding-x-sm !important;
  280. padding-right: $table-cell-padding-x-sm !important;
  281. }
  282. td,
  283. th {
  284. font-size: $font-size-sm;
  285. line-height: $line-height-sm;
  286. vertical-align: middle;
  287. &.min-width {
  288. width: 1%;
  289. }
  290. & input.form-check-input {
  291. // Ensure checkboxes aren't too small inside object tables.
  292. font-size: $font-size-base;
  293. margin-top: 0.125em;
  294. }
  295. & .btn-sm {
  296. line-height: $line-height-xs;
  297. }
  298. }
  299. &.object-list {
  300. th {
  301. font-size: $font-size-xs;
  302. line-height: $line-height-xs;
  303. vertical-align: bottom;
  304. }
  305. }
  306. &.attr-table {
  307. th {
  308. width: 25%;
  309. }
  310. }
  311. }
  312. }
  313. div.title-container {
  314. display: flex;
  315. justify-content: space-between;
  316. flex-wrap: wrap;
  317. div#content-title {
  318. display: flex;
  319. flex-direction: column;
  320. flex: 1 0 auto;
  321. padding-bottom: map.get($spacers, 2);
  322. }
  323. }
  324. nav.search {
  325. background-color: var(--nbx-body-bg);
  326. form button.dropdown-toggle {
  327. border-color: $input-border-color;
  328. font-weight: $input-group-addon-font-weight;
  329. line-height: $input-line-height;
  330. color: $input-group-addon-color;
  331. background-color: $input-group-addon-bg;
  332. border: $input-border-width solid $input-group-addon-border-color;
  333. @include border-radius($input-border-radius);
  334. border-left: 1px solid var(--nbx-search-filter-border-left-color);
  335. &:focus {
  336. box-shadow: unset !important;
  337. }
  338. }
  339. }
  340. main.login-container {
  341. display: flex;
  342. height: calc(100vh - 4rem);
  343. width: 100%;
  344. max-width: 100vw;
  345. align-items: center;
  346. justify-content: center;
  347. flex-direction: column;
  348. padding-top: 40px;
  349. padding-bottom: 40px;
  350. & + footer.footer button.color-mode-toggle {
  351. color: var(--nbx-color-mode-toggle-color);
  352. }
  353. }
  354. footer.login-footer {
  355. height: 4rem;
  356. margin-top: auto;
  357. .container-fluid {
  358. display: flex;
  359. justify-content: flex-end;
  360. padding: $container-padding-x $grid-gutter-width;
  361. }
  362. }
  363. h1 {
  364. font-weight: $font-weight-bolder;
  365. }
  366. h2 {
  367. font-weight: $font-weight-bold;
  368. }
  369. h3,
  370. h4 {
  371. font-weight: $font-weight-medium;
  372. }
  373. h5,
  374. h6 {
  375. font-weight: $font-weight-medium;
  376. }
  377. h1.accordion-item-title,
  378. h2.accordion-item-title,
  379. h3.accordion-item-title,
  380. h4.accordion-item-title,
  381. h5.accordion-item-title,
  382. h6.accordion-item-title {
  383. // padding: 0 0.5rem;
  384. padding: 0.25rem 0.5rem;
  385. font-weight: $font-weight-bold;
  386. text-transform: uppercase;
  387. color: var(--nbx-sidebar-title-color);
  388. font-size: $font-size-sm;
  389. }
  390. .form-login {
  391. width: 100%;
  392. max-width: 330px;
  393. padding: 15px;
  394. & input:focus {
  395. z-index: 1;
  396. }
  397. }
  398. .form-login input[type='text'] {
  399. margin-bottom: -1px;
  400. border-bottom-left-radius: 0;
  401. border-bottom-right-radius: 0;
  402. }
  403. .form-login input[type='password'] {
  404. margin-bottom: 10px;
  405. border-top-left-radius: 0;
  406. border-top-right-radius: 0;
  407. }
  408. .form-login .form-control {
  409. position: relative;
  410. box-sizing: border-box;
  411. height: auto;
  412. padding: 10px;
  413. font-size: 16px;
  414. }
  415. li.dropdown-item.dropdown-item-btns {
  416. display: flex;
  417. justify-content: space-between;
  418. align-items: center;
  419. }
  420. .sidebar-sticky {
  421. position: relative;
  422. top: 0;
  423. height: calc(100vh - 48px);
  424. padding-top: 0.5rem;
  425. overflow-x: hidden;
  426. overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
  427. }
  428. .navbar-brand {
  429. padding-top: 0.75rem;
  430. padding-bottom: 0.75rem;
  431. font-size: 1rem;
  432. }
  433. nav.nav.nav-pills {
  434. .nav-item.nav-link {
  435. padding: 0.25rem 0.5rem;
  436. font-size: $font-size-sm;
  437. border-radius: $border-radius;
  438. &:hover {
  439. background-color: $accordion-button-active-bg;
  440. color: $accordion-button-active-color;
  441. }
  442. }
  443. }
  444. // Ensure the content container is full-height, and that the content block is also full height so
  445. // that the footer is always at the bottom.
  446. div.content-container {
  447. min-height: 100vh;
  448. display: flex;
  449. flex-direction: column;
  450. overflow: hidden;
  451. @include media-breakpoint-up(md) {
  452. margin-left: $sidebar-width;
  453. }
  454. div.content {
  455. flex: 1;
  456. }
  457. }
  458. // Prevent scrolling of body content when nav menu is open on mobile.
  459. .sidebar.collapse.show ~ .content-container > .content {
  460. @media (max-width: map.get($grid-breakpoints, 'md')) {
  461. position: fixed;
  462. top: 0;
  463. left: 0;
  464. overflow-y: hidden;
  465. }
  466. }
  467. .sidebar {
  468. position: fixed;
  469. top: 0;
  470. bottom: 0;
  471. left: 0;
  472. z-index: 100; /* Behind the navbar */
  473. border-right: 1px solid $border-color;
  474. background-color: var(--nbx-sidebar-bg);
  475. max-height: 100%;
  476. width: 100%;
  477. @include media-breakpoint-up(md) {
  478. width: 100%;
  479. max-width: $sidebar-width;
  480. }
  481. @include media-breakpoint-down(md) {
  482. top: 8.125rem;
  483. background-color: var(--nbx-body-bg);
  484. }
  485. div.accordion-item {
  486. border: unset;
  487. padding: 0 $spacer / 2;
  488. // When an sidenav section is open, apply a shadow to provide a visual border.
  489. &.is-open {
  490. box-shadow: var(--nbx-sidebar-shadow);
  491. }
  492. & > a.accordion-button {
  493. &:not(.collapsed) {
  494. box-shadow: unset;
  495. }
  496. &.nav-link {
  497. border-radius: $border-radius;
  498. &:hover {
  499. color: $accordion-button-active-color;
  500. background-color: $accordion-button-active-bg;
  501. }
  502. &:focus {
  503. border-color: unset;
  504. box-shadow: unset;
  505. }
  506. }
  507. }
  508. }
  509. .accordion-body {
  510. max-height: calc(100vh - 24rem);
  511. overflow-y: auto;
  512. .nav-item {
  513. .nav-link {
  514. padding: 0.25rem 0.6rem;
  515. font-size: $font-size-sm;
  516. border-radius: $border-radius;
  517. &:hover {
  518. color: $accordion-button-active-color;
  519. background-color: $accordion-button-active-bg;
  520. }
  521. }
  522. }
  523. }
  524. // Ensure navigation accounts for the height of the header on mobile when nav is expanded.
  525. &.collapse.show div.position-sticky {
  526. @media (max-width: map.get($grid-breakpoints, 'md')) {
  527. height: calc(100vh - 16.125rem);
  528. overflow-y: auto;
  529. }
  530. }
  531. div.position-sticky {
  532. height: calc(100vh - #{$sidebar-bottom-height});
  533. }
  534. div.sidebar-bottom {
  535. padding-left: 0.5rem;
  536. padding-right: 0.5rem;
  537. position: sticky;
  538. height: $sidebar-bottom-height;
  539. background-color: var(--nbx-sidebar-bg);
  540. @include media-breakpoint-down(md) {
  541. background-color: var(--nbx-body-bg);
  542. }
  543. .nav {
  544. padding: 0 0.5rem;
  545. justify-content: space-between;
  546. margin: $spacer/2 0;
  547. .nav-link {
  548. padding: 0.5rem 0.25rem;
  549. }
  550. }
  551. }
  552. a.sidebar-logo {
  553. display: flex;
  554. flex-shrink: 1;
  555. width: 100%;
  556. height: 3rem;
  557. }
  558. }
  559. .tooltip {
  560. pointer-events: none;
  561. }
  562. .ws-nowrap {
  563. white-space: nowrap !important;
  564. }
  565. .search-obj-selector {
  566. .dropdown-item,
  567. .dropdown-header {
  568. font-size: $font-size-sm;
  569. }
  570. .dropdown-header {
  571. text-transform: uppercase;
  572. }
  573. }
  574. span.color-label {
  575. width: 5rem;
  576. height: 1rem;
  577. display: block;
  578. box-shadow: $box-shadow-sm;
  579. border: 1px solid #303030;
  580. border-radius: $border-radius;
  581. padding: $badge-padding-y $badge-padding-x;
  582. }
  583. pre {
  584. border-radius: $border-radius;
  585. border: 1px solid var(--nbx-pre-border-color);
  586. background-color: var(--nbx-pre-bg);
  587. padding: $spacer;
  588. white-space: pre;
  589. }
  590. .btn {
  591. white-space: nowrap;
  592. }
  593. .card {
  594. box-shadow: $box-shadow-sm;
  595. .card-header {
  596. color: $body-color;
  597. border-bottom: none;
  598. padding: $card-cap-padding-x;
  599. }
  600. .card-header + .card-body {
  601. padding-top: 0;
  602. }
  603. .card-body.small .form-control,
  604. .card-body.small .form-select {
  605. font-size: $input-font-size-sm;
  606. }
  607. }
  608. .form-floating {
  609. position: relative;
  610. > .input-group > .form-control,
  611. > .input-group > .form-select {
  612. height: $form-floating-height;
  613. padding: $form-floating-padding-y $form-floating-padding-x;
  614. }
  615. > .input-group > label {
  616. position: absolute;
  617. top: 0;
  618. left: 0;
  619. height: 100%; // allow textareas
  620. padding: $form-floating-padding-y $form-floating-padding-x;
  621. pointer-events: none;
  622. border: $input-border-width solid transparent; // Required for aligning label's text with the input as it affects inner box model
  623. transform-origin: 0 0;
  624. @include transition($form-floating-transition);
  625. }
  626. > .input-group > .form-control {
  627. &::placeholder {
  628. color: transparent;
  629. }
  630. &:focus,
  631. &:not(:placeholder-shown) {
  632. padding-top: $form-floating-input-padding-t;
  633. padding-bottom: $form-floating-input-padding-b;
  634. }
  635. // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
  636. &:-webkit-autofill {
  637. padding-top: $form-floating-input-padding-t;
  638. padding-bottom: $form-floating-input-padding-b;
  639. }
  640. }
  641. > .input-group > .form-select,
  642. > .choices > .choices__inner,
  643. > .ss-main span.placeholder, // SlimSelect Single
  644. > .ss-main div.ss-values // SlimSelect Multiple
  645. {
  646. padding-top: $form-floating-input-padding-t;
  647. padding-bottom: $form-floating-input-padding-b;
  648. }
  649. > .input-group > .form-control:focus,
  650. > .input-group > .form-control:not(:placeholder-shown),
  651. > .input-group > .form-select,
  652. > .choices,
  653. > .ss-main {
  654. ~ label {
  655. opacity: $form-floating-label-opacity;
  656. transform: $form-floating-label-transform;
  657. z-index: 4;
  658. }
  659. }
  660. // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
  661. > .input-group > .form-control:-webkit-autofill {
  662. ~ label {
  663. opacity: $form-floating-label-opacity;
  664. transform: $form-floating-label-transform;
  665. z-index: 4;
  666. }
  667. }
  668. }
  669. textarea.form-control[rows='10'] {
  670. height: 18rem;
  671. }
  672. textarea#id_local_context_data,
  673. textarea.markdown,
  674. textarea#id_public_key,
  675. textarea.form-control[name='csv'],
  676. textarea.form-control[name='data'] {
  677. font-family: $font-family-monospace;
  678. }
  679. table tr.vertical-align {
  680. vertical-align: middle;
  681. }
  682. .card:not(:only-of-type) {
  683. margin-bottom: $spacer;
  684. }
  685. .stat-btn {
  686. min-width: $spacer * 3;
  687. }
  688. nav.breadcrumb-container {
  689. padding: $badge-padding-y $badge-padding-x;
  690. font-size: $font-size-sm;
  691. width: fit-content;
  692. ol.breadcrumb {
  693. margin-bottom: 0;
  694. li.breadcrumb-item > a {
  695. text-decoration: none;
  696. }
  697. li.breadcrumb-item > a:hover {
  698. text-decoration: underline;
  699. }
  700. }
  701. }
  702. div.paginator > form > div.input-group {
  703. width: fit-content;
  704. }
  705. div.field-group:not(:first-of-type) {
  706. margin-top: $spacer * 3;
  707. h1,
  708. h2,
  709. h3,
  710. h4,
  711. h5,
  712. h6 {
  713. margin-bottom: $spacer;
  714. }
  715. }
  716. label.required {
  717. font-weight: $font-weight-bold;
  718. &::after {
  719. font-family: 'Material Design Icons';
  720. content: '\f06C4';
  721. font-weight: normal;
  722. font-size: 8px;
  723. font-style: normal;
  724. margin: 0 0 0 2px;
  725. text-decoration: none;
  726. display: inline-block;
  727. position: absolute;
  728. }
  729. }
  730. // Applied to containing element around table bulk-action buttons (bulk-edit, bulk-disconnect
  731. // bulk-delete, etc). Each usage of .bulk-buttons needs to have groups of buttons wrapped with
  732. // .bulk-button-group so that proper spacing is applied (even if there is only one group).
  733. div.bulk-buttons {
  734. display: flex;
  735. justify-content: space-between;
  736. margin: $spacer / 2 0;
  737. // Each group of buttons needs to be contained separately for alignment purposes. This way, you
  738. // can put some buttons in a group that aligns left, and other buttons in a group that aligns
  739. // right.
  740. & > div.bulk-button-group {
  741. display: flex;
  742. &:first-of-type:not(:last-of-type) {
  743. // If there are multiple bulk button groups and this is the first, the first button in the
  744. // group should *not* have left spacing applied, so the button group aligns with the rest
  745. // of the page elements.
  746. & > *:first-child {
  747. margin-left: 0;
  748. }
  749. }
  750. &:last-of-type:not(:first-of-type) {
  751. // If there are multiple bulk button groups and this is the last, the last button in the
  752. // group should *not* have right spacing applied, so the button group aligns with the rest
  753. // of the page elements.
  754. & > *:last-child {
  755. margin-right: 0;
  756. }
  757. }
  758. // However, the rest of the buttons should have spacing applied in all directions.
  759. & > * {
  760. margin: $spacer / 4;
  761. }
  762. }
  763. }
  764. i.bi-plus:before,
  765. span.bi-plus:before {
  766. font-weight: $font-weight-bold !important;
  767. }
  768. table tbody {
  769. @each $color, $value in $theme-colors {
  770. tr.#{$color} {
  771. background-color: rgba($value, 0.15);
  772. border-color: $gray-500;
  773. }
  774. }
  775. }
  776. pre.change-data {
  777. padding-left: 0;
  778. padding-right: 0;
  779. & > span {
  780. display: block;
  781. padding-left: $spacer;
  782. padding-right: $spacer;
  783. &.added {
  784. background-color: var(--nbx-change-added);
  785. }
  786. &.removed {
  787. background-color: var(--nbx-change-removed);
  788. }
  789. }
  790. }
  791. pre.change-diff {
  792. border-color: transparent;
  793. &.change-removed {
  794. background-color: var(--nbx-change-removed);
  795. }
  796. &.change-added {
  797. background-color: var(--nbx-change-added);
  798. }
  799. }
  800. div.card-overlay {
  801. position: absolute;
  802. width: 100%;
  803. height: 100%;
  804. background-color: rgba($white, 0.75);
  805. border-radius: $border-radius;
  806. display: flex;
  807. justify-content: center;
  808. align-items: center;
  809. & > div.spinner-border {
  810. width: 6rem;
  811. height: 6rem;
  812. color: $secondary;
  813. }
  814. }
  815. div.card > div.card-header > div.table-controls {
  816. max-width: 25%;
  817. width: 100%;
  818. display: flex;
  819. align-items: center;
  820. & .form-switch.form-check-inline {
  821. flex: 1 0 auto;
  822. font-size: $font-size-sm;
  823. }
  824. }
  825. // Right-align the paginator element.
  826. .paginator {
  827. display: flex;
  828. flex-direction: column;
  829. align-items: flex-end;
  830. padding: $spacer 0;
  831. }
  832. // Tabbed content
  833. .nav-tabs {
  834. .nav-link {
  835. &:hover {
  836. // Don't show a bottom-border on a hovered nav link because it overlaps with the .nav-tab border.
  837. border-bottom-color: transparent;
  838. }
  839. &.active {
  840. // Set the background-color of an active tab to the same color as the .tab-content
  841. // background-color so it visually indicates which tab is open.
  842. background-color: $tab-content-bg;
  843. border-bottom-color: $tab-content-bg;
  844. // Move the active tab down 1px to overtake the .nav-tabs element's border, but only for that
  845. // tab. This is an ugly hack, but it works.
  846. transform: translateY(1px);
  847. }
  848. }
  849. }
  850. .tab-content {
  851. display: flex;
  852. flex-direction: column;
  853. padding: $spacer;
  854. background-color: $tab-content-bg;
  855. border-bottom: 1px solid $nav-tabs-border-color;
  856. }
  857. // Page-specific styles.
  858. html {
  859. // Shade the home page content background-color.
  860. &[data-netbox-path='/'] {
  861. .content-container,
  862. .search {
  863. background-color: $gray-100;
  864. }
  865. &[data-netbox-color-mode='dark'] {
  866. .content-container,
  867. .search {
  868. background-color: $darkest;
  869. }
  870. }
  871. }
  872. // Don't show the django-messages toasts on the login screen in favor of the alert component.
  873. &[data-netbox-path*='/login'] {
  874. #django-messages {
  875. display: none;
  876. }
  877. }
  878. }