Files
fleet/frontend/components/TargetLabelSelector/_styles.scss
T
Nico b4c32d279e Policies: Include/Exclude label targeting in Save policy modal (#33441) (#47213)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46583 

Figma:
https://www.figma.com/design/0F1sw63SuYaKVWlcL7mnc6/-33441-Policies--Custom-targets-with-%22Include-any%22-and-%22Exclude-any%22?node-id=5303-5687&t=Fszpf83KhcZ7ViWh-0

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [x] Added/updated automated tests

- [x] QA'd all new/changed functionality manually

Note: policy creation will fail if more than one inclusion/exclusion
option is provided. This will be addressed as part of
https://github.com/fleetdm/fleet/issues/46582 (we'll relax that check to
make sure we can accept a combination).



https://github.com/user-attachments/assets/9cfbcbca-54ce-4978-8248-7d550f18785b



https://github.com/user-attachments/assets/16138fb1-da7c-4838-8819-f370bf7072c1

Empty state:

<img width="850" height="628" alt="Screenshot 2026-06-10 at 11 30 45 AM"
src="https://github.com/user-attachments/assets/141c4d26-e464-4ae1-b6ed-94d24a640e1c"
/>



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Add optional "exclude all" label targeting for policies
(labels_exclude_all) and tab-based Include/Exclude targeting UI.

* **Improvements**
* In-modal navigation to add new labels; Custom targeting requires at
least one selected label to enable Save.
* Payloads now include include/exclude label fields when using Custom
targeting.

* **Tests**
  * Updated modal tests to cover exclude-tab label selection.

* **Style**
  * Improved empty-state border styling in label selector.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-11 10:00:30 -03:00

147 lines
2.9 KiB
SCSS

.target-label-selector {
width: 100%;
font-size: $x-small;
&__custom-label-chooser {
display: flex;
flex-direction: column;
gap: $pad-medium;
// Hardcoded to fit all 3 custom target options (Exclude any, Include all,
// Include any) without scrolling
.Select-menu-outer {
max-height: 260px;
}
.Select-menu {
max-height: 244px;
}
}
&__checkboxes {
display: flex;
// 210px shows about 4.5 rows so the last row is half-visible, hinting
// there is more to scroll to
max-height: 210px;
flex-direction: column;
border-radius: $border-radius;
border: 1px solid $ui-fleet-black-10;
overflow-y: auto;
.loading-spinner {
margin: 69.5px auto;
}
}
&__label {
width: 100%;
padding: $pad-small $pad-medium;
box-sizing: border-box;
display: flex;
align-items: center;
&:not(:last-child) {
border-bottom: 1px solid $ui-fleet-black-10;
}
.form-field--checkbox {
width: auto;
}
}
&__label-name {
padding-left: $pad-small;
}
// Tabbed include/exclude experience (TargetLabelSelector).
.react-tabs {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
// react-tabs unmounts inactive panels by default, so only the selected
// panel needs layout.
.react-tabs__tab-panel--selected {
display: flex;
flex-direction: column;
gap: $pad-medium;
margin-top: 0;
}
// Truncate long label names in the tabbed checkbox list.
.react-tabs__tab-panel .fleet-checkbox {
height: 20px;
display: flex;
align-items: center;
&__label {
max-width: 490px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
&__mode-toggle {
display: flex;
flex-direction: column;
gap: $pad-small;
}
&__selected-badges {
display: flex;
flex-wrap: wrap;
gap: $pad-xsmall;
}
&__selected-badge {
display: flex;
align-items: center;
gap: $pad-xxsmall;
padding: $pad-xxsmall $pad-small;
background-color: $ui-fleet-black-5;
border: 1px solid $ui-fleet-black-10;
border-radius: $border-radius;
font-size: $xx-small;
cursor: pointer;
color: $ui-fleet-black-75;
&:hover {
background-color: $ui-fleet-black-10;
border-color: $ui-fleet-black-25;
}
}
&__empty-state {
display: flex;
height: 187px;
flex-direction: column;
align-items: center;
gap: $pad-small;
justify-content: center;
text-align: center;
border: 1px solid $ui-fleet-black-10;
border-radius: $border-radius-large;
span {
color: $ui-fleet-black-75;
}
&--title {
font-size: $small;
font-weight: $bold;
color: $core-fleet-black !important;
}
&--description {
font-size: $xx-small;
margin-top: -$pad-xsmall;
}
.button {
margin-top: $pad-small;
}
}
}