Skip to content

Conversation

@flang
Copy link

@flang flang commented Aug 14, 2025

Default overflow button:
image

Overflow button icon is customizable as well:
image

Summary by CodeRabbit

  • New Features
    • Responsive day-of-week selector web component with overflow menu mirroring hidden days, client-side toggling, label and i18n support, extra constructors, and customizable overflow icon/size.
  • Style
    • Read-only/disabled button styling refined; overflow menu padding and demo spacing improved; selector label weight emphasized; focus-ring box-shadow removed.
  • Documentation
    • Demo updated with richer layout, overflow showcase, live value display and interactive controls.
  • Chores
    • Project version bumped to 1.2.0-SNAPSHOT.

@coderabbitai
Copy link

coderabbitai bot commented Aug 14, 2025

Walkthrough

Version bumped to 1.2.0-SNAPSHOT. DayOfWeekSelector refactored into a Vaadin web component with programmatic DayOfWeekButton management, client-callable toggles, new APIs (overflow icon, I18N, constructors), and a LitElement frontend that handles responsive overflow. CSS and demo/test styles/layout updated.

Changes

Cohort / File(s) Summary of changes
Version bump
pom.xml
Bumped project version from 1.1.1-SNAPSHOT to 1.2.0-SNAPSHOT.
Core component refactor & API
src/main/java/.../dayofweekselector/DayOfWeekSelector.java
Replaced layout-based rendering with programmatic DayOfWeekButton list and DOM slots; added @Tag and @JsModule; introduced @ClientCallable toggleState; added constructors; added setOverflowIcon, setI18N, CssProperties; lifecycle helpers for button management; updated model/presentation mapping, first-day reordering, read-only propagation, and imports.
Frontend LitElement
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts
Added DaysOfWeekSelector LitElement custom element exposing theme and label, rendering a daysOfWeek slot and overflow context-menu; observes resize, detects overflow, hides/clones overflowing buttons into the menu, mirrors interactions to server, and manages overflow badge.
Component styles
src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css
Updated selectors to apply .readOnly on disabled buttons instead of ancestor [readonly]; added rule removing focus box-shadow; adjusted context-menu list padding.
Demo/test layout & styles
src/test/java/.../DemoLayout.java, src/test/java/.../dayofweekselector/DayOfWeekSelectorDemo.java, src/test/resources/.../shared-styles.css
Added @CssImport("/styles/shared-styles.css") to DemoLayout; refactored demo to VerticalLayout, added enabled/overflow interactive examples, overflow icon usage, live value display, and added demo CSS rules (.demo gap, bold label part, empty html selector).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue-5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (8)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1)

207-212: Toggle has-label only when label is non-empty

Current logic sets the attribute even for empty strings. Use a trimmed check.

-        if (_changedProperties.has('label')) {
-            this.toggleAttribute('has-label', this.label != null);
-        }
+        if (_changedProperties.has('label')) {
+            const has = typeof this.label === 'string' && this.label.trim().length > 0;
+            this.toggleAttribute('has-label', has);
+        }
src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (1)

75-76: ClientCallable visibility

@ClientCallable private void toggleState() is callable, but using private here is unconventional and may hinder future refactors. Consider making it public for clarity and consistency with Vaadin examples.

src/test/resources/META-INF/frontend/styles/shared-styles.css (3)

21-22: Remove empty html rule

This rule is a no-op and adds noise.

-html {
-}

24-26: Scope the demo gap rule to the component element

To avoid accidentally applying gap to non-layout elements that may also use the "demo" class, target the tag explicitly. This also clarifies the intent that the rule is for VerticalLayout instances.

