All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.18.4 - 2026-10-14
Fixed
menu: Runphx-click-awaybindings when an item is chosen.menu,menu_bar: Choose the focused item with Space.
0.18.3 - 2026-10-14
Added
tabs: Add adisabledattribute to the:panelslot. A disabled tab can be focused with the arrow keys but not selected.
Changed
field: Raise foraria-errormessageandaria-invalidin:restwhen diagnostics are enabled.
Fixed
Doggo.Storybook: Render the modifier variations of thefieldstory.field: Render global attributes, such asphx-change, on each control of acheckbox-grouporradio-group.field: Renderautofocuson one control of acheckbox-grouporradio-group.field: Mark the legend of acheckbox-groupas required whenrequiredis set.field: Don't submit any value for a disabledcheckbox,switchorcheckbox-group.field: Send the hidden input of acheckbox,switchorcheckbox-groupto the form named byform.field: Visually hide the legend of acheckbox-group,radio-groupor registered group type whenhide_labelis set.field: Let an attribute passed to the field, such asmaxlengthorrequired={false}, replace the one invalidationsor derived from the changeset.field: Show the required mark for arequiredattribute passed to the field.field: Let screen readers read the required mark in the legend of acheckbox-groupor registered group type.field: Render apasswordinput without avalue.menu: Close a menu opened by amenu_buttonand focus the button when an item is chosen.menu_button: Keep a menu opened with the keyboard open after a patch.relative_time: Show thetitlein the same format and time zone as the text whenlocalizeis set.
0.18.2 - 2026-10-05
Fixed
alert_dialog,modal: Show an open dialog as a modal again when a patch moves it without changing it, which 0.18.1 missed. Dialogs opened over it stay on top. Focus stays where it was, and goes back to the opener when the dialog closes.
0.18.1 - 2026-10-05
Fixed
alert_dialog,modal: Show an open dialog as a modal again after a patch moves it in the DOM, instead of leaving it open in the page.
0.18.0 - 2026-10-02
Added
Doggo.Components: Add adefaultsbuild option that sets the defaults of attributes and slots. Expressions written in the build call are evaluated at render time.Doggo.Form: New module withDoggo.Form.field_errors_id/1,Doggo.Form.field_description_id/1,Doggo.Form.input_aria_describedby/3,Doggo.Form.input_aria_errormessage/2andDoggo.Form.translate_error/1, for form controls with the same ids and ARIA attributes asfield.Doggo.JS: New module withDoggo.JS.show_modal/2,Doggo.JS.hide_modal/2andDoggo.JS.show_tab/3.accordion,property_list,table,tabs: Accept HEEx in the section title, the label of a property, the label of an action and the label of a panel.date: Add aprecisionattribute.date,datetime,time: Add alocalizeattribute that formats the value in the browser, in the language of the page and the time zone of the user.field: Add atranslate_errorbuild option.field,radio_group: Accept HEEx in the labels and descriptions of checkbox and radio options.relative_time: New component.table: Add alabelledbyattribute.@woylie/doggo: AddlocalizeTimes()andrelativeTimes().
Changed
Doggo.Components: Evaluate the texts and contents set in the build call at render time, so agettextcall returns the text for the current locale.alert,alert_dialog,modal: Replace theclose_labelattribute and thecloseslot with build options.alert,app_bar,callout,page_header: Replace thetitleattribute with a:titleslot.carousel: Replace thecarousel_roledescription,slide_roledescription,pagination_labelandpagination_slide_labelattributes with build options.combobox: Replace the:clearand:toggleslots with build options.date: Write the full value of aDateTimeorNaiveDateTimein thedatetimeattribute.date,datetime,time: Add the default base classesdate,datetimeandtime.datetime,time: Leave out the seconds withprecision={:minute}.drawer: Rename the:mainslot to:body, and thedrawer-mainclass todrawer-body.field: Rename the:addon_leftand:addon_rightslots to:addon_startand:addon_end, the classes tofield-input-addon-startandfield-input-addon-end, and thedata-addonvalues tostartandend.icon,icon_sprite: Renametexttolabelandtext_positiontolabel_position, thedata-text-positionattribute todata-label-position, and theicon-textclass toicon-label.time: Pass aDateTimeorNaiveDateTimeto the formatters as given, and write its full value in thedatetimeattribute.- Dependencies: Require Elixir
~> 1.17. - Dependencies: Make
phoenix_storybookan optional dependency.
Deprecated
Doggo: DeprecateDoggo.show_modal/2,Doggo.hide_modal/2andDoggo.show_tab/3in favour ofDoggo.JS.show_modal/2,Doggo.JS.hide_modal/2andDoggo.JS.show_tab/3.
Removed
field: Remove thegettextattribute and thegettext_modulebuild option.
Fixed
Doggo.Components: Recompile a module that builds components when a component module of Doggo changes.date,datetime,time: Raise anArgumentErrorthat names the accepted structs for a value of another type, instead of aFunctionClauseError.date,datetime,time: Write a validdatetimeattribute: at most three fractional digits, no attribute for a year before 1, and an offset with seconds in UTC.
How to upgrade
Add
phoenix_storybookto your dependencies if you use the Doggo stories.+ {:phoenix_storybook, "~> 1.1"}Doggo: ReplaceDoggo.show_modal/2,Doggo.hide_modal/2andDoggo.show_tab/3withDoggo.JS.show_modal/2,Doggo.JS.hide_modal/2andDoggo.JS.show_tab/3.- <.link phx-click={Doggo.show_modal("pet-modal")}>Open</.link> + <.link phx-click={Doggo.JS.show_modal("pet-modal")}>Open</.link>alert,alert_dialog,modal: Moveclose_labeland the:closeslot to the build call.- <.modal id="pet-modal" close_label={gettext("Close")}> + build_modal(close_label: gettext("Close"))alert,app_bar,callout,page_header: Pass the title in a slot.- <.alert title="Saved"> + <.alert> + <:title>Saved</:title>carousel: Movecarousel_roledescription,slide_roledescription,pagination_labelandpagination_slide_labelto the build call.combobox: Move the:clearand:toggleslots to the build call.date,datetime,time: Update CSS and tests that expectclass=""or six fractional digits, and tests that expect:00seconds withprecision={:minute}.date,time: Update tests that expect a date-only or time-onlydatetimeattribute for aDateTimeorNaiveDateTimevalue.time: Update formatters that match a%Time{}, since aDateTimeorNaiveDateTimevalue is passed as given.drawer: Rename the:mainslot and the.drawer-mainselectors.- <:main>…</:main> + <:body>…</:body>field: Rename the addon slots, classes anddata-addonvalues.- <:addon_left>…</:addon_left> + <:addon_start>…</:addon_start> - .field-input-addon-right, [data-addon="right"] + .field-input-addon-end, [data-addon="end"]field: Replace thegettextattribute and thegettext_modulebuild option with thetranslate_errorbuild option.- build_field(gettext_module: MyAppWeb.Gettext) + build_field(translate_error: &MyAppWeb.CoreComponents.translate_error/1)icon,icon_sprite: Renametextandtext_position, and the selectors.- <.icon name="info" text="Info" text_position="after" /> + <.icon name="info" label="Info" label_position="after" /> - [data-text-position], .icon-text + [data-label-position], .icon-label
0.17.0 - 2026-09-29
Added
Doggo.Components: Accept module attributes and function calls in build options, and raise for an anonymous function.Doggo.Components: Add a:diagnosticsapplication config. Withconfig :doggo, diagnostics: true, components check the values they get at render and raise when a check fails.Doggo.Components: Under diagnostics, raise when:restholds an attribute the component sets itself.Doggo.Storybook: Add a file input variation to thefieldstory.accordion,action_bar,alert,alert_dialog,app_bar,bottom_navigation,callout,carousel,combobox,fallback,icon,icon_sprite,menu_group,menu_item_radio_group,modal,page_header,property_list,switch,tabs: Under diagnostics, raise for a blank accessible name.accordion,action_bar,avatar,bottom_navigation,box,breadcrumb,card,field,icon,icon_sprite,radio_group,tree_item: Add a class to every part.action_bar: Addlabelandlabelledbyattributes.box: Add aheadingattribute.box: Add anidattribute. With it, the title and the body get{id}-titleand{id}-body.menu_item,menu_item_checkbox,toggle_button: Accept an event name or a JS command in every callback attribute.menu_item_checkbox: Accept:indeterminateascheckedvalue.navbar: Add alabelledbyattribute.property_list: Add aclassattribute to:prop.table: Add ascrollableattribute.toggletip: New component.vertical_nav: Add alandmarkattribute.
Changed
Doggo.Components: Run the label checks only under diagnostics.mix dog.safelist: Document the output format, which only changes in a major release.accordion,action_bar,bottom_navigation,carousel,drawer,menu,menu_bar,menu_group,menu_item_radio_group,navbar_items,property_list,steps,tab_navigation,tabs,vertical_nav,vertical_nav_nested,vertical_nav_section: Render nothing without items.accordion: Require thetitleof:section.action_bar: Requirelabelorlabelledby.alert_dialog,modal: Replacedismissablewithclosedby, which takes"any","closerequest"or"none".alert_dialog,modal: Setdata-canceltoon_cancelonly.carousel: Require thelabelof:previousand:next.combobox,field,switch: Setdir="auto"on text passed in attributes that is rendered next to the component's own text.drawer,fallback: Let arolein:restreplace the component's role.field: Replace theextra_typesbuild option withtypes.field: Suffix the ids of the field's own parts with-errors,-descriptionand-datalist, and derive option ids asPhoenix.HTML.Form.input_id/3does.frame,image: Turnratiofrom a modifier into an attribute, with aratiosbuild option.image: Render the box with theframebuild.navbar: Checklabelorlabelledbywith the label check instead of requiringlabelat compile time.radio_group: Suffix the ids of the group's own parts with-errorsand-description, and derive option ids asPhoenix.HTML.Form.input_id/3does.table: Under diagnostics, raise for a scrollable table withoutlabelorcaption.tooltip: Describe the control in the inner block, which receives thearia-describedbyattribute through:let. Removecontains_link.tree_item: Only setaria-selectedwhenselectedis set.vertical_nav: Take exactly one name fromlabel,labelledbyor the:titleslot.
Fixed
Doggo.Components: Keep LiveView's change tracking through derived assigns.Doggo.Components: Listalert_dialogandmodalunder their own group in the documentation.Doggo: Escape the id in the selectors ofshow_modal/2,hide_modal/2,show_tab/3and the commands the disclosure components use.alert_dialog,modal: Runon_cancelonce when the dialog is closed withJS.exec("data-cancel").breadcrumb: Render nothing without items instead of raising aMatchError.field: Listdata-addon,data-multipleanddata-visually-hiddenin the safelist instead ofdata-state.field: Keeparia-describedbyin step with the errors for a field without a form field.field: Omitvalueon a file input, and passmultipleon.navbar_items,vertical_nav,vertical_nav_nested: Omit an emptyclassattribute.switch,toggle_button: Rendernilasfalse.table: Treat a blanklabelorcaptionas unset.vertical_nav: Accept a nav named only by its:titleinstead of raising.
How to upgrade
Doggo.Components: Enable the diagnostics in development and test. Without them, no render-time check runs, including the label checks that used to raise everywhere.# config/dev.exs and config/test.exs + config :doggo, diagnostics: trueaccordion: Set atitleon every:section.action_bar: Passlabelorlabelledby.- <.action_bar id="dog-actions"> + <.action_bar id="dog-actions" label="Dog actions">alert_dialog,modal: Replacedismissablewithclosedby.- <.modal id="pet-modal" dismissable={false}> + <.modal id="pet-modal" closedby="none"> - <.alert_dialog id="end-session" dismissable> + <.alert_dialog id="end-session" closedby="any">closedby="any"is the default ofmodal, andclosedby="none"the default ofalert_dialog.alert_dialog,modal: Close the dialog withhide_modal/1.data-cancelonly runson_cancelnow.- <.link phx-click={JS.exec("data-cancel", to: "#pet-modal")}>Close</.link> + <.link phx-click={Doggo.hide_modal("pet-modal")}>Close</.link>carousel: Setlabelon:previousand:next.- <:previous>Previous</:previous> + <:previous label="Previous slide">Previous</:previous>field: Rename theextra_typesbuild option.- build_field(extra_types: %{"ranked" => &MyAppWeb.Inputs.ranked/1}) + build_field(types: %{"ranked" => &MyAppWeb.Inputs.ranked/1})field,radio_group: Update CSS and tests that name the ids of a field's own parts, and option ids with spaces or punctuation.- #pet_breed_errors, #pet_breed_description, #pet_breed_datalist + #pet_breed-errors, #pet_breed-description, #pet_breed-datalist - #pet_tags_golden retriever + #pet_tags_golden_retrieverframe,image: Replace theratiomodifier with theratiosbuild option, and[data-ratio]selectors with[data-numerator]and[data-denominator].- build_frame(modifiers: [ratio: [values: ["1:1", "16:9"], default: "1:1"]]) + build_frame(ratios: ["1:1", "16:9"])image: Buildframebeforeimage, or name the frame build.+ build_frame() build_image()table: Name every scrollable table, or render it without a scroll container.- <.table id="pets" rows={@pets}> + <.table id="pets" rows={@pets} label="Pets">captionnames the table as well, and renders a visible caption. For a table that fits its container, setscrollable={false}instead.tooltip: Spread the:letvalue on the control in the inner block, and removecontains_link.- <.tooltip id="labrador-info" contains_link> - <.link navigate={~p"/labradors"} aria-describedby="labrador-info-tooltip"> + <.tooltip id="labrador-info" :let={trigger}> + <.link navigate={~p"/labradors"} {trigger}> Labrador Retriever </.link> <:tooltip>Friendly and good swimmers.</:tooltip> </.tooltip>A tooltip no longer makes plain text focusable. Show that information as visible text, or use
toggletip.vertical_nav: Droplabelorlabelledbywhere a:titleis given.- <.vertical_nav id="project-nav" label="Projects"> + <.vertical_nav id="project-nav"> <:title>Projects</:title>
0.16.1 - 2026-09-25
Changed
tree_item: Handle theexpandedattribute as initial state only. The server cannot update it anymore.
Fixed
Doggo.Components: Raise at compile time when a modifier is named after a global HTML attribute.Doggo.Components: Raise at compile time when a modifier has the name of an attribute or slot of the component.Doggo.Components: Raise at compile time whennameis a function thatPhoenix.Componentimports.Doggo.Components: Raise at compile time when a build macro is called in a module that does notuse Doggo.Components.accordion: Raise anArgumentErrorfor an invalidexpandedvalue.fallback: Render the placeholder for a string of only whitespace and when the formatter returns an empty string.page_header: Render a navigation entry withouthref,navigate,patchoron_clickas its content instead of inside an empty link.tree: Keep the expanded state the user chose for a branch through LiveView patches, including patches of a LiveComponent inside the tree.tree: Keep the tab stop through patches of a LiveComponent inside the tree.tree: StopUpandDownat the first and last item.tree: Ignore hidden text and icons in the type-ahead.tree: Stop the hook from failing onRighton an expanded branch without a group.
0.16.0 - 2026-09-22
Added
- Example CSS: Add CSS examples for all remaining components.
table: Addlabelattribute to name the scroll container.
Changed
- All components: Update component categories.
app_bar,callout,drawer: Name the landmarks the components render.app_bar,drawer: Requireid.callout,drawer: Render as adivand only setrole="complementary"if the component has a name in order to prevent unnamed landmarks.field: Use-switch-state-onand-switch-state-offclasses on the switch instead of adata-stateattribute.modal: Render the title before the close button.switch: Render both states at once and togglehiddenbetween them instead of rendering only the current one.table: Put the scroll container in the tab order, name it withrole="region", and setscope="col"on the header cells.
Fixed
avatar: Label an avatar that falls back toplaceholder_content.bottom_navigation: Only setaria-labelon an item when its label is hidden.carousel: Put the slide container in the tab order, so the slides can be scrolled by keyboard.carousel: Stop the rotation under the pointer after the pause button resumes it.date: Removeform,nameandvalueas global attributes.menu_button: Close the menu when clicking outside it.
How to upgrade
app_bar,drawer: Pass anid.callout,drawer: If your CSS or tests select theasideelement the components used to render, select the base class instead.mix dog.gen.stories: Because the component categories were updated, the location of the stories also changed. Runmix dog.gen.storiesagain and delete the stories from their old folder.field: Replace[data-state]selectors on the switch with.field-switch-state-onand.field-switch-state-off.
0.15.1 - 2026-09-11
Fixed
carousel: Prevent pagination dots from flickering while scrolling.
0.15.0 - 2026-09-11
Added
- All components: Add a
labelledbyattribute to all components that take alabel. - JavaScript hooks: Publish the JavaScript hooks as ES modules, on npm as
@woylie/doggoand in the Hex package underassets/js. See the README for both install routes. accordion,action_bar,alert_dialog,combobox,menu,menu_bar,menu_button,modal,split_pane,tabs,toolbar,tooltip,tree,tree_item: Add hooks and keyboard support.alert: Add a:closeslot for the content of the close button.callout: Add an:actionslot.callout: Add an:actionslot.carousel: Add aloopattribute, defaulttrue. Withloop={false}, the first and last slide don't wrap around.carousel: Add arotation_interval_msattribute, default5000.carousel: AddHomeandEndkey handlers to the pagination, which move to the first and last slide.combobox: Support options written as keyword lists and maps, withdescriptionanddisabledkeys, and support option groups and:hrseparators.combobox: Add adisplay_valueattribute to set the text shown for the selected value.combobox: Add anon_searchattribute to filter the options on the server instead of in the browser.combobox: Addfree_textandfree_text_labelattributes, which let the user submit what they typed when it is not among the options.combobox: Add aclearableattribute, which renders a button that unselects, and aclear_labelattribute for its accessible name.combobox: Add:clearand:toggleslots for the content of the two buttons.combobox: Add an example stylesheet.field: Add an:extra_typesbuilder option for rendering a type with your own component.field: Add ahidden_inputattribute to omit the hidden input that submitsfalsefor an unchecked checkbox.field: Support nested options in thecheckbox-groupandradio-grouptypes.field: Support options written as keyword lists, and support option descriptions.split_pane: Make the panes resizable by dragging the separator or by moving it with the keyboard.tabs: Add anorientationattribute.tree_item: Addexpandedandselectedattributes.
Changed
- All components: Reject a blank
labelorlabelledby. action_bar,combobox,drawer,menu,menu_bar,menu_button,menu_group,menu_item,menu_item_checkbox,menu_item_radio_group,radio_group,split_pane,switch,toolbar,tree,tree_item: Raise the maturity level from experimental to developing, most of them because they gained their hook and keyboard support in this release.alert: Change the type of theclose_labelattribute to:string.alert: Remove the click handler from the root element.alert_dialog,modal: UseshowModal()to open dialogs to provide proper modal semantics. This adds support for the CSS::backdroppseudo element and ensures scroll locking without relying on CSS or JS.alert_dialog,modal: Close dialogs with theclosedbyattribute.alert_dialog,modal: Support the Invoker Commands API.alert_dialog,modal: Remove themodal-containerandalert-dialog-containerelement.app_bar: Require thelabelattribute of the:navigationand:actionslots.app_bar: Setaria-labelon the:navigationand:actionlinks.bottom_navigation: Require thelabelattribute of the:itemslot.bottom_navigation,breadcrumb,steps,tab_navigation,vertical_nav: Require alabelor alabelledby, and remove the default labels ofbreadcrumb,stepsandtab_navigation.button,toggle_button: Default thedisabledattribute tofalseinstead ofnil.button_link: Prevent activation of a disabled button link. The link is now rendered without a destination and withrole="link"andaria-disabled="true".button_link: Remove thedata-disabledattribute. The state is expressed witharia-disabledinstead.callout: Rename the defaultvariantmodifier tolevel.card: Rename the:mainslot to:body.carousel: Replace theauto_rotationattribute with a:pauseslot, which renders the button that stops and restarts the rotation. The rotation is enabled by the presence of the slot, so a rotating carousel always has a button to stop it, as WCAG 2.2.2 requires.carousel: Complete the tablist of the pagination:role="tablist"is set on thecarousel-paginationelement instead of a nesteddiv, each button has anid,aria-selectedandtabindex, and the slides are the tab panels the buttons select. The button contains a singlespaninstead of two nested ones.carousel: Label the pagination buttons with thelabelof the slide they select.pagination_slide_labelis only used for slides without a label.carousel: Setaria-livetooffwhile rotating and topolitewhile stopped.carousel: Move by settingscrollLefton the scroll container, so that thescroll-behaviorproperty decides whether the movement is animated.carousel: Render no controls and no pagination for a single item. The item is a group instead of a tab panel then.carousel: Mark the component asdeveloping.combobox: Render the listbox as adivwithrole="listbox"and each option as adivwithrole="option", instead of aulwithlielements.page_header: Render the title and the subtitle in anhgroupinstead of adivwith thepage-header-titleclass.property_list: Require the:propslot.tabs: Require thelabelattribute of the:panelslot.toolbar: Add anorientationattribute.action_bar,menu,menu_bar,toolbar,tree,vertical_nav: Require theidattribute.navbar_items,vertical_nav,vertical_nav_nested: Changeclassattribute of the item slots to:any, so that a list of classes can be passed.
Removed
combobox: Remove support for options written as{label, value, description}tuples. Write the option as a keyword list with adescriptionkey instead.
Fixed
card: Render the main content as adivinstead of amainelement. A document may hold only onemain, so a page of cards was invalid and exposed onemainlandmark per card.carousel: Scroll to the right slide if the slides have different widths, or ifscroll-snap-alignis notstart. The scroll position was calculated from the width of the first slide.carousel: Render the pause button first and the pagination between the previous and next buttons, so that the tab order matches the visual order.carousel: Keep working after a LiveView patch that adds or removes slides. Buttons rendered by the patch did nothing, and the active slide could point at a slide that had been removed.carousel: Stop the rotation timer when the element is removed. It kept running against a detached element and held it from being collected.cluster: Remove therole="group"attribute.combobox: Mark the option holding the value as selected when the option values are not strings.combobox: Mark only the first option when several options hold the same value.combobox: Render an option with an empty value forniland for an empty label, so that a blank option can be selected.field: Describe an errored field by its error text througharia-describedbyin addition toaria-errormessage.field: Always render the error list as anaria-live="polite"region, so that an error that appears after load is announced.field: Render a field built withoutfieldassign from just anameandvalue.field: Render options given as keyword lists.frame: Default to a1:1ratio instead of raising when noratiois given.image: Pass a validratioin the story.page_header: Add the missingon_clickattribute to the:navigationslot.split_pane: Clamp thearia-valuenowof the separator betweenmin_sizeandmax_size.tree_item: Render the expanded and collapsed state correctly.
How to upgrade
button_link: Replace[data-disabled]with[aria-disabled]in any styles you wrote for disabled button links.button_link: A disabled button link no longer renders anhref. Revisit any style or test that selectsa.button[href].property_list: Add a:propslot to any property list that has none, or remove the component from that call site.card: Rename the:mainslot to:body, and replacemainwith.card-bodyin any styles you wrote for it.- All components: Ensure to pass a
labelorlabelledbyattribute to every component that expects them. action_bar,menu,menu_bar,toolbar,tree,vertical_nav: Set anidon every instance.callout: Renamevarianttolevelif you use the defaults, and change[data-variant]to[data-level]in your CSS.- JavaScript hooks: Register the hooks of the components you build. See the README.
combobox: Rewrite any styles that select the listbox or its options asulandli. They aredivelements withrole="listbox"androle="option"now.combobox: Rewrite options given as{label, value, description}tuples as keyword lists with adescriptionkey.alert_dialog,modal: Remove the backdrop and scroll locking you added and style::backdropinstead.alert_dialog,modal: Move any styles on.modal-containerand.alert-dialog-containerto thedialogelement itself. The element is gone, and the dialog is the box now that it opens in the top layer.field: An empty.field-errorselement is now part of the layout. See the Field error announcements section of the README for the CSS that removes it from the flow without removing it from the accessibility tree.carousel: Replace theauto_rotationattribute with a:pauseslot.carousel: In pagination styles,[role="tablist"]is now thecarousel-paginationelement itself rather than a child of it, and the dot isbutton > spanrather thanbutton > span > span.carousel: Setlabelon every:itemof a carousel withpagination, since the pickers take their names from it.pagination_slide_labelnow applies only to slides without a label.carousel: A carousel with a single item renders nocarousel-controlselement anymore. Update your styles to account for its absence if necessary.
0.14.9 - 2026-08-27
Changed
- All components: Document the CSS rule the
data-visually-hiddenattribute needs, and whydisplay: noneis the wrong one. icon,toolbar: Document that omitting thetextattribute oficonleaves the icon without an accessible name, and correct the examples that omitted it. Thetoolbarexamples passed alabelattribute, whichicondoes not have.alert_dialog,modal: Document that the components are not modal in the browser's sense, so the caller has to supply a backdrop and lock scrolling.table: Document that therow_clickattribute is available to pointer users only, and that every action reachable through it needs a focusable equivalent in the row.
Fixed
Doggo.Storybook: Resolve the:moduleoption ofuse Doggo.Storybookin the caller's environment, so that a story module can refer to its components module through an alias.action_bar: Setaria-labelon the buttons, taken from the requiredlabelof the item. The name previously came fromtitlealone.action_bar,alert,alert_dialog,combobox,modal: Settype="button"on the buttons the components generate. Without it they defaulted tosubmitand submitted any form they sat in.alert_dialog,modal: Remove thehrefattribute from the close button, which is not valid on abuttonelement.fallback,vertical_nav_section: Setrole="img"on the placeholder offallbackandrole="group"on a titledvertical_nav_section. Both put an accessible name on an element whose implicit role prohibits one, so the name was dropped.field: Omit thedata-addonattribute when neither addon slot is filled. It was tested with&&, and an empty slot is truthy, so every field rendereddata-addon="left right".alert_dialog,modal: Focus the container rather than the content, so that a dialog whose body holds nothing focusable still moves focus into the dialog.steps: Remove the builder options the documentation listed. None of:current_class,:completed_class,:upcoming_classand:visually_hidden_classexists, so following the documentation raised anArgumentErrorat compile time.
0.14.8 - 2026-08-27
Security
date: Remove field values that are not a valid ISO 8601 date instead of truncating them to ten characters.field: Fix HTML injection in thedateinput, which marked the field value as already escaped. A value taken from user params could break out of thevalueattribute. Present since 0.1.0.
0.14.7 - 2026-07-24
Changed
carousel: Change hook name toDoggo.Components.Carousel.Hook.carousel: Support scrolling and swiping on mobile devices.carousel: Add auto rotation.carousel: Add items container for more flexible styling.
0.14.6 - 2026-06-11
Changed
- Dependencies: Loosen
phoenix_live_viewversion requirement to ~> 1.1. - JavaScript hooks: Add colocated JS hook for carousel pagination.
carousel: Add example CSS styles.
0.14.5 - 2026-05-15
Fixed
- Dependencies: Remove a type warning in Elixir 1.20.0-rc.5.
0.14.4 - 2026-04-09
Fixed
icon: Map icon names to functions at build time, so that an icon renders before its function name atom exists.
0.14.3 - 2026-04-08
Changed
icon: Simplify example styles.
Fixed
Doggo.Storybook: Handle modifiers without values and boolean modifiers in stories.icon: Remove extraneous whitespace.
0.14.2 - 2026-04-07
Fixed
Doggo.Storybook: Render all configured icons in the icon story instead of only the first one.
0.14.1 - 2026-04-07
Fixed
Doggo.Storybook: Toggle thehiddenattribute in the toggle button story.Doggo.Storybook: Set class name as string in the container function of some stories.
0.14.0 - 2026-03-16
Changed
image: Movedata-numeratoranddata-denominatorattributes to innerimage-frameelement.
Fixed
image: Add modifier data attributes.
How to upgrade
Before:
<figure class="image" data-numerator="16" data-denominator="9">
<div class="image-frame">
<img src="" alt="" loading="" />
</div>
<figcaption></figcaption>
</figure>After:
<figure class="image">
<div class="image-frame" data-numerator="16" data-denominator="9">
<img src="" alt="" loading="" />
</div>
<figcaption></figcaption>
</figure>0.13.3 - 2026-03-14
Changed
button: Allowpopovertargetattribute.
0.13.2 - 2026-03-04
Changed
- Dependencies: Require
phoenix_storybook~> 1.0.
0.13.1 - 2026-02-16
Changed
Doggo.Components: Add@doc type: {type}tags to compiled components for ExDoc grouping.
0.13.0 - 2026-02-05
This release contains significant breaking changes. Check your component styles carefully when upgrading.
Added
Doggo.Components: Add:typeoption to modifiers, so that any attribute type can be used instead of only strings.
Changed
Doggo: RenameDoggo.classes/1toDoggo.safelist/1.Doggo.Components: Usedata-attributes instead of classes for modifiers (see upgrade guide below).mix dog.classes: Renamemix dog.classestomix dog.safelist.mix dog.safelist: Include data attributes inmix dog.safelistandDoggo.safelist/1output.button_link: Removedisabled_classoption.button_link: Usedata-disabledattribute instead of thedisabled_class(selector:[data-disabled]).field: Removeaddon_left_class,addon_right_class, andvisually_hidden_classoptions.field: Usedata-addonattribute instead ofaddon_left_classandaddon_right_class(selectors:[data-addon~="left"],[data-addon~="right"]).field: Usedata-invalidattribute instead ofhas-errorsclass (selector:[data-invalid]).field: Usedata-stateattribute instead of{base_class}-switch-state-{on|off}classes (selectors:[data-state="on"],[data-state="off"]).frame: Makeratiorequired.frame,image: Change format ofratioattribute (before:16-by-9, after:16:9).frame,image: Usedata-numeratoranddata-denominatorattributes instead of adding a class for the ratio (before:class="is-16-by-9", after:data-numerator="16" data-denominator="9").icon,icon_sprite: Removetext_position_after_class,text_position_before_class,text_position_hidden_class, andvisually_hidden_classoptions.icon,icon_sprite: Usedata-text-positionclass instead oftext_position_*classes (selectors:[data-text-position="before"],[data-text-position="after"],[data-text-position="hidden"]).stack: Removerecursive_classoption.stack: Usedata-recursiveattribute instead ofrecursive_class(selector:[data-recursive]).steps: Usedata-visually-hiddenattribute instead ofvisually_hidden_class(selector:[data-visually-hidden]).steps: Usedata-visually-hiddenattribute instead ofvisually_hidden_class(selector:[data-visually-hidden]).steps: Removecurrent_class,completed_class,upcoming_class, andvisually_hidden_classoptions.steps: Usedata-visually-hiddenattribute instead ofvisually_hidden_class(selector:[data-visually-hidden]).steps: Usedata-stateattribute instead ofcurrent_class,completed_class, andupcoming_class(selectors:[data-state="current"],[data-state="completed"],[data-state="upcoming"]).
Removed
Doggo: RemoveDoggo.modifier_class_name/2.Doggo.Components: Removeclass_name_funoption.
How to upgrade
In previous versions, modifier attribute values would be reflected with CSS classes in the HTML output.
For example, if you had a tag component with a size modifier like this:
build_tag(
modifiers: [
size: [values: ["small", "medium", "large"], default: "medium"]
]
)And you used it like:
<.tag size="small">Hello</.tag>This would result in the addition of an is-small class.
<span class="tag is-small">Hello</span>The implementation was changed to use separate data attributes for each modifier instead. Now, the generated HTML will look like this:
<span class="tag" data-size="small">Hello</span>In your CSS styles, you will need to change the selectors accordingly.
Before:
.tag.is-small {
}After:
.tag[data-size="small"] {
}0.12.0 - 2026-01-15
Changed
icon: Render the inner SVG with a referenced icon module instead of using an inner block.page_header: Addnavigationslot.
0.11.0 - 2025-12-16
Added
mix dog.classes: Add--checkswitch tomix dog.classes.
Changed
- Dependencies: Require
phoenix_live_view~> 1.1.0andphoenix_storybook~> 0.9.
0.10.8 - 2025-09-15
Changed
- Dependencies: Support
gettext~> 1.0.
0.10.7 - 2025-07-31
Changed
- Dependencies: Require
phoenix_live_view~> 1.0.6 or ~> 1.1.0.
0.10.6 - 2025-07-08
Changed
- Dependencies: Loosen version requirement for
phoenix_storybook.
0.10.5 - 2025-06-10
Fixed
radio_group: Addrequiredattribute to radio inputs.
0.10.4 - 2025-02-22
Fixed
field: Escape select option values.
0.10.3 - 2025-02-11
Changed
field: Build select options with function components instead ofPhoenix.HTML.Form.options_for_select/2.
0.10.2 - 2025-01-08
Changed
- Dependencies: Require Phoenix LiveView ~> 1.0.0.
- Dependencies: Support Phoenix Storybook 0.8.
0.10.1 - 2024-11-20
Changed
- Dependencies: Support Phoenix Storybook 0.7.x.
0.10.0 - 2024-11-19
Changed
field: Removerequired_textattribute in favor of a compile-time option passed tobuild_field/1.field: Removerequired_titleattribute; removetitlefromspanelement.field: Change default forrequired_textfrom*to(required).field: Translaterequired_textwith Gettext module, if set.field: Addoptional_textoption tobuild_field/1to mark optional fields with a label suffix. Defaults tonil.field: Prefixcheckbox,checkbox-group,radio-group,required-mark,select,switch,switch-label,switch-state,switch-state-off, andswitch-state-onclasses with base class for consistency.
0.9.1 - 2024-10-18
Changed
mix dog.classes: Add header to file output ofmix dog.classes.
Fixed
- Dependencies: Remove a deprecation warning in Phoenix LiveView 1.0.7-rc.7.
0.9.0 - 2024-09-25
Changed
mix dog.modifiers: RenameDoggo.modifier_classes/1toDoggo.classes/1andmix dog.modifierstomix dog.classes. The function and mix task return all base classes, nested classes, and additional customizable classes in addition to the modifier classes now.box: Wrap inner block intodiv.box,tag: Add example styles.
Removed
fab: Remove the component. It might have made sense to have it as a separate component before components could be customized, but since the semantics are the same as a regular button, you can just make one withbuild_button(name: :fab, base_class: "fab")if you need it.
0.8.2 - 2024-07-28
Fixed
Doggo.Storybook: Ensure storybook module and components module are loaded before checking whether module exports function.Doggo.Storybook: Compile the menu stories under all circumstances.
0.8.1 - 2024-07-28
Fixed
- Dependencies: Declare
phoenix_storybookas required dependency.
0.8.0 - 2024-07-28
Added
- Example CSS: Set up design tokens and CSS for demo application based on Barker. Styles for all components will be added in the future.
Changed
Doggo.Components: Add documentation for the compile-time options of the builder macros.date,datetime: Improve story and documentation.date,datetime: Improve story and documentation.date,datetime: Improve story and documentation.date,datetime: Mark components asrefining.icon: Addright-to-leftvariation group to the story.icon,icon_sprite: Add styles to demo application.icon,icon_sprite: Add styles to demo application.icon,icon_sprite: Add styles to demo application.icon,icon_sprite: Renamelabelattribute totext.icon,icon_sprite: Renamelabel_placementattribute totext_position.icon,icon_sprite: Change type oflabel_placementattribute from atom to string for consistency.icon,icon_sprite: Usebeforeandafteras values fortext_positioninstead ofleftandrightto better apply to right-to-left languages. Rename default classes tohas-text-beforeandhas-text-afteraccordingly.icon,icon_sprite: Maketext_positionclasses configurable.icon,icon_sprite: Setsprite_urlas a compile time option.icon,icon_sprite: Mark both components asrefining.icon_sprite: Add story.button,cluster,property_list,stack: Mark components asstable.disclosure_button,tab_navigation: Mark component asrefining.
Fixed
Doggo.Components: Setattributesfor modifier variations when the map lacks a key.
0.7.0 - 2024-07-24
Changed
field: Use privatefield_description,field_errors, andlabelcomponents. Apply base class tofield_descriptionandfield_errorscomponents.image: Use plaindivwith{base_class}-frameclass instead of nestedframecomponent. Thisdivdoes not receive theratioattribute anymore. Apply the ratio with a CSS selector on the root div instead (e.g..image.is-4-by-3 > .image-frame).
Removed
field_description: Remove the component.field_errors: Remove the component.label: Remove the component.
0.6.0 - 2024-07-23
Added
Doggo: AddDoggo.modifier_classes/1.Doggo: AddDoggo.modifier_class_name/2.mix dog.gen.stories: AddDoggo.Storybookandmix dog.gen.storiesfor generatingPhoenix.Storybookstories for the configured components. The generated stories automatically render variation groups for all configured modifiers.
Changed
- All components: Improve consistency across all components, with various smaller improvements and optimizations.
- All components: Revise The component type classification.
- All components: Add maturity levels for all components (experimental, developing, refining, stable).
- Dependencies: Require
live_view ~> 1.0.0-rc.6. Doggo.Components: Replace all function components defined inDoggowith build macros inDoggo.Components. This allows you to customize the modifier attributes, component names, base classes, and some other options at compile time.Doggo.Components: Make modifier class name builder configurable.mix dog.modifiers: Addmoduleargument tomix dog.modifiersthat points to the module in which the Doggo components are configured.avatar: Replaceplaceholderattribute withplaceholder_srcandplaceholder_contentattributes.field: ConfigureGettextmodule (formerly oninput) via compile-time option instead of global attribute.field: Replacephx-feedback-forattribute in favor ofPhoenix.Component.used_input?/1.field,input: Rename build macro for formerinputcomponent tofield.input,label: Allow to set required text and required title attributes.page_header: Don't useh2for sub title.vertical_nav_nested: Nest into<div>.vertical_nav_nested: Renamedrawer-nav-titleclass to be based on configured component name (default:vertical-nav-nested-title).
Removed
mix dog.gen.stories: RemovePhoenix.Storybookstories bundled in theprivfolder in favor ofmix dog.gen.storiesandDoggo.Storybook.flash_group: Remove the component.
How to upgrade
- For all Doggo components you were using, call the corresponding
buildmacros inDoggo.Componentsin one of your modules and update your HEEx templates to call the generated functions instead of the ones from theDoggomodule. See readme for installation details. - The previous Doggo version instructed you to configure a separate Storybook that reads the stories from the
privfolder of the dependency. Remove that second Storybook and runmix dog.gen.stories -m [component-module] -o [storybook-folder] -ato generate stories for the configured Doggo components in the primary Storybook. - If you use
mix dog.modifiersin a script, add the--moduleargument. - If you were setting the
gettextattribute on theinputcomponent, pass thegettext_moduleoption toDoggo.Components.build_field/1instead.
0.5.0 - 2024-02-12
Added
Doggo.Storybook: Add a storybook page about modifier classes.mix dog.modifiers: Addmix dog.modifiersto list all modifier classes.alert_dialog: New component.carousel: New component.combobox: New component.disclosure_button: New component.menu: New component.menu_bar: New component.menu_button: New component.menu_group: New component.menu_item: New component.menu_item_checkbox: New component.menu_item_radio_group: New component.radio_group: New component.split_pane: New component.tabs: New component.toolbar: New component.tree: New component.
Changed
- Dependencies: Depend on
phoenix_storybook ~> 0.6.0. action_bar: Use buttons instead of links.action_bar: Addtoolbarrole.button_link: Removerole, addclass.drawer: Rename slots toheader,main, andfooter.drawer_nav,drawer_nav_nested,drawer_nav_section: Rename tovertical_nav,vertical_nav_nestedandvertical_nav_section.input: Setaria-invalidandaria-errormessageattributes.modal: Usesectioninstead ofarticle.modal: Usebuttonfor close button.modal: Adddismissableattribute.
0.4.0 - 2023-12-31
Added
cluster: New component.toggle_button: New component.
Changed
- All components: Remove
:errorvariant in favor of:danger. alert,flash_group: Change both components significantly.avatar: Add<span>around text placeholder.callout: Requireidattribute.drawer_nav: Requireidandlabelattributes.drawer_nav: Addclassattribute to item slot.drawer_nested_nav: Requireidattribute.drawer_nested_nav: Addclassattribute to item slot.drawer_section: Requireidattribute.drawer_section: Addaria-labelledbyattribute.field_description: Changedescriptionattribute to inner block.frame: Rename ratio classes fromx-to-xtox-by-x.icon_sprite: Add:normalas size.image: Add base class, addclassattribute.label: Addrequired_titleattribute.modal: Addclose_labelattribute.navbar: Add requiredlabelattribute.navbar_items: Addclassattribute to:itemslot.
Fixed
box: Render the header when only the action slot is used, without banner or title.breadcrumb: Let the aria label be overridden.input: Mark radio groups and checkbox groups as required only when they are.input: Render the text of datalist options.
0.3.1 - 2023-12-28
Changed
app_bar,steps: Allow event name as string inon_clickattributes.
Fixed
steps: Apply theon_clickattribute correctly.
0.3.0 - 2023-12-27
Added
avatar: New component.badge: New component.bottom_navigation: New component.box: New component.callout: New component.fab: New component.field_group: New component.input: Support autocomplete via<datalist>.input: Addaddon_leftandaddon_rightslots.input: Addgettextattribute, giving you the choice to set the Gettext module locally.label: Allow to visually hide labels.page_header: New component.skeleton: New component.steps: New component.tag: New component.tooltip: New component.
0.2.1 - 2023-12-19
Changed
- Dependencies: Ensure compatibility with Phoenix.HTML 4.0.
0.2.0 - 2023-12-17
Added
frame: New component.image: New component.tab_navigation: New component.
0.1.5 - 2023-12-16
Fixed
input: Remove default value forerrorsattribute.
0.1.4 - 2023-12-16
Added
Doggo.Storybook: Add storybook stories for the remaining components.
Fixed
field_description: Remove a stray<li>tag.input: Keep errors passed as an attribute instead of overriding them.
0.1.3 - 2023-12-15
Fixed
Doggo.Storybook: Add thepriv/storybookfolder to the package configuration.
0.1.2 - 2023-12-14
Changed
Doggo.Storybook: Add more storybook stories.
Fixed
table: Use the correct attribute name for rows.
0.1.1 - 2023-12-13
Changed
Doggo.Storybook: Add storybook stories for more components, and improve the documentation.
0.1.0 - 2023-12-13
Initial release.