From 5d91d97387a694fe8b1f01edeb2912b32b2d0998 Mon Sep 17 00:00:00 2001
From: Markus Sanin
- {{~! ~}}
-
\ No newline at end of file
diff --git a/docs/app/components/code-example.gts b/docs/app/components/code-example.gts
new file mode 100644
index 00000000..0cbb8c58
--- /dev/null
+++ b/docs/app/components/code-example.gts
@@ -0,0 +1,119 @@
+import Component from '@glimmer/component';
+import { tracked } from '@glimmer/tracking';
+import { action } from '@ember/object';
+import { on } from '@ember/modifier';
+import { fn } from '@ember/helper';
+import { eq, and } from 'ember-truth-helpers';
+import CodeBlock from './code-block';
+// @ts-expect-error Could not find a declaration file for module 'ember-code-snippet'.
+import { getCodeSnippet } from 'ember-code-snippet';
+
+interface CodeExampleSignature {
+ Element: HTMLElement;
+ Args: {
+ glimmerTs?: string;
+ hbs?: string;
+ hbs2?: string;
+ js?: string;
+ css?: string;
+ },
+ Blocks: {
+ default: []
+ }
+}
+
+export default class CodeExampleComponent extends Component
- {{~! ~}}{{this.prismCode}}{{~! ~}}
-
\ No newline at end of file
diff --git a/docs/app/components/snippets/how-to-use-it-1.gts b/docs/app/components/snippets/how-to-use-it-1.gts
new file mode 100644
index 00000000..a1b25d48
--- /dev/null
+++ b/docs/app/components/snippets/how-to-use-it-1.gts
@@ -0,0 +1,12 @@
+import Component from '@glimmer/component';
+import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
+
+// eslint-disable-next-line ember/no-empty-glimmer-component-classes
+export default class extends Component {
+
+
{{user.name}} - {{user.assignment}}
+ {{/each}} + {{/if}} +{{user.name}} - {{user.assignment}}
- {{/each}} - {{/if}} -{{user.name}} - {{user.assignment}}
+ {{/each}} +{{user.name}} - {{user.assignment}}
- {{/each}} -+ Who you love more? +
++ + +
++ + +
+- Who you love more? -
-- - -
-- - -
-I look like bootstrap, right?
+You can style me however you want
+I look like bootstrap, right?
-You can style me however you want
-
+
-
+ Horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+ Vertical
+
+
+
+
+
+
+
+
+ Button position
+
+
+
+
+
+
+ RenderInPlace
+
+
+
+
- Horizontal
-
-
-
-
-
-
-
-
-
-
-
-
- Vertical
-
-
-
-
-
-
-
-
- Button position
-
-
-
-
-
-
- RenderInPlace
-
-
-
-
I look like bootstrap, right?
+You can style me however you want
+Option 3
+Option 4
+I look like bootstrap, right?
-You can style me however you want
-Option 3
-Option 4
-Focus alternatively the input and the button next to it
+Option1
+Option2
+Focus alternatively the input and the button next to it
-Option1
-Option2
-String or ComponentComponentStringComponent
- { uniqueId: <string>, // Contains the unique of this instance of
- EmberBasicDropdown. It's of the form `ember1234`. disabled: <boolean>,
- // Truthy if the component received `disabled=true` isOpen: <boolean>,
- // Truthy if the component is currently opened actions: { close() { ... }, //
- Closes the dropdown open() { ... }, // Opens the dropdown reposition() { ...
- }, // Repositions the dropdown toggle() { ... } // Toggles the dropdown } }
+ {
+ uniqueId: <string>, // Contains the unique of this instance of EmberBasicDropdown. It's of the form `ember1234`.
+ disabled: <boolean>, // Truthy if the component received `disabled=true`
+ isOpen: <boolean>, // Truthy if the component is currently opened
+ actions: {
+ close() { ... }, // Closes the dropdown
+ open() { ... }, // Opens the dropdown
+ reposition() { ... }, // Repositions the dropdown
+ toggle() { ... } // Toggles the dropdown
+ }
+ }
MutationObservers.
-This sounds like a lot, but with an example it will be crystal clear.
-- Ember Basic Dropdown can take a fair amount of configuration options on - invocations to alter its default behavior. + Use the component without a trigger? Is that possible?
- If you want all your dropdowns to behave on a certain way or have some certain
- classes? Repeating the same options over and over on your templates is boring.
+ Yes, it is. You don't need to invoke the
+ <dropdown.trigger>
+ component to make the dropdown work. The yielded
+ dropdown
+ has actions you can invoke from any other item. Yes, it is. You don't need to
+ invoke the
+ <dropdown.trigger>
+ component to make the dropdown work. The yielded
+ dropdown
+ has actions you can invoke from any other item.
- If you want to apply a configuration option to all your dropdowns there is no
- special way or key in the
- /config/environment.js
- you need to learn. Just use The Ember Wayโข.
+ Sometimes you just cannot achieve what you want with this approach, so you
+ need to step down and wire things yourself.
- Inside your app's
- /app/components
- folder create a
- ember-basic-dropdown.js
- file:
+ If you invoke the
+ open
+ or
+ toggle
+ action from say, a button, the dropdown is going to open and will take as the
+ element to be anchored to element with
+ data-ebd-id="\{{dropdown.uniqueId}}-trigger".
+ What kind of things can you do with this? +
+ ++ By example, you can open or close the component when an item is clicked but + make the dropdown attach itself to an entirely different item in the page. +
+ ++ Let's create an input with a button. When that button is clicked the drodown + will open below the input, not not below the button that you clicked. +
+ +
- That's all. No new concepts to learn, just your usual ember-cli work flow.
+ Remember that almost always you will want to use the provided trigger
+ component
+ <dropdown.trigger>
+ because it takes care of all the A11y, bindings and classes for you, but when
+ you can't it's good to know that you can still use your own markup and wire
+ things together yourself.
- In this example the component is also named
- \{{basic-dropdown}}
- but using this approach you can create many components with different names
- that extend and customize the default one without modifying it.
+ A good middle-ground is to apply the same trigger modifier that the component
+ uses, but to your element or component. It will get all of the same a11y and
+ bindings that the
+ <dropdown.trigger>
+ component gets.
- Use the component without a trigger? Is that possible? -
- -
- Yes, it is. You don't need to invoke the
- <dropdown.trigger>
- component to make the dropdown work. The yielded
- dropdown
- has actions you can invoke from any other item. Yes, it is. You don't need to
- invoke the
- <dropdown.trigger>
- component to make the dropdown work. The yielded
- dropdown
- has actions you can invoke from any other item.
-
- Sometimes you just cannot achieve what you want with this approach, so you - need to step down and wire things yourself. -
- -
- If you invoke the
- open
- or
- toggle
- action from say, a button, the dropdown is going to open and will take as the
- element to be anchored to element with
- data-ebd-id="\{{dropdown.uniqueId}}-trigger".
-
- What kind of things can you do with this? -
- -- By example, you can open or close the component when an item is clicked but - make the dropdown attach itself to an entirely different item in the page. -
- -- Let's create an input with a button. When that button is clicked the drodown - will open below the input, not not below the button that you clicked. -
- -
- Remember that almost always you will want to use the provided trigger
- component
- <dropdown.trigger>
- because it takes care of all the A11y, bindings and classes for you, but when
- you can't it's good to know that you can still use your own markup and wire
- things together yourself.
-
- A good middle-ground is to apply the same trigger modifier that the component
- uses, but to your element or component. It will get all of the same a11y and
- bindings that the
- <dropdown.trigger>
- component gets.
-
- This component is pretty low lever and is intended to be a building block to - build your own components on top. -
- -- If you build something reusable that you think it's worth sharing you can - publish it as an addon so other can use it. -
- -If so, let me know and I'll add it to this section. You can use the one below - as inspiration.
- - \ No newline at end of file From 35390bc6ddd67a2a4c8714e62827f8348ce8ac86 Mon Sep 17 00:00:00 2001 From: Markus SaninI look like bootstrap, right?
-You can style me however you want
-I look like bootstrap, right?
+You can style me however you want
+
-
+ I look like bootstrap, right?
-You can style me however you want
-Option 3
-Option 4
-I look like bootstrap, right?
+You can style me however you want
+Option 3
+Option 4
+- The Ember Power Project started with the goal of providing the Ember - ecosystem with a set of curated components that cover common UX needs, - built in Ember and designed work well in Ember apps., from following good - patterns like DDAU to also be test-friend and render property in Fastboot. -
- -- Over the time this evolved a bit into a theory of how an ecosystem should - shape it's addons: Basic components that compose to create more complex - components using good practices and allowing programmers to customize or - directly replace the parts they don't like. -
- -- Those components are divided in three tiers of complexity: -
- By creating a network if addons that compose between them to create even - more addons, we share more. The more we share, the smaller our apps become - because we don't need to reinvent wheels. -
- -- If you enjoy the addons this project provides and they help you in your - daily work, you can support the development of the addons and it's - documentation pages with a any contribution you feel appropiate by - clicking on the button below but above all, by contributing, opening - issues and Pull Requests, answering questions in Slack or StackOverflow - and above all, showing appreciation for everyone who works on the Open - Source Software we all use everyday. -
- - - -- Thank you! -
-
+ What if your app doesn't scroll on the body tag? You can have the dropdown
+ render wherever you would like. If you render it on an element inside the
+ block that is scrolling the dropdown will automatically scroll with your
+ trigger. You need to give the target element
+ position: relative;
+ for the dropdown to be positioned properly.
+
- What if your app doesn't scroll on the body tag? You can have the dropdown
- render wherever you would like. If you render it on an element inside the
- block that is scrolling the dropdown will automatically scroll with your
- trigger. You need to give the target element
- position: relative;
- for the dropdown to be positioned properly.
-
+ Use the component without a trigger? Is that possible? +
+ +
+ Yes, it is. You don't need to invoke the
+ <dropdown.trigger>
+ component to make the dropdown work. The yielded
+ dropdown
+ has actions you can invoke from any other item. Yes, it is. You don't need to
+ invoke the
+ <dropdown.trigger>
+ component to make the dropdown work. The yielded
+ dropdown
+ has actions you can invoke from any other item.
+
+ Sometimes you just cannot achieve what you want with this approach, so you + need to step down and wire things yourself. +
+ +
+ If you invoke the
+ open
+ or
+ toggle
+ action from say, a button, the dropdown is going to open and will take as the
+ element to be anchored to element with
+ data-ebd-id="\{{dropdown.uniqueId}}-trigger".
+
+ What kind of things can you do with this? +
+ ++ By example, you can open or close the component when an item is clicked but + make the dropdown attach itself to an entirely different item in the page. +
+ ++ Let's create an input with a button. When that button is clicked the drodown + will open below the input, not not below the button that you clicked. +
+ +
+ Remember that almost always you will want to use the provided trigger
+ component
+ <dropdown.trigger>
+ because it takes care of all the A11y, bindings and classes for you, but when
+ you can't it's good to know that you can still use your own markup and wire
+ things together yourself.
+
+ A good middle-ground is to apply the same trigger modifier that the component
+ uses, but to your element or component. It will get all of the same a11y and
+ bindings that the
+ <dropdown.trigger>
+ component gets.
+
- Use the component without a trigger? Is that possible? -
- -
- Yes, it is. You don't need to invoke the
- <dropdown.trigger>
- component to make the dropdown work. The yielded
- dropdown
- has actions you can invoke from any other item. Yes, it is. You don't need to
- invoke the
- <dropdown.trigger>
- component to make the dropdown work. The yielded
- dropdown
- has actions you can invoke from any other item.
-
- Sometimes you just cannot achieve what you want with this approach, so you - need to step down and wire things yourself. -
- -
- If you invoke the
- open
- or
- toggle
- action from say, a button, the dropdown is going to open and will take as the
- element to be anchored to element with
- data-ebd-id="\{{dropdown.uniqueId}}-trigger".
-
- What kind of things can you do with this? -
- -- By example, you can open or close the component when an item is clicked but - make the dropdown attach itself to an entirely different item in the page. -
- -- Let's create an input with a button. When that button is clicked the drodown - will open below the input, not not below the button that you clicked. -
- -
- Remember that almost always you will want to use the provided trigger
- component
- <dropdown.trigger>
- because it takes care of all the A11y, bindings and classes for you, but when
- you can't it's good to know that you can still use your own markup and wire
- things together yourself.
-
- A good middle-ground is to apply the same trigger modifier that the component
- uses, but to your element or component. It will get all of the same a11y and
- bindings that the
- <dropdown.trigger>
- component gets.
-
+ Do you like animations in your dropdowns? Me too. Let's define some +
+ +
+ It is that simple as create a CSS3 animation using the
+ ember-basic-dropdown--transitioning-in,
+ ember-basic-dropdown--transitioned-in
+ and
+ ember-basic-dropdown--transitioning-out
+ classes that ember-basic-dropdown gives you automatically.
+
+ You will probably also want to use
+ .ember-basic-dropdown-content--below
+ and
+ .ember-basic-dropdown-content--above
+ to have different animations depending on where the dropdown is positioned.
+
+ There is nothing else to know about animations, other that you have to use CSS + animations, not transitions. +
+ ++ The dropdown takes care of creating a clone when closing the dropdown so you + animation works in both directions. +
+ +- Do you like animations in your dropdowns? Me too. Let's define some -
- -
- It is that simple as create a CSS3 animation using the
- ember-basic-dropdown--transitioning-in,
- ember-basic-dropdown--transitioned-in
- and
- ember-basic-dropdown--transitioning-out
- classes that ember-basic-dropdown gives you automatically.
-
- You will probably also want to use
- .ember-basic-dropdown-content--below
- and
- .ember-basic-dropdown-content--above
- to have different animations depending on where the dropdown is positioned.
-
- There is nothing else to know about animations, other that you have to use CSS - animations, not transitions. -
- -- The dropdown takes care of creating a clone when closing the dropdown so you - animation works in both directions. -
- -+ It's hard to find a proper place in the guides for explaining every single + option in depth, and some of them are so straightforward that they don't + require an example, so use this section as a more exhaustive list. +
+ +| Option | +Type | +Description | +
|---|---|---|
| calculatePosition | +Function |
+ Function to customize how the content of the dropdown is positioned. | +
| class | +String |
+ The class of the dropdown component. Since this component is tagless
+ by default, you need to combine it with the
+ tagName
+ to be effective |
+
| defaultClass | +String |
+ Another way of providing a class to the component without polluting
+ the
+ class
+ attribute. Useful in contextual component to allow users give their own
+ classes while still retaining some defaults |
+
| destination | +String |
+ The id of a DOM element where the dropdown will be rendered using
+ #in-element |
+
| destinationElement | +HTMLElement |
+ Instead of passing
+ destination, you can pass the DOM element where the
+ dropdown will be rendered using
+ #in-element |
+
| contentComponent | +Component |
+ The component to render as content instead of the default content + component. You + probably + don't want to use this option. | +
| horizontalPosition | +String |
+ The horizontal positioning strategy of the content. Can be one of
+ auto
+ (the default),
+ left,
+ center
+ or
+ right |
+
| matchTriggerWidth | +Boolean |
+ (Default:
+ false). Flag that indicates whether or not the content's
+ width should be equal to the width of the trigger. |
+
| preventScroll | +Boolean |
+ (Default:
+ false). Flag that prevents any elements on the page outside
+ the dropdown from scrolling. This matches platform-provided
+ select
+ element behavior. Note that this has no effect when scroll is performed
+ on a touch device |
+
| renderInPlace | +String |
+ When passed
+ true, the content will render next to the trigger instead
+ of being placed in the root of the body. |
+
| initiallyOpened | +Boolean |
+ (Default:
+ false). When passed
+ true
+ the component is first rendered open. Used in combination with
+ preventScroll
+ it changes Fastboot user experience, but other than that it does not
+ alter its behavior. The user can close it as usual. |
+
| tagName | +String |
+ (Default: "") The tag of the component. |
+
| triggerComponent | +Component |
+ The component to render as trigger instead of the default trigger + component. | +
| verticalPosition | +String |
+ The vertical positioning strategy of the content. Can be one of
+ auto
+ (the default),
+ above
+ or
+ below |
+
| registerAPI | +Function |
+ An action that will be invoked with the new public API of the + component every time there is a change in the state of the component. | +
| onOpen | +Function |
+ Action that will be called when the component is about to open.
+ Returning
+ false
+ from this function will prevent the component from being opened. |
+
| onClose | +Function |
+ Action that will be called when the component is about to close.
+ Returning
+ false
+ from this function will prevent the component from being closed. |
+
| rootEventType | +String | +(Default:
+ 'click') The type of mouse event that handles closing the
+ dropdown. Valid values: "mousedown" and "click" |
+
| Option | +Type | +Description | +
|---|---|---|
| ariaDescribedBy | +String | +Maps to aria-described-by |
+
| ariaInvalid | +Boolean | +Maps to aria-invalid |
+
| ariaLabel | +String | +Maps to aria-label |
+
| ariaLabelledBy | +String | +Maps to aria-labeledby |
+
| class | +String | +Extra classes to be added to the trigger components | +
| tabindex | +Number | +Tabindex of the trigger, which defaults to 0 so the trigger is + focusable by default | +
| htmlTag | +String | +(Default: 'div') The tag of the trigger component |
+
| title | +String | +Maps to the title attribute |
+
| eventType | +String | +(Default:
+ 'click') The type of mouse event that triggers the trigger.
+ Valid values: "mousedown" and "click" |
+
| stopPropagation | +Boolean | +(Default:
+ false) Whether the trigger should prevent the propagation
+ of the event that triggers it (click or mousedown) |
+
| Option | +Type | +Description | +
|---|---|---|
| class | +String | +The class of the dropdown's content | +
| animationEnabled | +boolean | +Flag to determine whether the content will allow CSS animations. + Defaults to true | +
| htmlTag | +String | +(Default: 'div') The tag of the content component |
+
| shouldReposition | +Function | +An optional function that can be used to avoid uncecessary
+ repositions. To skip a reposition, simply return
+ false. This function will be invoked when the DOM of the
+ content is changed. It receives two arguments: a
+ MutationRecord
+ and the public API object. |
+
+ All actions and subcomponents of Ember Basic Dropdown receive a single object + containing the entirety of the public API of the component. +
+ ++ Any non-underscored property or action of this object can be considered public + and it's not going to change without causing a major version bump, so if you + are building another component on top of Ember Basic Dropdown, you know that + you are safe as long as you use this object. +
+ +
+ {
+ uniqueId: <string>, // Contains the unique of this instance of EmberBasicDropdown. It's of the form `ember1234`.
+ disabled: <boolean>, // Truthy if the component received `disabled=true`
+ isOpen: <boolean>, // Truthy if the component is currently opened
+ actions: {
+ close() { ... }, // Closes the dropdown
+ open() { ... }, // Opens the dropdown
+ reposition() { ... }, // Repositions the dropdown
+ toggle() { ... } // Toggles the dropdown
+ }
+ }
+
+
+ - It's hard to find a proper place in the guides for explaining every single - option in depth, and some of them are so straightforward that they don't - require an example, so use this section as a more exhaustive list. -
- -| Option | -Type | -Description | -
|---|---|---|
| calculatePosition | -Function |
- Function to customize how the content of the dropdown is positioned. | -
| class | -String |
- The class of the dropdown component. Since this component is tagless
- by default, you need to combine it with the
- tagName
- to be effective |
-
| defaultClass | -String |
- Another way of providing a class to the component without polluting
- the
- class
- attribute. Useful in contextual component to allow users give their own
- classes while still retaining some defaults |
-
| destination | -String |
- The id of a DOM element where the dropdown will be rendered using
- #in-element |
-
| destinationElement | -HTMLElement |
- Instead of passing
- destination, you can pass the DOM element where the
- dropdown will be rendered using
- #in-element |
-
| contentComponent | -Component |
- The component to render as content instead of the default content - component. You - probably - don't want to use this option. | -
| horizontalPosition | -String |
- The horizontal positioning strategy of the content. Can be one of
- auto
- (the default),
- left,
- center
- or
- right |
-
| matchTriggerWidth | -Boolean |
- (Default:
- false). Flag that indicates whether or not the content's
- width should be equal to the width of the trigger. |
-
| preventScroll | -Boolean |
- (Default:
- false). Flag that prevents any elements on the page outside
- the dropdown from scrolling. This matches platform-provided
- select
- element behavior. Note that this has no effect when scroll is performed
- on a touch device |
-
| renderInPlace | -String |
- When passed
- true, the content will render next to the trigger instead
- of being placed in the root of the body. |
-
| initiallyOpened | -Boolean |
- (Default:
- false). When passed
- true
- the component is first rendered open. Used in combination with
- preventScroll
- it changes Fastboot user experience, but other than that it does not
- alter its behavior. The user can close it as usual. |
-
| tagName | -String |
- (Default: "") The tag of the component. |
-
| triggerComponent | -Component |
- The component to render as trigger instead of the default trigger - component. | -
| verticalPosition | -String |
- The vertical positioning strategy of the content. Can be one of
- auto
- (the default),
- above
- or
- below |
-
| registerAPI | -Function |
- An action that will be invoked with the new public API of the - component every time there is a change in the state of the component. | -
| onOpen | -Function |
- Action that will be called when the component is about to open.
- Returning
- false
- from this function will prevent the component from being opened. |
-
| onClose | -Function |
- Action that will be called when the component is about to close.
- Returning
- false
- from this function will prevent the component from being closed. |
-
| rootEventType | -String | -(Default:
- 'click') The type of mouse event that handles closing the
- dropdown. Valid values: "mousedown" and "click" |
-
| Option | -Type | -Description | -
|---|---|---|
| ariaDescribedBy | -String | -Maps to aria-described-by |
-
| ariaInvalid | -Boolean | -Maps to aria-invalid |
-
| ariaLabel | -String | -Maps to aria-label |
-
| ariaLabelledBy | -String | -Maps to aria-labeledby |
-
| class | -String | -Extra classes to be added to the trigger components | -
| tabindex | -Number | -Tabindex of the trigger, which defaults to 0 so the trigger is - focusable by default | -
| htmlTag | -String | -(Default: 'div') The tag of the trigger component |
-
| title | -String | -Maps to the title attribute |
-
| eventType | -String | -(Default:
- 'click') The type of mouse event that triggers the trigger.
- Valid values: "mousedown" and "click" |
-
| stopPropagation | -Boolean | -(Default:
- false) Whether the trigger should prevent the propagation
- of the event that triggers it (click or mousedown) |
-
| Option | -Type | -Description | -
|---|---|---|
| class | -String | -The class of the dropdown's content | -
| animationEnabled | -boolean | -Flag to determine whether the content will allow CSS animations. - Defaults to true | -
| htmlTag | -String | -(Default: 'div') The tag of the content component |
-
| shouldReposition | -Function | -An optional function that can be used to avoid uncecessary
- repositions. To skip a reposition, simply return
- false. This function will be invoked when the DOM of the
- content is changed. It receives two arguments: a
- MutationRecord
- and the public API object. |
-
- All actions and subcomponents of Ember Basic Dropdown receive a single object - containing the entirety of the public API of the component. -
- -- Any non-underscored property or action of this object can be considered public - and it's not going to change without causing a major version bump, so if you - are building another component on top of Ember Basic Dropdown, you know that - you are safe as long as you use this object. -
- -
- {
- uniqueId: <string>, // Contains the unique of this instance of EmberBasicDropdown. It's of the form `ember1234`.
- disabled: <boolean>, // Truthy if the component received `disabled=true`
- isOpen: <boolean>, // Truthy if the component is currently opened
- actions: {
- close() { ... }, // Closes the dropdown
- open() { ... }, // Opens the dropdown
- reposition() { ... }, // Repositions the dropdown
- toggle() { ... } // Toggles the dropdown
- }
- }
-
-
-+ Like the trigger, the dropdown accepts function to bind a few handy events. +
+ +onFocusIn/onFocusOut(dropdown, event)+ Those events are just identical to the ones in the trigger. +
+ +onMouseEnter / onMouseLeave(dropdown, event)+ Used in conjunction with the same events in the trigger it quite easy to make + a dropdown that opens when you hover the trigger and closes leave it, but + stays open if you move from the trigger to the content. +
+ ++ You can even delay the closing a bit to allow the users to briefly pass + outside the boundaries of the dropdown without closing it. Think the navbar of + your favourite social network: +
+ ++ Let's break this down. +
+ +
+ First we
+ <dd.Trigger \{{on "mousedown" this.prevent\\}}>
+ neglect mouse input: Open/close both by click and hover will trip our users.
+
+ Then
+ \{{on "mouseenter" (fn this.open dd)}}
+ and
+ \{{on "mouseleave" (fn this.closeLater dd)}}
+ open a close the dropdown, but we we leave we don't close immediately. Instead
+ we delay the close a few milliseconds as a grace period, allowing the user to
+ transition from the trigger to the content even if the trajectory of the mouse
+ is not perfect.
+
+ If before that grace period they enter again the boundaries of the component,
+ we cancel the scheduled close. This would be much cleaner using
+ ember-concurrency
+ tasks.
+
+ In the following chapters we will learn how to customize the dropdown + behaviour with all the different options. +
+ +- Like the trigger, the dropdown accepts function to bind a few handy events. -
- -onFocusIn/onFocusOut(dropdown, event)- Those events are just identical to the ones in the trigger. -
- -onMouseEnter / onMouseLeave(dropdown, event)- Used in conjunction with the same events in the trigger it quite easy to make - a dropdown that opens when you hover the trigger and closes leave it, but - stays open if you move from the trigger to the content. -
- -- You can even delay the closing a bit to allow the users to briefly pass - outside the boundaries of the dropdown without closing it. Think the navbar of - your favourite social network: -
- -- Let's break this down. -
- -
- First we
- <dd.Trigger \{{on "mousedown" this.prevent\\}}>
- neglect mouse input: Open/close both by click and hover will trip our users.
-
- Then
- \{{on "mouseenter" (fn this.open dd)}}
- and
- \{{on "mouseleave" (fn this.closeLater dd)}}
- open a close the dropdown, but we we leave we don't close immediately. Instead
- we delay the close a few milliseconds as a grace period, allowing the user to
- transition from the trigger to the content even if the trajectory of the mouse
- is not perfect.
-
- If before that grace period they enter again the boundaries of the component,
- we cancel the scheduled close. This would be much cleaner using
- ember-concurrency
- tasks.
-
- In the following chapters we will learn how to customize the dropdown - behaviour with all the different options. -
- -+ In + a previous section + we already say that the dropdown bundles a few positioning strategies both + horizontally and vertically. +
+ ++ But you don't want to be limited to the positioning strategies I designed for + you. You might want the dropdown to float to the left of the trigger or + perhaps one inch south-west of it. +
+ ++ Fear not, my friend, the component has an escape valve for this. You can + design your own positioning function and pass it to the component. It just has + to fulfill a specific contract. +
+ +calculatePosition+ This function is the only thing you have to implement to tell the component + where it should be positioned. +
+ +
+ The complete signature of the function is:
+
+ calculatePosition(trigger, content, destination, {
+ previousHorizontalPosition, horizontalPosition, previousVerticalPosition,
+ verticalPosition, matchTriggerWidth })
+
+
trigger: The DOM element of the trigger componentcontent: The DOM element of the content componentdestination: The DOM element where the content component is
+ going to be insertedpreviousHorizontalPosition: The string with the horizontal
+ position the component had in the last time it was repositioned. If you
+ don't provide any or you pass
+ horizontalPosition="auto"
+ it will be
+ "left"
+ or
+ "right"
+ depending on the space around the triggerhorizontalPosition: The string with the current horizontal
+ position. If you don't provide any or you pass
+ horizontalPosition="auto"
+ it will be
+ "left"
+ or
+ "right"
+ depending on the space around the triggerpreviousVerticalPosition: The string with the vertical
+ position the component had in the last time it was repositioned. If you
+ don't provide any or you pass
+ verticalPosition="auto"
+ it will be
+ "above"
+ or
+ "below"
+ depending on the space around the triggerverticalPosition: The string with the current vertical
+ position. If you don't provide any or you pass
+ verticalPosition="auto"
+ it will be
+ "above"
+ or
+ "below"
+ depending on the space around the triggermatchTriggerWidth: Boolean that express the intention of the
+ developer to make the dropdown have the same width as the triggerrenderInPlace: Boolean that express if the content will be
+ rendered in place. Useful since very usually the reposition logic must be
+ entirely different
+ The return value of this function must also be an object with a specific
+ shape:
+
+ { horizontalPosition, verticalPosition, style }
+
horizontalPosition: The new value of horizontalPositionverticalPosition: The new value of verticalPositionstyle: An object containing the CSS properties that will
+ position the object. It supports
+ top,
+ left,
+ right
+ and
+ width+ Sounds like a lot, but with an example you will see that it's not really hard. + Let's create a dropdown that opens to the right of the trigger, vertically + centered with it. +
+ +
+ You can resize the window and scroll and you can see that the content stays
+ just where it should. It will even reposition automatically if the content
+ inside changes thanks to the magic of
+ MutationObservers.
+
+ The key concept that you need to extract is that all the machinery to position + the content and reposition when the content, scroll or screen changes is + handled by the dropdown, so the only missing piece you have to provide is the + function that calculates the cordinates. +
+ +- In - a previous section - we already say that the dropdown bundles a few positioning strategies both - horizontally and vertically. -
- -- But you don't want to be limited to the positioning strategies I designed for - you. You might want the dropdown to float to the left of the trigger or - perhaps one inch south-west of it. -
- -- Fear not, my friend, the component has an escape valve for this. You can - design your own positioning function and pass it to the component. It just has - to fulfill a specific contract. -
- -calculatePosition- This function is the only thing you have to implement to tell the component - where it should be positioned. -
- -
- The complete signature of the function is:
-
- calculatePosition(trigger, content, destination, {
- previousHorizontalPosition, horizontalPosition, previousVerticalPosition,
- verticalPosition, matchTriggerWidth })
-
-
trigger: The DOM element of the trigger componentcontent: The DOM element of the content componentdestination: The DOM element where the content component is
- going to be insertedpreviousHorizontalPosition: The string with the horizontal
- position the component had in the last time it was repositioned. If you
- don't provide any or you pass
- horizontalPosition="auto"
- it will be
- "left"
- or
- "right"
- depending on the space around the triggerhorizontalPosition: The string with the current horizontal
- position. If you don't provide any or you pass
- horizontalPosition="auto"
- it will be
- "left"
- or
- "right"
- depending on the space around the triggerpreviousVerticalPosition: The string with the vertical
- position the component had in the last time it was repositioned. If you
- don't provide any or you pass
- verticalPosition="auto"
- it will be
- "above"
- or
- "below"
- depending on the space around the triggerverticalPosition: The string with the current vertical
- position. If you don't provide any or you pass
- verticalPosition="auto"
- it will be
- "above"
- or
- "below"
- depending on the space around the triggermatchTriggerWidth: Boolean that express the intention of the
- developer to make the dropdown have the same width as the triggerrenderInPlace: Boolean that express if the content will be
- rendered in place. Useful since very usually the reposition logic must be
- entirely different
- The return value of this function must also be an object with a specific
- shape:
-
- { horizontalPosition, verticalPosition, style }
-
horizontalPosition: The new value of horizontalPositionverticalPosition: The new value of verticalPositionstyle: An object containing the CSS properties that will
- position the object. It supports
- top,
- left,
- right
- and
- width- Sounds like a lot, but with an example you will see that it's not really hard. - Let's create a dropdown that opens to the right of the trigger, vertically - centered with it. -
- -
- You can resize the window and scroll and you can see that the content stays
- just where it should. It will even reposition automatically if the content
- inside changes thanks to the magic of
- MutationObservers.
-
- The key concept that you need to extract is that all the machinery to position - the content and reposition when the content, scroll or screen changes is - handled by the dropdown, so the only missing piece you have to provide is the - function that calculates the cordinates. -
- -+ If you disable the dropdown, it will not open or close by any mean, mouse, + keyboard or touch screen. +
+ +
+ Note that being disabled does not prevent the dropdown or any of its
+ sub-components from firing events like
+ onMouseEnter.
+
+ The component takes care by default of usual good practices, removing the
+ tabindex
+ of the trigger and set
+ [aria-disabled="true"]
+ to assist screen readers.
+
- If you disable the dropdown, it will not open or close by any mean, mouse, - keyboard or touch screen. -
- -
- Note that being disabled does not prevent the dropdown or any of its
- sub-components from firing events like
- onMouseEnter.
-
- The component takes care by default of usual good practices, removing the
- tabindex
- of the trigger and set
- [aria-disabled="true"]
- to assist screen readers.
-
+ Although the top-level component is tagless, it does fire a few events that + you can use to react to changes in the state of the dropdown. +
+ ++ This has no mystery. +
+ +onOpen(dropdown, event?)
+ Pretty self-explanatory. The
+ dropdown
+ argument in the signature is the public API of the component. The
+ event
+ argument will be passed if this event is fired as a consequence of another
+ event (e.g. a click), but will be undefined if it was fired programmatically.
+
What kinds of things you can do with this event?
+ ++ In general when you want to do something outside the component when this + loads. By example, you can delay the loading of some data until the dropdown + is opened. +
+ +
+ There is something you should know about this hook: If you
+ return false;
+ from it you will prevent the component from opening.
+
+ Let's use this feature along with the public API and event received as + aguments to do a nifty trick. We are going to iterate over the example above + so we prevent the component from opening, load the users and once loaded we + open it. +
+ +For the record, I don't think this is good UX
+ +onClose(dropdown, event?)
+ Symmetrically, you can perform on action when the dropdown is closed. For
+ example, save the a user selection, and you can also
+ return false
+ to prevent the component from closing.
+
+ Example: Create a dropdown with some checkboxes inside, and don't allow it to + close until one checkbox is selected. +
+ +Cruel, isn't it?
+ ++ Those were the events fired by the top-level component, now let's go deep on + the events that are fired by the trigger. +
+ +- Although the top-level component is tagless, it does fire a few events that - you can use to react to changes in the state of the dropdown. -
- -- This has no mystery. -
- -onOpen(dropdown, event?)
- Pretty self-explanatory. The
- dropdown
- argument in the signature is the public API of the component. The
- event
- argument will be passed if this event is fired as a consequence of another
- event (e.g. a click), but will be undefined if it was fired programmatically.
-
What kinds of things you can do with this event?
- -- In general when you want to do something outside the component when this - loads. By example, you can delay the loading of some data until the dropdown - is opened. -
- -
- There is something you should know about this hook: If you
- return false;
- from it you will prevent the component from opening.
-
- Let's use this feature along with the public API and event received as - aguments to do a nifty trick. We are going to iterate over the example above - so we prevent the component from opening, load the users and once loaded we - open it. -
- -For the record, I don't think this is good UX
- -onClose(dropdown, event?)
- Symmetrically, you can perform on action when the dropdown is closed. For
- example, save the a user selection, and you can also
- return false
- to prevent the component from closing.
-
- Example: Create a dropdown with some checkboxes inside, and don't allow it to - close until one checkbox is selected. -
- -Cruel, isn't it?
- -- Those were the events fired by the top-level component, now let's go deep on - the events that are fired by the trigger. -
- -+ This component is built with a technique known as + Contextual Components. If you haven't heard of it, check + the official guides + for some background. +
+ +
+ The basic usage is pretty simple. There are no mandatory fields. Just invoke
+ the
+ basic-dropdown
+ component which yields the public API to its block. That top-level component
+ has no markup, just pure behaviour. Once inside the block, the yielded API has
+ two contextual components on it that you can use:
+ trigger
+ and
+ content.
+
+ Go, use it and inspect the DOM. I know it looks ugly, we'll style it later. +
+ ++ As you've inspected, the markup is very simple. +
+
+ The
+ \{{dd.Trigger}}
+ component generates a simple div with some self-explainatory classes and
+ \{{dd.Content}}
+ doesn't render anything until you open the select.
+
+ Out of the box the component already takes care of most things you need. +
+ ++ First of all, the component opens when you click on the trigger and closes + when you click anywhere else in the page. If you are reading this on a + smartphone you can also see that it opens when you tap on the trigger and it + already distinguishes proper taps from taps used for scrolling. The dropdown + is rendered not next to the trigger, but in a placeholder div in the root of + the application and positioned automatically with inline styles. +
+ ++ Lastly, if you inspect the DOM a second time you can see all the + a11y + machinery in place to make the component accesible. Even the trigger, despite + being a div, is focusable as it should be for a good keyboard experience. Also + if you have the trigger focus, you can open and close it with the enter or + space keys. +
+ ++ Now let's fix that terrible look. I'll give the dropdown a look and feel + inspired by dropdown buttons in bootstrap: +
+ ++ It just took a little bit of CSS. You could also have just assigned the right + classes and reused the styles from the framework (I can't demo that because I + don't have bootstrap here). +
+ ++ I want to stress that when it comes to CSS, the dropdown really doesn't care. + Let's make a material-like round button with a round content. +
+ ++ I got you. +
+ ++ And this is more or less everything you need to know about styles. Basically + there is none, so you can add create your own in CSS or reuse the classes that + CSS frameworks give you. +
+ ++ In the next section we will see the basic action hooks that this component + gives you to hook to events like opening and closing and many others. +
+ +- This component is built with a technique known as - Contextual Components. If you haven't heard of it, check - the official guides - for some background. -
- -
- The basic usage is pretty simple. There are no mandatory fields. Just invoke
- the
- basic-dropdown
- component which yields the public API to its block. That top-level component
- has no markup, just pure behaviour. Once inside the block, the yielded API has
- two contextual components on it that you can use:
- trigger
- and
- content.
-
- Go, use it and inspect the DOM. I know it looks ugly, we'll style it later. -
- -- As you've inspected, the markup is very simple. -
-
- The
- \{{dd.Trigger}}
- component generates a simple div with some self-explainatory classes and
- \{{dd.Content}}
- doesn't render anything until you open the select.
-
- Out of the box the component already takes care of most things you need. -
- -- First of all, the component opens when you click on the trigger and closes - when you click anywhere else in the page. If you are reading this on a - smartphone you can also see that it opens when you tap on the trigger and it - already distinguishes proper taps from taps used for scrolling. The dropdown - is rendered not next to the trigger, but in a placeholder div in the root of - the application and positioned automatically with inline styles. -
- -- Lastly, if you inspect the DOM a second time you can see all the - a11y - machinery in place to make the component accesible. Even the trigger, despite - being a div, is focusable as it should be for a good keyboard experience. Also - if you have the trigger focus, you can open and close it with the enter or - space keys. -
- -- Now let's fix that terrible look. I'll give the dropdown a look and feel - inspired by dropdown buttons in bootstrap: -
- -- It just took a little bit of CSS. You could also have just assigned the right - classes and reused the styles from the framework (I can't demo that because I - don't have bootstrap here). -
- -- I want to stress that when it comes to CSS, the dropdown really doesn't care. - Let's make a material-like round button with a round content. -
- -- I got you. -
- -- And this is more or less everything you need to know about styles. Basically - there is none, so you can add create your own in CSS or reuse the classes that - CSS frameworks give you. -
- -- In the next section we will see the basic action hooks that this component - gives you to hook to events like opening and closing and many others. -
- -I'm going to tell you the story of how this dropdown addon was born.
+ ++ I was building a select component but I realized that a select is nothing more + than a dropdown with some extra stuff on top. And datepickers too. And + colorpickers, contextual menus and many other widgets. +
+ ++ Essentially, any floating box of content that is opened when you interact with + a trigger is basically a dropdown. Dropdowns are the foundation to at least + half a dozen common UI widgets we use daily, so I decided to shape this addon + in a way that was easy to reuse and customize to create those other widgets. +
+ ++ But if a dropdown is just a floating box activated by a trigger, + why would you want to use a third part addon for such a simple thing? +
+ ++ Well, there are two kinds of people. Those who think that dropdowns + are an easy thing and those who have actually built one. +
+ ++ When I transitioned from the first kind to the second I learned a lot of + stuff. +
+ ++ After I built the initial version, I started to build other widgets on top and + I had to step back a few times and identify where it wasn't flexible enough. + This process ended up in a component that distilled the essence of what a + dropdown is with as few assumptions as possible. +
+ ++ I honestly want to save you time and tears. I've been there. +
+ ++ This component is a + building block + for you to build other components on top, so it prioritizes flexibility and + explicitness over succinctness in its API, but still allows allows basic usage + out of the box with no ceremony. +
+ ++ Another thing to note is that this component doesn't have any theme by + default, so unless you do something about it, it will look pretty ugly. The + few styles it has are only to deal with positioning. +
+ +I hope you like it.
+ +I'm going to tell you the story of how this dropdown addon was born.
- -- I was building a select component but I realized that a select is nothing more - than a dropdown with some extra stuff on top. And datepickers too. And - colorpickers, contextual menus and many other widgets. -
- -- Essentially, any floating box of content that is opened when you interact with - a trigger is basically a dropdown. Dropdowns are the foundation to at least - half a dozen common UI widgets we use daily, so I decided to shape this addon - in a way that was easy to reuse and customize to create those other widgets. -
- -- But if a dropdown is just a floating box activated by a trigger, - why would you want to use a third part addon for such a simple thing? -
- -- Well, there are two kinds of people. Those who think that dropdowns - are an easy thing and those who have actually built one. -
- -- When I transitioned from the first kind to the second I learned a lot of - stuff. -
- -- After I built the initial version, I started to build other widgets on top and - I had to step back a few times and identify where it wasn't flexible enough. - This process ended up in a component that distilled the essence of what a - dropdown is with as few assumptions as possible. -
- -- I honestly want to save you time and tears. I've been there. -
- -- This component is a - building block - for you to build other components on top, so it prioritizes flexibility and - explicitness over succinctness in its API, but still allows allows basic usage - out of the box with no ceremony. -
- -- Another thing to note is that this component doesn't have any theme by - default, so unless you do something about it, it will look pretty ugly. The - few styles it has are only to deal with positioning. -
- -I hope you like it.
- -+ Ember-basic-dropdown is distributed as an + Ember CLI + addon. To install it, run the following command in your ember project + directory +
+ +$ ember install
+ ember-basic-dropdown
+
+ When installing this through
+ ember install
+ the addon will add the necessary snippet above automatically in your app.
+
+ After the installation you need to add the following lines somewhere in your
+ templates where you want to render the dropdown content into e.g. your
+ application.hbs. In this component will be rendered the dropdown
+ content.
+
+ If you use vanilla CSS, you need to add the following line into
+ app.js
+ or in any route/controller/component
+ .js/.ts
+ file:
+
+ Instead of adding the styling in an
+ .js
+ file and depending from your build config you can also add the css in any
+ template/component css file by using following line
+
+ However, if you are using SASS or LESS you need to add an import statement to + your styles. +
+ +
+ If you are using LESS there is also necessary to register the
+ paths
+ in
+ lessOptions
+
+ The styles of the addon are + very minimal + and deal mostly with positioning. You can tweak a couple things but we'll get + to that later. +
+ ++ Now let's learn the API of the component. +
+ +- Ember-basic-dropdown is distributed as an - Ember CLI - addon. To install it, run the following command in your ember project - directory -
- -$ ember install
- ember-basic-dropdown
-
- When installing this through
- ember install
- the addon will add the necessary snippet above automatically in your app.
-
- After the installation you need to add the following lines somewhere in your
- templates where you want to render the dropdown content into e.g. your
- application.hbs. In this component will be rendered the dropdown
- content.
-
- If you use vanilla CSS, you need to add the following line into
- app.js
- or in any route/controller/component
- .js/.ts
- file:
-
- Instead of adding the styling in an
- .js
- file and depending from your build config you can also add the css in any
- template/component css file by using following line
-
- However, if you are using SASS or LESS you need to add an import statement to - your styles. -
- -{{#let (get-code-snippet "installation-1.scss") as |snippet|}} -
- If you are using LESS there is also necessary to register the
- paths
- in
- lessOptions
-
- The styles of the addon are - very minimal - and deal mostly with positioning. You can tweak a couple things but we'll get - to that later. -
- -- Now let's learn the API of the component. -
- -The addon is now a + V2 + Embroider Addon. The following changes are necessary:
+ +Add following line to your application.hbs
Vanilla JS: If you have used vanilla js you must now import the css in
+ app.js
+ manually like (for other css adding examples see under installation)
LESS: If you are using with less you need to add
+ lessOptions
+ into your
+ ember-cli-build.js
+ file
Typescript: There were added / modified / fixed the typescript + declarations. This could be braking for consumer app
+The addon is now a - V2 - Embroider Addon. The following changes are necessary:
- -Add following line to your application.hbs
Vanilla JS: If you have used vanilla js you must now import the css in
- app.js
- manually like (for other css adding examples see under installation)
LESS: If you are using with less you need to add
- lessOptions
- into your
- ember-cli-build.js
- file
Typescript: There were added / modified / fixed the typescript - declarations. This could be braking for consumer app
-+ By default the dropdown renders floating above the rest of your page but it + doesn't prevent the user from clicking on any other item. Overlays can fix + that and make dropdowns look cooler. +
+ ++ What do you have to know: +
+ +$ember-basic-dropdown-overlay-background
+ SASS variable or target the
+ .ember-basic-dropdown-overlay
+ pointer-events: none, so it is transparent to clicks but you
+ can change that using the
+ $ember-basic-dropdown-overlay-pointer-events
+ SASS variable or target the same class.
+ + In the next section we'll talk more how to customize the styles. +
+ +- By default the dropdown renders floating above the rest of your page but it - doesn't prevent the user from clicking on any other item. Overlays can fix - that and make dropdowns look cooler. -
- -- What do you have to know: -
- -$ember-basic-dropdown-overlay-background
- SASS variable or target the
- .ember-basic-dropdown-overlay
- pointer-events: none, so it is transparent to clicks but you
- can change that using the
- $ember-basic-dropdown-overlay-pointer-events
- SASS variable or target the same class.
- - In the next section we'll talk more how to customize the styles. -
- -+ The number one thing that you will want to customize in a dropdown is where + the floating content will be positioned in relation to the trigger. +
+ +horizontalPosition / verticalPosition+ Ember Basic Dropdown comes with a nice set of defaults. The rules are as + follow: +
+ +<dd.Content>
+ has not pre-defined size, so it will adapt to the size its childs.
+ This sounds like a lot, but with an example it will be crystal clear.
+ +
+ In this example above I'm using the options
+ verticalPosition
+ and
+ horizontalPosition
+ to override the default behaviour.
+
+ The default value for both options is
+ auto, but you can pass
+ verticalPosition=above|below
+ and
+ horizontalPosition=auto-right|right|center|left.
+
Narrow the window of the browser and play with scroll to see the automatic + positioning in action.
+ +renderInPlace+ Although by default the component renders the content in the root of the app + and positions it absolutely, there are some situations where you want the + content to be + physically + next to the trigger. +
+ +
+ To do so, pass
+ renderInPlace=true
+ to the component. Inspect the DOM of the next example to see the difference.
+
+ Please note that when rendering the content in place, the vertical position
+ will not automatically detect the best position based on the space around the
+ trigger. You have to explicitly pass
+ verticalPosition="above"
+ to render it over the trigger.
+
matchTriggerWidth+ There is a few widgets in which the width of the floating box has to match the + width of the trigger design reasons. Since this is common enough, there is an + option to enable this behaviour. +
+ ++ In the section about + Custom Position + strategies we will see how to totally customize how the dropdown is positioned + by passing it a function. If you do so the options in this section will not + work unless your function, which will receive those options, honors them. +
+ +- The number one thing that you will want to customize in a dropdown is where - the floating content will be positioned in relation to the trigger. -
- -horizontalPosition / verticalPosition- Ember Basic Dropdown comes with a nice set of defaults. The rules are as - follow: -
- -<dd.Content>
- has not pre-defined size, so it will adapt to the size its childs.
- This sounds like a lot, but with an example it will be crystal clear.
- -
- In this example above I'm using the options
- verticalPosition
- and
- horizontalPosition
- to override the default behaviour.
-
- The default value for both options is
- auto, but you can pass
- verticalPosition=above|below
- and
- horizontalPosition=auto-right|right|center|left.
-
Narrow the window of the browser and play with scroll to see the automatic - positioning in action.
- -renderInPlace- Although by default the component renders the content in the root of the app - and positions it absolutely, there are some situations where you want the - content to be - physically - next to the trigger. -
- -
- To do so, pass
- renderInPlace=true
- to the component. Inspect the DOM of the next example to see the difference.
-
- Please note that when rendering the content in place, the vertical position
- will not automatically detect the best position based on the space around the
- trigger. You have to explicitly pass
- verticalPosition="above"
- to render it over the trigger.
-
matchTriggerWidth- There is a few widgets in which the width of the floating box has to match the - width of the trigger design reasons. Since this is common enough, there is an - option to enable this behaviour. -
- -- In the section about - Custom Position - strategies we will see how to totally customize how the dropdown is positioned - by passing it a function. If you do so the options in this section will not - work unless your function, which will receive those options, honors them. -
- -+ Since this component doesn't any visual theme, you can apply styles to it just + with plain CSS or even adding the classes your favourite CSS framework gives + you. +
+ +
+ If don't use any css pre-processor this is all. If you do use SASS or LESS,
+ the addon will know it and will have to
+ @import
+ the styles explicitly. This gives you the chance to set a few variables that
+ Ember Basic Dropdown will use.
+
+ There is only four variables you can tweak (Sass syntax) +
+ +
+ If by example you want to change the colour of the overlay to be blue, you
+ could do this in your
+ app.scss/app.less.
+
+ In the next sections we'll give in more involved customizations. +
+ +- Since this component doesn't any visual theme, you can apply styles to it just - with plain CSS or even adding the classes your favourite CSS framework gives - you. -
- -
- If don't use any css pre-processor this is all. If you do use SASS or LESS,
- the addon will know it and will have to
- @import
- the styles explicitly. This gives you the chance to set a few variables that
- Ember Basic Dropdown will use.
-
- There is only four variables you can tweak (Sass syntax) -
- -{{#let (get-code-snippet "styles-1.scss") as |snippet|}} -
- If by example you want to change the colour of the overlay to be blue, you
- could do this in your
- app.scss/app.less.
-
- In the next sections we'll give in more involved customizations. -
- -
+ Ember Basic Dropdown bundles some handy test helpers (clickDropdown
+ and
+ tapDropdown) that make it easier to simulate user interaction in
+ acceptance tests.
+
+ You can just have to import them at the top of your tests and call them
+ preceded by
+ await.
+
clickTrigger(scope = null, eventOptions)
+ Simulates a click to open or close the dropdown. As all integration test
+ helpers is already runloop aware, so you don't need to wrap it in
+ Ember.run.
+
+ In case there is more than one dropdown rendered at the same time you can pass + a string with the scope to trigger it over the desired one. +
+ +tapTrigger(scope = null, eventOptions)
+ Identical to
+ clickTrigger
+ but simulates a tap instead.
+
- Ember Basic Dropdown bundles some handy test helpers (clickDropdown
- and
- tapDropdown) that make it easier to simulate user interaction in
- acceptance tests.
-
- You can just have to import them at the top of your tests and call them
- preceded by
- await.
-
clickTrigger(scope = null, eventOptions)
- Simulates a click to open or close the dropdown. As all integration test
- helpers is already runloop aware, so you don't need to wrap it in
- Ember.run.
-
- In case there is more than one dropdown rendered at the same time you can pass - a string with the scope to trigger it over the desired one. -
- -{{#let (get-code-snippet "test-helpers-2-js.js") as |snippet|}} -tapTrigger(scope = null, eventOptions)
- Identical to
- clickTrigger
- but simulates a tap instead.
-
+ The trigger is the component in charge of opening and closing the dropdown
+ (although it also closes if you click outside it). By default the event that
+ to which the trigger reacts is the
+ click
+ event.
+
+ You can change that passing the
+ eventType="mousedown"
+ to the trigger. Check below for both approaches. The difference is subtle.
+
+ This does not affect to the behavior of the dropdown on touch devices. On
+ mobile or tablets the dropdown automatically depends on the
+ "touchend"
+ event.
+
+ As with any regular HTML element, you can attach events to the trigger using
+ the
+ \{{on}}
+ element modifier. The events you subscribe to using this approach will aways
+ run before the default events that this component attaches, giving you a
+ chance to prevent the default behavior by calling
+ event.stopImmediatePropagation().
+
+ What can you do with this? Let's see some examples. +
+ +\{{on "keydown"}}+ One real world situation where I found this to be necessary, is when you want + to open the dropdown with a key that usually does not open it, like by example + the arrow keys. +
+ +
+ As with any other event, calling
+ e.stopImmediatePropagation()
+ will stop the default handler from running, so you can use this action to
+ prevent the
+ space,
+ enter
+ and
+ esc
+ keys from doing what they do by default.
+
\{{on "click"}}
+ The
+ click
+ event is the one that usually opens the dropdown, but you can pass your own
+ function.
+
+ Good examples of this are preventing the component from opening with the mouse + and/or react in some way to those attempts. +
+ +\{{on "touchend"}}
+ Exactly identical to
+ \{{on "click"}}
+ but for touch screens. I'm not even going to create another example.
+
\{{on "mouseenter"}} / \{{on "mouseleave"}}+ I use this event to open the dropdown when you hover it and close it when you + leave but you can really use it a lot more. +
+ ++ By example, imagine that a dropdown is disabled and you want to highlight some + other element in the form that the user must enable first. +
+ +\{{on "focus"}}/\{{on "blur"}}
+ I've used this two events in conjuntion to style a parent element while some
+ of the components inside it have the focus, achieving a poor mans' version of
+ the upcoming CSS
+ :focus-within
+ pseudo selector.
+
+ This is the most involved example yet. Both the text input and the trigger are + focusable on their own, but by tracking when they get and loose the focus we + simulate that the entire input-group is focused, which would be impossible + just just CSS today. +
+ ++ Right now this behavior cannot be achieved across browsers without some help + from javascript. +
+ ++ Those are just some examples of the kind of behaviors you can implement adding + custom events to the trigger. +
+ +
- The trigger is the component in charge of opening and closing the dropdown
- (although it also closes if you click outside it). By default the event that
- to which the trigger reacts is the
- click
- event.
-
- You can change that passing the
- eventType="mousedown"
- to the trigger. Check below for both approaches. The difference is subtle.
-
- This does not affect to the behavior of the dropdown on touch devices. On
- mobile or tablets the dropdown automatically depends on the
- "touchend"
- event.
-
- As with any regular HTML element, you can attach events to the trigger using
- the
- \{{on}}
- element modifier. The events you subscribe to using this approach will aways
- run before the default events that this component attaches, giving you a
- chance to prevent the default behavior by calling
- event.stopImmediatePropagation().
-
- What can you do with this? Let's see some examples. -
- -\{{on "keydown"}}- One real world situation where I found this to be necessary, is when you want - to open the dropdown with a key that usually does not open it, like by example - the arrow keys. -
- -
- As with any other event, calling
- e.stopImmediatePropagation()
- will stop the default handler from running, so you can use this action to
- prevent the
- space,
- enter
- and
- esc
- keys from doing what they do by default.
-
\{{on "click"}}
- The
- click
- event is the one that usually opens the dropdown, but you can pass your own
- function.
-
- Good examples of this are preventing the component from opening with the mouse - and/or react in some way to those attempts. -
- -\{{on "touchend"}}
- Exactly identical to
- \{{on "click"}}
- but for touch screens. I'm not even going to create another example.
-
\{{on "mouseenter"}} / \{{on "mouseleave"}}- I use this event to open the dropdown when you hover it and close it when you - leave but you can really use it a lot more. -
- -- By example, imagine that a dropdown is disabled and you want to highlight some - other element in the form that the user must enable first. -
- -\{{on "focus"}}/\{{on "blur"}}
- I've used this two events in conjuntion to style a parent element while some
- of the components inside it have the focus, achieving a poor mans' version of
- the upcoming CSS
- :focus-within
- pseudo selector.
-
- This is the most involved example yet. Both the text input and the trigger are - focusable on their own, but by tracking when they get and loose the focus we - simulate that the entire input-group is focused, which would be impossible - just just CSS today. -
- -- Right now this behavior cannot be achieved across browsers without some help - from javascript. -
- -- Those are just some examples of the kind of behaviors you can implement adding - custom events to the trigger. -
- -
+ needs
+
- needs
- cause of glint bug
---
.../public-pages/docs/api-reference.gts | 23 +++++++++----------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/docs/app/templates/public-pages/docs/api-reference.gts b/docs/app/templates/public-pages/docs/api-reference.gts
index b448fbd9..5f48c5d8 100644
--- a/docs/app/templates/public-pages/docs/api-reference.gts
+++ b/docs/app/templates/public-pages/docs/api-reference.gts
@@ -291,19 +291,18 @@ import { LinkTo } from "@ember/routing";
you are safe as long as you use this object.
-
- {
- uniqueId: <string>, // Contains the unique of this instance of EmberBasicDropdown. It's of the form `ember1234`.
- disabled: <boolean>, // Truthy if the component received `disabled=true`
- isOpen: <boolean>, // Truthy if the component is currently opened
- actions: {
- close() { ... }, // Closes the dropdown
- open() { ... }, // Opens the dropdown
- reposition() { ... }, // Repositions the dropdown
- toggle() { ... } // Toggles the dropdown
- }
+
+ {
+ uniqueId: <string>, // Contains the unique of this instance of EmberBasicDropdown. It's of the form 'ember1234'.
+ disabled: <boolean>, // Truthy if the component received 'disabled=true'
+ isOpen: <boolean>, // Truthy if the component is currently opened
+ actions: {
+ close() { ... }, // Closes the dropdown
+ open() { ... }, // Opens the dropdown
+ reposition() { ... }, // Repositions the dropdown
+ toggle() { ... } // Toggles the dropdown
}
+ }
From bc7521ef400bed38f7bd8c22b7ceb2504d89d673 Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 08:23:26 +0200
Subject: [PATCH 10/22] Fix prettier
---
docs/app/components/code-block.gts | 6 +---
docs/app/components/code-example.gts | 17 ++++++----
docs/app/components/code-inline.gts | 4 +--
.../components/snippets/content-events-1.gts | 9 +++--
.../components/snippets/custom-position-1.gts | 12 +++++--
.../components/snippets/custom-position-2.gts | 12 +++++--
.../components/snippets/dropdown-events-2.gts | 4 ++-
.../components/snippets/installation-0.gts | 4 +--
...tallation-1.css => installation-1.css.txt} | 0
docs/app/components/snippets/position-1.gts | 5 ++-
.../components/snippets/trigger-events-0.gts | 5 +--
.../components/snippets/trigger-events-1.gts | 9 +++--
.../components/snippets/trigger-events-2.gts | 5 ++-
.../components/snippets/trigger-events-3.gts | 5 ++-
docs/app/templates/helpers-testing.gts | 2 +-
docs/app/templates/public-pages.gts | 18 +++++++---
docs/app/templates/public-pages/cookbook.gts | 6 ++--
.../templates/public-pages/cookbook/index.gts | 20 +++++------
.../public-pages/docs/animations.gts | 3 +-
.../public-pages/docs/api-reference.gts | 33 +++++++++---------
.../public-pages/docs/content-events.gts | 22 ++++++------
.../public-pages/docs/custom-position.gts | 26 +++++++-------
.../public-pages/docs/dropdown-events.gts | 7 ++--
.../public-pages/docs/how-to-use-it.gts | 26 +++++++-------
.../app/templates/public-pages/docs/index.gts | 25 +++++++-------
.../public-pages/docs/installation.gts | 30 +++++++++++-----
.../public-pages/docs/migrate-7-0-to-8-0.gts | 6 +++-
.../templates/public-pages/docs/position.gts | 31 +++++++++--------
.../templates/public-pages/docs/styles.gts | 6 ++--
.../public-pages/docs/test-helpers.gts | 8 ++---
.../public-pages/docs/trigger-events.gts | 34 +++++++++----------
docs/app/templates/public-pages/index.gts | 10 +++---
32 files changed, 236 insertions(+), 174 deletions(-)
rename docs/app/components/snippets/{installation-1.css => installation-1.css.txt} (100%)
diff --git a/docs/app/components/code-block.gts b/docs/app/components/code-block.gts
index ecd8f2e8..351001b5 100644
--- a/docs/app/components/code-block.gts
+++ b/docs/app/components/code-block.gts
@@ -17,11 +17,7 @@ export default class CodeBlock extends Component {
{{~! ~}}
-
+
{{~! ~}}
diff --git a/docs/app/components/code-example.gts b/docs/app/components/code-example.gts
index b21adc8f..91d63a1c 100644
--- a/docs/app/components/code-example.gts
+++ b/docs/app/components/code-example.gts
@@ -19,10 +19,10 @@ interface CodeExampleSignature {
scss?: string;
activeTab?: string;
showResult?: boolean;
- },
+ };
Blocks: {
- default: []
- }
+ default: [];
+ };
}
export default class CodeExample extends Component {
@@ -33,7 +33,10 @@ export default class CodeExample extends Component {
}
get activeTab() {
- return this._activeTab || (this.showResult ? 'result' : this.args.activeTab || 'js');
+ return (
+ this._activeTab ||
+ (this.showResult ? 'result' : this.args.activeTab || 'js')
+ );
}
@action
@@ -46,7 +49,8 @@ export default class CodeExample extends Component {
Booleanfalse). Flag that prevents any elements on the page outside
- the dropdown from scrolling. This matches platform-provided
+ false). Flag that prevents any elements on the page
+ outside the dropdown from scrolling. This matches platform-provided
select
- element behavior. Note that this has no effect when scroll is performed
- on a touch device'click') The type of mouse event that triggers the trigger.
- Valid values: "mousedown" and "click"'click') The type of mouse event that triggers the
+ trigger. Valid values: "mousedown" and "click"
- All actions and subcomponents of Ember Basic Dropdown receive a single object - containing the entirety of the public API of the component. + All actions and subcomponents of Ember Basic Dropdown receive a single + object containing the entirety of the public API of the component.
- Any non-underscored property or action of this object can be considered public - and it's not going to change without causing a major version bump, so if you - are building another component on top of Ember Basic Dropdown, you know that - you are safe as long as you use this object. + Any non-underscored property or action of this object can be considered + public and it's not going to change without causing a major version bump, so + if you are building another component on top of Ember Basic Dropdown, you + know that you are safe as long as you use this object.
-
+
{
uniqueId: <string>, // Contains the unique of this instance of EmberBasicDropdown. It's of the form 'ember1234'.
disabled: <boolean>, // Truthy if the component received 'disabled=true'
diff --git a/docs/app/templates/public-pages/docs/content-events.gts b/docs/app/templates/public-pages/docs/content-events.gts
index 0367a428..129d6ba4 100644
--- a/docs/app/templates/public-pages/docs/content-events.gts
+++ b/docs/app/templates/public-pages/docs/content-events.gts
@@ -18,15 +18,15 @@ import ContentEvents1Component from '../../../components/snippets/content-events
onMouseEnter / onMouseLeave(dropdown, event)
- Used in conjunction with the same events in the trigger it quite easy to make
- a dropdown that opens when you hover the trigger and closes leave it, but
- stays open if you move from the trigger to the content.
+ Used in conjunction with the same events in the trigger it quite easy to
+ make a dropdown that opens when you hover the trigger and closes leave it,
+ but stays open if you move from the trigger to the content.
You can even delay the closing a bit to allow the users to briefly pass
- outside the boundaries of the dropdown without closing it. Think the navbar of
- your favourite social network:
+ outside the boundaries of the dropdown without closing it. Think the navbar
+ of your favourite social network:
@@ -48,15 +48,15 @@ import ContentEvents1Component from '../../../components/snippets/content-events
\{{on "mouseenter" (fn this.open dd)}}
and
\{{on "mouseleave" (fn this.closeLater dd)}}
- open a close the dropdown, but we we leave we don't close immediately. Instead
- we delay the close a few milliseconds as a grace period, allowing the user to
- transition from the trigger to the content even if the trajectory of the mouse
- is not perfect.
+ open a close the dropdown, but we we leave we don't close immediately.
+ Instead we delay the close a few milliseconds as a grace period, allowing
+ the user to transition from the trigger to the content even if the
+ trajectory of the mouse is not perfect.
- If before that grace period they enter again the boundaries of the component,
- we cancel the scheduled close. This would be much cleaner using
+ If before that grace period they enter again the boundaries of the
+ component, we cancel the scheduled close. This would be much cleaner using
ember-concurrency
tasks.
diff --git a/docs/app/templates/public-pages/docs/custom-position.gts b/docs/app/templates/public-pages/docs/custom-position.gts
index 6381bc66..0370cf51 100644
--- a/docs/app/templates/public-pages/docs/custom-position.gts
+++ b/docs/app/templates/public-pages/docs/custom-position.gts
@@ -14,15 +14,15 @@ import { LinkTo } from '@ember/routing';
- But you don't want to be limited to the positioning strategies I designed for
- you. You might want the dropdown to float to the left of the trigger or
+ But you don't want to be limited to the positioning strategies I designed
+ for you. You might want the dropdown to float to the left of the trigger or
perhaps one inch south-west of it.
Fear not, my friend, the component has an escape valve for this. You can
- design your own positioning function and pass it to the component. It just has
- to fulfill a specific contract.
+ design your own positioning function and pass it to the component. It just
+ has to fulfill a specific contract.
calculatePosition
@@ -80,8 +80,8 @@ import { LinkTo } from '@ember/routing';
or
"below"
depending on the space around the trigger
- matchTriggerWidth: Boolean that express the intention of the
- developer to make the dropdown have the same width as the trigger
+ matchTriggerWidth: Boolean that express the intention of
+ the developer to make the dropdown have the same width as the trigger
renderInPlace: Boolean that express if the content will be
rendered in place. Useful since very usually the reposition logic must be
entirely different
@@ -107,9 +107,9 @@ import { LinkTo } from '@ember/routing';
- Sounds like a lot, but with an example you will see that it's not really hard.
- Let's create a dropdown that opens to the right of the trigger, vertically
- centered with it.
+ Sounds like a lot, but with an example you will see that it's not really
+ hard. Let's create a dropdown that opens to the right of the trigger,
+ vertically centered with it.
@@ -128,10 +128,10 @@ import { LinkTo } from '@ember/routing';
- The key concept that you need to extract is that all the machinery to position
- the content and reposition when the content, scroll or screen changes is
- handled by the dropdown, so the only missing piece you have to provide is the
- function that calculates the cordinates.
+ The key concept that you need to extract is that all the machinery to
+ position the content and reposition when the content, scroll or screen
+ changes is handled by the dropdown, so the only missing piece you have to
+ provide is the function that calculates the cordinates.
diff --git a/docs/app/templates/public-pages/docs/dropdown-events.gts b/docs/app/templates/public-pages/docs/dropdown-events.gts
index cc69a005..a6d17d53 100644
--- a/docs/app/templates/public-pages/docs/dropdown-events.gts
+++ b/docs/app/templates/public-pages/docs/dropdown-events.gts
@@ -24,7 +24,8 @@ import DropDownEvents3Component from '../../../components/snippets/dropdown-even
argument in the signature is the public API of the component. The
event
argument will be passed if this event is fired as a consequence of another
- event (e.g. a click), but will be undefined if it was fired programmatically.
+ event (e.g. a click), but will be undefined if it was fired
+ programmatically.
What kinds of things you can do with this event?
@@ -68,8 +69,8 @@ import DropDownEvents3Component from '../../../components/snippets/dropdown-even
- Example: Create a dropdown with some checkboxes inside, and don't allow it to
- close until one checkbox is selected.
+ Example: Create a dropdown with some checkboxes inside, and don't allow it
+ to close until one checkbox is selected.
diff --git a/docs/app/templates/public-pages/docs/how-to-use-it.gts b/docs/app/templates/public-pages/docs/how-to-use-it.gts
index ad152458..e71ee3ef 100644
--- a/docs/app/templates/public-pages/docs/how-to-use-it.gts
+++ b/docs/app/templates/public-pages/docs/how-to-use-it.gts
@@ -21,8 +21,8 @@ import HowToUseIt3Component from '../../../components/snippets/how-to-use-it-3';
the
basic-dropdown
component which yields the public API to its block. That top-level component
- has no markup, just pure behaviour. Once inside the block, the yielded API has
- two contextual components on it that you can use:
+ has no markup, just pure behaviour. Once inside the block, the yielded API
+ has two contextual components on it that you can use:
trigger
and
content.
@@ -63,10 +63,10 @@ import HowToUseIt3Component from '../../../components/snippets/how-to-use-it-3';
Lastly, if you inspect the DOM a second time you can see all the
a11y
- machinery in place to make the component accesible. Even the trigger, despite
- being a div, is focusable as it should be for a good keyboard experience. Also
- if you have the trigger focus, you can open and close it with the enter or
- space keys.
+ machinery in place to make the component accesible. Even the trigger,
+ despite being a div, is focusable as it should be for a good keyboard
+ experience. Also if you have the trigger focus, you can open and close it
+ with the enter or space keys.
@@ -79,14 +79,14 @@ import HowToUseIt3Component from '../../../components/snippets/how-to-use-it-3';
- It just took a little bit of CSS. You could also have just assigned the right
- classes and reused the styles from the framework (I can't demo that because I
- don't have bootstrap here).
+ It just took a little bit of CSS. You could also have just assigned the
+ right classes and reused the styles from the framework (I can't demo that
+ because I don't have bootstrap here).
- I want to stress that when it comes to CSS, the dropdown really doesn't care.
- Let's make a material-like round button with a round content.
+ I want to stress that when it comes to CSS, the dropdown really doesn't
+ care. Let's make a material-like round button with a round content.
@@ -99,8 +99,8 @@ import HowToUseIt3Component from '../../../components/snippets/how-to-use-it-3';
And this is more or less everything you need to know about styles. Basically
- there is none, so you can add create your own in CSS or reuse the classes that
- CSS frameworks give you.
+ there is none, so you can add create your own in CSS or reuse the classes
+ that CSS frameworks give you.
diff --git a/docs/app/templates/public-pages/docs/index.gts b/docs/app/templates/public-pages/docs/index.gts
index b780d9a4..0cec3014 100644
--- a/docs/app/templates/public-pages/docs/index.gts
+++ b/docs/app/templates/public-pages/docs/index.gts
@@ -6,16 +6,17 @@ import { LinkTo } from '@ember/routing';
I'm going to tell you the story of how this dropdown addon was born.
- I was building a select component but I realized that a select is nothing more
- than a dropdown with some extra stuff on top. And datepickers too. And
+ I was building a select component but I realized that a select is nothing
+ more than a dropdown with some extra stuff on top. And datepickers too. And
colorpickers, contextual menus and many other widgets.
- Essentially, any floating box of content that is opened when you interact with
- a trigger is basically a dropdown. Dropdowns are the foundation to at least
- half a dozen common UI widgets we use daily, so I decided to shape this addon
- in a way that was easy to reuse and customize to create those other widgets.
+ Essentially, any floating box of content that is opened when you interact
+ with a trigger is basically a dropdown. Dropdowns are the foundation to at
+ least half a dozen common UI widgets we use daily, so I decided to shape
+ this addon in a way that was easy to reuse and customize to create those
+ other widgets.
@@ -44,10 +45,10 @@ import { LinkTo } from '@ember/routing';
- After I built the initial version, I started to build other widgets on top and
- I had to step back a few times and identify where it wasn't flexible enough.
- This process ended up in a component that distilled the essence of what a
- dropdown is with as few assumptions as possible.
+ After I built the initial version, I started to build other widgets on top
+ and I had to step back a few times and identify where it wasn't flexible
+ enough. This process ended up in a component that distilled the essence of
+ what a dropdown is with as few assumptions as possible.
@@ -58,8 +59,8 @@ import { LinkTo } from '@ember/routing';
This component is a
building block
for you to build other components on top, so it prioritizes flexibility and
- explicitness over succinctness in its API, but still allows allows basic usage
- out of the box with no ceremony.
+ explicitness over succinctness in its API, but still allows allows basic
+ usage out of the box with no ceremony.
diff --git a/docs/app/templates/public-pages/docs/installation.gts b/docs/app/templates/public-pages/docs/installation.gts
index 767be212..bbccd536 100644
--- a/docs/app/templates/public-pages/docs/installation.gts
+++ b/docs/app/templates/public-pages/docs/installation.gts
@@ -27,11 +27,15 @@ import { LinkTo } from '@ember/routing';
After the installation you need to add the following lines somewhere in your
templates where you want to render the dropdown content into e.g. your
- application.hbs. In this component will be rendered the dropdown
- content.
+ application.hbs. In this component will be rendered the
+ dropdown content.
-
+
If you use vanilla CSS, you need to add the following line into
@@ -50,14 +54,22 @@ import { LinkTo } from '@ember/routing';
template/component css file by using following line
-
+
- However, if you are using SASS or LESS you need to add an import statement to
- your styles.
+ However, if you are using SASS or LESS you need to add an import statement
+ to your styles.
-
+
If you are using LESS there is also necessary to register the
@@ -71,8 +83,8 @@ import { LinkTo } from '@ember/routing';
The styles of the addon are
very minimal
- and deal mostly with positioning. You can tweak a couple things but we'll get
- to that later.
+ and deal mostly with positioning. You can tweak a couple things but we'll
+ get to that later.
diff --git a/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts b/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts
index 79461384..a5547f5e 100644
--- a/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts
+++ b/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts
@@ -11,7 +11,11 @@ import { LinkTo } from '@ember/routing';
-
Add following line to your application.hbs
-
+
-
Vanilla JS: If you have used vanilla js you must now import the css in
diff --git a/docs/app/templates/public-pages/docs/position.gts b/docs/app/templates/public-pages/docs/position.gts
index 5fd2fc40..4b9a3e27 100644
--- a/docs/app/templates/public-pages/docs/position.gts
+++ b/docs/app/templates/public-pages/docs/position.gts
@@ -26,17 +26,17 @@ import Position3Component from '../../../components/snippets/position-3';
has not pre-defined size, so it will adapt to the size its childs.
-
- The dropdown's content is positioned below the trigger, unless there is not
- enough space to fit it, in which case it is positioned above it.
+ The dropdown's content is positioned below the trigger, unless there is
+ not enough space to fit it, in which case it is positioned above it.
-
- The content's left border will be aligned with the trigger's left border and
- content will flow towards the right.
+ The content's left border will be aligned with the trigger's left border
+ and content will flow towards the right.
-
- If there isn't enough size towards the right to fit the content but there is
- enough room to the left, the right border of the content will align with the
- right border of the trigger and it will grow towards the left.
+ If there isn't enough size towards the right to fit the content but there
+ is enough room to the left, the right border of the content will align
+ with the right border of the trigger and it will grow towards the left.
-
All the rules above are re-checked every time the content of the dropdown
@@ -91,8 +91,8 @@ import Position3Component from '../../../components/snippets/position-3';
Please note that when rendering the content in place, the vertical position
- will not automatically detect the best position based on the space around the
- trigger. You have to explicitly pass
+ will not automatically detect the best position based on the space around
+ the trigger. You have to explicitly pass
verticalPosition="above"
to render it over the trigger.
@@ -100,9 +100,9 @@ import Position3Component from '../../../components/snippets/position-3';
matchTriggerWidth
- There is a few widgets in which the width of the floating box has to match the
- width of the trigger design reasons. Since this is common enough, there is an
- option to enable this behaviour.
+ There is a few widgets in which the width of the floating box has to match
+ the width of the trigger design reasons. Since this is common enough, there
+ is an option to enable this behaviour.
@@ -112,9 +112,10 @@ import Position3Component from '../../../components/snippets/position-3';
In the section about
Custom Position
- strategies we will see how to totally customize how the dropdown is positioned
- by passing it a function. If you do so the options in this section will not
- work unless your function, which will receive those options, honors them.
+ strategies we will see how to totally customize how the dropdown is
+ positioned by passing it a function. If you do so the options in this
+ section will not work unless your function, which will receive those
+ options, honors them.
diff --git a/docs/app/templates/public-pages/docs/styles.gts b/docs/app/templates/public-pages/docs/styles.gts
index 491d1c0c..8df723bc 100644
--- a/docs/app/templates/public-pages/docs/styles.gts
+++ b/docs/app/templates/public-pages/docs/styles.gts
@@ -5,9 +5,9 @@ import CodeExample from '../../../components/code-example';
Styles
- Since this component doesn't any visual theme, you can apply styles to it just
- with plain CSS or even adding the classes your favourite CSS framework gives
- you.
+ Since this component doesn't any visual theme, you can apply styles to it
+ just with plain CSS or even adding the classes your favourite CSS framework
+ gives you.
diff --git a/docs/app/templates/public-pages/docs/test-helpers.gts b/docs/app/templates/public-pages/docs/test-helpers.gts
index a30da7fd..93a2bea0 100644
--- a/docs/app/templates/public-pages/docs/test-helpers.gts
+++ b/docs/app/templates/public-pages/docs/test-helpers.gts
@@ -10,8 +10,8 @@ import CodeExample from '../../../components/code-example';
Ember Basic Dropdown bundles some handy test helpers (clickDropdown
and
- tapDropdown) that make it easier to simulate user interaction in
- acceptance tests.
+ tapDropdown) that make it easier to simulate user interaction
+ in acceptance tests.
@@ -31,8 +31,8 @@ import CodeExample from '../../../components/code-example';
- In case there is more than one dropdown rendered at the same time you can pass
- a string with the scope to trigger it over the desired one.
+ In case there is more than one dropdown rendered at the same time you can
+ pass a string with the scope to trigger it over the desired one.
diff --git a/docs/app/templates/public-pages/docs/trigger-events.gts b/docs/app/templates/public-pages/docs/trigger-events.gts
index 031fafda..d637ef88 100644
--- a/docs/app/templates/public-pages/docs/trigger-events.gts
+++ b/docs/app/templates/public-pages/docs/trigger-events.gts
@@ -53,9 +53,9 @@ import TriggerEvents4Component from '../../../components/snippets/trigger-events
\{{on "keydown"}}
- One real world situation where I found this to be necessary, is when you want
- to open the dropdown with a key that usually does not open it, like by example
- the arrow keys.
+ One real world situation where I found this to be necessary, is when you
+ want to open the dropdown with a key that usually does not open it, like by
+ example the arrow keys.
@@ -84,8 +84,8 @@ import TriggerEvents4Component from '../../../components/snippets/trigger-events
- Good examples of this are preventing the component from opening with the mouse
- and/or react in some way to those attempts.
+ Good examples of this are preventing the component from opening with the
+ mouse and/or react in some way to those attempts.
@@ -103,13 +103,13 @@ import TriggerEvents4Component from '../../../components/snippets/trigger-events
\{{on "mouseenter"}} / \{{on "mouseleave"}}
- I use this event to open the dropdown when you hover it and close it when you
- leave but you can really use it a lot more.
+ I use this event to open the dropdown when you hover it and close it when
+ you leave but you can really use it a lot more.
- By example, imagine that a dropdown is disabled and you want to highlight some
- other element in the form that the user must enable first.
+ By example, imagine that a dropdown is disabled and you want to highlight
+ some other element in the form that the user must enable first.
@@ -120,8 +120,8 @@ import TriggerEvents4Component from '../../../components/snippets/trigger-events
I've used this two events in conjuntion to style a parent element while some
- of the components inside it have the focus, achieving a poor mans' version of
- the upcoming CSS
+ of the components inside it have the focus, achieving a poor mans' version
+ of the upcoming CSS
:focus-within
pseudo selector.
@@ -131,10 +131,10 @@ import TriggerEvents4Component from '../../../components/snippets/trigger-events
- This is the most involved example yet. Both the text input and the trigger are
- focusable on their own, but by tracking when they get and loose the focus we
- simulate that the entire input-group is focused, which would be impossible
- just just CSS today.
+ This is the most involved example yet. Both the text input and the trigger
+ are focusable on their own, but by tracking when they get and loose the
+ focus we simulate that the entire input-group is focused, which would be
+ impossible just just CSS today.
@@ -143,8 +143,8 @@ import TriggerEvents4Component from '../../../components/snippets/trigger-events
- Those are just some examples of the kind of behaviors you can implement adding
- custom events to the trigger.
+ Those are just some examples of the kind of behaviors you can implement
+ adding custom events to the trigger.
diff --git a/docs/app/templates/public-pages/index.gts b/docs/app/templates/public-pages/index.gts
index 9f42d61c..1fb6277f 100644
--- a/docs/app/templates/public-pages/index.gts
+++ b/docs/app/templates/public-pages/index.gts
@@ -35,8 +35,8 @@ import { LinkTo } from '@ember/routing';
With Ember for Ember
- Built on top of other ember addons, it provides an API based on contextual
- components that feels natural to use and style.
+ Built on top of other ember addons, it provides an API based on
+ contextual components that feels natural to use and style.
@@ -54,9 +54,9 @@ import { LinkTo } from '@ember/routing';
Low level primitives
- Designed as a building block for your own components, it has no styles and
- makes no assumptions. It gives you the right primitives to taylor your
- perfect widget.
+ Designed as a building block for your own components, it has no styles
+ and makes no assumptions. It gives you the right primitives to taylor
+ your perfect widget.
From 8b1a25cb5d96e45260e305d2b6de375d809fde7c Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 08:29:57 +0200
Subject: [PATCH 11/22] Remove tests
---
.../integration/components/code-block-test.ts | 19 -------------------
.../components/code-inline-test.ts | 19 -------------------
2 files changed, 38 deletions(-)
delete mode 100644 docs/tests/integration/components/code-block-test.ts
delete mode 100644 docs/tests/integration/components/code-inline-test.ts
diff --git a/docs/tests/integration/components/code-block-test.ts b/docs/tests/integration/components/code-block-test.ts
deleted file mode 100644
index deb637a1..00000000
--- a/docs/tests/integration/components/code-block-test.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { module, test } from 'qunit';
-import { setupRenderingTest } from 'docs/tests/helpers';
-import { render } from '@ember/test-helpers';
-import { hbs } from 'ember-cli-htmlbars';
-
-module('Integration | Component | code-block', function (hooks) {
- setupRenderingTest(hooks);
-
- test('it renders', async function (assert) {
- // Set any properties with this.set('myProperty', 'value');
- // Handle any actions with this.set('myAction', function(val) { ... });
-
- await render(
- hbs` `,
- );
-
- assert.dom().hasText("console.log('hello');");
- });
-});
diff --git a/docs/tests/integration/components/code-inline-test.ts b/docs/tests/integration/components/code-inline-test.ts
deleted file mode 100644
index 073abb09..00000000
--- a/docs/tests/integration/components/code-inline-test.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { module, test } from 'qunit';
-import { setupRenderingTest } from 'docs/tests/helpers';
-import { render } from '@ember/test-helpers';
-import { hbs } from 'ember-cli-htmlbars';
-
-module('Integration | Component | code-inline', function (hooks) {
- setupRenderingTest(hooks);
-
- test('it renders', async function (assert) {
- // Set any properties with this.set('myProperty', 'value');
- // Handle any actions with this.set('myAction', function(val) { ... });
-
- await render(
- hbs` `,
- );
-
- assert.dom().hasText("console.log('hello');");
- });
-});
From c095e6fce87e142da661d287e8f0e60eae7a1ccb Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 08:51:21 +0200
Subject: [PATCH 12/22] Improve readme
---
ember-basic-dropdown/README.md | 84 +++++++++++++++++-----------------
1 file changed, 43 insertions(+), 41 deletions(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index e54d58db..014bef32 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -1,25 +1,24 @@
# Ember-basic-dropdown
-[](https://travis-ci.org/cibernox/ember-basic-dropdown)
+[](https://github.com/cibernox/ember-basic-dropdown)
+[](https://www.npmjs.com/package/ember-basic-dropdown)
+[](http://emberobserver.com/addons/ember-basic-dropdown)
+
This is a very minimal dropdown. That means that it is agnostic about what it is going to contain.
It is intended to be a building block for more complex components but is perfectly usable. It is
-by example the addon on which [ember-power-select](https://www.ember-power-select.com)
-or `ember-paper`'s [menu component](http://miguelcobain.github.io/ember-paper/#/components/menu) are built upon.
+by example the addon on which [ember-power-select](https://www.ember-power-select.com) is built upon.
+
+- โ
TypeScript and Glint ready
+- ๐งต V2 addon format
+- ๐ FastBoot support
+- ๐ซ Shadow root support
### Compatibility
+- Embroider or ember-auto-import v2
- Ember.js v3.28 or above
-- Ember CLI v3.28 or above
-
-Versions 1.X require Ember 2.16 or greater
-
-Version 2.X requires Ember 3.13 or greater
-
-Version 3.X - 6.X requires Ember 3.24 or greater
-
-Version 7.X - 8.X requires Ember 3.28 or greater
### Installation
@@ -33,11 +32,15 @@ For more installation details see [documentation](https://ember-basic-dropdown.c
This component leverages contextual components for its API:
-```hbs
-
- Click me
- Content of the trigger
-
+```glimmer-ts
+import BasicDropdown from "ember-basic-dropdown/components/basic-dropdown";
+
+
+
+ Click me
+ Content of the trigger
+
+
```
The yielded `dropdown` object is the public API of the component, and contains
@@ -76,13 +79,17 @@ You don't need to care about adding or removing events, it does that for you.
You can make the dropdown content standout a little more by adding `overlay=true` to the content options, see example below. This will add a semi transparent overlay covering the whole screen. Also this will stop bubbling the click/touch event which closed the dropdown.
```hbs
-
- Click me!
-
- {{! here! }}
- content!
-
-
+import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
+
+
+
+ Click me!
+
+ {{! here! }}
+ content!
+
+
+
```
NOTE: If for some reason clicking outside a dropdown doesn't work, you might want to make sure the `` spans the entire viewport. Adding a css rule like `body {min-height: 100vh;}` would do the trick. It ensures that wherever you click on the page, it will close the dropdown.
@@ -92,14 +99,18 @@ NOTE: If for some reason clicking outside a dropdown doesn't work, you might wan
If you'd like the dropdown to close itself after a user clicks on it, you can use `dd.actions.close` from our public API.
```hbs
-
- Click me!
-
-
- {{yield dd}}
-
-
-
+import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
+
+
+
+ Click me!
+
+
+ {{yield dd}}
+
+
+
+
```
#### Keyboard and touchscreen support
@@ -140,12 +151,3 @@ where `horizontalPosition` is a string (`"right" | "center" | "left"`), `vertica
It has a handy collection of test helpers to make interaction with the component seamless in your
test suite.
-
-### Providing an Ember Twiddle
-
-If you want to provide an [Ember Twiddle](https://www.ember-twiddle.com) with an issue/reproduction **you need to add the following to the end of your template**:
-``
-
-Since `Ember Twiddle` does not run `EmberCLI's` hooks this `div` won't be added to the application and it's required (There's an issue in [Ember Twiddle](https://github.com/joostdevries/twiddle-backend/issues/35) tracking this).
-
-In order to create the Ember Twiddle you'll also need to add a reference to `ember-basic-dropdown: version` in the `addons` section of `twiddle.json`
From dac7a1de720e468e6bc68bfc232409562f380f17 Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 08:51:45 +0200
Subject: [PATCH 13/22] Improve readme
---
ember-basic-dropdown/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index 014bef32..c52e011b 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -1,4 +1,4 @@
-# Ember-basic-dropdown
+# ember-basic-dropdown
[](https://github.com/cibernox/ember-basic-dropdown)
[](https://www.npmjs.com/package/ember-basic-dropdown)
From 3eb9a720cfbfb2d2a65e541dc7273f7236fd5754 Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 08:52:49 +0200
Subject: [PATCH 14/22] Improve readme
---
ember-basic-dropdown/README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index c52e011b..e556155c 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -78,7 +78,7 @@ You don't need to care about adding or removing events, it does that for you.
You can make the dropdown content standout a little more by adding `overlay=true` to the content options, see example below. This will add a semi transparent overlay covering the whole screen. Also this will stop bubbling the click/touch event which closed the dropdown.
-```hbs
+```glimmer-ts
import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
@@ -98,7 +98,7 @@ NOTE: If for some reason clicking outside a dropdown doesn't work, you might wan
If you'd like the dropdown to close itself after a user clicks on it, you can use `dd.actions.close` from our public API.
-```hbs
+```glimmer-ts
import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
From 1e0071d4bb00a9e48782fee20de2bc24742ceb2c Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 10:58:14 +0200
Subject: [PATCH 15/22] Update README.md
---
ember-basic-dropdown/README.md | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index e556155c..e8fc8bda 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -1,9 +1,11 @@
-# ember-basic-dropdown
-[](https://github.com/cibernox/ember-basic-dropdown)
[](https://www.npmjs.com/package/ember-basic-dropdown)
[](http://emberobserver.com/addons/ember-basic-dropdown)
-
+
+[](https://discord.com/channels/480462759797063690/486202731766349824)
+[](https://github.com/cibernox/ember-basic-dropdown)
+
+# ember-basic-dropdown
This is a very minimal dropdown. That means that it is agnostic about what it is going to contain.
From f726ffacc781e7e197a46b2c24eedb96c65d692e Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 13:23:59 +0200
Subject: [PATCH 16/22] Update README.md
---
ember-basic-dropdown/README.md | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index e8fc8bda..84425254 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -1,4 +1,3 @@
-
[](https://www.npmjs.com/package/ember-basic-dropdown)
[](http://emberobserver.com/addons/ember-basic-dropdown)

@@ -9,13 +8,20 @@
This is a very minimal dropdown. That means that it is agnostic about what it is going to contain.
-It is intended to be a building block for more complex components but is perfectly usable. It is
-by example the addon on which [ember-power-select](https://www.ember-power-select.com) is built upon.
+It is intended to be a building block for more complex components but is perfectly usable.
+
+### Highlights
-- โ
TypeScript and Glint ready
-- ๐งต V2 addon format
-- ๐ FastBoot support
-- ๐ซ Shadow root support
+* ๐ **TypeScript support** โ ships with type definitions for smooth TypeScript integration.
+* โจ **Glint support** โ template type-checking out of the box for safer templates.
+* ๐ **FastBoot compatible** โ works in server-rendered Ember apps.
+* ๐ถ **Shadow DOM support** โ can be rendered inside shadow roots without breaking positioning or events.
+* ๐ **Addon v2 ready** โ modern Ember Addon v2 format.
+* ๐ฏ **Headless & lightweight** โ provides dropdown logic and accessibility without forcing styles.
+* ๐ง **Flexible API** โ fully customizable trigger and content; you control the markup and styling.
+* ๐งฉ **Composable** โ integrates seamlessly with other Ember addons (e.g. [ember-power-select](https://www.ember-power-select.com)).
+* โฟ **Accessible by default** โ full keyboard navigation, ARIA attributes, and focus management built-in.
+* ๐ฑ **Responsive positioning** โ automatic repositioning on scroll and viewport boundaries.
### Compatibility
@@ -68,7 +74,7 @@ Check the full documentation with live examples in http://ember-basic-dropdown.c
#### Renders on the body or in place
-By default this component will render the dropdown in the body using `#-in-element` and absolutely
+By default this component will render the dropdown in the body using `#in-element` and absolutely
position it to place it in the proper coordinates.
You can opt out to this behavior by passing `renderInPlace=true`. That will add the dropdown just
From 369556c755f89ba903b3f2b67f2db0631d39d0f8 Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 13:25:26 +0200
Subject: [PATCH 17/22] Update README.md
---
ember-basic-dropdown/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index 84425254..a3a16fdf 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -41,7 +41,7 @@ For more installation details see [documentation](https://ember-basic-dropdown.c
This component leverages contextual components for its API:
```glimmer-ts
-import BasicDropdown from "ember-basic-dropdown/components/basic-dropdown";
+import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
From b730936ee0735071423675bad1a6a63a6acbdf5a Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 14:03:46 +0200
Subject: [PATCH 18/22] Update README.md
---
ember-basic-dropdown/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index a3a16fdf..8dcd5803 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -1,6 +1,6 @@
[](https://www.npmjs.com/package/ember-basic-dropdown)
[](http://emberobserver.com/addons/ember-basic-dropdown)
-
+
[](https://discord.com/channels/480462759797063690/486202731766349824)
[](https://github.com/cibernox/ember-basic-dropdown)
From 27d8b4b671a8de81213adbeec28242e3ff3f6960 Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 17:05:30 +0200
Subject: [PATCH 19/22] Fix lint
---
ember-basic-dropdown/README.md | 24 +++++++++---------
test-app/app/components/my-custom-content.hbs | 2 +-
test-app/app/components/my-custom-trigger.hbs | 2 +-
test-app/app/styles/app.scss | 2 +-
.../components/basic-dropdown-test.js | 25 +++++++++++++------
5 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index 8dcd5803..3312c978 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -12,16 +12,16 @@ It is intended to be a building block for more complex components but is perfect
### Highlights
-* ๐ **TypeScript support** โ ships with type definitions for smooth TypeScript integration.
-* โจ **Glint support** โ template type-checking out of the box for safer templates.
-* ๐ **FastBoot compatible** โ works in server-rendered Ember apps.
-* ๐ถ **Shadow DOM support** โ can be rendered inside shadow roots without breaking positioning or events.
-* ๐ **Addon v2 ready** โ modern Ember Addon v2 format.
-* ๐ฏ **Headless & lightweight** โ provides dropdown logic and accessibility without forcing styles.
-* ๐ง **Flexible API** โ fully customizable trigger and content; you control the markup and styling.
-* ๐งฉ **Composable** โ integrates seamlessly with other Ember addons (e.g. [ember-power-select](https://www.ember-power-select.com)).
-* โฟ **Accessible by default** โ full keyboard navigation, ARIA attributes, and focus management built-in.
-* ๐ฑ **Responsive positioning** โ automatic repositioning on scroll and viewport boundaries.
+- ๐ **TypeScript support** โ ships with type definitions for smooth TypeScript integration.
+- โจ **Glint support** โ template type-checking out of the box for safer templates.
+- ๐ **FastBoot compatible** โ works in server-rendered Ember apps.
+- ๐ถ **Shadow DOM support** โ can be rendered inside shadow roots without breaking positioning or events.
+- ๐ **Addon v2 ready** โ modern Ember Addon v2 format.
+- ๐ฏ **Headless & lightweight** โ provides dropdown logic and accessibility without forcing styles.
+- ๐ง **Flexible API** โ fully customizable trigger and content; you control the markup and styling.
+- ๐งฉ **Composable** โ integrates seamlessly with other Ember addons (e.g. [ember-power-select](https://www.ember-power-select.com)).
+- โฟ **Accessible by default** โ full keyboard navigation, ARIA attributes, and focus management built-in.
+- ๐ฑ **Responsive positioning** โ automatic repositioning on scroll and viewport boundaries.
### Compatibility
@@ -41,7 +41,7 @@ For more installation details see [documentation](https://ember-basic-dropdown.c
This component leverages contextual components for its API:
```glimmer-ts
-import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
+import BasicDropdown from "ember-basic-dropdown/components/basic-dropdown";
@@ -87,7 +87,7 @@ You don't need to care about adding or removing events, it does that for you.
You can make the dropdown content standout a little more by adding `overlay=true` to the content options, see example below. This will add a semi transparent overlay covering the whole screen. Also this will stop bubbling the click/touch event which closed the dropdown.
```glimmer-ts
-import BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';
+import BasicDropdown from "ember-basic-dropdown/components/basic-dropdown";
diff --git a/test-app/app/components/my-custom-content.hbs b/test-app/app/components/my-custom-content.hbs
index 81704f2a..3415a3fd 100644
--- a/test-app/app/components/my-custom-content.hbs
+++ b/test-app/app/components/my-custom-content.hbs
@@ -1 +1 @@
-My custom content
\ No newline at end of file
+My custom content
\ No newline at end of file
diff --git a/test-app/app/components/my-custom-trigger.hbs b/test-app/app/components/my-custom-trigger.hbs
index 2a65423f..399e864f 100644
--- a/test-app/app/components/my-custom-trigger.hbs
+++ b/test-app/app/components/my-custom-trigger.hbs
@@ -1 +1 @@
-My custom trigger
\ No newline at end of file
+My custom trigger
\ No newline at end of file
diff --git a/test-app/app/styles/app.scss b/test-app/app/styles/app.scss
index bea4c62d..0bfa078d 100644
--- a/test-app/app/styles/app.scss
+++ b/test-app/app/styles/app.scss
@@ -1,2 +1,2 @@
// Basic dropdown
-@import 'ember-basic-dropdown';
+@import "ember-basic-dropdown";
diff --git a/test-app/tests/integration/components/basic-dropdown-test.js b/test-app/tests/integration/components/basic-dropdown-test.js
index f2efa623..154daf74 100644
--- a/test-app/tests/integration/components/basic-dropdown-test.js
+++ b/test-app/tests/integration/components/basic-dropdown-test.js
@@ -1421,12 +1421,17 @@ module('Integration | Component | basic-dropdown', function (hooks) {
.dom('.ember-basic-dropdown-content', find('[data-shadow]').shadowRoot)
.exists('The dropdown is rendered');
+ assert
+ .dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot)
+ .exists('The dropdown is opened');
- assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown is opened');
-
- await click(find('[data-shadow]').shadowRoot.getElementById('dropdown-is-opened'));
+ await click(
+ find('[data-shadow]').shadowRoot.getElementById('dropdown-is-opened'),
+ );
- assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown stays opened when clicking content');
+ assert
+ .dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot)
+ .exists('The dropdown stays opened when clicking content');
await click(triggerElement);
@@ -1436,11 +1441,17 @@ module('Integration | Component | basic-dropdown', function (hooks) {
await click(triggerElement);
- assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown is opened 2d time');
+ assert
+ .dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot)
+ .exists('The dropdown is opened 2d time');
- await click(find('[data-shadow]').shadowRoot.getElementById('dropdown-is-opened'));
+ await click(
+ find('[data-shadow]').shadowRoot.getElementById('dropdown-is-opened'),
+ );
- assert.dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot).exists('The dropdown stays opened when clicking content after 2d open');
+ assert
+ .dom('#dropdown-is-opened', find('[data-shadow]').shadowRoot)
+ .exists('The dropdown stays opened when clicking content after 2d open');
});
test('Shadow dom: Its `toggle` action opens and closes the dropdown when wormhole is inside shadow dom', async function (assert) {
From 2adcee9c83c86492fd1d836cf07a6d954c992d3b Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 17:23:19 +0200
Subject: [PATCH 20/22] More readme changes
---
ember-basic-dropdown/README.md | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/ember-basic-dropdown/README.md b/ember-basic-dropdown/README.md
index 3312c978..2362036d 100644
--- a/ember-basic-dropdown/README.md
+++ b/ember-basic-dropdown/README.md
@@ -1,6 +1,6 @@
[](https://www.npmjs.com/package/ember-basic-dropdown)
-[](http://emberobserver.com/addons/ember-basic-dropdown)
-
+[](https://emberobserver.com/addons/ember-basic-dropdown)
+
[](https://discord.com/channels/480462759797063690/486202731766349824)
[](https://github.com/cibernox/ember-basic-dropdown)
@@ -57,18 +57,23 @@ properties and actions that you can use to control the component.
```js
{
uniqueId: ,
- isOpen: ,
disabled: ,
+ isOpen: ,
actions: {
open: ,
close: ,
toggle: ,
- reposition:
- }
+ reposition: ,
+ registerTriggerElement: ,
+ registerDropdownElement: ,
+ getTriggerElement:
+ },
+ Trigger: ,
+ Content:
}
```
-Check the full documentation with live examples in http://ember-basic-dropdown.com
+Check the full documentation with live examples in https://ember-basic-dropdown.com
### Features
@@ -134,7 +139,7 @@ you can do pretty much anything you want.
#### Easy to animate.
You can animate it, in an out, with just CSS3 animations.
-Check the example in the [Ember Power Select documentation](http://www.ember-power-select.com/cookbook/css-animations)
+Check the example in the [Ember Power Select documentation](https://www.ember-power-select.com/cookbook/css-animations)
#### Intelligent and customizable positioning
From 818d1aff155391dd8d4127703998b32e40e2c755 Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 17:28:30 +0200
Subject: [PATCH 21/22] Fix examples in docs
---
docs/app/components/code-example.gts | 4 ++--
docs/app/templates/public-pages/docs/installation.gts | 9 +++++----
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/docs/app/components/code-example.gts b/docs/app/components/code-example.gts
index 91d63a1c..d3a539c0 100644
--- a/docs/app/components/code-example.gts
+++ b/docs/app/components/code-example.gts
@@ -116,7 +116,7 @@ export default class CodeExample extends Component {
{{/if}}
{{#if (and @js (eq this.activeTab "js"))}}
{{#let (getCodeSnippet @js) as |snippet|}}
-
+
{{/let}}
{{/if}}
{{#if (and @scss (eq this.activeTab "scss"))}}
@@ -126,7 +126,7 @@ export default class CodeExample extends Component {
{{/if}}
{{#if (and @css (eq this.activeTab "css"))}}
{{#let (getCodeSnippet @css) as |snippet|}}
-
+
{{/let}}
{{/if}}
{{#if (and this.showResult (has-block))}}
diff --git a/docs/app/templates/public-pages/docs/installation.gts b/docs/app/templates/public-pages/docs/installation.gts
index bbccd536..533dafd1 100644
--- a/docs/app/templates/public-pages/docs/installation.gts
+++ b/docs/app/templates/public-pages/docs/installation.gts
@@ -11,10 +11,11 @@ import { LinkTo } from '@ember/routing';
directory
-
- $ ember install
- ember-basic-dropdown
-
+
+
+ $ ember install ember-basic-dropdown
+
+
When installing this through
From 21c10c4967b7af2cbd0e6a61a9b02fb4bdf7f6c6 Mon Sep 17 00:00:00 2001
From: Markus Sanin
Date: Sat, 4 Oct 2025 17:53:14 +0200
Subject: [PATCH 22/22] Move all snippets into same folder
---
.../snippets/installation-2-snippet.js} | 0
.../snippets/test-helpers-1-js-snippet.js} | 0
.../snippets/test-helpers-2-js-snippet.js} | 0
.../snippets/test-helpers-3-js-snippet.js} | 0
docs/app/templates/public-pages/docs/installation.gts | 2 +-
docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts | 2 +-
docs/app/templates/public-pages/docs/test-helpers.gts | 6 +++---
docs/ember-cli-build.js | 2 +-
docs/eslint.config.mjs | 2 +-
9 files changed, 7 insertions(+), 7 deletions(-)
rename docs/app/{templates/snippets/installation-2.js => components/snippets/installation-2-snippet.js} (100%)
rename docs/app/{templates/snippets/test-helpers-1-js.js => components/snippets/test-helpers-1-js-snippet.js} (100%)
rename docs/app/{templates/snippets/test-helpers-2-js.js => components/snippets/test-helpers-2-js-snippet.js} (100%)
rename docs/app/{templates/snippets/test-helpers-3-js.js => components/snippets/test-helpers-3-js-snippet.js} (100%)
diff --git a/docs/app/templates/snippets/installation-2.js b/docs/app/components/snippets/installation-2-snippet.js
similarity index 100%
rename from docs/app/templates/snippets/installation-2.js
rename to docs/app/components/snippets/installation-2-snippet.js
diff --git a/docs/app/templates/snippets/test-helpers-1-js.js b/docs/app/components/snippets/test-helpers-1-js-snippet.js
similarity index 100%
rename from docs/app/templates/snippets/test-helpers-1-js.js
rename to docs/app/components/snippets/test-helpers-1-js-snippet.js
diff --git a/docs/app/templates/snippets/test-helpers-2-js.js b/docs/app/components/snippets/test-helpers-2-js-snippet.js
similarity index 100%
rename from docs/app/templates/snippets/test-helpers-2-js.js
rename to docs/app/components/snippets/test-helpers-2-js-snippet.js
diff --git a/docs/app/templates/snippets/test-helpers-3-js.js b/docs/app/components/snippets/test-helpers-3-js-snippet.js
similarity index 100%
rename from docs/app/templates/snippets/test-helpers-3-js.js
rename to docs/app/components/snippets/test-helpers-3-js-snippet.js
diff --git a/docs/app/templates/public-pages/docs/installation.gts b/docs/app/templates/public-pages/docs/installation.gts
index 533dafd1..48e1f44f 100644
--- a/docs/app/templates/public-pages/docs/installation.gts
+++ b/docs/app/templates/public-pages/docs/installation.gts
@@ -79,7 +79,7 @@ import { LinkTo } from '@ember/routing';
lessOptions
-
+
The styles of the addon are
diff --git a/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts b/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts
index a5547f5e..e2cc73fd 100644
--- a/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts
+++ b/docs/app/templates/public-pages/docs/migrate-7-0-to-8-0.gts
@@ -29,7 +29,7 @@ import { LinkTo } from '@ember/routing';
into your
ember-cli-build.js
file
-
+
-
Typescript: There were added / modified / fixed the typescript
diff --git a/docs/app/templates/public-pages/docs/test-helpers.gts b/docs/app/templates/public-pages/docs/test-helpers.gts
index 93a2bea0..b85a06d4 100644
--- a/docs/app/templates/public-pages/docs/test-helpers.gts
+++ b/docs/app/templates/public-pages/docs/test-helpers.gts
@@ -20,7 +20,7 @@ import CodeExample from '../../../components/code-example';
await.
-
+
clickTrigger(scope = null, eventOptions)
@@ -35,7 +35,7 @@ import CodeExample from '../../../components/code-example';
pass a string with the scope to trigger it over the desired one.
-
+
tapTrigger(scope = null, eventOptions)
@@ -45,7 +45,7 @@ import CodeExample from '../../../components/code-example';
but simulates a tap instead.
-
+