Skip to content

Commit

Permalink
Implement state-dependent accordion background colors (aiidalab#1038)
Browse files Browse the repository at this point in the history
This PR uses the experimental `:has` CSS selector to apply background colors to the accordion item headers bases on the state of the accordion item's content (the wizard steps). If `has` is not supported by the browser (old version), the colors simply do not apply.
  • Loading branch information
edan-bainglass authored Dec 30, 2024
1 parent 1ad6fd2 commit 68cdb8d
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/aiidalab_qe/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ def __init__(self, qe_auto_setup=True):

self._wizard_app_widget.selected_index = None

self.structure_step.state = QeWizardStep.State.READY

self._update_blockers()

@property
Expand Down
3 changes: 2 additions & 1 deletion src/aiidalab_qe/app/result/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ def reset(self):
self._model.reset()

@tl.observe("state")
def _on_state_change(self, _):
def _on_state_change(self, change):
super()._on_state_change(change)
self._update_kill_button_layout()

def _on_previous_step_state_change(self, _):
Expand Down
22 changes: 22 additions & 0 deletions src/aiidalab_qe/app/static/styles/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,25 @@
footer {
text-align: right;
}

.p-Accordion-child:has(.qe-app-step-ready) > .p-Collapse-header {
background-color: var(--color-ready);
}

.p-Accordion-child:has(.qe-app-step-configured) > .p-Collapse-header {
background-color: var(--color-ready);
filter: brightness(0.95);
-webkit-filter: brightness(0.95);
}

.p-Accordion-child:has(.qe-app-step-active) > .p-Collapse-header {
background-color: var(--color-active);
}

.p-Accordion-child:has(.qe-app-step-success) > .p-Collapse-header {
background-color: var(--color-success);
}

.p-Accordion-child:has(.qe-app-step-fail) > .p-Collapse-header {
background-color: var(--color-failed);
}
7 changes: 7 additions & 0 deletions src/aiidalab_qe/app/static/styles/variables.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:root {
--color-init: #eee;
--color-ready: #fcf8e3;
--color-active: #d9edf7;
--color-success: #dff0d8;
--color-failed: #f2dede;
}
10 changes: 10 additions & 0 deletions src/aiidalab_qe/common/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,7 @@ def __init__(self, model: QWSM, **kwargs):
super().__init__(children=[self.loading_message], **kwargs)
self._model = model
self.rendered = False
self._background_class = ""

def render(self):
if self.rendered:
Expand All @@ -1168,12 +1169,21 @@ def render(self):
self.rendered = True
self._post_render()

@traitlets.observe("state")
def _on_state_change(self, change):
self._update_background_color(change["new"])

def _render(self):
raise NotImplementedError()

def _post_render(self):
pass

def _update_background_color(self, state: WizardAppWidgetStep.State):
self.remove_class(self._background_class)
self._background_class = f"qe-app-step-{state.name.lower()}"
self.add_class(self._background_class)


class QeDependentWizardStep(QeWizardStep[QWSM]):
missing_information_warning = "Missing information"
Expand Down
8 changes: 8 additions & 0 deletions tests_integration/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ def test_qe_app_select_silicon_and_confirm(
driver = selenium_driver("qe.ipynb", wait_time=30.0)
driver.set_window_size(1920, 1485)

driver.find_element(By.CLASS_NAME, "qe-app-step-ready") # ready on start

# Open structure selection step
element = WebDriverWait(driver, 60).until(
EC.presence_of_element_located((By.CLASS_NAME, "p-Accordion-child"))
)
element.click()
# check that element has CSS class
driver.find_element(By.CLASS_NAME, "qe-app-step-ready") # still ready

# Select the Silicon example
element = WebDriverWait(driver, 60 * 2).until(
Expand All @@ -35,10 +39,14 @@ def test_qe_app_select_silicon_and_confirm(
try:
driver.find_element(By.XPATH, "//option[@value='Diamond']").click()
time.sleep(10)
# Selection configures the step
driver.find_element(By.CLASS_NAME, "qe-app-step-configured")
element = WebDriverWait(driver, 60).until(
EC.element_to_be_clickable((By.XPATH, "//button[text()='Confirm']"))
)
element.click()
# Confirming means step is successful
driver.find_element(By.CLASS_NAME, "qe-app-step-success")
except Exception:
driver.find_element(By.TAG_NAME, "summary").click()
time.sleep(10)
Expand Down

0 comments on commit 68cdb8d

Please sign in to comment.