-.demo {
+vaadin-vertical-layout.demo {
     gap: var(--lumo-space-m);
 }

28-30: Use Lumo design token for font weight

Aligns with theming and makes the style consistent with Lumo’s design system.

-fc-days-of-week-selector::part(label) {
-    font-weight: bold;
-}
+fc-days-of-week-selector::part(label) {
+    font-weight: var(--lumo-font-weight-bold);
+}
src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java (3)

41-45: Switch to VerticalLayout and hook shared styles — looks good; also disable default spacing

Extending VerticalLayout and adding the "demo" class matches the new shared styles. To avoid double spacing (default VerticalLayout spacing + custom CSS gap), explicitly disable the built-in spacing.

 public DayOfWeekSelectorDemo() {
-    addClassName("demo");
+    addClassName("demo");
+    setSpacing(false);

62-67: Render value in a deterministic weekday order

Sets are unordered; rendering in calendar order avoids flicker and improves readability.

-    Consumer<Set<DayOfWeek>> valueRenderer =
-      value -> valueContent.setText("Value: " + value.stream().map(Enum::name).collect(Collectors.joining(" - ")));
+    Consumer<Set<DayOfWeek>> valueRenderer =
+      value -> valueContent.setText("Value: " + value.stream()
+          .sorted(java.util.Comparator.comparingInt(DayOfWeek::getValue))
+          .map(Enum::name)
+          .collect(Collectors.joining(" - "))));

Add this import outside the shown range:

import java.util.Comparator;

65-65: Consider a HorizontalLayout for selector + live value row

Places the selector and its live value on a single row (import already present), improving the demo ergonomics.

-    add(new Div(selectorOverflow, valueContent));
+    add(new HorizontalLayout(selectorOverflow, valueContent));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between acd6e03 and 6f946e7.

📒 Files selected for processing (7)
  • pom.xml (1 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (7 hunks)
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css (2 hunks)
  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java (2 hunks)
  • src/test/resources/META-INF/frontend/styles/shared-styles.css (1 hunks)
🔇 Additional comments (8)
pom.xml (1)

7-7: Version bump looks good

The artifact version update to 1.2.0-SNAPSHOT aligns with the new public API surface introduced in this PR.

src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css (1)

54-56: Context menu padding addition LGTM

The padding adjustment for the context-menu list box is scoped and non-invasive.

src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1)

193-194: Recompute overflow when slot content changes

Couldn't locate src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts in the repo during verification. If this component (or the component that renders the days slot) contains the , add a slotchange handler so overflow is recalculated when days are added/removed or localized.

  • Target file (verify path): src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts — or the component that renders

Suggested change:

-                <slot name="daysOfWeek"></slot>
+                <slot name="daysOfWeek" @slotchange=${this._updateOnOverflow}></slot>

Ensure this._updateOnOverflow exists and triggers the overflow recomputation (debounced if appropriate). Please confirm the file path or apply this change in the correct component.

src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (2)

255-264: initDefaultDayButtons LGTM

Seven buttons initialized with expected labels and mapped days. Works well with the new slotted rendering.


266-286: Lifecycle helpers LGTM

The add/clear/set helpers correctly manage slots and listeners. Good separation of concerns.

src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java (1)

27-28: Shared styles import LGTM

@CssImport("/styles/shared-styles.css") correctly targets src/test/resources/META-INF/frontend/styles/shared-styles.css for the demo scope.

src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java (2)

57-61: Overflow demo usage reads well

Good showcase: constrained width, custom overflow icon via slot, and size customized through the new CSS property.


69-76: Read-only and Disabled examples — good coverage

These standard states are still demonstrated clearly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (3)

194-204: Verify: server-side value sync when clicking overflow items

Calling originalButton.$server.toggleState() toggles the server-side button, but make sure the field’s server-side value is recomputed too (e.g., CustomField model update). If your Java host doesn’t recompute on child toggle, add a server method (e.g., requestValueUpdateFromClient) and call it here after toggleState().

Do you want me to propose the corresponding server-side stub and wire-up?


25-26: Fix: use queryAssignedElements and HTMLElement typing to avoid TS errors and runtime crashes

Using @queryAssignedNodes yields Node[] (includes Text nodes) but the code uses element APIs (style, getBoundingClientRect). This can break at runtime (e.g., whitespace becomes a Text node) and fails type-checking. Switch to @queryAssignedElements and type as HTMLElement[]. Also type overflowButtons accordingly.

Apply:

-import {customElement, property, query, queryAssignedNodes, state} from 'lit/decorators.js';
+import {customElement, property, query, queryAssignedElements, state} from 'lit/decorators.js';
@@
-    @queryAssignedNodes({slot: 'daysOfWeek', flatten: true})
-    _daysOfWeek!: Array<Node>;
+    @queryAssignedElements({slot: 'daysOfWeek', flatten: true})
+    _daysOfWeek!: Array<HTMLElement>;
@@
-        const overflowButtons: Node[] = [];
+        const overflowButtons: HTMLElement[] = [];
@@
-        for (const button of this._daysOfWeek) {
+        for (const button of this._daysOfWeek) {
             button.style.display = '';
             const width = button.getBoundingClientRect().width;

Also applies to: 34-36, 159-169


189-206: Fix typing and prevent duplicate IDs on cloned overflow items

cloneNode returns a Node, _originalButton is not a declared property, and $server isn’t on the HTMLElement type. This won’t type-check and can be brittle at runtime. Also, cloning preserves id, which can cause duplicate IDs.

Apply:

-    private _cloneButton(originalButton: Button) {
-        const clonedButton = originalButton.cloneNode(true);
-        clonedButton._originalButton = originalButton;
+    private _cloneButton(originalButton: HTMLElement) {
+        const clonedButton = originalButton.cloneNode(true) as HTMLElement & { _originalButton?: HTMLElement };
+        clonedButton._originalButton = originalButton;
         clonedButton.removeAttribute("slot");
+        clonedButton.removeAttribute("id");
         clonedButton.style.display = '';
         clonedButton.addEventListener('click', ev => {
             // Update server side button component state
-            clonedButton._originalButton.$server.toggleState();
+            (clonedButton._originalButton as any)?.$server?.toggleState?.();
             if (clonedButton.getAttribute("theme")) {
                 clonedButton.removeAttribute("theme")
             } else {
                 clonedButton.setAttribute("theme", "primary");
             }
             // Notify value change to DayOfWeekSelector component
             this.dispatchEvent(new CustomEvent('change', {bubbles: true}));
         });
         return clonedButton;
     }
🧹 Nitpick comments (2)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (2)

216-223: Accessibility: add an aria-label/title to the overflow trigger

The overflow button is icon-only. Provide an accessible name.

-                    <vaadin-button part="overflow-badge" theme="${this.theme} tertiary-inline"
-                                   class="overflow-badge" hidden style="cursor: pointer">
+                    <vaadin-button part="overflow-badge" theme="${this.theme} tertiary-inline"
+                                   class="overflow-badge" hidden style="cursor: pointer"
+                                   aria-label="More options" title="More options">

If you have an i18n API, consider wiring this to a localized string.


77-95: Nit: consider component-scoped CSS custom property names

These variables are named --badge-list-label-*. For clarity and encapsulation, consider namespaced variants like --fc-days-of-week-selector-label-*.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6f946e7 and 3bcc790.

📒 Files selected for processing (4)
  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (7 hunks)
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css (2 hunks)
  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-18T14:30:50.223Z
Learnt from: flang
PR: FlowingCode/DayOfWeekSelectorAddon#14
File: src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts:195-197
Timestamp: 2025-08-18T14:30:50.223Z
Learning: For Vaadin/LitElement components, when a property like theme can be empty, prefer setting the default value to an empty string (`''`) rather than `null` to avoid rendering "null" in template attribute bindings. This is cleaner than using conditional logic in templates.

Applied to files:

  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts
🔇 Additional comments (2)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (2)

138-157: Nice: removed magic number with dynamic overflow-button measurement

Measuring the actual overflow trigger width and subtracting it from the container width is robust and theming-safe. Good improvement.

Also applies to: 159-170


41-41: Good call: default theme to empty string

This avoids “null” leaks in attribute bindings and aligns with prior guidance.

@flang flang marked this pull request as ready for review August 18, 2025 16:14
@flang flang requested a review from paodb August 18, 2025 16:15
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (4)

228-231: Only set [has-label] when the label is non-empty

The current condition treats empty string as present, leaving blank label space visible. Switch to a non-empty check.

-        if (_changedProperties.has('label')) {
-            this.toggleAttribute('has-label', this.label != null);
-        }
+        if (_changedProperties.has('label')) {
+            const hasLabel = (this.label ?? '').trim().length > 0;
+            this.toggleAttribute('has-label', hasLabel);
+        }

25-25: Use queryAssignedElements instead of queryAssignedNodes to avoid runtime errors with Text nodes

The code treats assigned nodes as HTMLElements (style and getBoundingClientRect), but @queryAssignedNodes returns Node[]. Whitespace becomes Text nodes and will throw at runtime. Switch to queryAssignedElements to ensure elements and correct typing.

Apply:

-import {customElement, property, query, queryAssignedNodes, state} from 'lit/decorators.js';
+import {customElement, property, query, queryAssignedElements, state} from 'lit/decorators.js';

34-36: Type assigned slotted items as HTMLElement[]

Follow-up to the previous comment: ensure the property uses queryAssignedElements and HTMLElement[]. This resolves both TS and runtime issues.

-    @queryAssignedNodes({slot: 'daysOfWeek', flatten: true})
-    _daysOfWeek!: Array<Node>;
+    @queryAssignedElements({slot: 'daysOfWeek', flatten: true})
+    _daysOfWeek!: Array<HTMLElement>;

189-206: Fix typing and robustness in _cloneButton; avoid duplicate ids; null-safe server calls

  • Parameter type should be HTMLElement to match the assigned elements.
  • Cast the clone to include a private _originalButton link.
  • Remove id on the clone to prevent duplicate ids.
  • Use optional chaining on $server.toggleState() to avoid hard crashes if not present.
-    private _cloneButton(originalButton: Button) {
-        const clonedButton = originalButton.cloneNode(true);
-        clonedButton._originalButton = originalButton;
-        clonedButton.removeAttribute("slot");
-        clonedButton.style.display = '';
-        clonedButton.addEventListener('click', ev => {
-            // Update server side button component state
-            clonedButton._originalButton.$server.toggleState();
-            if (clonedButton.getAttribute("theme")) {
-                clonedButton.removeAttribute("theme")
-            } else {
-                clonedButton.setAttribute("theme", "primary");
-            }
-            // Notify value change to DayOfWeekSelector component
-            this.dispatchEvent(new CustomEvent('change', {bubbles: true}));
-        });
-        return clonedButton;
-    }
+    private _cloneButton(originalButton: HTMLElement) {
+        const clonedButton = originalButton.cloneNode(true) as HTMLElement & { _originalButton?: HTMLElement };
+        clonedButton._originalButton = originalButton;
+        clonedButton.removeAttribute('slot');
+        clonedButton.removeAttribute('id'); // avoid duplicate ids
+        clonedButton.style.display = '';
+        clonedButton.addEventListener('click', () => {
+            // Update server side button component state
+            (clonedButton._originalButton as any)?.$server?.toggleState?.();
+            // Toggle visual state on the clone
+            if (clonedButton.getAttribute('theme')) {
+                clonedButton.removeAttribute('theme');
+            } else {
+                clonedButton.setAttribute('theme', 'primary');
+            }
+            // Notify value change to DayOfWeekSelector component
+            this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
+        });
+        return clonedButton;
+    }

Note: After this change, the Button import at Line 26 becomes unused and can be removed for cleanliness.

🧹 Nitpick comments (1)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1)

213-218: Trigger overflow recalculation on slot changes; add aria-label for overflow button

  • Without listening to slotchange, initial layout may be stale until the first ResizeObserver tick. Hook the slot event to recalc promptly.
  • Add an accessible name to the overflow trigger.
-            <div part="container" class="container" id="container">
-                <slot name="daysOfWeek"></slot>
-                <vaadin-context-menu open-on="click" .items=${this._overflowItems}>
-                    <vaadin-button part="overflow-badge" theme="${this.theme} tertiary-inline"
-                                   class="overflow-badge" hidden style="cursor: pointer">
+            <div part="container" class="container" id="container">
+                <slot name="daysOfWeek" @slotchange=${this._updateOnOverflow}></slot>
+                <vaadin-context-menu open-on="click" .items=${this._overflowItems}>
+                    <vaadin-button part="overflow-badge" theme="${this.theme} tertiary-inline"
+                                   class="overflow-badge" hidden style="cursor: pointer"
+                                   aria-label="${this.label ? `${this.label}: more` : 'More'}">

Please verify if vaadin-icon is guaranteed to be registered by your app shell; if not, consider importing it here to ensure the fallback renders:

import '@vaadin/icon';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3bcc790 and 806cb74.

📒 Files selected for processing (7)
  • pom.xml (1 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (7 hunks)
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css (2 hunks)
  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java (2 hunks)
  • src/test/resources/META-INF/frontend/styles/shared-styles.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
  • pom.xml
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-18T14:30:50.223Z
Learnt from: flang
PR: FlowingCode/DayOfWeekSelectorAddon#14
File: src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts:195-197
Timestamp: 2025-08-18T14:30:50.223Z
Learning: For Vaadin/LitElement components, when a property like theme can be empty, prefer setting the default value to an empty string (`''`) rather than `null` to avoid rendering "null" in template attribute bindings. This is cleaner than using conditional logic in templates.

Applied to files:

  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts
🔇 Additional comments (1)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1)

40-44: Good: defaulting theme to empty string avoids “null” in attribute bindings

Setting theme: string = '' aligns with best practice and prevents accidental theme="null ..." in the template.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (1)
src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (1)

139-142: Correct equality semantics for CustomField

valueEquals should delegate to Objects.equals. The current check returns false for identical instances, which is surprising and may cause unnecessary value change handling.

Apply:

-  @Override
-  protected boolean valueEquals(Set<DayOfWeek> value1, Set<DayOfWeek> value2) {
-    return value1 != value2 && Objects.equals(value1, value2);
-  }
+  @Override
+  protected boolean valueEquals(Set<DayOfWeek> value1, Set<DayOfWeek> value2) {
+    return Objects.equals(value1, value2);
+  }
♻️ Duplicate comments (5)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (4)

159-187: Avoid false positives: don’t reserve overflow button width unless overflow actually occurs (two-pass)

Always subtracting the overflow badge width can push one item into overflow needlessly. Measure once without reserving; if overflow occurs, redo with reservation.

Apply:

-    private _updateOnOverflow() {
-        const containerWidth = this.getBoundingClientRect().width;
-        let usedWidth = 0;
-        const overflowButtons: Node[] = [];
-        const overflowButtonWidth = this._getOverflowButtonWidth();
-
-        for (const button of this._daysOfWeek) {
-            button.style.display = '';
-            const width = button.getBoundingClientRect().width;
-
-            if (usedWidth + width > containerWidth - overflowButtonWidth) {
-                const clonedButton = this._cloneButton(button);
-                overflowButtons.push(clonedButton);
-
-                // hide button from slot
-                button.style.display = 'none';
-            } else {
-                usedWidth += width;
-            }
-        }
-
-        // Update context menu items from hidden buttons
-        this._overflowItems = overflowButtons.map(button => ({
-            component: button,
-        }));
-
-        // Update badges visibility
-        this._overflowBadge.toggleAttribute('hidden', this._overflowItems.length < 1);
-    }
+    private _updateOnOverflow() {
+        const containerWidth = this.getBoundingClientRect().width;
+        const allButtons = this._daysOfWeek;
+
+        // Reset visibility before measuring
+        for (const btn of allButtons) {
+            btn.style.display = '';
+        }
+
+        const measure = (reserveOverflow: boolean) => {
+            const overflowWidth = reserveOverflow ? this._getOverflowButtonWidth() : 0;
+            let used = 0;
+            const overflow: HTMLElement[] = [];
+            for (const btn of allButtons) {
+                const w = btn.getBoundingClientRect().width;
+                if (used + w > containerWidth - overflowWidth) {
+                    overflow.push(this._cloneButton(btn));
+                    btn.style.display = 'none';
+                } else {
+                    used += w;
+                }
+            }
+            return overflow;
+        };
+
+        // First pass without reserving badge space
+        let overflowButtons = measure(false);
+        if (overflowButtons.length > 0) {
+            // Second pass reserving badge space
+            for (const btn of allButtons) {
+                btn.style.display = '';
+            }
+            overflowButtons = measure(true);
+        }
+
+        this._overflowItems = overflowButtons.map((button) => ({ component: button }));
+        this._overflowBadge.toggleAttribute('hidden', this._overflowItems.length < 1);
+    }

34-36: Fix typing: assigned nodes are treated as HTMLElements; switch to queryAssignedElements

You access style and getBoundingClientRect on items from _daysOfWeek, but it’s typed as Node[]. This is a TS/type safety and potential runtime issue. Use queryAssignedElements and HTMLElement[].

Apply:

-import {customElement, property, query, queryAssignedNodes, state} from 'lit/decorators.js';
+import {customElement, property, query, queryAssignedElements, state} from 'lit/decorators.js';
@@
-    @queryAssignedNodes({slot: 'daysOfWeek', flatten: true})
-    _daysOfWeek!: Array<Node>;
+    @queryAssignedElements({slot: 'daysOfWeek'})
+    _daysOfWeek!: Array<HTMLElement>;

Also applies to: 25-25, 165-175


228-231: Fix has-label for empty/whitespace labels

this.label != null treats '' as present. Only set has-label when non-empty after trimming.

Apply:

-        if (_changedProperties.has('label')) {
-            this.toggleAttribute('has-label', this.label != null);
-        }
+        if (_changedProperties.has('label')) {
+            const hasLabel = (this.label ?? '').trim().length > 0;
+            this.toggleAttribute('has-label', hasLabel);
+        }

189-206: Critical: overflow menu changes don’t update server-side value; fix typing and invoke host value update

Clicking a cloned item calls originalButton.$server.toggleState(), but does not call updateValue() on the field, so the CustomField model value stays stale. Also, the clone typing relies on ad-hoc properties on Node and will fail TS checks.

Apply:

-    private _cloneButton(originalButton: Button) {
-        const clonedButton = originalButton.cloneNode(true);
-        clonedButton._originalButton = originalButton;
+    private _cloneButton(originalButton: HTMLElement) {
+        const clonedButton = originalButton.cloneNode(true) as HTMLElement & { _originalButton?: HTMLElement };
+        clonedButton._originalButton = originalButton;
         clonedButton.removeAttribute("slot");
+        clonedButton.removeAttribute("id");
         clonedButton.style.display = '';
         clonedButton.addEventListener('click', ev => {
             // Update server side button component state
-            clonedButton._originalButton.$server.toggleState();
+            (clonedButton._originalButton as any).$server.toggleState();
+            // Ensure the server-side field value is recomputed
+            (this as any).$server.requestValueUpdateFromClient();
             if (clonedButton.getAttribute("theme")) {
                 clonedButton.removeAttribute("theme")
             } else {
                 clonedButton.setAttribute("theme", "primary");
             }
             // Notify value change to DayOfWeekSelector component
             this.dispatchEvent(new CustomEvent('change', {bubbles: true}));
         });
         return clonedButton;
     }

Note: This requires a new @ClientCallable method on the Java host to recompute the value (see Java review).

src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (1)

302-302: Add host-level client-callable to recompute model value (needed by overflow menu actions)

When an overflow clone triggers originalButton.$server.toggleState() from the client, no server-side click event fires and updateValue() isn’t invoked. Provide a callable the TS component can invoke after toggling.

Apply:

@@
-}
+  @ClientCallable
+  private void requestValueUpdateFromClient() {
+    updateValue();
+  }
+}
🧹 Nitpick comments (3)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (2)

37-39: Remove unused query _container

_container is queried but never used. Drop it to avoid dead code.

Apply:

-    @query('[part~="container"]')
-    _container!: HTMLElement;
+    // (removed unused _container)

214-214: Trigger overflow recalculation when slotted content changes

Overflow should be recalculated on slot content changes, not only on resize. Add a slotchange handler.

Apply:

-                <slot name="daysOfWeek"></slot>
+                <slot name="daysOfWeek" @slotchange=${this._updateOnOverflow}></slot>
src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (1)

255-268: LGTM: overflow icon setter removes previous slotted icon

Removing prior overflowIcon before appending avoids duplicates; class name assignment is fine. Consider extracting the "overflowIcon" slot name into a private constant for reuse.

Optional:

private static final String OVERFLOW_ICON_SLOT = "overflowIcon";

Then replace string literals accordingly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 806cb74 and 65eaefe.

📒 Files selected for processing (7)
  • pom.xml (1 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (7 hunks)
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css (1 hunks)
  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java (2 hunks)
  • src/test/resources/META-INF/frontend/styles/shared-styles.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • pom.xml
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-18T12:15:44.547Z
Learnt from: flang
PR: FlowingCode/DayOfWeekSelectorAddon#14
File: src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java:155-160
Timestamp: 2025-08-18T12:15:44.547Z
Learning: Vaadin's Element API has an overloaded setAttribute(String attribute, boolean value) method that automatically handles boolean-to-attribute conversion: when value is true, it sets the attribute to an empty string (""); when value is false, it removes the attribute entirely via removeAttribute(). This means code like getElement().setAttribute("readonly", readOnly) is correct in Vaadin applications.

Applied to files:

  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java
📚 Learning: 2025-08-18T14:30:50.223Z
Learnt from: flang
PR: FlowingCode/DayOfWeekSelectorAddon#14
File: src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts:195-197
Timestamp: 2025-08-18T14:30:50.223Z
Learning: For Vaadin/LitElement components, when a property like theme can be empty, prefer setting the default value to an empty string (`''`) rather than `null` to avoid rendering "null" in template attribute bindings. This is cleaner than using conditional logic in templates.

Applied to files:

  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts
🔇 Additional comments (5)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (3)

31-33: LGTM: correct element typing for overflow badge

Using HTMLElement for _overflowBadge matches the queried and avoids incorrect narrowing.


143-157: LGTM: robust overflow badge width measurement

Temporarily unhiding to measure and restoring hidden state removes the magic number and adapts to theme/icon changes.


40-45: LGTM: theme default avoids “null” leakage in attribute

Defaulting theme and label to '' aligns with past guidance and prevents rendering "null" in theme binding.

Also applies to: 216-221

src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (2)

156-168: LGTM: readOnly property/attribute handling and button enablement

Using Element#setAttribute(String, boolean) is correct in Vaadin and the per-button enable/disable plus CSS class toggling is consistent.


238-246: LGTM: first-day-of-week reordering logic

Rotation after sorting by DayOfWeek is correct and handles Sunday-first via modulo math.

Copy link
Member

@paodb paodb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation LGTM. And I tested and it looks good. I just left a minor comment on the demo, and there are also some CodeRabbit suggestions that need to be addressed.

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The imports for FlexComponent & HorizontalLayout are unused imports. Please remove them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@github-project-automation github-project-automation bot moved this from To Do to In Progress in Flowing Code Addons Aug 19, 2025
@paodb paodb self-requested a review August 19, 2025 17:27
Copy link
Member

@paodb paodb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Please rebase the WIP commit and squash them into their corresponding non-WIP commit (as explained here)

@paodb paodb self-requested a review August 19, 2025 18:26
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (1)

140-142: valueEquals logic is inverted for identical references; return Objects.equals directly

Returning value1 != value2 && Objects.equals(value1, value2) means identical instances are considered “not equal” (false), which can break value change detection. Use Objects.equals.

Apply:

-  @Override
-  protected boolean valueEquals(Set<DayOfWeek> value1, Set<DayOfWeek> value2) {
-    return value1 != value2 && Objects.equals(value1, value2);
-  }
+  @Override
+  protected boolean valueEquals(Set<DayOfWeek> value1, Set<DayOfWeek> value2) {
+    return Objects.equals(value1, value2);
+  }
♻️ Duplicate comments (4)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (4)

159-187: Prevent false positives: use two-pass measurement so overflow button is only reserved when needed

Always reserving the overflow trigger width can cause an unnecessary overflow entry when all buttons would otherwise fit.

Apply:

-    private _updateOnOverflow() {
-        const containerWidth = this.getBoundingClientRect().width;
-        let usedWidth = 0;
-        const overflowButtons: Node[] = [];
-        const overflowButtonWidth = this._getOverflowButtonWidth();
-
-        for (const button of this._daysOfWeek) {
-            button.style.display = '';
-            const width = button.getBoundingClientRect().width;
-
-            if (usedWidth + width > containerWidth - overflowButtonWidth) {
-                const clonedButton = this._cloneButton(button);
-                overflowButtons.push(clonedButton);
-
-                // hide button from slot
-                button.style.display = 'none';
-            } else {
-                usedWidth += width;
-            }
-        }
-
-        // Update context menu items from hidden buttons
-        this._overflowItems = overflowButtons.map(button => ({
-            component: button,
-        }));
-
-        // Update badges visibility
-        this._overflowBadge.toggleAttribute('hidden', this._overflowItems.length < 1);
-    }
+    private _updateOnOverflow() {
+        const containerWidth = this.getBoundingClientRect().width;
+        const allButtons = this._daysOfWeek;
+        // Reset visibility before measuring
+        for (const btn of allButtons) btn.style.display = '';
+        const measure = (reserveOverflow: boolean) => {
+            const overflowWidth = reserveOverflow ? this._getOverflowButtonWidth() : 0;
+            let used = 0;
+            const overflow: HTMLElement[] = [];
+            for (const btn of allButtons) {
+                const w = btn.getBoundingClientRect().width;
+                if (used + w > containerWidth - overflowWidth) {
+                    overflow.push(this._cloneButton(btn));
+                    btn.style.display = 'none';
+                } else {
+                    used += w;
+                }
+            }
+            return overflow;
+        };
+        // First pass: assume no overflow badge
+        let overflowButtons = measure(false);
+        if (overflowButtons.length > 0) {
+            // Second pass: reserve space for the overflow badge
+            for (const btn of allButtons) btn.style.display = '';
+            overflowButtons = measure(true);
+        }
+        this._overflowItems = overflowButtons.map((button) => ({ component: button }));
+        this._overflowBadge.toggleAttribute('hidden', this._overflowItems.length < 1);
+    }

228-231: has-label should only reflect non-empty labels

this.label != null toggles the attribute even for ''. Use a non-empty check.

Apply:

-        if (_changedProperties.has('label')) {
-            this.toggleAttribute('has-label', this.label != null);
-        }
+        if (_changedProperties.has('label')) {
+            const hasLabel = (this.label ?? '').trim().length > 0;
+            this.toggleAttribute('has-label', hasLabel);
+        }

25-25: Type errors: using Node where HTMLElement is required; switch to queryAssignedElements and fix typings

You access element APIs (style, getBoundingClientRect) and pass items to _cloneButton(originalButton: Button), but _daysOfWeek is typed as Node[] from @queryAssignedNodes. This will fail type-checking and risks runtime issues. Prefer @queryAssignedElements and type as HTMLElement[]. Also adjust the import.

Apply:

-import {customElement, property, query, queryAssignedNodes, state} from 'lit/decorators.js';
+import {customElement, property, query, queryAssignedElements, state} from 'lit/decorators.js';
@@
-    @queryAssignedNodes({slot: 'daysOfWeek', flatten: true})
-    _daysOfWeek!: Array<Node>;
+    @queryAssignedElements({slot: 'daysOfWeek'})
+    _daysOfWeek!: Array<HTMLElement>;
@@
-        for (const button of this._daysOfWeek) {
+        for (const button of this._daysOfWeek) {
             button.style.display = '';
             const width = button.getBoundingClientRect().width;

Also applies to: 34-36, 165-168


189-206: Overflow clone click doesn’t update server-side field value; fix typing and invoke host updater

Clicking an overflow clone calls $server.toggleState() on the original button but never calls updateValue() on the host, so the CustomField model value isn’t recomputed server-side. Typings are also too narrow (Node) and rely on an undeclared _originalButton property.

Apply:

-    private _cloneButton(originalButton: Button) {
-        const clonedButton = originalButton.cloneNode(true);
-        clonedButton._originalButton = originalButton;
+    private _cloneButton(originalButton: HTMLElement) {
+        const clonedButton = originalButton.cloneNode(true) as HTMLElement & { _originalButton?: HTMLElement };
+        clonedButton._originalButton = originalButton;
         clonedButton.removeAttribute("slot");
+        clonedButton.removeAttribute("id");
         clonedButton.style.display = '';
         clonedButton.addEventListener('click', ev => {
             // Update server side button component state
-            clonedButton._originalButton.$server.toggleState();
+            (clonedButton._originalButton as any).$server.toggleState();
+            // Ensure the server-side field value is recomputed
+            (this as any).$server.requestValueUpdateFromClient?.();
             if (clonedButton.getAttribute("theme")) {
                 clonedButton.removeAttribute("theme")
             } else {
                 clonedButton.setAttribute("theme", "primary");
             }
             // Notify value change to DayOfWeekSelector component
             this.dispatchEvent(new CustomEvent('change', {bubbles: true}));
         });
         return clonedButton;
     }

Follow-up required in Java host (see inline comment on DayOfWeekSelector.java) to add @ClientCallable requestValueUpdateFromClient().

🧹 Nitpick comments (2)
src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (2)

201-210: Validate i18n lists length to avoid IndexOutOfBounds

Both setters assume 7 entries. Add a precondition check to fail fast with a clear message.

Apply:

   public void setWeekDaysShort(List<String> weekdaysShort) {
     Objects.requireNonNull(weekdaysShort);
+    if (weekdaysShort.size() != 7) {
+      throw new IllegalArgumentException("weekdaysShort must contain 7 items (sun..sat)");
+    }
@@
   public void setWeekDaysTooltip(List<String> weekdaysTooltip) {
     Objects.requireNonNull(weekdaysTooltip);
+    if (weekdaysTooltip.size() != 7) {
+      throw new IllegalArgumentException("weekdaysTooltip must contain 7 items (sun..sat)");
+    }

Also applies to: 217-226


237-247: Simplify reordering logic using rotation on an already-sorted list

Current approach sorts then manual-indexes. You can simplify and reduce allocation by rotating a sorted list view.

Apply:

-    DayOfWeekButton[] buttons = dayButtons.toArray(DayOfWeekButton[]::new);
-    if (buttons[0].dayOfWeek != first) {
-      var sortedButtons = new ArrayList<DayOfWeekButton>();
-      Arrays.sort(buttons, Comparator.comparing(DayOfWeekButton::getDayOfWeek));
-      for (int i = 0; i < buttons.length; i++) {
-        sortedButtons.add(buttons[(i + first.getValue() - 1) % buttons.length]);
-      }
-      setDayButtons(sortedButtons);
-    }
+    var sorted = new ArrayList<>(dayButtons);
+    sorted.sort(Comparator.comparing(DayOfWeekButton::getDayOfWeek));
+    if (!sorted.isEmpty() && sorted.get(0).dayOfWeek != first) {
+      int offset = first.getValue() - 1; // 0..6
+      Collections.rotate(sorted, -offset);
+    }
+    setDayButtons(sorted);

Note: Add import java.util.Collections; if not present.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2ca84ee and c12c9b5.

📒 Files selected for processing (7)
  • pom.xml (1 hunks)
  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (7 hunks)
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css (1 hunks)
  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java (2 hunks)
  • src/test/resources/META-INF/frontend/styles/shared-styles.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
  • src/main/resources/META-INF/frontend/styles/fc-days-of-week-selector-styles.css
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/test/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelectorDemo.java
  • pom.xml
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-18T14:30:50.252Z
Learnt from: flang
PR: FlowingCode/DayOfWeekSelectorAddon#14
File: src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts:195-197
Timestamp: 2025-08-18T14:30:50.252Z
Learning: For Vaadin/LitElement components, when a property like theme can be empty, prefer setting the default value to an empty string (`''`) rather than `null` to avoid rendering "null" in template attribute bindings. This is cleaner than using conditional logic in templates.

Applied to files:

  • src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts
📚 Learning: 2025-08-18T12:15:44.614Z
Learnt from: flang
PR: FlowingCode/DayOfWeekSelectorAddon#14
File: src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java:155-160
Timestamp: 2025-08-18T12:15:44.614Z
Learning: Vaadin's Element API has an overloaded setAttribute(String attribute, boolean value) method that automatically handles boolean-to-attribute conversion: when value is true, it sets the attribute to an empty string (""); when value is false, it removes the attribute entirely via removeAttribute(). This means code like getElement().setAttribute("readonly", readOnly) is correct in Vaadin applications.

Applied to files:

  • src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java
🔇 Additional comments (4)
src/main/resources/META-INF/resources/frontend/src/fc-days-of-week-selector.ts (2)

40-45: Good: theme/label default to empty string to avoid “null” rendering

Using '' defaults prevents leaking literal “null” into the theme attribute. This aligns with the prior learning for Lit/Vaadin components.


139-157: Measuring overflow button width when hidden is handled correctly

Temporarily unhiding to measure actual width avoids magic numbers and adapts to theme/icon changes. Solid approach.

src/main/java/com/flowingcode/vaadin/addons/dayofweekselector/DayOfWeekSelector.java (2)

156-168: Good: correct boolean attribute handling for readonly and per-button state

Using getElement().setAttribute("readonly", readOnly) leverages Vaadin’s boolean overload to add/remove the attribute. Disabling buttons and adding a readOnly class per button is consistent with styling.


249-268: Overflow icon replacement logic looks good

Removing any existing slotted icon before appending the new one prevents accumulation and keeps DOM clean. Nice touch adding a public CssProperties constant for the size variable.

@paodb paodb merged commit d2c32bb into master Aug 19, 2025
3 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Pending release in Flowing Code Addons Aug 19, 2025
@paodb paodb deleted the issue-5 branch August 19, 2025 18:34
@paodb paodb moved this from Pending release to Done in Flowing Code Addons Sep 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

4 participants