fleet/frontend/styles/var/mixins.scss
jacobshandling 8b09e9d239
UI: Linux setup experience - IT admin updates (#32569)
## PR 1/2 for #32037 

- Implements update for the Linux setup experience from the IT admin's
point of view. Updates for the end-user ("My device" page) to follow
- Works in concert with the new endpoints implemented in
https://github.com/fleetdm/fleet/pull/32493

- Splits Controls > Setup experience > Install software into 3 tabbed
sections, one for each of macOS, Windows (placeholder state for now, to
be implemented in following iteration), and Linux.
- Dynamically calls new GET and PUT endpoints and routes data
accordingly depending on which platform software for install is being
updated for.
- Update the software selection modal to display software package
versions, including the package type (deb, rpm, or tar) for Linux
software packges.
- New activity feed item
- Update relevant tests


![ezgif-86da6f2b97d770](https://github.com/user-attachments/assets/6ae95bb7-f629-472e-b996-fcba1cf83e76)
_Note that the lower-right-hand image in this GIF is outdated and will
be updated with new content once this entire feature is integrated_


~- [ ] Changes file added for user-visible changes in `changes/`~ will
include in PR 2/2
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

- [x] Verified that any relevant UI is disabled when GitOps mode is
enabled

---------

Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
2025-09-04 10:24:05 -07:00

467 lines
9.2 KiB
SCSS

$min-width: $break-xs;
$medium-width: 1024px;
$desktop-width: 1200px;
$max-width: 2560px;
@mixin breakpoint($size: desktop) {
@if ($size == tablet) {
@media (max-width: $medium-width) {
@content;
}
} @else if ($size == ltdesktop) {
@media (max-width: ($desktop-width - 1)) {
@content;
}
} @else if ($size == desktop) {
@media (min-width: ($medium-width + 1)) {
@content;
}
} @else if ($size == smalldesk) {
@media (max-width: 1185px) {
@content;
}
} @else {
@content;
}
}
// Used to normalize styling of team header wrapper on various pages
@mixin normalize-team-header {
display: flex;
align-items: center;
height: 38px;
justify-content: space-between;
}
// Used to keep the settings description sticky under the main nav and sub nav.
// TODO: figure out how to calculate these values with variables. Will be tedious to change otherwise
@mixin sticky-settings-description {
position: sticky;
// this is the current spacing needed to keep the description looking correct under the sub nav when scrolling.
top: 104px;
z-index: 2;
background-color: $core-white;
margin: 0;
padding: $pad-xxlarge 0 54px 0;
}
@mixin grey-badge {
background-color: $ui-fleet-black-25;
color: $core-white;
font-size: $xx-small;
font-weight: $bold;
padding: 0 $pad-xsmall;
border-radius: $border-radius;
position: relative;
margin-left: $pad-xsmall;
}
// Used to create a list item with the item data (name, created at, etc...) on
// the left and the item actions (download, delete, etc...) on the right.
@mixin list-item {
display: flex;
justify-content: space-between;
align-items: center;
&__list-item-data {
display: flex;
align-items: center;
}
&__list-item-info {
margin-left: $pad-medium;
display: flex;
flex-direction: column;
}
&__list-item-name {
font-size: $x-small;
font-weight: $bold;
}
&__list-item-uploaded {
font-size: $xx-small;
}
&__list-item-actions {
display: flex;
justify-content: flex-end;
}
&__list-item-button {
width: 40px;
height: 40px;
}
&__list-item-button:not(:last-child) {
margin-right: $pad-medium;
}
}
// used to share styles across the manual enroll mdm modal and the auto enroll mdm modal.
@mixin enroll-mdm-modal {
&__description {
margin: $pad-large 0;
}
&__download-button {
margin-top: 12px;
}
ol {
padding-left: 0;
}
li {
margin-bottom: $pad-large;
list-style-position: inside;
}
}
@mixin disabled {
opacity: 0.5;
filter: grayscale(0.5);
pointer-events: none;
cursor: default;
// Must override
&:hover,
&:focus {
cursor: default;
}
}
@mixin disabled-checkbox {
background-color: $ui-fleet-black-25;
border-color: $ui-fleet-black-25;
pointer-events: none;
cursor: default;
}
@mixin grey-text {
color: $ui-fleet-black-75;
}
@mixin help-text {
font-size: $xx-small;
font-weight: $regular;
@include grey-text;
.custom-link,
button {
font-size: inherit;
}
}
@mixin link {
color: $core-vibrant-blue;
font-weight: $bold;
font-size: $x-small;
text-decoration: none;
&:focus-visible {
outline-color: #d9d9fe;
outline-offset: 3px;
outline-style: solid;
outline-width: 2px;
border-radius: 2px;
}
}
@mixin table-link {
display: inline-flex;
align-items: center;
padding: $pad-small $pad-xxsmall; // larger clickable area
gap: $pad-small;
white-space: nowrap;
@include link;
&:hover {
text-decoration: underline;
}
}
@mixin cell-with-link {
display: inline-flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
@mixin direction-link {
display: inline-flex;
align-items: center;
padding: $pad-small $pad-xxsmall; // larger clickable area
border-radius: 3px; // Visible while tabbing;
gap: $pad-xsmall;
&:hover {
color: $core-vibrant-blue-over;
text-decoration: underline;
svg {
path {
stroke: $core-vibrant-blue-over;
}
}
}
}
@mixin ellipse-text($max-width: auto) {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: $max-width;
}
@mixin copy-message {
font-weight: $regular;
font-size: $x-small;
vertical-align: top;
background-color: $ui-light-grey;
border: solid 1px #e2e4ea;
border-radius: 10px;
padding: 2px 6px;
}
@mixin color-contrasted-sections {
background-color: $ui-off-white;
.section {
display: flex;
flex-direction: column;
background-color: $core-white;
border-radius: 16px;
border: 1px solid $ui-fleet-black-10;
padding: $pad-xxlarge;
box-shadow: 0px 3px 0px rgba(226, 228, 234, 0.4);
}
}
@mixin tooltip-text {
width: max-content;
max-width: 360px;
padding: 6px;
color: $core-white;
background-color: $tooltip-bg;
font-weight: $regular;
font-size: $xx-small;
border-radius: 4px;
box-sizing: border-box;
z-index: 100;
line-height: 1.375;
white-space: initial;
// Hyphenated words will still break at hyphens first
// while non-hyphenated strings will break only when necessary
overflow-wrap: break-word; // Preferred property for modern browsers
word-wrap: break-word; // Fallback for older browsers e.g. IE
word-break: break-word; // Ensures words break when necessary
p {
margin: 0;
}
}
@mixin flex-column-1rem-gap {
display: flex;
flex-direction: column;
gap: 1rem;
}
@mixin page {
@include flex-column-1rem-gap;
}
@mixin form-button-extra-clickable-area-compensation {
// compensate in layout for extra clickable area button height
margin: -8px 0;
}
@mixin button-dropdown {
.form-field {
margin: 0;
}
.Select {
position: relative;
border: 0;
height: auto;
&.is-focused,
&:hover {
border: 0;
}
&.is-focused:not(.is-open) {
.Select-control {
background-color: initial;
}
}
.Select-control {
display: flex;
background-color: initial;
height: auto;
justify-content: space-between;
border: 0;
cursor: pointer;
&:hover {
box-shadow: none;
}
&:hover .Select-placeholder {
color: $core-vibrant-blue;
}
.Select-placeholder {
font-size: 14px;
line-height: normal;
padding-left: 0;
margin-top: 1px;
}
.Select-input {
height: auto;
// When tabbing
&:focus-visible {
outline: 2px solid $ui-vibrant-blue-25;
outline-offset: 1px;
border-radius: 4px;
}
}
.Select-arrow-zone {
display: flex;
}
}
.Select-placeholder {
display: flex;
align-items: center;
}
.Select-menu-outer {
margin-top: $pad-xsmall;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
border-radius: $border-radius;
z-index: 6;
overflow: hidden;
border: 0;
width: 188px;
left: unset;
top: unset;
max-height: none;
padding: $pad-small;
position: absolute;
.Select-menu {
max-height: none;
}
}
.Select-arrow {
transition: transform 0.25s ease;
}
&:not(.is-open) {
.Select-control:hover .Select-arrow {
content: url("../assets/images/icon-chevron-blue-16x16@2x.png");
}
}
&.is-open {
.Select-control .Select-placeholder {
color: $core-vibrant-blue;
}
.Select-arrow {
transform: rotate(180deg);
}
}
}
}
@mixin tooltip5-arrow-styles {
// arrow styles directly from react-tooltip-5 css
.react-tooltip-arrow {
width: 8px;
height: 8px;
}
[class*="react-tooltip__place-top"] > .styles-module_arrow__K0L3T {
transform: rotate(45deg);
}
[class*="react-tooltip__place-right"] > .styles-module_arrow__K0L3T {
transform: rotate(135deg);
}
[class*="react-tooltip__place-bottom"] > .styles-module_arrow__K0L3T {
transform: rotate(225deg);
}
[class*="react-tooltip__place-left"] > .styles-module_arrow__K0L3T {
transform: rotate(315deg);
}
}
@mixin side-nav-list {
position: -webkit-sticky;
position: sticky;
// this is the spacing needed to make the sticky form nav position correctly when scrolling
// TODO: find a way to calculate these sticky positions this and use variables.
// will be tedious to update otherwise.
top: 217px;
width: 260px;
padding: 0 64px 0 0;
list-style: none;
font-size: $x-small;
display: flex;
flex-direction: column;
gap: $pad-small;
margin: 0;
}
@mixin side-nav-item {
white-space: nowrap;
height: 32px;
border-radius: 4px;
a {
display: flex;
align-items: center;
height: 100%;
padding: 0 16px;
color: $core-fleet-black;
font-weight: $regular;
text-decoration: none;
cursor: pointer;
&:hover {
color: $core-vibrant-blue;
}
}
&--active {
background-color: $ui-fleet-black-5;
a {
font-weight: $bold;
color: $ui-fleet-black-75;
* > .__react_component_tooltip {
font-weight: initial;
}
}
}
}
@mixin tab-empty-state {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid $ui-fleet-black-10;
border-radius: $pad-xsmall;
padding: $pad-xxlarge;
gap: $pad-small;
font-size: $small;
p {
margin: 0;
@include help-text;
}
}