Skip to content

POC: Ember Freestyle#1674

Open
SmitGala wants to merge 1 commit intodevelopfrom
PD-2208-Ember-Freestyle
Open

POC: Ember Freestyle#1674
SmitGala wants to merge 1 commit intodevelopfrom
PD-2208-Ember-Freestyle

Conversation

@SmitGala
Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 12, 2026

Walkthrough

This pull request adds comprehensive freestyle documentation and interactive demo infrastructure for a component library (Irene Components). It introduces 70+ new files including demo components, Handlebars templates, routing, styling, and an ember-freestyle integration for showcasing 36 UI components with interactive examples and usage patterns.

Changes

Cohort / File(s) Summary
Accordion Component Demo
app/components/ak-accordion/freestyle-section.hbs
New freestyle section template showcasing multiple accordion variants (secondary, primary, disabled, default open) with icon support and multi-section expansion settings.
Appbar Component Demo
app/components/ak-appbar/freestyle-section.hbs
New freestyle section demonstrating basic appbar configuration with typography and close icon button.
Autocomplete Component Demo
app/components/ak-autocomplete/freestyle-demo.hbs, app/components/ak-autocomplete/freestyle-demo.ts, app/components/ak-autocomplete/freestyle-section.hbs
Interactive demo component with configurable options, search query binding, loading state support, and freestyle section showcasing basic and loading state variants.
Button Component Demo
app/components/ak-button/freestyle-section.hbs
Freestyle section displaying button variants including primary, outlined, neutral, text buttons with disabled, icon, and loading states.
Checkbox Component Demo
app/components/ak-checkbox/freestyle-demo.hbs, app/components/ak-checkbox/freestyle-demo.ts, app/components/ak-checkbox/freestyle-section.hbs
Interactive demo supporting basic, labeled, and indeterminate checkbox patterns with select-all logic and multi-checkbox state management.
Checkbox Tree Component Demo
app/components/ak-checkbox-tree/freestyle-demo.hbs, app/components/ak-checkbox-tree/freestyle-demo.ts, app/components/ak-checkbox-tree/freestyle-section.hbs
Hierarchical tree structure demo with expand/collapse and checkbox selection handlers; includes nested tree data with root and child nodes.
Chip Component Demo
app/components/ak-chip/freestyle-section.hbs
Freestyle section showcasing default, icon-adorned, and deletable chip variants across filled and outlined styles.
Clipboard Component Demo
app/components/ak-clipboard/freestyle-section.hbs
Two clipboard usage patterns: static text copy and target-based input field copying.
Date Picker Component Demo
app/components/ak-date-picker/freestyle-demo.hbs, app/components/ak-date-picker/freestyle-demo.ts, app/components/ak-date-picker/freestyle-section.hbs
Interactive date picker with selection state tracking, quick-select options (clear), and conditional success messaging.
Divider Component Demo
app/components/ak-divider/freestyle-section.hbs
Horizontal and vertical divider usage examples with list items and typography integration.
Drawer Component Demo
app/components/ak-drawer/freestyle-demo.hbs, app/components/ak-drawer/freestyle-demo.ts, app/components/ak-drawer/freestyle-section.hbs
Left-anchored drawer with open/close state management and button-triggered interactions; tracked boolean for visibility control.
Icon Button Component Demo
app/components/ak-icon-button/freestyle-section.hbs
Multiple icon button variants with sizes, colors (success, error), outlined styling, and disabled states.
Icon Component Demo
app/components/ak-icon/freestyle-section.hbs
Simple icon usage example with delete icon and primary color in medium size.
Link Component Demo
app/components/ak-link/freestyle-section.hbs
Link variants including color options (textPrimary, textSecondary, primary, secondary), underline behaviors, icon placement, and disabled states.
List Component Demo
app/components/ak-list/freestyle-demo.hbs, app/components/ak-list/freestyle-demo.ts, app/components/ak-list/freestyle-section.hbs
Data-driven list rendering with icon and label support; three variants demonstrating default, button, and link behaviors with configurable props.
Loader Component Demo
app/components/ak-loader/freestyle-section.hbs
Circular and linear loader variants with determinate/indeterminate states, progress indicators, labels, and configurable sizing/thickness.
Menu Component Demo
app/components/ak-menu/freestyle-demo.hbs, app/components/ak-menu/freestyle-demo.ts, app/components/ak-menu/freestyle-section.hbs
Context menu implementation with anchor reference tracking, data-driven menu items (labels, icons, dividers), and open/close handlers.
Modal Component Demo
app/components/ak-modal/freestyle-demo.hbs, app/components/ak-modal/freestyle-demo.ts, app/components/ak-modal/freestyle-section.hbs
Modal dialog with controlled visibility, header, content area, overlay click handling, and dual action buttons (OK/Cancel).
Pagination Component Demo
app/components/ak-pagination/freestyle-demo.hbs, app/components/ak-pagination/freestyle-demo.ts, app/components/ak-pagination/freestyle-section.hbs
Pagination with provider setup, item-per-page controls, offset/limit state tracking, and result slice calculation; 50-item dataset demo.
Popover Component Demo
app/components/ak-popover/freestyle-demo.hbs, app/components/ak-popover/freestyle-demo.ts, app/components/ak-popover/freestyle-section.hbs
Popover anchored to element with backdrop, auto-placement, close handlers, and styled content container.
Radio Component Demo
app/components/ak-radio/freestyle-section.hbs
Radio group with form control labels demonstrating basic radio pair selection pattern.
Select Component Demo
app/components/ak-select/freestyle-demo.hbs, app/components/ak-select/freestyle-demo.ts, app/components/ak-select/freestyle-section.hbs
Single and multiple selection modes with options rendering, state normalization, and change handlers; includes placeholder and helper text support.
Skeleton Component Demo
app/components/ak-skeleton/freestyle-section.hbs
Skeleton loaders with circular, rectangular, and rounded variants in different dimensions.
Stack Component Demo
app/components/ak-stack/freestyle-section.hbs
Horizontal stack with spacing, alignment, justification, and styled items demonstration.
Table Component Demo
app/components/ak-table/freestyle-demo.hbs, app/components/ak-table/freestyle-demo.ts, app/components/ak-table/freestyle-section.hbs
Data table with columns/rows binding, header/body rendering, density control, and border variants (default and full-bordered).
Tabs Component Demo
app/components/ak-tabs/freestyle-demo.hbs, app/components/ak-tabs/freestyle-demo.ts, app/components/ak-tabs/freestyle-section.hbs
Tab navigation with active state tracking, badge support, button variants, indicator styling, and icon rendering per tab item.
Text Field Component Demo
app/components/ak-text-field/freestyle-section.hbs
Text input variants with labels, placeholders, helper text, error states, disabled/readonly modes, password type, and left/right adornments.
Toggle Component Demo
app/components/ak-toggle/freestyle-demo.hbs, app/components/ak-toggle/freestyle-demo.ts, app/components/ak-toggle/freestyle-section.hbs
Toggle with three variants: basic, label-wrapped, and size demonstrations (small/medium/large) with independent state tracking.
Tooltip Component Demo
app/components/ak-tooltip/freestyle-section.hbs
Tooltip placements (left, top, bottom, right), delay settings, and dark color with arrow configuration.
Tree Component Demo
app/components/ak-tree/freestyle-demo.hbs, app/components/ak-tree/freestyle-demo.ts, app/components/ak-tree/freestyle-section.hbs
Hierarchical tree with expand/collapse support, depth-based padding calculation, and nested node rendering with icons.
Typography Component Demo
app/components/ak-typography/freestyle-section.hbs
Typography variants (h1–h6, subtitle1/2, body1/2/3) with spacing, color, truncation, and wrapping demonstrations.
Freestyle Infrastructure
app/components/freestyle-component-renderer.hbs, app/components/freestyle-component-renderer.ts, app/components/freestyle-section.hbs, app/components/freestyle-section.ts, app/components/freestyle-usage.hbs, app/components/freestyle-usage.ts, app/components/freestyle-nav.hbs, app/components/freestyle-nav.ts
Core freestyle documentation system with component routing, section/usage wrappers (overriding addon defaults), and navigation list of 36 components.
Freestyle Routes & Controllers
app/routes/freestyle.ts, app/routes/freestyle/component.ts, app/routes/freestyle/index.ts, app/controllers/freestyle/component.ts, app/controllers/freestyle/index.ts, app/router.ts
Nested route structure supporting dynamic component ID routing, fallback handling (defaults to 'ak-accordion'), and service integration for ember-freestyle configuration.
Freestyle Templates
app/templates/freestyle.hbs, app/templates/freestyle/component.hbs, app/templates/freestyle/index.hbs
Layout templates with sidebar navigation and outlet for dynamic component section rendering.
Styling & Dependencies
app/styles/_freestyle.scss, app/styles/app.scss, package.json
New stylesheet defining two-column layout with sticky 260px sidebar, main content area, navigation styling, and section typography; adds ember-freestyle devDependency with override for @ember/string version.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A warren of components, now on display,
Each dressed in its freestyle in every which way!
From accordion folds to tabs that click clear,
Our interactive gallery brings structure so dear.
With routes and with routing and routes in between,
The finest freestyle docs you ever have seen! 🎭

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author, making it impossible to assess whether the description is related to the changeset. Add a pull request description explaining the purpose of introducing Ember Freestyle, the components being documented, and any relevant setup or configuration details.
Title check ❓ Inconclusive The title 'POC: Ember Freestyle' is vague and generic, using 'POC' (Proof of Concept) without clearly conveying what this changeset accomplishes beyond introducing a concept. Consider a more descriptive title such as 'Add Ember Freestyle component library documentation' or 'Introduce Ember Freestyle integration for component showcase'.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch PD-2208-Ember-Freestyle

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Stylelint (17.4.0)
app/styles/_freestyle.scss

