diff --git a/bundlesize.config.json b/bundlesize.config.json index 453e676777..fc61445eec 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -42,11 +42,11 @@ }, { "path": "./packages/instantsearch.css/themes/algolia.css", - "maxSize": "10.25 kB" + "maxSize": "10.5 kB" }, { "path": "./packages/instantsearch.css/themes/algolia-min.css", - "maxSize": "9.5 kB" + "maxSize": "10 kB" }, { "path": "./packages/instantsearch.css/themes/reset.css", @@ -54,31 +54,39 @@ }, { "path": "./packages/instantsearch.css/themes/reset-min.css", - "maxSize": "1.25 kB" + "maxSize": "1.5 kB" + }, + { + "path": "./packages/instantsearch.css/themes/nova.css", + "maxSize": "10.5 kB" + }, + { + "path": "./packages/instantsearch.css/themes/nova-min.css", + "maxSize": "9.75 kB" }, { "path": "./packages/instantsearch.css/themes/satellite.css", - "maxSize": "11.25 kB" + "maxSize": "11.5 kB" }, { "path": "./packages/instantsearch.css/themes/satellite-min.css", - "maxSize": "10.5 kB" + "maxSize": "10.75 kB" }, { "path": "./packages/instantsearch.css/components/chat.css", - "maxSize": "5.5 kB" + "maxSize": "6 kB" }, { "path": "./packages/instantsearch.css/components/chat-min.css", - "maxSize": "5.25 kB" + "maxSize": "5.5 kB" }, { "path": "./packages/instantsearch.css/components/autocomplete.css", - "maxSize": "4.25 kB" + "maxSize": "4.75 kB" }, { "path": "./packages/instantsearch.css/components/autocomplete-min.css", - "maxSize": "4 kB" + "maxSize": "4.25 kB" } ] } diff --git a/packages/instantsearch.css/devtools/index.js b/packages/instantsearch.css/devtools/index.js index ff5b3af54d..8538080898 100644 --- a/packages/instantsearch.css/devtools/index.js +++ b/packages/instantsearch.css/devtools/index.js @@ -411,6 +411,19 @@ const variablesConfig = { unit: 'rem', }, }, + { + name: '--ais-hit-min-width', + type: 'dimension-px', + themeVariable: false, + category: 'Other', + control: { + label: 'Hit Min Width', + min: 100, + max: 800, + step: 10, + unit: 'px', + }, + }, { name: '--ais-autocomplete-search-input-height', type: 'dimension-px', diff --git a/packages/instantsearch.css/package.json b/packages/instantsearch.css/package.json index daf93e6088..aa5b8deb3f 100644 --- a/packages/instantsearch.css/package.json +++ b/packages/instantsearch.css/package.json @@ -40,7 +40,7 @@ "scripts": { "build": "rm -rf themes components && yarn styles:build && yarn styles:minify && yarn styles:autoprefixer && yarn generate-variables-config", "styles:autoprefixer": "postcss themes/ components/ --use autoprefixer --replace --no-map", - "styles:minify": "sass src/themes/algolia.scss:themes/algolia-min.css src/themes/satellite.scss:themes/satellite-min.css src/themes/reset.scss:themes/reset-min.css src/components/chat.scss:components/chat-min.css src/components/autocomplete.scss:components/autocomplete-min.css --no-source-map --style compressed", + "styles:minify": "sass src/themes/algolia.scss:themes/algolia-min.css src/themes/satellite.scss:themes/satellite-min.css src/themes/nova.scss:themes/nova-min.css src/themes/reset.scss:themes/reset-min.css src/components/chat.scss:components/chat-min.css src/components/autocomplete.scss:components/autocomplete-min.css --no-source-map --style compressed", "styles:build": "sass src/themes:themes src/components:components --no-source-map", "watch": "sass src/themes:themes src/components:components --no-source-map --watch", "prepare": "yarn build", diff --git a/packages/instantsearch.css/src/components/autocomplete.scss b/packages/instantsearch.css/src/components/autocomplete.scss index dcf12cbb5b..232e48c989 100644 --- a/packages/instantsearch.css/src/components/autocomplete.scss +++ b/packages/instantsearch.css/src/components/autocomplete.scss @@ -36,14 +36,12 @@ position: relative; width: 100%; - @media (prefers-reduced-motion: no-preference) { - transition: border-color var(--ais-transition-duration) - var(--ais-transition-timing-function), - box-shadow var(--ais-transition-duration) - var(--ais-transition-timing-function), - outline-color var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: border-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + box-shadow var(--ais-transition-duration) + var(--ais-transition-timing-function), + outline-color var(--ais-transition-duration) + var(--ais-transition-timing-function); &:focus-within { border-color: rgba(var(--ais-primary-color-rgb), 1); @@ -77,11 +75,12 @@ .ais-AutocompleteLoadingIndicator { height: 100%; padding-left: calc(var(--ais-spacing) * 0.75 - 1px); - padding-right: calc(var(--ais-spacing) / 2); - width: calc(var(--ais-spacing) * 1.75 + var(--ais-icon-size) - 1px); + padding-right: calc(var(--ais-spacing) * 0.75 - 1px); + width: calc(var(--ais-spacing) * 1.5 + var(--ais-icon-size) - 2px); @media (hover: none) and (pointer: coarse) { - padding-left: calc(calc(var(--ais-spacing) / 2) / 2 - 1px); - width: calc(var(--ais-icon-size) + (var(--ais-spacing) * 1.25) - 1px); + padding-left: calc(var(--ais-spacing) * 0.625); + padding-right: calc(var(--ais-spacing) * 0.625); + width: calc(var(--ais-icon-size) + var(--ais-spacing) * 1.25); } } @at-root .ais-AutocompleteSubmitButton { @@ -149,10 +148,8 @@ margin: 0; padding: 0 calc(var(--ais-spacing) * (5 / 6) - 0.5px); - @media (prefers-reduced-motion: no-preference) { - transition: color var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: color var(--ais-transition-duration) + var(--ais-transition-timing-function); @media (hover: none) and (pointer: coarse) { padding: 0 calc(var(--ais-spacing) * (2 / 3) - 0.5px); @@ -203,12 +200,10 @@ transform-origin: top center; transform: scale(0.95) translateY(calc(var(--ais-spacing) * -1)); - @media (prefers-reduced-motion: no-preference) { - transition: opacity var(--ais-transition-duration) - var(--ais-transition-timing-function), - transform var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: opacity var(--ais-transition-duration) + var(--ais-transition-timing-function), + transform var(--ais-transition-duration) + var(--ais-transition-timing-function); &--open { opacity: 1; @@ -308,10 +303,8 @@ min-height: calc(var(--ais-spacing) * 2.5); padding: calc(calc(var(--ais-spacing) / 2) / 2); - @media (prefers-reduced-motion: no-preference) { - transition: background-color var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); // When the result is active, either by hover or keyboard navigation @media (hover: hover) { @@ -387,10 +380,8 @@ flex-shrink: 0; padding: 0; - @media (prefers-reduced-motion: no-preference) { - transition: color var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: color var(--ais-transition-duration) + var(--ais-transition-timing-function); &:hover, &:focus { @@ -562,12 +553,10 @@ body.ais-Autocomplete--detached { text-align: left; width: 100%; - @media (prefers-reduced-motion: no-preference) { - transition: border-color var(--ais-transition-duration) - var(--ais-transition-timing-function), - box-shadow var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: border-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + box-shadow var(--ais-transition-duration) + var(--ais-transition-timing-function); } .ais-AutocompleteDetachedSearchButtonIcon { @@ -616,10 +605,8 @@ body.ais-Autocomplete--detached { margin-left: auto; padding: 0 calc(var(--ais-spacing) * 0.5); - @media (prefers-reduced-motion: no-preference) { - transition: color var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: color var(--ais-transition-duration) + var(--ais-transition-timing-function); @media (hover: hover) { &:hover { diff --git a/packages/instantsearch.css/src/components/button.scss b/packages/instantsearch.css/src/components/button.scss index 56584f2a0f..6dffdf15fc 100644 --- a/packages/instantsearch.css/src/components/button.scss +++ b/packages/instantsearch.css/src/components/button.scss @@ -29,11 +29,9 @@ cursor: not-allowed; } - @media (prefers-reduced-motion: no-preference) { - transition: background-color var(--ais-transition-duration) - var(--ais-transition-timing-function), - color var(--ais-transition-duration) var(--ais-transition-timing-function); - } + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + color var(--ais-transition-duration) var(--ais-transition-timing-function); } // Button sizes diff --git a/packages/instantsearch.css/src/components/chat/_chat-carousel.scss b/packages/instantsearch.css/src/components/chat/_chat-carousel.scss index 6bb2d1e2f2..2790ea5704 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-carousel.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-carousel.scss @@ -122,10 +122,8 @@ z-index: -1; transform: scale(0.95); - @media (prefers-reduced-motion: no-preference) { - transition: all var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: all var(--ais-transition-duration) + var(--ais-transition-timing-function); } @media (hover: hover) { @@ -181,10 +179,8 @@ overflow: hidden; img { - @media (prefers-reduced-motion: no-preference) { - transition: transform var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: transform var(--ais-transition-duration) + var(--ais-transition-timing-function); } } diff --git a/packages/instantsearch.css/src/components/chat/_chat-message-loader.scss b/packages/instantsearch.css/src/components/chat/_chat-message-loader.scss index d190b8b825..9abfa6b69a 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-message-loader.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-message-loader.scss @@ -15,9 +15,7 @@ height: calc(var(--ais-spacing) * 1.5); color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); - @media (prefers-reduced-motion: no-preference) { - animation: ais-chat-loader-spinner 1.4s linear infinite; - } + animation: ais-chat-loader-spinner 1.4s linear infinite; } .ais-ChatMessageLoader-text { @@ -39,12 +37,10 @@ background-position: -100% 0; font-weight: var(--ais-font-weight-medium); - @media (prefers-reduced-motion: no-preference) { - animation-delay: 0.5s; - animation-duration: 3s; - animation-iteration-count: infinite; - animation-name: ais-chat-loader-text; - } + animation-delay: 0.5s; + animation-duration: 3s; + animation-iteration-count: infinite; + animation-name: ais-chat-loader-text; } .ais-ChatMessageLoader-skeletonWrapper { @@ -58,9 +54,7 @@ background-color: rgba(var(--ais-muted-color-rgb), 0.2); border-radius: var(--ais-border-radius-sm); - @media (prefers-reduced-motion: no-preference) { - animation: ais-chat-loader-skeleton 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; - } + animation: ais-chat-loader-skeleton 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; &:nth-child(2) { width: 40%; diff --git a/packages/instantsearch.css/src/components/chat/_chat-message.scss b/packages/instantsearch.css/src/components/chat/_chat-message.scss index 1a8cb2c3bb..7b84fcc52e 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-message.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-message.scss @@ -77,10 +77,8 @@ .ais-ChatMessage--auto-hide-actions .ais-ChatMessage-actions { opacity: 0; - @media (prefers-reduced-motion: no-preference) { - transition: opacity var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: opacity var(--ais-transition-duration) + var(--ais-transition-timing-function); } .ais-ChatMessage-feedbackSpinner svg, @@ -89,9 +87,7 @@ } .ais-ChatMessage-feedbackSpinner svg { - @media (prefers-reduced-motion: no-preference) { - animation: ais-chat-loader-spinner 1.4s linear infinite; - } + animation: ais-chat-loader-spinner 1.4s linear infinite; } .ais-ChatMessage-feedbackCheck { diff --git a/packages/instantsearch.css/src/components/chat/_chat-messages.scss b/packages/instantsearch.css/src/components/chat/_chat-messages.scss index eff3ec632c..9b915571d4 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-messages.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-messages.scss @@ -23,12 +23,10 @@ gap: calc(var(--ais-spacing) * 1.5); width: 100%; - @media (prefers-reduced-motion: no-preference) { - transition: opacity var(--ais-transition-duration) - var(--ais-transition-timing-function), - filter var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: opacity var(--ais-transition-duration) + var(--ais-transition-timing-function), + filter var(--ais-transition-duration) + var(--ais-transition-timing-function); } .ais-ChatMessages-content--clearing { @@ -45,14 +43,12 @@ height: calc(var(--ais-spacing) * 1.5); border-radius: var(--ais-border-radius-full); - @media (prefers-reduced-motion: no-preference) { - transition: background-color var(--ais-transition-duration) - var(--ais-transition-timing-function), - transform var(--ais-transition-duration) - var(--ais-transition-timing-function), - opacity var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + transform var(--ais-transition-duration) + var(--ais-transition-timing-function), + opacity var(--ais-transition-duration) + var(--ais-transition-timing-function); } .ais-ChatMessages-scrollToBottom--hidden { diff --git a/packages/instantsearch.css/src/components/chat/_chat-overlay-layout.scss b/packages/instantsearch.css/src/components/chat/_chat-overlay-layout.scss index 3c40f0e5aa..8cce06ea02 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-overlay-layout.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-overlay-layout.scss @@ -14,12 +14,10 @@ z-index: var(--ais-z-index-chat); pointer-events: none; - @media (prefers-reduced-motion: no-preference) { - transition: width var(--ais-transition-duration) - var(--ais-transition-timing-function), - height var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: width var(--ais-transition-duration) + var(--ais-transition-timing-function), + height var(--ais-transition-duration) + var(--ais-transition-timing-function); &--maximized { width: var(--ais-chat-maximized-width); @@ -32,12 +30,10 @@ transform-origin: bottom right; transform: scale(0.95) translateY(var(--ais-spacing)); - @media (prefers-reduced-motion: no-preference) { - transition: opacity var(--ais-transition-duration) - var(--ais-transition-timing-function), - transform var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: opacity var(--ais-transition-duration) + var(--ais-transition-timing-function), + transform var(--ais-transition-duration) + var(--ais-transition-timing-function); } .ais-Chat-container--open { diff --git a/packages/instantsearch.css/src/components/chat/_chat-prompt.scss b/packages/instantsearch.css/src/components/chat/_chat-prompt.scss index 0aa8829b02..1f7bae7b94 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-prompt.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-prompt.scss @@ -59,12 +59,10 @@ outline: 1px solid transparent; z-index: 1; - @media (prefers-reduced-motion: no-preference) { - transition: border-color var(--ais-transition-duration) - var(--ais-transition-timing-function), - outline-color var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: border-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + outline-color var(--ais-transition-duration) + var(--ais-transition-timing-function); } .ais-ChatPrompt-body:focus-within { diff --git a/packages/instantsearch.css/src/components/chat/_chat-sidepanel-layout.scss b/packages/instantsearch.css/src/components/chat/_chat-sidepanel-layout.scss index 4a3341fb97..f08e3ec9fc 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-sidepanel-layout.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-sidepanel-layout.scss @@ -13,10 +13,7 @@ max-width: calc(100% - var(--ais-chat-margin) * 2); z-index: var(--ais-z-index-chat); pointer-events: none; - - @media (prefers-reduced-motion: no-preference) { - transition: width var(--ais-transition-duration) var(--ais-transition-timing-function); - } + transition: width var(--ais-transition-duration) var(--ais-transition-timing-function); &--maximized { width: var(--ais-chat-maximized-width); @@ -27,11 +24,8 @@ border-radius: 0; opacity: 0; transform: translateX(100%); - - @media (prefers-reduced-motion: no-preference) { - transition: opacity var(--ais-transition-duration) var(--ais-transition-timing-function), - transform var(--ais-transition-duration) var(--ais-transition-timing-function); - } + transition: opacity var(--ais-transition-duration) var(--ais-transition-timing-function), + transform var(--ais-transition-duration) var(--ais-transition-timing-function); } .ais-Chat-container--open { @@ -45,11 +39,8 @@ position: absolute; bottom: var(--ais-chat-margin); right: var(--ais-chat-margin); - - @media (prefers-reduced-motion: no-preference) { - transition: right var(--ais-transition-duration) var(--ais-transition-timing-function), - transform var(--ais-transition-duration) var(--ais-transition-timing-function); - } + transition: right var(--ais-transition-duration) var(--ais-transition-timing-function), + transform var(--ais-transition-duration) var(--ais-transition-timing-function); } .ais-Chat-container--open ~ .ais-Chat-toggleButtonWrapper { diff --git a/packages/instantsearch.css/src/components/chat/_chat-toggle-button.scss b/packages/instantsearch.css/src/components/chat/_chat-toggle-button.scss index 000cad0f1e..7c60f2f50d 100644 --- a/packages/instantsearch.css/src/components/chat/_chat-toggle-button.scss +++ b/packages/instantsearch.css/src/components/chat/_chat-toggle-button.scss @@ -12,12 +12,10 @@ width: calc(var(--ais-icon-size) * 1.4); } - @media (prefers-reduced-motion: no-preference) { - transition: transform var(--ais-transition-duration) - var(--ais-transition-timing-function), - background-color var(--ais-transition-duration) - var(--ais-transition-timing-function); - } + transition: transform var(--ais-transition-duration) + var(--ais-transition-timing-function), + background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); } .ais-ChatToggleButton--open { diff --git a/packages/instantsearch.css/src/components/filter-suggestions.scss b/packages/instantsearch.css/src/components/filter-suggestions.scss index 4430865626..f6baa6c1b1 100644 --- a/packages/instantsearch.css/src/components/filter-suggestions.scss +++ b/packages/instantsearch.css/src/components/filter-suggestions.scss @@ -91,9 +91,7 @@ width: 20%; } - @media (prefers-reduced-motion: no-preference) { - animation: ais-filter-suggestions-skeleton 1.5s ease-in-out infinite; - } + animation: ais-filter-suggestions-skeleton 1.5s ease-in-out infinite; } @keyframes ais-filter-suggestions-skeleton { diff --git a/packages/instantsearch.css/src/shared/_common.scss b/packages/instantsearch.css/src/shared/_common.scss index 4bf8a34cb7..69116fe7a3 100644 --- a/packages/instantsearch.css/src/shared/_common.scss +++ b/packages/instantsearch.css/src/shared/_common.scss @@ -35,6 +35,19 @@ } } +// Reduced motion +@media (prefers-reduced-motion: reduce) { + [class^='ais-'], + [class^='ais-'] *, + [class^='ais-']::before, + [class^='ais-']::after, + [class^='ais-'] *::before, + [class^='ais-'] *::after { + transition: none !important; + animation: none !important; + } +} + // Fade-in animation @keyframes ais-fadeIn { from { diff --git a/packages/instantsearch.css/src/shared/_nova-common.scss b/packages/instantsearch.css/src/shared/_nova-common.scss new file mode 100644 index 0000000000..85b4bf22a9 --- /dev/null +++ b/packages/instantsearch.css/src/shared/_nova-common.scss @@ -0,0 +1,125 @@ +@use 'variables'; + +// Auto dark mode +@media (prefers-color-scheme: dark) { + :root:not([data-theme='light']) { + @include variables.dark-theme; + } +} + +// Focus outline (generic) +a[class^='ais-']:focus-visible, +button[class^='ais-']:focus-visible, +input[class^='ais-']:not(.ais-AutocompleteInput):not( + .ais-SearchBox-input + ):focus-visible, +select[class^='ais-']:focus-visible { + outline: 2px solid + rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + outline-offset: 2px; +} + +// Shared button / showMore styles +[class^='ais-'][class*='-showMore'], +[class^='ais-'][class*='-button'] { + border-radius: var(--ais-border-radius-sm); + font-size: 0.9em; + font-weight: var(--ais-font-weight-medium); + color: rgba( + var(--ais-button-text-color-rgb), + var(--ais-button-text-color-alpha) + ); + padding: calc(var(--ais-spacing) / 2) var(--ais-spacing) + calc(var(--ais-spacing) / 2) var(--ais-spacing); + background-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + box-shadow: var(--ais-shadow-xs); +} + +[class^='ais-'][class*='-showMore'] { + margin-top: calc(var(--ais-spacing) * 0.75); +} + +@media (hover: hover) { + [class^='ais-'][class*='-showMore']:not([class^='ais-'][disabled]):hover { + background-color: rgba(var(--ais-primary-color-rgb), 0.85); + } +} + +// Disabled state +[class^='ais-'][disabled] { + opacity: 0.75; + cursor: not-allowed; +} + +// Count badge +[class^='ais-'][class*='-count'] { + margin-left: auto; + color: rgba(var(--ais-text-color-rgb), 0.7); + border-radius: var(--ais-border-radius-full); + padding: calc(var(--ais-spacing) * 0.125) calc(var(--ais-spacing) * 0.625); + border: 1px solid rgba(var(--ais-muted-color-rgb), 0.3); + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + white-space: nowrap; + font-size: 0.75em; +} + +// Custom select (MenuSelect, HitsPerPage, SortBy) +.ais-MenuSelect, +.ais-HitsPerPage, +.ais-SortBy { + &:after { + transition: transform var(--ais-transition-duration) + var(--ais-transition-timing-function); + background-image: var(--ais-chevron-icon); + background-repeat: no-repeat; + content: ''; + display: inline-block; + height: 1rem; + margin-left: calc(var(--ais-spacing) * -1 - 1rem); + transform: translateY(0.2rem); + pointer-events: none; + user-select: none; + width: 1rem; + } +} + +.ais-MenuSelect-select, +.ais-HitsPerPage-select, +.ais-SortBy-select { + width: 100%; + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + font: inherit; + padding: calc(var(--ais-spacing) / 2) calc(var(--ais-spacing) * 2 + 0.5rem) + calc(var(--ais-spacing) / 2) var(--ais-spacing); + border-radius: var(--ais-border-radius-sm); + border: 1px solid + rgba(var(--ais-border-color-rgb), var(--ais-border-color-alpha)); + + &:focus-visible { + outline-offset: -1px; + } +} + +// Checked checkbox +input[class^='ais-'][type='checkbox']:checked { + background-image: var(--ais-check-icon); + background-repeat: no-repeat; + background-size: calc(var(--ais-spacing) * 0.625); + background-position: 50%; + background-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + border-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); +} diff --git a/packages/instantsearch.css/src/shared/_variables.scss b/packages/instantsearch.css/src/shared/_variables.scss index 484b9e2d84..da4f3116f0 100644 --- a/packages/instantsearch.css/src/shared/_variables.scss +++ b/packages/instantsearch.css/src/shared/_variables.scss @@ -34,6 +34,7 @@ $ais-chat-breakpoint: 680px; --ais-spacing: calc(var(--ais-base-unit) * var(--ais-spacing-factor) * 1px); /* Shadows */ + --ais-shadow-xs: 0px 1px 2px 0px rgba(var(--ais-shadow-color-rgb), 0.15); --ais-shadow-sm: 0px 0px 0px 1px rgba(var(--ais-shadow-color-rgb), 0.05), 0px 1px 3px 0px rgba(var(--ais-shadow-color-rgb), 0.25); --ais-shadow-md: 0px 0px 0px 1px rgba(var(--ais-shadow-color-rgb), 0.05), @@ -56,6 +57,9 @@ $ais-chat-breakpoint: 680px; /* Icons */ --ais-icon-size: 20px; --ais-icon-stroke-width: 1.6; + --ais-chevron-icon: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23262626%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E'); + --ais-selected-chevron-icon: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%231f6ff2%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E'); + --ais-check-icon: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20aria-hidden%3D%22true%22%20viewBox%3D%220%200%2016%2012%22%3E%3Cpath%20stroke%3D%22%23fff%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20stroke-width%3D%221.6%22%20d%3D%22M1%205.917%205.724%2010.5%2015%201.5%22%2F%3E%3C%2Fsvg%3E'); /* Transitions */ --ais-transition-duration: 0.3s; @@ -75,6 +79,9 @@ $ais-chat-breakpoint: 680px; /* Chat carousel component */ --ais-chat-carousel-item-width: calc(var(--ais-spacing) * 10); + /* Hit grid */ + --ais-hit-min-width: 200px; + /* Autocomplete component */ --ais-autocomplete-search-input-height: 44px; --ais-autocomplete-panel-max-height: 650px; @@ -105,16 +112,13 @@ $ais-chat-breakpoint: 680px; /* Shadow color */ --ais-shadow-color-rgb: 0, 0, 0; + + /* Icons */ + --ais-chevron-icon: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23ebebeb%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E'); + --ais-selected-chevron-icon: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%235B96F5%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpolyline%20points%3D%226%209%2012%2015%2018%209%22%3E%3C%2Fpolyline%3E%3C%2Fsvg%3E'); } :root[data-theme='dark'], .dark { @include dark-theme; } - -// Disabled until all widgets support dark mode -// @media (prefers-color-scheme: dark) { -// :root:not([data-theme='light']) { -// @include dark-theme; -// } -// } diff --git a/packages/instantsearch.css/src/themes/nova.scss b/packages/instantsearch.css/src/themes/nova.scss new file mode 100644 index 0000000000..b66a91cbde --- /dev/null +++ b/packages/instantsearch.css/src/themes/nova.scss @@ -0,0 +1,28 @@ +@use 'reset'; + +@use '../shared/_variables'; +@use '../shared/_common'; +@use '../shared/_nova-common'; + +@use '../components/chat'; +@use '../components/autocomplete'; +@use '../components/filter-suggestions'; + +@use '../widgets/searchbox'; +@use '../widgets/breadcrumb'; +@use '../widgets/hierarchical-menu'; +@use '../widgets/menu'; +@use '../widgets/refinement-list'; +@use '../widgets/toggle-refinement'; +@use '../widgets/numeric-menu'; +@use '../widgets/range-input'; +@use '../widgets/panel'; +@use '../widgets/current-refinements'; +@use '../widgets/pagination'; +@use '../widgets/rating-menu'; +@use '../widgets/hits'; +@use '../widgets/infinite-hits'; +@use '../widgets/geo-search'; +@use '../widgets/highlight'; +@use '../widgets/relevant-sort'; +@use '../widgets/powered-by'; diff --git a/packages/instantsearch.css/src/themes/reset.scss b/packages/instantsearch.css/src/themes/reset.scss index c8f5057db8..6ab45542df 100644 --- a/packages/instantsearch.css/src/themes/reset.scss +++ b/packages/instantsearch.css/src/themes/reset.scss @@ -4,6 +4,15 @@ box-sizing: border-box; } +a[class^='ais-'] { + text-decoration: none; +} + +select[class^='ais-'] { + appearance: none; + background: none; +} + // Reset all lists .ais-Breadcrumb-list, @@ -45,6 +54,7 @@ .ais-RangeInput-submit, .ais-RefinementList-showMore, .ais-AiModeButton, +.ais-RelevantSort-button, .ais-SearchBox-submit, .ais-SearchBox-reset, .ais-VoiceSearch-button { @@ -115,6 +125,11 @@ height: 20px; } +.ais-RefinementList-checkbox, +.ais-ToggleRefinement-checkbox { + margin: 0; +} + .ais-SearchBox-input { &::-ms-clear, &::-ms-reveal { diff --git a/packages/instantsearch.css/src/widgets/_breadcrumb.scss b/packages/instantsearch.css/src/widgets/_breadcrumb.scss new file mode 100644 index 0000000000..36e4626aad --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_breadcrumb.scss @@ -0,0 +1,39 @@ +.ais-Breadcrumb-list { + @media screen and (min-width: 768px) { + align-items: center; + display: flex; + flex-wrap: wrap; + row-gap: calc(var(--ais-spacing) / 3); + } +} + +.ais-Breadcrumb-item { + margin-block-end: calc(var(--ais-spacing) / 2); + + @media screen and (min-width: 768px) { + margin-block-end: 0; + } +} + +.ais-Breadcrumb-item--selected { + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + font-weight: var(--ais-font-weight-semibold); +} + +.ais-Breadcrumb-separator { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + font-weight: normal; + margin: 0 calc(var(--ais-spacing) / 3); +} + +.ais-Breadcrumb-link { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + transition: color var(--ais-transition-duration) + var(--ais-transition-timing-function); + + &:hover, + &:focus { + text-decoration: underline; + text-underline-offset: 2px; + } +} diff --git a/packages/instantsearch.css/src/widgets/_current-refinements.scss b/packages/instantsearch.css/src/widgets/_current-refinements.scss new file mode 100644 index 0000000000..f258927116 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_current-refinements.scss @@ -0,0 +1,35 @@ +.ais-CurrentRefinements-list { + display: flex; + gap: calc(var(--ais-spacing) / 2); + flex-wrap: wrap; +} + +.ais-CurrentRefinements-item { + align-items: center; + font-size: 0.9em; + display: inline-flex; + border: 1px solid + rgba(var(--ais-border-color-rgb), var(--ais-border-color-alpha)); + border-radius: var(--ais-border-radius-sm); + padding: calc(var(--ais-spacing) / 3) calc(var(--ais-spacing) / 2); + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); +} + +.ais-CurrentRefinements-label { + text-transform: capitalize; +} + +.ais-CurrentRefinements-category { + margin-left: calc(var(--ais-spacing) / 2); + display: flex; + align-items: center; +} + +.ais-CurrentRefinements-delete { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + margin-left: calc(var(--ais-spacing) / 3); + + &:hover { + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + } +} diff --git a/packages/instantsearch.css/src/widgets/_geo-search.scss b/packages/instantsearch.css/src/widgets/_geo-search.scss new file mode 100644 index 0000000000..2f49df9e38 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_geo-search.scss @@ -0,0 +1,86 @@ +.ais-GeoSearch { + position: relative; +} + +.ais-GeoSearch-control { + position: absolute; + top: 0.75rem; + left: 0.75rem; +} + +.ais-GeoSearch-label { + display: inline-flex; + align-items: center; + padding: calc(var(--ais-spacing) * 0.375) calc(var(--ais-spacing) * 0.625); + font-size: 0.85em; + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border-radius: var(--ais-border-radius-sm); + box-shadow: var(--ais-shadow-sm); + cursor: pointer; + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); +} + +@media (hover: hover) { + .ais-GeoSearch-label:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + } +} + +.ais-GeoSearch-label--selected { + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-GeoSearch-input { + border-radius: calc(var(--ais-spacing) / 4); + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border: 1px solid rgba(var(--ais-border-color-rgb), 0.5); + appearance: none; + width: var(--ais-spacing); + height: var(--ais-spacing); + margin: 0 calc(var(--ais-spacing) * 0.5) 0 0; + cursor: inherit; + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); +} + +.ais-GeoSearch-label, +.ais-GeoSearch-redo, +.ais-GeoSearch-reset { + white-space: nowrap; +} + +.ais-GeoSearch-redo, +.ais-GeoSearch-reset { + padding: calc(var(--ais-spacing) * 0.375) calc(var(--ais-spacing) * 0.625); + font-size: 0.85em; + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border-radius: var(--ais-border-radius-sm); + box-shadow: var(--ais-shadow-sm); + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); +} + +@media (hover: hover) { + .ais-GeoSearch-redo:not([disabled]):hover, + .ais-GeoSearch-reset:not([disabled]):hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + } +} + +.ais-GeoSearch-reset { + position: absolute; + bottom: 1.25rem; + left: 50%; + transform: translateX(-50%); +} diff --git a/packages/instantsearch.css/src/widgets/_hierarchical-menu.scss b/packages/instantsearch.css/src/widgets/_hierarchical-menu.scss new file mode 100644 index 0000000000..e82a47b0e1 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_hierarchical-menu.scss @@ -0,0 +1,68 @@ +.ais-HierarchicalMenu-list .ais-HierarchicalMenu-list { + margin-left: calc(var(--ais-spacing) * 1); + padding-left: calc(var(--ais-spacing) * 0.375); + border-left: 1px solid + rgba(var(--ais-border-color-rgb), var(--ais-border-color-alpha)); +} + +.ais-HierarchicalMenu-list, +.ais-HierarchicalMenu-item--parent { + display: flex; + flex-direction: column; + row-gap: calc(var(--ais-spacing) / 4); +} + +.ais-HierarchicalMenu-link { + color: rgba(var(--ais-text-color-rgb), 0.9); + display: flex; + align-items: center; + padding: calc(var(--ais-spacing) * 0.375) calc(var(--ais-spacing) / 2); + border-radius: var(--ais-border-radius-sm); + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + color var(--ais-transition-duration) var(--ais-transition-timing-function); + + &:before { + transition: transform var(--ais-transition-duration) + var(--ais-transition-timing-function); + background-image: var(--ais-chevron-icon); + background-repeat: no-repeat; + content: ''; + display: inline-block; + height: 1rem; + margin-right: 0.5rem; + user-select: none; + width: 1rem; + flex-shrink: 0; + transform: rotate(-90deg); + } +} + +.ais-HierarchicalMenu-link--selected:before { + transform: rotate(0deg); + background-image: var(--ais-selected-chevron-icon); +} + +.ais-HierarchicalMenu-link--selected { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-HierarchicalMenu-label { + margin-right: var(--ais-spacing); +} + +@media (hover: hover) { + .ais-HierarchicalMenu-link:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + + &:before { + background-image: var(--ais-selected-chevron-icon); + } + } + + .ais-HierarchicalMenu-link--selected:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.2); + } +} diff --git a/packages/instantsearch.css/src/widgets/_highlight.scss b/packages/instantsearch.css/src/widgets/_highlight.scss new file mode 100644 index 0000000000..a51f940616 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_highlight.scss @@ -0,0 +1,9 @@ +.ais-Highlight-highlighted, +.ais-Snippet-highlighted, +// instantsearch.js renders plain without classes (e.g. RefinementList search) +[class^='ais-'] mark { + background-color: rgba(var(--ais-primary-color-rgb), 0.2); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + border-radius: 2px; + padding: calc(var(--ais-spacing) * 0.125); +} diff --git a/packages/instantsearch.css/src/widgets/_hits.scss b/packages/instantsearch.css/src/widgets/_hits.scss new file mode 100644 index 0000000000..a9c029c2b2 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_hits.scss @@ -0,0 +1,43 @@ +.ais-Hits-list, +.ais-InfiniteHits-list { + display: grid; + grid-template-columns: repeat( + auto-fill, + minmax(var(--ais-hit-min-width), 1fr) + ); + gap: var(--ais-spacing); +} + +.ais-Hits-item, +.ais-InfiniteHits-item { + overflow: hidden; + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border-radius: var(--ais-border-radius-sm); + box-shadow: var(--ais-shadow-xs); + border: 1px solid rgba(var(--ais-border-color-rgb), 0.3); + transition: box-shadow var(--ais-transition-duration) + var(--ais-transition-timing-function), + background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + + @media (hover: hover) { + &:hover { + box-shadow: var(--ais-shadow-md); + background-color: rgba(var(--ais-primary-color-rgb), 0.05); + } + } +} + +.ais-Hits-banner, +.ais-InfiniteHits-banner { + margin-bottom: var(--ais-spacing); +} + +.ais-Hits-banner-image, +.ais-InfiniteHits-banner-image { + width: 100%; + border-radius: var(--ais-border-radius-sm); +} diff --git a/packages/instantsearch.css/src/widgets/_infinite-hits.scss b/packages/instantsearch.css/src/widgets/_infinite-hits.scss new file mode 100644 index 0000000000..c7a721cc6a --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_infinite-hits.scss @@ -0,0 +1,34 @@ +.ais-InfiniteHits-loadPrevious, +.ais-InfiniteHits-loadMore { + border-radius: var(--ais-border-radius-sm); + font-size: 0.9em; + font-weight: var(--ais-font-weight-medium); + color: rgba( + var(--ais-button-text-color-rgb), + var(--ais-button-text-color-alpha) + ); + padding: calc(var(--ais-spacing) / 2) var(--ais-spacing); + background-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + box-shadow: var(--ais-shadow-xs); + width: 100%; +} + +.ais-InfiniteHits-loadPrevious { + margin-bottom: var(--ais-spacing); +} + +.ais-InfiniteHits-loadMore { + margin-top: var(--ais-spacing); +} + +@media (hover: hover) { + .ais-InfiniteHits-loadPrevious:not([disabled]):hover, + .ais-InfiniteHits-loadMore:not([disabled]):hover { + background-color: rgba(var(--ais-primary-color-rgb), 0.85); + } +} diff --git a/packages/instantsearch.css/src/widgets/_menu.scss b/packages/instantsearch.css/src/widgets/_menu.scss new file mode 100644 index 0000000000..ce6b8f2465 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_menu.scss @@ -0,0 +1,43 @@ +.ais-Menu-list { + display: flex; + flex-direction: column; + row-gap: calc(var(--ais-spacing) / 4); +} + +.ais-Menu-item { + color: rgba(var(--ais-text-color-rgb), 0.9); +} + +.ais-Menu-item--selected { + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-Menu-link { + display: flex; + align-items: center; + padding: calc(var(--ais-spacing) * 0.375) calc(var(--ais-spacing) / 2); + border-radius: var(--ais-border-radius-sm); + color: inherit; + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + color var(--ais-transition-duration) var(--ais-transition-timing-function); +} + +.ais-Menu-item--selected .ais-Menu-link { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); +} + +.ais-Menu-label { + margin-right: var(--ais-spacing); +} + +@media (hover: hover) { + .ais-Menu-link:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + } + + .ais-Menu-item--selected .ais-Menu-link:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.2); + } +} diff --git a/packages/instantsearch.css/src/widgets/_numeric-menu.scss b/packages/instantsearch.css/src/widgets/_numeric-menu.scss new file mode 100644 index 0000000000..5996a0ee9b --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_numeric-menu.scss @@ -0,0 +1,78 @@ +.ais-NumericMenu-list { + display: flex; + flex-direction: column; + row-gap: calc(var(--ais-spacing) / 4); +} + +.ais-NumericMenu-item { + color: rgba(var(--ais-text-color-rgb), 0.9); +} + +.ais-NumericMenu-item--selected { + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-NumericMenu-item--selected .ais-NumericMenu-label { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); +} + +.ais-NumericMenu-label { + display: flex; + align-items: center; + padding: calc(var(--ais-spacing) * 0.375) calc(var(--ais-spacing) / 2); + border-radius: var(--ais-border-radius-sm); + cursor: pointer; + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + color var(--ais-transition-duration) var(--ais-transition-timing-function); +} + +.ais-NumericMenu-radio { + border-radius: var(--ais-border-radius-full); + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border: 1px solid rgba(var(--ais-border-color-rgb), 0.5); + appearance: none; + width: var(--ais-spacing); + height: var(--ais-spacing); + flex-shrink: 0; + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + border-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + margin-right: calc(var(--ais-spacing) * 0.625); +} + +.ais-NumericMenu-radio:checked { + background-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + border-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + box-shadow: inset 0 0 0 2px + rgba(var(--ais-background-color-rgb), var(--ais-background-color-alpha)); +} + +.ais-NumericMenu-labelText { + user-select: none; +} + +@media (hover: hover) { + .ais-NumericMenu-label:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + + .ais-NumericMenu-radio:not(:checked) { + background-color: rgba(var(--ais-primary-color-rgb), 0.1); + } + } + + .ais-NumericMenu-item--selected .ais-NumericMenu-label:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.2); + } +} diff --git a/packages/instantsearch.css/src/widgets/_pagination.scss b/packages/instantsearch.css/src/widgets/_pagination.scss new file mode 100644 index 0000000000..65bf1494e8 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_pagination.scss @@ -0,0 +1,75 @@ +.ais-Pagination { + display: flex; + justify-content: center; + font-variant-numeric: tabular-nums; + + .ais-Pagination-list { + display: flex; + box-shadow: var(--ais-shadow-xs); + border-radius: var(--ais-border-radius-sm); + border: 1px solid rgba(var(--ais-border-color-rgb), 0.3); + } + + .ais-Pagination-link { + padding: calc(var(--ais-spacing) / 2) var(--ais-spacing); + text-align: center; + } + + .ais-Pagination-item { + .ais-Pagination-link { + display: block; + border-right: 1px solid rgba(var(--ais-border-color-rgb), 0.3); + color: currentColor; + transition: background var(--ais-transition-duration) + var(--ais-transition-timing-function); + + &:hover { + background: rgba(var(--ais-muted-color-rgb), 0.1); + } + } + + &:last-of-type { + .ais-Pagination-link { + border-right: none; + } + } + } + + .ais-Pagination-item--firstPage, + .ais-Pagination-item--previousPage, + .ais-Pagination-item--nextPage, + .ais-Pagination-item--lastPage { + .ais-Pagination-link { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + } + } + + .ais-Pagination-item--disabled { + .ais-Pagination-link { + color: rgba(var(--ais-muted-color-rgb), 0.4); + cursor: not-allowed; + + &:hover { + background: none; + } + } + } + + .ais-Pagination-item--selected { + .ais-Pagination-link { + background: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + color: rgba( + var(--ais-button-text-color-rgb), + var(--ais-button-text-color-alpha) + ); + cursor: default; + + &:hover { + background: rgba(var(--ais-primary-color-rgb), 0.8); + } + } + } +} diff --git a/packages/instantsearch.css/src/widgets/_panel.scss b/packages/instantsearch.css/src/widgets/_panel.scss new file mode 100644 index 0000000000..76acbdcc92 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_panel.scss @@ -0,0 +1,40 @@ +.ais-Panel-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: calc(var(--ais-spacing) * 0.75); + font-size: 0.85em; + font-weight: var(--ais-font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.05em; + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); +} + +.ais-Panel-collapseButton { + appearance: none; + background: none; + border: 0; + padding: 0; + margin: 0; + cursor: pointer; + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + transition: color var(--ais-transition-duration) + var(--ais-transition-timing-function); +} + +@media (hover: hover) { + .ais-Panel-collapseButton:hover { + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + } +} + +.ais-Panel--collapsed .ais-Panel-body, +.ais-Panel--collapsed .ais-Panel-footer { + display: none; +} + +.ais-Panel-footer { + margin-top: calc(var(--ais-spacing) * 0.75); + font-size: 0.85em; + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); +} diff --git a/packages/instantsearch.css/src/widgets/_powered-by.scss b/packages/instantsearch.css/src/widgets/_powered-by.scss new file mode 100644 index 0000000000..fc8cfda871 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_powered-by.scss @@ -0,0 +1,3 @@ +.ais-PoweredBy-logo path:first-of-type { + fill: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); +} diff --git a/packages/instantsearch.css/src/widgets/_range-input.scss b/packages/instantsearch.css/src/widgets/_range-input.scss new file mode 100644 index 0000000000..2a9b016c7b --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_range-input.scss @@ -0,0 +1,76 @@ +.ais-RangeInput-form { + display: flex; + align-items: center; + gap: calc(var(--ais-spacing) * 0.5); +} + +.ais-RangeInput-label { + flex: 1; +} + +.ais-RangeInput-input { + appearance: none; + border: 1px solid rgba(var(--ais-border-color-rgb), 0.5); + border-radius: var(--ais-border-radius-sm); + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + font: inherit; + padding: calc(var(--ais-spacing) * 0.5) calc(var(--ais-spacing) * 0.625); + width: 100%; + transition: border-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + + &::placeholder { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + opacity: 1; + } + + &:focus { + border-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + box-shadow: rgba(var(--ais-primary-color-rgb), 0.3) 0 0 0 2px; + outline: none; + } +} + +.ais-RangeInput-separator { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + font-size: 0.9em; + flex-shrink: 0; +} + +.ais-RangeInput-submit { + align-self: stretch; + border-radius: var(--ais-border-radius-sm); + font-size: 0.9em; + font-weight: var(--ais-font-weight-medium); + color: rgba( + var(--ais-button-text-color-rgb), + var(--ais-button-text-color-alpha) + ); + padding: 0 calc(var(--ais-spacing) * 0.875); + background-color: rgba( + var(--ais-primary-color-rgb), + var(--ais-primary-color-alpha) + ); + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + box-shadow: var(--ais-shadow-xs); + flex-shrink: 0; +} + +@media (hover: hover) { + .ais-RangeInput-submit:not(:disabled):hover { + background-color: rgba(var(--ais-primary-color-rgb), 0.85); + } +} + +.ais-RangeInput-submit:disabled { + opacity: 0.75; + cursor: not-allowed; +} diff --git a/packages/instantsearch.css/src/widgets/_rating-menu.scss b/packages/instantsearch.css/src/widgets/_rating-menu.scss new file mode 100644 index 0000000000..579c282096 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_rating-menu.scss @@ -0,0 +1,69 @@ +.ais-RatingMenu-list { + display: flex; + flex-direction: column; + row-gap: calc(var(--ais-spacing) / 4); +} + +.ais-RatingMenu-item { + color: rgba(var(--ais-text-color-rgb), 0.9); +} + +.ais-RatingMenu-item--disabled { + opacity: 0.5; + pointer-events: none; +} + +.ais-RatingMenu-link { + display: flex; + align-items: center; + padding: calc(var(--ais-spacing) * 0.375) calc(var(--ais-spacing) / 2); + border-radius: var(--ais-border-radius-sm); + color: inherit; + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + color var(--ais-transition-duration) var(--ais-transition-timing-function); +} + +.ais-RatingMenu-item--selected .ais-RatingMenu-link { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-RatingMenu-starIcon { + width: 1em; + height: 1em; +} + +.ais-RatingMenu-starIcon--full { + fill: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + transition: fill var(--ais-transition-duration) + var(--ais-transition-timing-function); +} + +.ais-RatingMenu-starIcon--empty { + fill: rgba(var(--ais-muted-color-rgb), 0.3); +} + +.ais-RatingMenu-item--selected .ais-RatingMenu-starIcon--full { + fill: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-RatingMenu-label { + margin-left: calc(var(--ais-spacing) * 0.25); + margin-right: var(--ais-spacing); +} + +@media (hover: hover) { + .ais-RatingMenu-link:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + + .ais-RatingMenu-starIcon--full { + fill: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + } + } + + .ais-RatingMenu-item--selected .ais-RatingMenu-link:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.2); + } +} diff --git a/packages/instantsearch.css/src/widgets/_refinement-list.scss b/packages/instantsearch.css/src/widgets/_refinement-list.scss new file mode 100644 index 0000000000..fe285436f2 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_refinement-list.scss @@ -0,0 +1,62 @@ +.ais-RefinementList-searchBox { + margin-bottom: calc(var(--ais-spacing) * 0.5); +} + +.ais-RefinementList-list { + display: flex; + flex-direction: column; + row-gap: calc(var(--ais-spacing) / 4); +} + +.ais-RefinementList-item { + color: rgba(var(--ais-text-color-rgb), 0.9); +} + +.ais-RefinementList-item--selected { + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-RefinementList-item--selected .ais-RefinementList-label { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); +} + +.ais-RefinementList-label { + display: flex; + align-items: center; + padding: calc(var(--ais-spacing) * 0.375) calc(var(--ais-spacing) / 2); + border-radius: var(--ais-border-radius-sm); + cursor: pointer; + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + color var(--ais-transition-duration) var(--ais-transition-timing-function); +} + +@media (hover: hover) { + .ais-RefinementList-label:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.1); + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + + .ais-RefinementList-checkbox { + background-color: rgba(var(--ais-primary-color-rgb), 0.1); + } + } + + .ais-RefinementList-item--selected .ais-RefinementList-label:hover { + background-color: rgba(var(--ais-muted-color-rgb), 0.2); + } +} + +.ais-RefinementList-checkbox { + border-radius: calc(var(--ais-spacing) / 4); + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border: 1px solid rgba(var(--ais-border-color-rgb), 0.5); + appearance: none; + width: var(--ais-spacing); + height: var(--ais-spacing); + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + margin-right: calc(var(--ais-spacing) * 0.625); +} diff --git a/packages/instantsearch.css/src/widgets/_relevant-sort.scss b/packages/instantsearch.css/src/widgets/_relevant-sort.scss new file mode 100644 index 0000000000..66ecd8cc05 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_relevant-sort.scss @@ -0,0 +1,15 @@ +.ais-RelevantSort { + display: flex; + flex-direction: column; + gap: calc(var(--ais-spacing) * 0.75); +} + +.ais-RelevantSort-text { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + font-size: 0.9em; + line-height: 1.5; +} + +.ais-RelevantSort-button { + align-self: flex-start; +} diff --git a/packages/instantsearch.css/src/widgets/_searchbox.scss b/packages/instantsearch.css/src/widgets/_searchbox.scss new file mode 100644 index 0000000000..2dbe17edf1 --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_searchbox.scss @@ -0,0 +1,136 @@ +.ais-SearchBox-form { + display: flex; + align-items: center; + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border: 1px solid rgba(var(--ais-border-color-rgb), 0.8); + border-radius: var(--ais-border-radius-sm); + line-height: 1em; + margin: 0; + width: 100%; + height: calc(var(--ais-spacing) * 2.75); + + transition: border-color var(--ais-transition-duration) + var(--ais-transition-timing-function), + box-shadow var(--ais-transition-duration) + var(--ais-transition-timing-function), + outline-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + + &:focus-within { + border-color: rgba(var(--ais-primary-color-rgb), 1); + box-shadow: rgba(var(--ais-primary-color-rgb), 0.3) 0 0 0 2px, + inset rgba(var(--ais-primary-color-rgb), 0.3) 0 0 0 2px; + outline: currentColor none medium; + } + + .ais-SearchBox-submit, + .ais-SearchBox-loadingIndicator { + cursor: initial; + flex-shrink: 0; + height: 100%; + padding-left: var(--ais-spacing); + padding-right: calc(var(--ais-spacing) * 0.75); + + svg { + color: rgba(var(--ais-primary-color-rgb), 1); + height: auto; + max-height: var(--ais-spacing); + width: var(--ais-spacing); + stroke-width: var(--ais-icon-stroke-width); + } + } + + .ais-SearchBox-submit { + appearance: none; + background: none; + border: 0; + margin: 0; + order: 1; + + &:has(~ .ais-SearchBox-loadingIndicator:not([hidden])) { + display: none; + } + + .ais-SearchBox-submitIcon { + fill: currentColor; + transform: translateY(1px); + } + } + + .ais-SearchBox-loadingIndicator { + align-items: center; + display: flex; + justify-content: center; + + &[hidden] { + display: none; + } + + .ais-SearchBox-loadingIcon { + stroke: currentColor; + } + } + + .ais-SearchBox-input { + appearance: none; + background: none; + border: 0; + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + font: inherit; + height: 100%; + padding: 0; + width: 100%; + order: 2; + + &::placeholder { + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + opacity: 1; + } + + &:focus { + outline: none; + } + + &::-webkit-search-decoration, + &::-webkit-search-cancel-button, + &::-webkit-search-results-button, + &::-webkit-search-results-decoration { + appearance: none; + } + } + + .ais-SearchBox-reset { + align-items: center; + background: none; + border: 0; + color: rgba(var(--ais-muted-color-rgb), var(--ais-muted-color-alpha)); + cursor: pointer; + display: flex; + height: 100%; + margin: 0; + padding: 0 var(--ais-spacing); + order: 3; + transition: color var(--ais-transition-duration) + var(--ais-transition-timing-function); + + &:hover, + &:focus { + color: rgba(var(--ais-text-color-rgb), var(--ais-text-color-alpha)); + } + + &[hidden] { + display: none; + } + + .ais-SearchBox-resetIcon { + stroke-width: var(--ais-icon-stroke-width); + height: auto; + max-height: calc(var(--ais-spacing) * 0.675); + width: calc(var(--ais-spacing) * 0.675); + fill: currentColor; + } + } +} diff --git a/packages/instantsearch.css/src/widgets/_toggle-refinement.scss b/packages/instantsearch.css/src/widgets/_toggle-refinement.scss new file mode 100644 index 0000000000..1f208ff2cf --- /dev/null +++ b/packages/instantsearch.css/src/widgets/_toggle-refinement.scss @@ -0,0 +1,44 @@ +.ais-ToggleRefinement { + color: rgba(var(--ais-text-color-rgb), 0.9); +} + +.ais-ToggleRefinement-label { + display: flex; + align-items: center; + cursor: pointer; + transition: color var(--ais-transition-duration) + var(--ais-transition-timing-function); +} + +@media (hover: hover) { + .ais-ToggleRefinement-label:hover { + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); + + .ais-ToggleRefinement-checkbox { + background-color: rgba(var(--ais-primary-color-rgb), 0.1); + } + } +} + +.ais-ToggleRefinement-checkbox { + border-radius: calc(var(--ais-spacing) / 4); + background-color: rgba( + var(--ais-background-color-rgb), + var(--ais-background-color-alpha) + ); + border: 1px solid rgba(var(--ais-border-color-rgb), 0.5); + appearance: none; + width: var(--ais-spacing); + height: var(--ais-spacing); + transition: background-color var(--ais-transition-duration) + var(--ais-transition-timing-function); + margin-right: calc(var(--ais-spacing) * 0.625); +} + +.ais-ToggleRefinement-checkbox:checked ~ .ais-ToggleRefinement-labelText { + color: rgba(var(--ais-primary-color-rgb), var(--ais-primary-color-alpha)); +} + +.ais-ToggleRefinement-labelText { + user-select: none; +}