AllFilesIgnoredError: All input files were ignored because of the ignore pattern. Either change your input, ignore pattern or use "--allow-empty-input" to allow no inputs
at standalone (file:///usr/local/lib/node_modules/stylelint/lib/standalone.mjs:289:43)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)

app/styles/app.scss

AllFilesIgnoredError: All input files were ignored because of the ignore pattern. Either change your input, ignore pattern or use "--allow-empty-input" to allow no inputs
at standalone (file:///usr/local/lib/node_modules/stylelint/lib/standalone.mjs:289:43)
at process.processTicksAndRejections (node:internal/process/task_queues:105: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

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying irenestaging with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6a9f981
Status: ✅  Deploy successful!
Preview URL: https://089ad83a.irenestaging.pages.dev
Branch Preview URL: https://pd-2208-ember-freestyle.irenestaging.pages.dev

View logs

@cypress
Copy link
Copy Markdown

cypress bot commented Mar 12, 2026

Irene    Run #815

Run Properties:  status check failed Failed #815  •  git commit 1716990d05 ℹ️: Merge 6a9f981cd5014c406b3667051548a226df609582 into 17b412c8b9a13fef9f52528f9a0c...
Project Irene
Branch Review PD-2208-Ember-Freestyle
Run status status check failed Failed #815
Run duration 04m 10s
Commit git commit 1716990d05 ℹ️: Merge 6a9f981cd5014c406b3667051548a226df609582 into 17b412c8b9a13fef9f52528f9a0c...
Committer SmitGala
View all properties for this run ↗︎

Test results
Tests that failed  Failures 1
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 1
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 30
View all changes introduced in this branch ↗︎

Tests for review

Failed  cypress/tests/dynamic-scan.spec.ts • 1 failed test

View Output

Test Artifacts
Dynamic Scan > it tests dynamic scan for an apk file: 132571 Test Replay Screenshots

Copy link
Copy Markdown

@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: 15

🧹 Nitpick comments (16)
app/components/ak-list/freestyle-demo.hbs (1)

5-11: Consider forwarding @noGutters from args instead of hardcoding.

Line 8 hardcodes @noGutters={{false}}, but based on the component signature described in the summary, this should likely be @noGutters={{@noGutters}} to allow the freestyle section to demonstrate different gutter configurations.

💡 Suggested fix
         <akl.listItem
           `@button`={{`@button`}}
           `@link`={{`@link`}}
-          `@noGutters`={{false}}
+          `@noGutters`={{`@noGutters`}}
           `@disabled`={{`@disabled`}}
           `@selected`={{`@selected`}}
           as |li|
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-list/freestyle-demo.hbs` around lines 5 - 11, The template
hardcodes `@noGutters`={{false}} on the akl.listItem invocation; change it to
forward the incoming arg by replacing the hardcoded value with
`@noGutters`={{`@noGutters`}} so the freestyle-demo can demonstrate different gutter
configurations—update the akl.listItem invocation in the freestyle-demo.hbs to
use the `@noGutters` arg passed into the component.
app/components/ak-tree/freestyle-demo.ts (2)

10-18: Potentially confusing expanded: true in static data.

The expanded: true property on Child1.1 in TREE_DATA may be misleading since the component manages expansion state via the @tracked expanded array (initialized to ['Root1', 'Root2']), not through this property. Consider removing it if it's not used by AkTree, or add a comment clarifying its purpose.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-tree/freestyle-demo.ts` around lines 10 - 18, The TREE_DATA
entry for the node with key 'Child1.1' currently includes expanded: true which
conflicts with or misleads about the component-controlled expansion state held
in the `@tracked` expanded array (initialized to ['Root1', 'Root2']); either
remove the expanded property from the static TREE_DATA node or add a brief
comment next to the 'Child1.1' node explaining it is unused by AkTree and kept
only for illustrative/legacy purposes so readers aren’t confused by the
component’s actual expansion source.

37-39: Consider documenting the magic number in calculatePadding.

The multiplier 0.9286 appears to be a specific design constant. A brief comment explaining the rationale (e.g., alignment with a design system's spacing scale) would improve maintainability.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-tree/freestyle-demo.ts` around lines 37 - 39, Document the
magic multiplier used in calculatePadding: add a short explanatory comment above
calculatePadding (or extract 0.9286 into a well-named constant like
PADDING_SCALE) that explains why 0.9286 is used (e.g., alignment with the design
system's spacing scale or conversion from pixel values), reference the
calculatePadding(treeDepth: number) function and ensure the comment mentions the
expected units (em) and any source or formula for the value so future
maintainers understand and can update it safely.
app/routes/freestyle/component.ts (1)

38-40: Prefer a canonical redirect for unknown component IDs.

Line 40 silently maps any invalid slug to 'ak-accordion', so /freestyle/not-a-real-component will render accordion content under a bogus URL. Redirect to the default component route, or show a not-found state instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/routes/freestyle/component.ts` around lines 38 - 40, The model function
currently silently maps invalid slugs to 'ak-accordion'; update model(params: {
component_id?: string }) to detect when params.component_id is not in
VALID_COMPONENTS and then perform a canonical redirect to the default route
(e.g. redirect to '/freestyle/ak-accordion') or return a proper not-found
response (e.g. throw a 404 Response) instead of returning 'ak-accordion'. Use
the same VALID_COMPONENTS check to decide and invoke your framework's
redirect/response mechanism from within model rather than silently substituting
the id.
app/components/freestyle-section.ts (1)

3-6: Consider adding override keyword to show getter.

For consistency with TypeScript best practices and to explicitly signal the intention to override a base class member, consider adding the override keyword.

♻️ Suggested change
 export default class FreestyleSection extends FreestyleSectionAddon {
-  get show(): boolean {
+  override get show(): boolean {
     return true;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/freestyle-section.ts` around lines 3 - 6, The show getter in
class FreestyleSection is intended to override the base class member from
FreestyleSectionAddon; add the TypeScript override modifier to the getter (i.e.,
declare `override get show(): boolean`) in the FreestyleSection class to make
the override explicit and consistent with TS best practices.
app/styles/_freestyle.scss (1)

1-8: Note: Using !important to override third-party styles.

The !important declarations are acceptable here for overriding ember-freestyle's built-in header elements. Consider adding a brief comment clarifying this is intentional to prevent future developers from thinking it's a code smell.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/styles/_freestyle.scss` around lines 1 - 8, Add a short explanatory
comment above the rules indicating the use of !important is intentional to
override ember-freestyle defaults, so future maintainers won't remove it;
reference the selector block (.FreestyleGuide-header, .FreestyleGuide-cta,
.FreestyleGuide-nav, .FreestyleGuide-aside) and state that we hide the built-in
header/sidebar in favor of our own sidebar and therefore need the !important
overrides.
app/components/freestyle-usage.ts (1)

3-6: Consider adding override keyword to show getter for consistency.

The hasCode getter uses the override keyword, but show does not. For consistency and to make the intent explicit, consider adding it.

♻️ Suggested change
 export default class FreestyleUsage extends FreestyleUsageAddon {
-  get show(): boolean {
+  override get show(): boolean {
     return true;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/freestyle-usage.ts` around lines 3 - 6, The show getter in
class FreestyleUsage lacks the override keyword while other inherited getters
(e.g., hasCode) use it; update the show getter in FreestyleUsage to include the
override modifier (i.e., change the declaration of the show getter in
FreestyleUsage to explicitly use override) so the intent is clear and consistent
with hasCode.
app/components/freestyle-nav.ts (1)

3-35: Consider adding TypeScript typing for better type safety.

The component entries would benefit from explicit typing for improved developer experience and type safety.

♻️ Proposed type definition
 import Component from '@glimmer/component';
 
+interface ComponentNavItem {
+  id: string;
+  label: string;
+}
+
-const COMPONENTS = [
+const COMPONENTS: readonly ComponentNavItem[] = [
   { id: 'ak-accordion', label: 'Accordion' },
   // ... rest of entries
-];
+] as const;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/freestyle-nav.ts` around lines 3 - 35, The COMPONENTS array
lacks explicit TypeScript types; define a small interface or type (e.g.,
ComponentItem with id: string and label: string) and annotate COMPONENTS as
ComponentItem[] (or readonly ComponentItem[] if immutable) so each entry (the
objects in COMPONENTS) is type-checked; update any exports/usages of COMPONENTS
to use the new type for better autocomplete and compile-time safety.
app/components/ak-tabs/freestyle-demo.hbs (1)

16-16: Avoid using !important in inline styles.

Using !important in inline styles is generally a code smell and can make styles difficult to override. Consider addressing the underlying specificity issue in the component's CSS instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-tabs/freestyle-demo.hbs` at line 16, The inline style on
AkIcon using "!important" should be removed; instead, create a CSS rule (e.g.,
.ak-icon--large or a contextual selector in the freestyle-demo component
stylesheet) that sets font-size: 1.29rem with appropriate specificity, then
replace the inline {{style ...}} usage in the template by adding that class to
the AkIcon invocation (AkIcon `@iconName`={{item.iconName}} class="ak-icon--large"
or the equivalent class-binding in the template) so styling is controlled via
stylesheet rather than an inline !important.
app/components/ak-chip/freestyle-section.hbs (1)

22-27: Consider clarifying the "Deletable" terminology.

The section is labeled "Deletable" but uses @button={{true}} which makes the chip clickable, not specifically deletable. If the intent is to demonstrate delete functionality, consider adding an @onDelete handler or renaming this section to "Clickable" or "Button Chips" to avoid confusion for developers using this documentation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-chip/freestyle-section.hbs` around lines 22 - 27, The
"Deletable" demo uses AkChip with `@button`={{true}} which only makes chips
clickable, causing mismatch with the title; either rename the FreestyleUsage
title from 'Deletable' to 'Clickable' or 'Button Chips', or update the AkChip
examples to demonstrate actual delete behavior by adding an `@onDelete` handler to
each <AkChip> (and optionally keep `@button` if both behaviours are supported) so
the section label matches the implemented interactivity; look for the
FreestyleUsage block and AkChip components in this snippet to apply the change.
app/components/freestyle-component-renderer.hbs (1)

1-66: Move the component registry out of the template.

This else if ladder requires manual synchronization: every new showcase must be added to both the template branches and the filesystem. A registry-based approach using a lightweight TypeScript map and dynamic component lookup would eliminate this source of drift and make extensions less error-prone.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/freestyle-component-renderer.hbs` around lines 1 - 66, The
template's long else-if ladder (checking `@componentId` and rendering
AkX::FreestyleSection) should be replaced by a TS registry and dynamic lookup:
create a lightweight module (e.g., freestyle-component-registry.ts) that exports
a map from componentId strings (like "ak-accordion") to the corresponding
component reference/name (the same values currently used in the template, e.g.,
"AkAccordion::FreestyleSection"); update the component backing class for this
template (FreestyleComponentRenderer) to import that registry and expose a
computed/derived property (e.g., selectedComponent) that returns
registry[this.args.componentId] or null; then simplify the HBS to render
dynamically via the component helper (e.g., {{`#if`
this.selectedComponent}}{{component this.selectedComponent}}{{else}}<p
class='text-secondary'>Component not found: {{`@componentId`}}</p>{{/if}}). This
moves the registry out of freestyle-component-renderer.hbs into a single source
of truth and uses `@componentId`, FreestyleComponentRenderer, selectedComponent,
and the component helper for the dynamic lookup.
app/components/ak-icon-button/freestyle-section.hbs (1)

5-8: Omit the @color argument instead of passing an empty string.

@color='' relies on treating empty string as falsy to default to inherit. Omitting the argument is clearer, safer, and aligns with the type definition which doesn't include empty string as a valid AkIconColorVariant value.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-icon-button/freestyle-section.hbs` around lines 5 - 8, The
AkIcon components are passing `@color`='' which relies on an empty string as
falsy; remove the `@color`='' attribute from the AkIcon tags (e.g., the AkIcon
instances nested in AkIconButton with `@iconName`='close' and `@iconName`='refresh')
so the prop is omitted and the component falls back to the intended default
(inherit) that matches the AkIconColorVariant type.
app/components/ak-pagination/freestyle-demo.ts (1)

16-32: Collapse the repeated pagination updates into one helper.

These three actions currently duplicate the same state transition. Pulling the assignments into one helper keeps future pagination changes from diverging.

♻️ Proposed fix
+type PaginationArgs = { limit: number; offset: number };
+
 export default class AkPaginationFreestyleDemoComponent extends Component {
   totalPaginationData = TOTAL_DATA;
   `@tracked` limit = 5;
   `@tracked` offset = 0;
 
   get tableData() {
     return this.totalPaginationData.slice(this.offset, this.limit + this.offset);
   }
 
+  private updatePagination({ limit, offset }: PaginationArgs) {
+    this.limit = limit;
+    this.offset = offset;
+  }
+
   `@action`
-  onItemPerPageChange(args: { limit: number; offset: number }) {
-    this.limit = args.limit;
-    this.offset = args.offset;
+  onItemPerPageChange(args: PaginationArgs) {
+    this.updatePagination(args);
   }
 
   `@action`
-  nextAction(args: { limit: number; offset: number }) {
-    this.limit = args.limit;
-    this.offset = args.offset;
+  nextAction(args: PaginationArgs) {
+    this.updatePagination(args);
   }
 
   `@action`
-  prevAction(args: { limit: number; offset: number }) {
-    this.limit = args.limit;
-    this.offset = args.offset;
+  prevAction(args: PaginationArgs) {
+    this.updatePagination(args);
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-pagination/freestyle-demo.ts` around lines 16 - 32, The
three actions onItemPerPageChange, nextAction, and prevAction duplicate setting
this.limit and this.offset; extract a single helper method (e.g.,
updatePagination or setPagination) that accepts { limit, offset } and performs
the assignments, then have each action call that helper instead of repeating the
two assignments so future pagination logic is centralized.
app/components/ak-select/freestyle-demo.ts (1)

13-13: Drop the no-op non-null assertion.

SELECT_ITEMS[0]! is already typed as SelectItem here, so ! does not narrow anything and just adds noise.

♻️ Proposed fix
-const DEFAULT_ITEM: SelectItem = SELECT_ITEMS[0]!;
+const DEFAULT_ITEM: SelectItem = SELECT_ITEMS[0];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-select/freestyle-demo.ts` at line 13, DEFAULT_ITEM is
initialized with SELECT_ITEMS[0]! using a no-op non-null assertion; remove the
trailing "!" so the initializer reads SELECT_ITEMS[0] and let the declared type
SelectItem handle typing. Update the declaration of DEFAULT_ITEM (symbol
DEFAULT_ITEM) to use SELECT_ITEMS[0] without "!" to eliminate the unnecessary
assertion.
app/components/ak-pagination/freestyle-demo.hbs (1)

5-5: Derive @totalItems from the backing dataset.

@totalItems={{50}} is a second source of truth for the demo count. If TOTAL_DATA changes, the pagination footer and navigation state will drift from the actual dataset.

♻️ Proposed fix
-    `@totalItems`={{50}}
+    `@totalItems`={{this.totalPaginationData.length}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-pagination/freestyle-demo.hbs` at line 5, The template
currently hardcodes `@totalItems`={{50}} which diverges from the actual dataset;
remove the literal and derive totalItems from the backing dataset (TOTAL_DATA)
instead — either pass TOTAL_DATA.length directly into the template (e.g.
`@totalItems`={{TOTAL_DATA.length}}) or compute a getter/property (e.g.
totalItems) in the freestyle-demo component/controller that returns
TOTAL_DATA.length and reference that property in the template (replace
`@totalItems` with `@totalItems`={{this.totalItems}}); ensure any code that uses
`@totalItems` (pagination component) continues to receive the dynamic value.
app/components/ak-toggle/freestyle-demo.ts (1)

28-32: Avoid mapping unknown sizes to large.

Line 32's fallback else mutates checkedLarge for any unexpected runtime value, which can mask a bad template arg and show the wrong demo state. Make the 'large' branch explicit and ignore or assert on unknown input instead.

Proposed refactor
   `@action`
   handleSizeChange(size: 'small' | 'medium' | 'large', _event: Event, checked: boolean) {
-    if (size === 'small') this.checkedSmall = checked;
-    else if (size === 'medium') this.checkedMedium = checked;
-    else this.checkedLarge = checked;
+    if (size === 'small') {
+      this.checkedSmall = checked;
+    } else if (size === 'medium') {
+      this.checkedMedium = checked;
+    } else if (size === 'large') {
+      this.checkedLarge = checked;
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-toggle/freestyle-demo.ts` around lines 28 - 32, The handler
handleSizeChange currently treats any non-'small'/'medium' value as 'large',
which can mask bad inputs; update handleSizeChange to explicitly check for size
=== 'large' and set checkedLarge only in that branch, and for any other
unexpected size either ignore the call (no state change) or throw/assert (e.g.
throw new Error or console.warn) so invalid values are not silently mapped to
checkedLarge; reference the properties checkedSmall, checkedMedium, and
checkedLarge when implementing the explicit branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/components/ak-appbar/freestyle-section.hbs`:
- Around line 15-18: The trailing icon-only button (AkIconButton in
freestyle-section.hbs) lacks an accessible name; add an aria-label (e.g.,
aria-label="Close") to the AkIconButton element so screen readers announce the
action—ensure the attribute is set on the AkIconButton component (not just
AkIcon) to provide the accessible name.

In `@app/components/ak-checkbox/freestyle-demo.hbs`:
- Around line 26-32: The standalone AkCheckbox in the demo lacks an accessible
name; update the freestyle variant so the checkbox is either wrapped with
AkFormControlLabel (use AkFormControlLabel around the AkCheckbox and supply a
visible label string) or supply an explicit accessible name prop (e.g.,
ariaLabel or label prop passed down) to AkCheckbox; modify the template where
AkCheckbox is rendered (the instance using `@checked`={{this.checked}}
`@indeterminate`={{this.indeterminate}} `@onChange`={{this.handleChange}}) to
include the chosen accessibility fix.

In `@app/components/ak-clipboard/freestyle-section.hbs`:
- Around line 12-15: The hard-coded id 'copy-input' on AkTextField and the
data-clipboard-target:'#copy-input' can produce duplicate DOM IDs; change to a
generated/dynamic id (e.g., create a local uniqueId variable or use an
Ember/utility helper) and use that id for both the AkTextField id and the
AkButton data-clipboard-target (prefixing with '#'), keeping the existing usage
of {{cb.triggerId}} for the button id; update the template to bind the generated
id instead of the literal 'copy-input' so each render instance gets a unique
selector.

In `@app/components/ak-drawer/freestyle-demo.hbs`:
- Line 9: The template uses the {{style}} modifier (in the div with class 'p-4')
which requires the ember-style-modifier addon that isn’t installed; either add
the addon (install ember-style-modifier and add it to package.json) so {{style}}
works across templates, or replace the modifier usage with a plain static style
attribute (e.g., style="width:250px") in the freestyle-demo.hbs and the other
templates (loading.hbs, payment-failure.hbs, etc.) that use {{style}}.

In `@app/components/ak-icon-button/freestyle-section.hbs`:
- Around line 2-36: Several AkIconButton usages render icon-only buttons without
accessible names; update each icon-only example (instances of AkIconButton with
child AkIcon in freestyle-section.hbs) to include an aria-label describing the
action (e.g., "close", "refresh", "delete", "done") so screen readers announce
the purpose; ensure every AkIconButton that has no visible text gets an
appropriate aria-label attribute matching the icon action.

In `@app/components/ak-list/freestyle-demo.ts`:
- Around line 11-18: The Args type in the AkListFreestyleDemoSignature is
missing the optional noGutters property which the template passes; update the
AkListFreestyleDemoSignature interface so its Args includes noGutters?: boolean
to match the template usage (ensure the property is optional and typed boolean)
so Glint template type-checking succeeds.

In `@app/components/ak-menu/freestyle-demo.hbs`:
- Around line 3-5: The icon-only menu trigger lacks an accessible name; update
the AkIconButton used in freestyle-demo.hbs (the element that calls
handleMoreClick) to include an accessible label by adding an aria-label (or
aria-labelledby) and appropriate ARIA state such as aria-haspopup="true" and
aria-expanded bound to the menu open state; ensure the label text clearly
describes the button (e.g., "Open menu") and keep references to AkIconButton and
handleMoreClick when making the change.

In `@app/components/ak-popover/freestyle-section.hbs`:
- Around line 2-4: The example's icon-only trigger lacks an accessible name;
update the FreestyleUsage `@source` so the AkIconButton used as the trigger
provides an explicit aria-label (e.g., "More options") or uses the component's
accepted aria prop so the icon button has an accessible name, keeping the
existing {{on "click" this.handleMoreClick}} handler and AkIcon/AkIconButton
usage intact.

In `@app/components/ak-skeleton/freestyle-section.hbs`:
- Around line 6-8: The AkSkeleton usages in freestyle-section.hbs pass
`@height`='' which can cause unexpected collapse; remove the `@height` attribute on
the three AkSkeleton instances when you want the default height or replace
`@height`='' with an explicit value (e.g., '20px' or another intended height) for
the rectangular/rounded variants so they render predictably; update the three
AkSkeleton tags (the ones with `@width`='250px' and `@tag`='span' and variants
'rectangular'/'rounded') accordingly.

In `@app/components/ak-text-field/freestyle-section.hbs`:
- Around line 9-18: Update the demo copy in the AkTextField examples: change the
helper text strings passed via `@helperText` from "I am an helper text" / "I am an
helper text in error state" to "I am a helper text" / "I am a helper text in
error state", update the label values that currently read "Helper Text" and
"Readonly" to use consistent casing and wording like "Helper text" and "Read
only", and adjust any `@readonly` attribute labels (e.g., "Readonly with value")
to "Read only" phrasing so all visible showcase strings are polished and
consistent.

In `@app/components/ak-toggle/freestyle-demo.hbs`:
- Around line 1-40: The demo hardcodes `@disabled` and `@readonly` as false for
AkToggle and AkFormControlLabel, ignoring incoming args; change every occurrence
to forward the incoming args instead (e.g. replace `@disabled`={{false}} and
`@readonly`={{false}} with `@disabled`={{`@disabled`}} and `@readonly`={{`@readonly`}}),
and ensure the AkFormControlLabel also receives `@disabled`={{`@disabled`}} so
fcl.disabled reflects the passed-in disabled state; keep existing bindings like
`@onChange` (this.handleChange / this.handleSizeChange / this.handleLabelChange)
unchanged.

In `@app/router.ts`:
- Around line 12-14: The freestyle route (this.route('freestyle', ...) /
this.route('component', { path: '/:component_id' })) is currently public; move
it into the existing authenticated route block or gate its registration by
environment. Fix by either relocating the this.route('freestyle', ...)
declaration inside the authenticated route callback (e.g., inside
this.route('authenticated', function() { ... })), or wrap the freestyle route
registration with an environment check (e.g., if (process.env.NODE_ENV !==
'production') { /* register freestyle route */ }) so it only registers in
dev/staging.

In `@app/routes/freestyle.ts`:
- Around line 8-15: The route currently mutates the singleton service directly
and hard-codes values; update activate() to save the existing
emberFreestyle.showCode and emberFreestyle.showLabels into route instance
properties (e.g. this._prevShowCode, this._prevShowLabels), then set both flags
to true; update deactivate() to restore both flags from those saved properties
(this.emberFreestyle.showCode = this._prevShowCode;
this.emberFreestyle.showLabels = this._prevShowLabels) and clear the saved
properties to avoid leaks. Ensure you reference the existing methods activate
and deactivate and the emberFreestyle service properties showCode and
showLabels.

In `@app/styles/_freestyle.scss`:
- Around line 93-97: The .&--active rule uses text color `#1976d2` on background
`#e3f2fd` which fails WCAG AA; update the color in the &--active selector to a
darker blue that achieves a contrast ratio ≥ 4.5 (for example swap `#1976d2` for a
darker shade such as `#0d47a1` or update the relevant variable), and if your
codebase uses a color variable (e.g., a $primary-... or --color-... token)
update that token instead so all references remain consistent; confirm the final
contrast ratio meets WCAG AA for normal text.

In `@app/templates/freestyle/index.hbs`:
- Around line 1-5: The template is bound to the wrong route because it
references this.model (used by the component route) but lives in
freestyle/index.hbs; move or rename this template so it becomes
freestyle/component.hbs (so the route will provide the component_id model), or
alternatively update the route/controller wiring to expose the expected model to
the index route; specifically ensure the {{component (concat (or this.model
'ak-accordion') '/freestyle-section')}} usage inside the FreestyleGuide receives
the route model from the component route (or change the template to read the
correct property exposed by the index route) so component rendering works as
intended.

---

Nitpick comments:
In `@app/components/ak-chip/freestyle-section.hbs`:
- Around line 22-27: The "Deletable" demo uses AkChip with `@button`={{true}}
which only makes chips clickable, causing mismatch with the title; either rename
the FreestyleUsage title from 'Deletable' to 'Clickable' or 'Button Chips', or
update the AkChip examples to demonstrate actual delete behavior by adding an
`@onDelete` handler to each <AkChip> (and optionally keep `@button` if both
behaviours are supported) so the section label matches the implemented
interactivity; look for the FreestyleUsage block and AkChip components in this
snippet to apply the change.

In `@app/components/ak-icon-button/freestyle-section.hbs`:
- Around line 5-8: The AkIcon components are passing `@color`='' which relies on
an empty string as falsy; remove the `@color`='' attribute from the AkIcon tags
(e.g., the AkIcon instances nested in AkIconButton with `@iconName`='close' and
`@iconName`='refresh') so the prop is omitted and the component falls back to the
intended default (inherit) that matches the AkIconColorVariant type.

In `@app/components/ak-list/freestyle-demo.hbs`:
- Around line 5-11: The template hardcodes `@noGutters`={{false}} on the
akl.listItem invocation; change it to forward the incoming arg by replacing the
hardcoded value with `@noGutters`={{`@noGutters`}} so the freestyle-demo can
demonstrate different gutter configurations—update the akl.listItem invocation
in the freestyle-demo.hbs to use the `@noGutters` arg passed into the component.

In `@app/components/ak-pagination/freestyle-demo.hbs`:
- Line 5: The template currently hardcodes `@totalItems`={{50}} which diverges
from the actual dataset; remove the literal and derive totalItems from the
backing dataset (TOTAL_DATA) instead — either pass TOTAL_DATA.length directly
into the template (e.g. `@totalItems`={{TOTAL_DATA.length}}) or compute a
getter/property (e.g. totalItems) in the freestyle-demo component/controller
that returns TOTAL_DATA.length and reference that property in the template
(replace `@totalItems` with `@totalItems`={{this.totalItems}}); ensure any code that
uses `@totalItems` (pagination component) continues to receive the dynamic value.

In `@app/components/ak-pagination/freestyle-demo.ts`:
- Around line 16-32: The three actions onItemPerPageChange, nextAction, and
prevAction duplicate setting this.limit and this.offset; extract a single helper
method (e.g., updatePagination or setPagination) that accepts { limit, offset }
and performs the assignments, then have each action call that helper instead of
repeating the two assignments so future pagination logic is centralized.

In `@app/components/ak-select/freestyle-demo.ts`:
- Line 13: DEFAULT_ITEM is initialized with SELECT_ITEMS[0]! using a no-op
non-null assertion; remove the trailing "!" so the initializer reads
SELECT_ITEMS[0] and let the declared type SelectItem handle typing. Update the
declaration of DEFAULT_ITEM (symbol DEFAULT_ITEM) to use SELECT_ITEMS[0] without
"!" to eliminate the unnecessary assertion.

In `@app/components/ak-tabs/freestyle-demo.hbs`:
- Line 16: The inline style on AkIcon using "!important" should be removed;
instead, create a CSS rule (e.g., .ak-icon--large or a contextual selector in
the freestyle-demo component stylesheet) that sets font-size: 1.29rem with
appropriate specificity, then replace the inline {{style ...}} usage in the
template by adding that class to the AkIcon invocation (AkIcon
`@iconName`={{item.iconName}} class="ak-icon--large" or the equivalent
class-binding in the template) so styling is controlled via stylesheet rather
than an inline !important.

In `@app/components/ak-toggle/freestyle-demo.ts`:
- Around line 28-32: The handler handleSizeChange currently treats any
non-'small'/'medium' value as 'large', which can mask bad inputs; update
handleSizeChange to explicitly check for size === 'large' and set checkedLarge
only in that branch, and for any other unexpected size either ignore the call
(no state change) or throw/assert (e.g. throw new Error or console.warn) so
invalid values are not silently mapped to checkedLarge; reference the properties
checkedSmall, checkedMedium, and checkedLarge when implementing the explicit
branches.

In `@app/components/ak-tree/freestyle-demo.ts`:
- Around line 10-18: The TREE_DATA entry for the node with key 'Child1.1'
currently includes expanded: true which conflicts with or misleads about the
component-controlled expansion state held in the `@tracked` expanded array
(initialized to ['Root1', 'Root2']); either remove the expanded property from
the static TREE_DATA node or add a brief comment next to the 'Child1.1' node
explaining it is unused by AkTree and kept only for illustrative/legacy purposes
so readers aren’t confused by the component’s actual expansion source.
- Around line 37-39: Document the magic multiplier used in calculatePadding: add
a short explanatory comment above calculatePadding (or extract 0.9286 into a
well-named constant like PADDING_SCALE) that explains why 0.9286 is used (e.g.,
alignment with the design system's spacing scale or conversion from pixel
values), reference the calculatePadding(treeDepth: number) function and ensure
the comment mentions the expected units (em) and any source or formula for the
value so future maintainers understand and can update it safely.

In `@app/components/freestyle-component-renderer.hbs`:
- Around line 1-66: The template's long else-if ladder (checking `@componentId`
and rendering AkX::FreestyleSection) should be replaced by a TS registry and
dynamic lookup: create a lightweight module (e.g.,
freestyle-component-registry.ts) that exports a map from componentId strings
(like "ak-accordion") to the corresponding component reference/name (the same
values currently used in the template, e.g., "AkAccordion::FreestyleSection");
update the component backing class for this template
(FreestyleComponentRenderer) to import that registry and expose a
computed/derived property (e.g., selectedComponent) that returns
registry[this.args.componentId] or null; then simplify the HBS to render
dynamically via the component helper (e.g., {{`#if`
this.selectedComponent}}{{component this.selectedComponent}}{{else}}<p
class='text-secondary'>Component not found: {{`@componentId`}}</p>{{/if}}). This
moves the registry out of freestyle-component-renderer.hbs into a single source
of truth and uses `@componentId`, FreestyleComponentRenderer, selectedComponent,
and the component helper for the dynamic lookup.

In `@app/components/freestyle-nav.ts`:
- Around line 3-35: The COMPONENTS array lacks explicit TypeScript types; define
a small interface or type (e.g., ComponentItem with id: string and label:
string) and annotate COMPONENTS as ComponentItem[] (or readonly ComponentItem[]
if immutable) so each entry (the objects in COMPONENTS) is type-checked; update
any exports/usages of COMPONENTS to use the new type for better autocomplete and
compile-time safety.

In `@app/components/freestyle-section.ts`:
- Around line 3-6: The show getter in class FreestyleSection is intended to
override the base class member from FreestyleSectionAddon; add the TypeScript
override modifier to the getter (i.e., declare `override get show(): boolean`)
in the FreestyleSection class to make the override explicit and consistent with
TS best practices.

In `@app/components/freestyle-usage.ts`:
- Around line 3-6: The show getter in class FreestyleUsage lacks the override
keyword while other inherited getters (e.g., hasCode) use it; update the show
getter in FreestyleUsage to include the override modifier (i.e., change the
declaration of the show getter in FreestyleUsage to explicitly use override) so
the intent is clear and consistent with hasCode.

In `@app/routes/freestyle/component.ts`:
- Around line 38-40: The model function currently silently maps invalid slugs to
'ak-accordion'; update model(params: { component_id?: string }) to detect when
params.component_id is not in VALID_COMPONENTS and then perform a canonical
redirect to the default route (e.g. redirect to '/freestyle/ak-accordion') or
return a proper not-found response (e.g. throw a 404 Response) instead of
returning 'ak-accordion'. Use the same VALID_COMPONENTS check to decide and
invoke your framework's redirect/response mechanism from within model rather
than silently substituting the id.

In `@app/styles/_freestyle.scss`:
- Around line 1-8: Add a short explanatory comment above the rules indicating
the use of !important is intentional to override ember-freestyle defaults, so
future maintainers won't remove it; reference the selector block
(.FreestyleGuide-header, .FreestyleGuide-cta, .FreestyleGuide-nav,
.FreestyleGuide-aside) and state that we hide the built-in header/sidebar in
favor of our own sidebar and therefore need the !important overrides.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 078e2bc5-f72b-46cd-b2f4-cf37ab00728f

📥 Commits

Reviewing files that changed from the base of the PR and between 17b412c and 6a9f981.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (81)
  • app/components/ak-accordion/freestyle-section.hbs
  • app/components/ak-appbar/freestyle-section.hbs
  • app/components/ak-autocomplete/freestyle-demo.hbs
  • app/components/ak-autocomplete/freestyle-demo.ts
  • app/components/ak-autocomplete/freestyle-section.hbs
  • app/components/ak-button/freestyle-section.hbs
  • app/components/ak-checkbox-tree/freestyle-demo.hbs
  • app/components/ak-checkbox-tree/freestyle-demo.ts
  • app/components/ak-checkbox-tree/freestyle-section.hbs
  • app/components/ak-checkbox/freestyle-demo.hbs
  • app/components/ak-checkbox/freestyle-demo.ts
  • app/components/ak-checkbox/freestyle-section.hbs
  • app/components/ak-chip/freestyle-section.hbs
  • app/components/ak-clipboard/freestyle-section.hbs
  • app/components/ak-date-picker/freestyle-demo.hbs
  • app/components/ak-date-picker/freestyle-demo.ts
  • app/components/ak-date-picker/freestyle-section.hbs
  • app/components/ak-divider/freestyle-section.hbs
  • app/components/ak-drawer/freestyle-demo.hbs
  • app/components/ak-drawer/freestyle-demo.ts
  • app/components/ak-drawer/freestyle-section.hbs
  • app/components/ak-icon-button/freestyle-section.hbs
  • app/components/ak-icon/freestyle-section.hbs
  • app/components/ak-link/freestyle-section.hbs
  • app/components/ak-list/freestyle-demo.hbs
  • app/components/ak-list/freestyle-demo.ts
  • app/components/ak-list/freestyle-section.hbs
  • app/components/ak-loader/freestyle-section.hbs
  • app/components/ak-menu/freestyle-demo.hbs
  • app/components/ak-menu/freestyle-demo.ts
  • app/components/ak-menu/freestyle-section.hbs
  • app/components/ak-modal/freestyle-demo.hbs
  • app/components/ak-modal/freestyle-demo.ts
  • app/components/ak-modal/freestyle-section.hbs
  • app/components/ak-pagination/freestyle-demo.hbs
  • app/components/ak-pagination/freestyle-demo.ts
  • app/components/ak-pagination/freestyle-section.hbs
  • app/components/ak-popover/freestyle-demo.hbs
  • app/components/ak-popover/freestyle-demo.ts
  • app/components/ak-popover/freestyle-section.hbs
  • app/components/ak-radio/freestyle-section.hbs
  • app/components/ak-select/freestyle-demo.hbs
  • app/components/ak-select/freestyle-demo.ts
  • app/components/ak-select/freestyle-section.hbs
  • app/components/ak-skeleton/freestyle-section.hbs
  • app/components/ak-stack/freestyle-section.hbs
  • app/components/ak-table/freestyle-demo.hbs
  • app/components/ak-table/freestyle-demo.ts
  • app/components/ak-table/freestyle-section.hbs
  • app/components/ak-tabs/freestyle-demo.hbs
  • app/components/ak-tabs/freestyle-demo.ts
  • app/components/ak-tabs/freestyle-section.hbs
  • app/components/ak-text-field/freestyle-section.hbs
  • app/components/ak-toggle/freestyle-demo.hbs
  • app/components/ak-toggle/freestyle-demo.ts
  • app/components/ak-toggle/freestyle-section.hbs
  • app/components/ak-tooltip/freestyle-section.hbs
  • app/components/ak-tree/freestyle-demo.hbs
  • app/components/ak-tree/freestyle-demo.ts
  • app/components/ak-tree/freestyle-section.hbs
  • app/components/ak-typography/freestyle-section.hbs
  • app/components/freestyle-component-renderer.hbs
  • app/components/freestyle-component-renderer.ts
  • app/components/freestyle-nav.hbs
  • app/components/freestyle-nav.ts
  • app/components/freestyle-section.hbs
  • app/components/freestyle-section.ts
  • app/components/freestyle-usage.hbs
  • app/components/freestyle-usage.ts
  • app/controllers/freestyle/component.ts
  • app/controllers/freestyle/index.ts
  • app/router.ts
  • app/routes/freestyle.ts
  • app/routes/freestyle/component.ts
  • app/routes/freestyle/index.ts
  • app/styles/_freestyle.scss
  • app/styles/app.scss
  • app/templates/freestyle.hbs
  • app/templates/freestyle/component.hbs
  • app/templates/freestyle/index.hbs
  • package.json

Comment on lines +15 to +18
<AkTypography @variant='h5' @color='inherit'>Appbar title</AkTypography>
<AkIconButton class={{ab.classes.defaultIconBtn}}>
<AkIcon @iconName='close' />
</AkIconButton>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Label the close action for screen readers.

The trailing icon button is icon-only, so it needs an accessible name such as aria-label='Close'.

♿ Suggested fix
-      <AkIconButton class={{ab.classes.defaultIconBtn}}>
+      <AkIconButton class={{ab.classes.defaultIconBtn}} aria-label='Close'>
         <AkIcon `@iconName`='close' />
       </AkIconButton>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<AkTypography @variant='h5' @color='inherit'>Appbar title</AkTypography>
<AkIconButton class={{ab.classes.defaultIconBtn}}>
<AkIcon @iconName='close' />
</AkIconButton>
<AkTypography `@variant`='h5' `@color`='inherit'>Appbar title</AkTypography>
<AkIconButton class={{ab.classes.defaultIconBtn}} aria-label='Close'>
<AkIcon `@iconName`='close' />
</AkIconButton>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-appbar/freestyle-section.hbs` around lines 15 - 18, The
trailing icon-only button (AkIconButton in freestyle-section.hbs) lacks an
accessible name; add an aria-label (e.g., aria-label="Close") to the
AkIconButton element so screen readers announce the action—ensure the attribute
is set on the AkIconButton component (not just AkIcon) to provide the accessible
name.

Comment on lines +26 to +32
<AkCheckbox
@checked={{this.checked}}
@indeterminate={{this.indeterminate}}
@disabled={{false}}
@readonly={{false}}
@onChange={{this.handleChange}}
/>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Give the standalone checkbox an accessible name.

The default branch renders a bare checkbox with no associated label, so assistive tech users get an unlabeled control. Wrap this variant in AkFormControlLabel or pass an explicit accessible name through to the underlying input.

♿ Suggested fix
 {{else}}
-  <AkCheckbox
-    `@checked`={{this.checked}}
-    `@indeterminate`={{this.indeterminate}}
-    `@disabled`={{false}}
-    `@readonly`={{false}}
-    `@onChange`={{this.handleChange}}
-  />
+  <AkFormControlLabel `@label`='Check me'>
+    <AkCheckbox
+      `@checked`={{this.checked}}
+      `@indeterminate`={{this.indeterminate}}
+      `@disabled`={{false}}
+      `@readonly`={{false}}
+      `@onChange`={{this.handleChange}}
+    />
+  </AkFormControlLabel>
 {{/if}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<AkCheckbox
@checked={{this.checked}}
@indeterminate={{this.indeterminate}}
@disabled={{false}}
@readonly={{false}}
@onChange={{this.handleChange}}
/>
{{else}}
<AkFormControlLabel `@label`='Check me'>
<AkCheckbox
`@checked`={{this.checked}}
`@indeterminate`={{this.indeterminate}}
`@disabled`={{false}}
`@readonly`={{false}}
`@onChange`={{this.handleChange}}
/>
</AkFormControlLabel>
{{/if}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-checkbox/freestyle-demo.hbs` around lines 26 - 32, The
standalone AkCheckbox in the demo lacks an accessible name; update the freestyle
variant so the checkbox is either wrapped with AkFormControlLabel (use
AkFormControlLabel around the AkCheckbox and supply a visible label string) or
supply an explicit accessible name prop (e.g., ariaLabel or label prop passed
down) to AkCheckbox; modify the template where AkCheckbox is rendered (the
instance using `@checked`={{this.checked}} `@indeterminate`={{this.indeterminate}}
`@onChange`={{this.handleChange}}) to include the chosen accessibility fix.

Comment on lines +12 to +15
<AkTextField id='copy-input' @value='I will be copied!' />
<AkClipboard as |cb|>
<AkButton class='mt-2' data-clipboard-target='#copy-input' id={{cb.triggerId}}>
Copy Input text
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect how AkTextField applies incoming id attributes and where the real input lives.
fd 'ak-text-field' app/components | while read -r file; do
  case "$file" in
    *.hbs|*.ts|*.gts)
      echo "== $file =="
      rg -n -C2 '(<input|@id|inputId|id=|\.{3}attributes)' "$file"
      ;;
  esac
done

Repository: appknox/irene

Length of output: 39


🏁 Script executed:

# First, let's understand the component directory structure
fd --type f -e ts -e gts -e hbs app/components | head -20

Repository: appknox/irene

Length of output: 418


🏁 Script executed:

# Search for AkTextField definition more broadly
rg 'AkTextField|ak-text-field' app/components --type ts --type gts --type hbs -l

Repository: appknox/irene

Length of output: 84


🏁 Script executed:

# Also check for text field components with different naming
fd 'text.*field|field.*text' app/components --type f

Repository: appknox/irene

Length of output: 39


🏁 Script executed:

# Fix the fd syntax and explore the components directory
fd . app/components --type f | grep -i text | head -20

Repository: appknox/irene

Length of output: 1575


🏁 Script executed:

# Search for AkTextField component definition across codebase
rg 'AkTextField' --type ts --type hbs -l

Repository: appknox/irene

Length of output: 4395


🏁 Script executed:

# Read the freestyle-section.hbs file directly to see imports and component usage
cat -n app/components/ak-clipboard/freestyle-section.hbs

Repository: appknox/irene

Length of output: 910


🏁 Script executed:

# Read the AkTextField component implementation
cat -n app/components/ak-text-field/index.ts

Repository: appknox/irene

Length of output: 1531


🏁 Script executed:

# Check if there's a template file for AkTextField
fd . app/components/ak-text-field --type f

Repository: appknox/irene

Length of output: 270


🏁 Script executed:

# Read the AkTextField template to see where id is applied
cat -n app/components/ak-text-field/index.hbs

Repository: appknox/irene

Length of output: 2461


Consider using a dynamic ID or ref to avoid duplicate IDs in the demo.

The id='copy-input' is hard-coded and will cause duplicate DOM IDs if this freestyle section is ever rendered multiple times. While AkTextField correctly forwards the id to its internal <Input> element (so the selector works), it would be more robust to use a dynamic or generated ID for this example.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-clipboard/freestyle-section.hbs` around lines 12 - 15, The
hard-coded id 'copy-input' on AkTextField and the
data-clipboard-target:'#copy-input' can produce duplicate DOM IDs; change to a
generated/dynamic id (e.g., create a local uniqueId variable or use an
Ember/utility helper) and use that id for both the AkTextField id and the
AkButton data-clipboard-target (prefixing with '#'), keeping the existing usage
of {{cb.triggerId}} for the button id; update the template to bind the generated
id instead of the literal 'copy-input' so each render instance gets a unique
selector.

@disableBackdropClick={{false}}
@onClose={{this.handleClose}}
>
<div class='p-4' {{style width='250px'}}>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n-- dependency check --\n'
rg -n '"ember-style-modifier"|"style-modifier"|".*styled.*modifier.*"' package.json || true

printf '\n-- local style helper/modifier candidates --\n'
fd '^style\.(ts|js)$' app/modifiers app/helpers lib 2>/dev/null || true
rg -n "export default .*modifier|modifier\\(" app/modifiers lib 2>/dev/null || true
rg -n "export default .*helper|helper\\(" app/helpers lib 2>/dev/null || true

Repository: appknox/irene

Length of output: 1834


🏁 Script executed:

# Check if {{style is used elsewhere in templates
rg -n "{{style" app/ --type hbs || true

# Check package.json for all dependencies to see if any might provide style
rg -n '"dependencies"|"devDependencies"' package.json -A 50 | head -100 || true

# Check if there are any addon imports or registrations in app
rg -n "ember-style-modifier|@ember|style.*modifier" app/ --type ts --type js | head -20 || true

Repository: appknox/irene

Length of output: 4835


🏁 Script executed:

# Read the freestyle-demo.hbs file
cat -n app/components/ak-drawer/freestyle-demo.hbs

# Search for style usage in templates with proper escaping
rg 'style' app/ --type hbs -n | grep -i 'style.*=' | head -20

Repository: appknox/irene

Length of output: 2510


🏁 Script executed:

# Check if there's a style modifier in app/modifiers
ls -la app/modifiers/

# Check if `@ember/render-modifiers` provides style modifier
rg -n "export.*style|style.*export" app/ --type ts --type js | head -10

# Check for any modifiers index or re-exports
cat -n app/modifiers/index.ts 2>/dev/null || echo "No modifiers/index.ts"

# Search for where style modifier might be defined
rg -n "style.*modifier|modifier.*style" . --type ts --type js --type hbs | head -20

Repository: appknox/irene

Length of output: 1552


🏁 Script executed:

# Check ember-cli-build.js for addon setup
cat -n ember-cli-build.js | head -50

# Check if there's an ember.json or app config
cat -n .ember.json 2>/dev/null || cat -n ember.json 2>/dev/null || echo "No ember config found"

# Check package.json for ember-freestyle
rg -n "ember-freestyle" package.json

# Search for any documentation or imports of style modifier in the app
rg -n "import.*style|from.*style" app/ --type ts --type js --type hbs | head -10

# Check Ember version to see if style is built-in
rg -n '"ember-source"|"ember"' package.json | head -5

Repository: appknox/irene

Length of output: 2832


🌐 Web query:

Ember 5.12 style modifier built-in template helper

💡 Result:

Ember 5.12 does not include a built-in {{style}} template helper/element modifier. Ember’s only built-in element modifier is {{on}} (for event listeners). [1], [2]

If you want {{style ...}} behavior, it typically comes from the ember-style-modifier addon, which “provides a {{style}} element modifier to set element’s style.” [3]

Sources: [1] [2] [3]


🌐 Web query:

ember-freestyle provides style modifier

💡 Result:

ember-freestyle does not provide a {{style}} element modifier—it’s a component explorer / living style guide addon. [1]

If you’re looking for a {{style}} modifier, use ember-style-modifier, which explicitly provides a {{style}} element modifier for setting inline styles safely. [2]

Install

ember install ember-style-modifier

Use

<div {{style width="100%" backgroundColor="red"}}></div>

Sources: ember-freestyle package overview [1]; ember-style-modifier README/description [2].


Install ember-style-modifier addon or use plain style attribute instead.

Line 9 uses {{style width='250px'}}, but this requires the ember-style-modifier addon which is not listed in package.json. Ember 5.12 has no built-in {{style}} modifier. Either add the addon with ember install ember-style-modifier or use a static style attribute.

Fallback using plain style attribute
-  <div class='p-4' {{style width='250px'}}>
+  <div class='p-4' style='width: 250px;'>

Note: This pattern is used in 8+ other templates (loading.hbs, payment-failure.hbs, etc.), suggesting the addon should be added to resolve issues across the codebase.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div class='p-4' {{style width='250px'}}>
<div class='p-4' style='width: 250px;'>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-drawer/freestyle-demo.hbs` at line 9, The template uses the
{{style}} modifier (in the div with class 'p-4') which requires the
ember-style-modifier addon that isn’t installed; either add the addon (install
ember-style-modifier and add it to package.json) so {{style}} works across
templates, or replace the modifier usage with a plain static style attribute
(e.g., style="width:250px") in the freestyle-demo.hbs and the other templates
(loading.hbs, payment-failure.hbs, etc.) that use {{style}}.

Comment on lines +2 to +36
<FreestyleUsage @slug='ak-icon-button-default' @title='Default'>
<AkTypography @color='textSecondary' @gutterBottom={{true}}>Experiment with me</AkTypography>
<AkIconButton @type='button' @size='medium' disabled={{false}}>
<AkIcon @color='' @iconName='close' />
</AkIconButton>
<AkIconButton @type='button' @variant='outlined' @size='medium' disabled={{false}}>
<AkIcon @color='' @iconName='refresh' />
</AkIconButton>
</FreestyleUsage>

<FreestyleUsage @slug='ak-icon-button-variants' @title='Variants'>
<AkIconButton><AkIcon @iconName='delete' /></AkIconButton>
<AkIconButton @variant='outlined'><AkIcon @iconName='refresh' /></AkIconButton>
</FreestyleUsage>

<FreestyleUsage @slug='ak-icon-button-sizes' @title='Sizes'>
<AkIconButton @size='small'><AkIcon @iconName='delete' /></AkIconButton>
<AkIconButton><AkIcon @iconName='delete' /></AkIconButton>
<AkIconButton @variant='outlined' @size='small'><AkIcon @iconName='delete' /></AkIconButton>
<AkIconButton @variant='outlined'><AkIcon @iconName='delete' /></AkIconButton>
</FreestyleUsage>

<FreestyleUsage @slug='ak-icon-button-disabled' @title='Disabled'>
<AkIconButton disabled={{true}}><AkIcon @iconName='delete' /></AkIconButton>
<AkIconButton disabled={{true}} @variant='outlined'><AkIcon @iconName='refresh' /></AkIconButton>
</FreestyleUsage>

<FreestyleUsage @slug='ak-icon-button-colors' @title='Colors'>
<AkIconButton><AkIcon @iconName='refresh' /></AkIconButton>
<AkIconButton><AkIcon @color='success' @iconName='done' /></AkIconButton>
<AkIconButton><AkIcon @color='error' @iconName='delete' /></AkIconButton>
<AkIconButton @variant='outlined'><AkIcon @iconName='refresh' /></AkIconButton>
<AkIconButton @variant='outlined'><AkIcon @color='success' @iconName='done' /></AkIconButton>
<AkIconButton @variant='outlined' @color='danger'><AkIcon @color='error' @iconName='delete' /></AkIconButton>
</FreestyleUsage>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add accessible names to the icon-only buttons.

Every example here renders a clickable icon without a text alternative, so assistive tech will announce unlabeled buttons. Please pass an aria-label that matches the action on each example.

♿ Suggested fix
-    <AkIconButton `@type`='button' `@size`='medium' disabled={{false}}>
+    <AkIconButton `@type`='button' `@size`='medium' aria-label='Close' disabled={{false}}>
       <AkIcon `@iconName`='close' />
     </AkIconButton>
-    <AkIconButton `@type`='button' `@variant`='outlined' `@size`='medium' disabled={{false}}>
+    <AkIconButton `@type`='button' `@variant`='outlined' `@size`='medium' aria-label='Refresh' disabled={{false}}>
       <AkIcon `@iconName`='refresh' />
     </AkIconButton>

Apply the same pattern to the delete/done examples below.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-icon-button/freestyle-section.hbs` around lines 2 - 36,
Several AkIconButton usages render icon-only buttons without accessible names;
update each icon-only example (instances of AkIconButton with child AkIcon in
freestyle-section.hbs) to include an aria-label describing the action (e.g.,
"close", "refresh", "delete", "done") so screen readers announce the purpose;
ensure every AkIconButton that has no visible text gets an appropriate
aria-label attribute matching the icon action.

Comment on lines +1 to +40
{{#if (eq @variant 'label')}}
<AkFormControlLabel @label='Check me' @disabled={{false}} as |fcl|>
<AkToggle
@checked={{this.checkedLabel}}
@size='small'
@disabled={{fcl.disabled}}
@readonly={{false}}
@onChange={{this.handleLabelChange}}
/>
</AkFormControlLabel>
{{else if (eq @variant 'sizes')}}
<AkToggle
@checked={{this.checkedSmall}}
@size='small'
@disabled={{false}}
@readonly={{false}}
@onChange={{fn this.handleSizeChange 'small'}}
/>
<AkToggle
@checked={{this.checkedMedium}}
@size='medium'
@disabled={{false}}
@readonly={{false}}
@onChange={{fn this.handleSizeChange 'medium'}}
/>
<AkToggle
@checked={{this.checkedLarge}}
@size='large'
@disabled={{false}}
@readonly={{false}}
@onChange={{fn this.handleSizeChange 'large'}}
/>
{{else}}
<AkToggle
@checked={{this.checked}}
@size='small'
@disabled={{false}}
@readonly={{false}}
@onChange={{this.handleChange}}
/>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Forward @disabled and @readonly instead of hardcoding false.

Every branch ignores the incoming args, so disabled/readonly freestyle usages will still render interactive toggles. That breaks the showcase states this demo is supposed to cover.

🐛 Proposed fix
 {{`#if` (eq `@variant` 'label')}}
-  <AkFormControlLabel `@label`='Check me' `@disabled`={{false}} as |fcl|>
+  <AkFormControlLabel `@label`='Check me' `@disabled`={{`@disabled`}} as |fcl|>
     <AkToggle
       `@checked`={{this.checkedLabel}}
       `@size`='small'
       `@disabled`={{fcl.disabled}}
-      `@readonly`={{false}}
+      `@readonly`={{`@readonly`}}
       `@onChange`={{this.handleLabelChange}}
     />
   </AkFormControlLabel>
 {{else if (eq `@variant` 'sizes')}}
   <AkToggle
     `@checked`={{this.checkedSmall}}
     `@size`='small'
-    `@disabled`={{false}}
-    `@readonly`={{false}}
+    `@disabled`={{`@disabled`}}
+    `@readonly`={{`@readonly`}}
     `@onChange`={{fn this.handleSizeChange 'small'}}
   />
   <AkToggle
     `@checked`={{this.checkedMedium}}
     `@size`='medium'
-    `@disabled`={{false}}
-    `@readonly`={{false}}
+    `@disabled`={{`@disabled`}}
+    `@readonly`={{`@readonly`}}
     `@onChange`={{fn this.handleSizeChange 'medium'}}
   />
   <AkToggle
     `@checked`={{this.checkedLarge}}
     `@size`='large'
-    `@disabled`={{false}}
-    `@readonly`={{false}}
+    `@disabled`={{`@disabled`}}
+    `@readonly`={{`@readonly`}}
     `@onChange`={{fn this.handleSizeChange 'large'}}
   />
 {{else}}
   <AkToggle
     `@checked`={{this.checked}}
     `@size`='small'
-    `@disabled`={{false}}
-    `@readonly`={{false}}
+    `@disabled`={{`@disabled`}}
+    `@readonly`={{`@readonly`}}
     `@onChange`={{this.handleChange}}
   />
 {{/if}}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{#if (eq @variant 'label')}}
<AkFormControlLabel @label='Check me' @disabled={{false}} as |fcl|>
<AkToggle
@checked={{this.checkedLabel}}
@size='small'
@disabled={{fcl.disabled}}
@readonly={{false}}
@onChange={{this.handleLabelChange}}
/>
</AkFormControlLabel>
{{else if (eq @variant 'sizes')}}
<AkToggle
@checked={{this.checkedSmall}}
@size='small'
@disabled={{false}}
@readonly={{false}}
@onChange={{fn this.handleSizeChange 'small'}}
/>
<AkToggle
@checked={{this.checkedMedium}}
@size='medium'
@disabled={{false}}
@readonly={{false}}
@onChange={{fn this.handleSizeChange 'medium'}}
/>
<AkToggle
@checked={{this.checkedLarge}}
@size='large'
@disabled={{false}}
@readonly={{false}}
@onChange={{fn this.handleSizeChange 'large'}}
/>
{{else}}
<AkToggle
@checked={{this.checked}}
@size='small'
@disabled={{false}}
@readonly={{false}}
@onChange={{this.handleChange}}
/>
{{`#if` (eq `@variant` 'label')}}
<AkFormControlLabel `@label`='Check me' `@disabled`={{`@disabled`}} as |fcl|>
<AkToggle
`@checked`={{this.checkedLabel}}
`@size`='small'
`@disabled`={{fcl.disabled}}
`@readonly`={{`@readonly`}}
`@onChange`={{this.handleLabelChange}}
/>
</AkFormControlLabel>
{{else if (eq `@variant` 'sizes')}}
<AkToggle
`@checked`={{this.checkedSmall}}
`@size`='small'
`@disabled`={{`@disabled`}}
`@readonly`={{`@readonly`}}
`@onChange`={{fn this.handleSizeChange 'small'}}
/>
<AkToggle
`@checked`={{this.checkedMedium}}
`@size`='medium'
`@disabled`={{`@disabled`}}
`@readonly`={{`@readonly`}}
`@onChange`={{fn this.handleSizeChange 'medium'}}
/>
<AkToggle
`@checked`={{this.checkedLarge}}
`@size`='large'
`@disabled`={{`@disabled`}}
`@readonly`={{`@readonly`}}
`@onChange`={{fn this.handleSizeChange 'large'}}
/>
{{else}}
<AkToggle
`@checked`={{this.checked}}
`@size`='small'
`@disabled`={{`@disabled`}}
`@readonly`={{`@readonly`}}
`@onChange`={{this.handleChange}}
/>
{{/if}}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/ak-toggle/freestyle-demo.hbs` around lines 1 - 40, The demo
hardcodes `@disabled` and `@readonly` as false for AkToggle and AkFormControlLabel,
ignoring incoming args; change every occurrence to forward the incoming args
instead (e.g. replace `@disabled`={{false}} and `@readonly`={{false}} with
`@disabled`={{`@disabled`}} and `@readonly`={{`@readonly`}}), and ensure the
AkFormControlLabel also receives `@disabled`={{`@disabled`}} so fcl.disabled
reflects the passed-in disabled state; keep existing bindings like `@onChange`
(this.handleChange / this.handleSizeChange / this.handleLabelChange) unchanged.

Comment thread app/router.ts
Comment on lines +12 to +14
this.route('freestyle', function () {
this.route('component', { path: '/:component_id' });
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if there's any route-level protection or environment gating for freestyle
rg -n 'freestyle' --type ts -g '!*.d.ts' app/routes/

Repository: appknox/irene

Length of output: 268


🏁 Script executed:

# View the app/router.ts file to understand the full structure
head -40 app/router.ts | cat -n

Repository: appknox/irene

Length of output: 1259


🏁 Script executed:

# Check the freestyle route handler for any authentication guards
cat -n app/routes/freestyle.ts

Repository: appknox/irene

Length of output: 644


🏁 Script executed:

# Search for authentication middleware or route guards
rg -n 'authenticated|protect|auth|requireLogin' app/router.ts -A 3

Repository: appknox/irene

Length of output: 204


🏁 Script executed:

# Check the application route for guards
cat -n app/routes/application.ts 2>/dev/null | head -30

Repository: appknox/irene

Length of output: 1363


🏁 Script executed:

# Check if ember-freestyle is a devDependency
grep -A 2 -B 2 "ember-freestyle" package.json

Repository: appknox/irene

Length of output: 327


🏁 Script executed:

# Check if there's environment-based configuration for freestyle route
rg -n 'environment|development|production' app/router.ts -B 2 -A 2

Repository: appknox/irene

Length of output: 221


🏁 Script executed:

# Find the authenticated route to check if it has guards
rg -n "class.*Authenticated.*Route" app/routes/ -A 20

Repository: appknox/irene

Length of output: 50370


🏁 Script executed:

# Also check if there's a specific authenticated.ts route file
cat -n app/routes/authenticated.ts 2>/dev/null | head -40

Repository: appknox/irene

Length of output: 2250


🏁 Script executed:

# Check ember-freestyle documentation or usage patterns in the codebase
rg -n "ember-freestyle" --type ts -B 3 -A 3

Repository: appknox/irene

Length of output: 1302


Move the freestyle route into the authenticated block or environment-gate it.

The freestyle route is publicly accessible without authentication. If this is an internal documentation/component library tool, it should either be:

  1. Moved inside the authenticated route block, or
  2. Conditionally registered only in development/staging environments.

Currently, anyone can access the route without logging in.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/router.ts` around lines 12 - 14, The freestyle route
(this.route('freestyle', ...) / this.route('component', { path: '/:component_id'
})) is currently public; move it into the existing authenticated route block or
gate its registration by environment. Fix by either relocating the
this.route('freestyle', ...) declaration inside the authenticated route callback
(e.g., inside this.route('authenticated', function() { ... })), or wrap the
freestyle route registration with an environment check (e.g., if
(process.env.NODE_ENV !== 'production') { /* register freestyle route */ }) so
it only registers in dev/staging.

Comment thread app/routes/freestyle.ts
Comment on lines +8 to +15
activate() {
this.emberFreestyle.showCode = true;
this.emberFreestyle.showLabels = true;
}

deactivate() {
this.emberFreestyle.showCode = true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify where these flags are mutated today.
rg -n -C2 'show(Code|Labels)\s*=' app

Repository: appknox/irene

Length of output: 492


🏁 Script executed:

#!/bin/bash
# Find the EmberFreestyleService definition
fd -e ts -e js | xargs grep -l "EmberFreestyleService" | head -20

Repository: appknox/irene

Length of output: 164


🏁 Script executed:

#!/bin/bash
# Check for any tests related to FreestyleRoute
fd -e ts -e js -path "*/test*" -o -path "*/.test.*" | xargs grep -l "FreestyleRoute" 2>/dev/null | head -10

Repository: appknox/irene

Length of output: 225


🏁 Script executed:

#!/bin/bash
# Look at the full FreestyleRoute file to understand context
cat -n app/routes/freestyle.ts

Repository: appknox/irene

Length of output: 644


🏁 Script executed:

#!/bin/bash
# Search for any service definitions or configurations
rg -n "ember-freestyle" app --type ts --type js -A 3 -B 3

Repository: appknox/irene

Length of output: 1302


🏁 Script executed:

#!/bin/bash
# Search for tests related to FreestyleRoute across all test directories
find . -type f \( -name "*.test.ts" -o -name "*.spec.ts" -o -name "*-test.ts" \) | xargs grep -l "freestyle" 2>/dev/null | head -10

Repository: appknox/irene

Length of output: 39


🏁 Script executed:

#!/bin/bash
# Look for any integration or unit tests that might test route lifecycle
rg -n "FreestyleRoute|activate|deactivate" --type-list | head -5

Repository: appknox/irene

Length of output: 446


🏁 Script executed:

#!/bin/bash
# Check if there's a README or documentation about the freestyle route
fd -e md -e txt | xargs grep -l -i "freestyle" 2>/dev/null | head -5

Repository: appknox/irene

Length of output: 39


Restore the previous Freestyle flags on teardown instead of hard-coding state.

This route mutates a singleton service: activate() sets both showCode and showLabels to true, but deactivate() only touches showCode. This leaves showLabels = true after navigating away from /freestyle, causing later consumers to inherit route-specific state.

Additionally, deactivate() sets showCode = true again, which appears incorrect—it should restore the prior value instead.

Save and restore the previous state for both flags:

Suggested fix
 export default class FreestyleRoute extends Route {
   `@service`('ember-freestyle') declare emberFreestyle: EmberFreestyleService;
+  private previousShowCode?: boolean;
+  private previousShowLabels?: boolean;
 
   activate() {
+    this.previousShowCode = this.emberFreestyle.showCode;
+    this.previousShowLabels = this.emberFreestyle.showLabels;
     this.emberFreestyle.showCode = true;
     this.emberFreestyle.showLabels = true;
   }
 
   deactivate() {
-    this.emberFreestyle.showCode = true;
+    this.emberFreestyle.showCode =
+      this.previousShowCode ?? this.emberFreestyle.showCode;
+    this.emberFreestyle.showLabels =
+      this.previousShowLabels ?? this.emberFreestyle.showLabels;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/routes/freestyle.ts` around lines 8 - 15, The route currently mutates the
singleton service directly and hard-codes values; update activate() to save the
existing emberFreestyle.showCode and emberFreestyle.showLabels into route
instance properties (e.g. this._prevShowCode, this._prevShowLabels), then set
both flags to true; update deactivate() to restore both flags from those saved
properties (this.emberFreestyle.showCode = this._prevShowCode;
this.emberFreestyle.showLabels = this._prevShowLabels) and clear the saved
properties to avoid leaks. Ensure you reference the existing methods activate
and deactivate and the emberFreestyle service properties showCode and
showLabels.

Comment on lines +93 to +97
&--active {
background: #e3f2fd;
color: #1976d2;
font-weight: 500;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify contrast ratio using a simple calculation
# `#1976d2` (R:25, G:118, B:210) on `#e3f2fd` (R:227, G:242, B:253)
python3 << 'EOF'
def relative_luminance(r, g, b):
    def adjust(c):
        c = c / 255.0
        return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
    return 0.2126 * adjust(r) + 0.7152 * adjust(g) + 0.0722 * adjust(b)

fg = relative_luminance(25, 118, 210)  # `#1976d2`
bg = relative_luminance(227, 242, 253)  # `#e3f2fd`

lighter = max(fg, bg)
darker = min(fg, bg)
ratio = (lighter + 0.05) / (darker + 0.05)

print(f"Contrast ratio: {ratio:.2f}:1")
print(f"WCAG AA (4.5:1): {'PASS' if ratio >= 4.5 else 'FAIL'}")
print(f"WCAG AAA (7:1): {'PASS' if ratio >= 7 else 'FAIL'}")
EOF

Repository: appknox/irene

Length of output: 122


Improve text contrast for accessibility compliance.

The text color #1976d2 on background #e3f2fd has a contrast ratio of 4.03:1, which falls below the WCAG AA minimum of 4.5:1 for normal text. Use a darker shade of blue to meet accessibility standards.

Suggested fix
   &--active {
     background: `#e3f2fd`;
-    color: `#1976d2`;
+    color: `#1565c0`;
     font-weight: 500;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
&--active {
background: #e3f2fd;
color: #1976d2;
font-weight: 500;
}
&--active {
background: `#e3f2fd`;
color: `#1565c0`;
font-weight: 500;
}
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 95-95: Text does not meet the minimal contrast requirement with its background.

See more on https://sonarcloud.io/project/issues?id=appknox_irene&issues=AZzg3K6KBs171Xl6ablT&open=AZzg3K6KBs171Xl6ablT&pullRequest=1674

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/styles/_freestyle.scss` around lines 93 - 97, The .&--active rule uses
text color `#1976d2` on background `#e3f2fd` which fails WCAG AA; update the color
in the &--active selector to a darker blue that achieves a contrast ratio ≥ 4.5
(for example swap `#1976d2` for a darker shade such as `#0d47a1` or update the
relevant variable), and if your codebase uses a color variable (e.g., a
$primary-... or --color-... token) update that token instead so all references
remain consistent; confirm the final contrast ratio meets WCAG AA for normal
text.

Comment on lines +1 to +5
<div class='freestyle-content'>
<FreestyleGuide @title='Irene Component Library' @subtitle='Appknox Dashboard Components'>
{{component (concat (or this.model 'ak-accordion') '/freestyle-section')}}
</FreestyleGuide>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

This template is wired to the wrong route.

Line 3 reads this.model, but the dynamic selector model in the provided context lives in app/routes/freestyle/component.ts. With this file under freestyle/index.hbs, the selected component_id will not flow here, so the component-specific page will render from the wrong route or not at all. This needs to be app/templates/freestyle/component.hbs, or the route/controller names need to be aligned.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/templates/freestyle/index.hbs` around lines 1 - 5, The template is bound
to the wrong route because it references this.model (used by the component
route) but lives in freestyle/index.hbs; move or rename this template so it
becomes freestyle/component.hbs (so the route will provide the component_id
model), or alternatively update the route/controller wiring to expose the
expected model to the index route; specifically ensure the {{component (concat
(or this.model 'ak-accordion') '/freestyle-section')}} usage inside the
FreestyleGuide receives the route model from the component route (or change the
template to read the correct property exposed by the index route) so component
rendering works as intended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant