diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 11bf3a90ee4..f9aa349030a 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -11,7 +11,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@v5.0.1 + - uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1 if: ${{ github.repository_owner == 'home-assistant' }} with: github-token: ${{ github.token }} diff --git a/.github/workflows/restrict-task-creation.yml b/.github/workflows/restrict-task-creation.yml index a3fbe2bb7f7..83653b159e9 100644 --- a/.github/workflows/restrict-task-creation.yml +++ b/.github/workflows/restrict-task-creation.yml @@ -12,7 +12,7 @@ jobs: if: github.event.issue.type.name == 'Task' steps: - name: Check if user is authorized - uses: actions/github-script@v7 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | const issueAuthor = context.payload.issue.user.login; diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f41d0bbeda0..f3788e50271 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,7 +12,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/stale@v9.1.0 + - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 if: ${{ github.repository_owner == 'home-assistant' }} with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fb127a1aea5..83c4031a1c5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,9 +8,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v5.0.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setting up Node.js - uses: actions/setup-node@v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: 20 cache: "npm" @@ -35,9 +35,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out files from GitHub - uses: actions/checkout@v5.0.0 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setting up Node.js - uses: actions/setup-node@v4.4.0 + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version: 20 cache: "npm" diff --git a/.gitignore b/.gitignore index 878022feb08..9926d52aafe 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,9 @@ source/_data/blueprint_exchange_data.json source/_data/version_data.json source/_data/alerts_data.json source/_data/language_scores.json +source/_data/codeowners.json source/_stash +source/stylesheets/homeassistant/pages/community/index.css source/stylesheets/screen.css source/.jekyll-cache/ vendor diff --git a/Gemfile b/Gemfile index 7f5b289baec..6d66889d697 100644 --- a/Gemfile +++ b/Gemfile @@ -10,8 +10,8 @@ group :development do gem 'stringex', '2.8.6' # > 2.1.0 causes slowdowns https://github.com/sass/sassc-ruby/issues/189 gem 'sassc', '2.1.0' - gem 'sass-embedded', '1.91.0' - gem 'rubocop', '1.80.1' + gem 'sass-embedded', '1.93.0' + gem 'rubocop', '1.80.2' gem 'ruby-lsp', '0.26.1' gem 'rackup', '2.2.1' end @@ -24,7 +24,7 @@ group :jekyll_plugins do end gem 'sinatra', '4.1.1' -gem 'nokogiri', '1.18.9' +gem 'nokogiri', '1.18.10' # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem # and associated library diff --git a/Gemfile.lock b/Gemfile.lock index 569a27516e9..387a8695d63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,10 +5,10 @@ GEM public_suffix (>= 2.0.2, < 7.0) ast (2.4.3) base64 (0.3.0) - bigdecimal (3.2.2) + bigdecimal (3.2.3) chunky_png (1.4.0) colorator (1.1.0) - commonmarker (0.23.11) + commonmarker (0.23.12) compass (1.0.3) chunky_png (~> 1.2) compass-core (~> 1.0.2) @@ -30,10 +30,10 @@ GEM ffi (1.17.2-arm64-darwin) ffi (1.17.2-x86_64-linux-gnu) forwardable-extended (2.6.0) - google-protobuf (4.32.0-arm64-darwin) + google-protobuf (4.32.1-arm64-darwin) bigdecimal rake (>= 13) - google-protobuf (4.32.0-x86_64-linux-gnu) + google-protobuf (4.32.1-x86_64-linux-gnu) bigdecimal rake (>= 13) http_parser.rb (0.8.0) @@ -70,7 +70,7 @@ GEM nokogiri (~> 1.12) jekyll-watch (2.2.1) listen (~> 3.0) - json (2.13.2) + json (2.14.1) kramdown (2.5.1) rexml (>= 3.3.9) kramdown-parser-gfm (1.1.0) @@ -86,9 +86,9 @@ GEM multi_json (1.17.0) mustermann (3.0.4) ruby2_keywords (~> 0.0.1) - nokogiri (1.18.9-arm64-darwin) + nokogiri (1.18.10-arm64-darwin) racc (~> 1.4) - nokogiri (1.18.9-x86_64-linux-gnu) + nokogiri (1.18.10-x86_64-linux-gnu) racc (~> 1.4) parallel (1.27.0) parser (3.3.9.0) @@ -96,7 +96,7 @@ GEM racc pathutil (0.16.2) forwardable-extended (~> 2.6) - prism (1.4.0) + prism (1.5.1) public_suffix (6.0.2) racc (1.8.1) rack (3.2.1) @@ -114,12 +114,12 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rbs (3.9.4) + rbs (3.9.5) logger - regexp_parser (2.11.2) - rexml (3.4.2) + regexp_parser (2.11.3) + rexml (3.4.4) rouge (4.6.0) - rubocop (1.80.1) + rubocop (1.80.2) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -130,7 +130,7 @@ GEM rubocop-ast (>= 1.46.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.46.0) + rubocop-ast (1.47.1) parser (>= 3.3.7.2) prism (~> 1.4) ruby-lsp (0.26.1) @@ -141,9 +141,9 @@ GEM ruby2_keywords (0.0.5) safe_yaml (1.0.5) sass (3.4.25) - sass-embedded (1.91.0-arm64-darwin) + sass-embedded (1.93.0-arm64-darwin) google-protobuf (~> 4.31) - sass-embedded (1.91.0-x86_64-linux-gnu) + sass-embedded (1.93.0-x86_64-linux-gnu) google-protobuf (~> 4.31) sass-globbing (1.1.5) sass (>= 3.1) @@ -180,12 +180,12 @@ DEPENDENCIES jekyll-paginate (= 1.1.0) jekyll-sitemap (= 1.4.0) jekyll-toc (= 0.19.0) - nokogiri (= 1.18.9) + nokogiri (= 1.18.10) rackup (= 2.2.1) rake (= 13.3.0) - rubocop (= 1.80.1) + rubocop (= 1.80.2) ruby-lsp (= 0.26.1) - sass-embedded (= 1.91.0) + sass-embedded (= 1.93.0) sass-globbing (= 1.1.5) sassc (= 2.1.0) sinatra (= 4.1.1) diff --git a/Rakefile b/Rakefile index 0948a8b0655..722d7e1eed8 100644 --- a/Rakefile +++ b/Rakefile @@ -32,6 +32,8 @@ task :generate do abort("Generating version data failed") unless success success = system "rake language_scores_data" abort("Generating language scores data failed") unless success + success = system "rake codeowners_data" + abort("Extracting codeowners") unless success success = system "jekyll build" abort("Generating site failed") unless success if ENV["CONTEXT"] != 'production' @@ -71,6 +73,7 @@ task :preview, :listen do |t, args| system "rake analytics_data" system "rake version_data" system "rake language_scores_data" + system "rake codeowners_data" system "rake alerts_data" jekyllPid = Process.spawn({"OCTOPRESS_ENV"=>"preview"}, "jekyll build -t --watch --incremental") compassPid = Process.spawn("compass watch") @@ -128,3 +131,25 @@ task :language_scores_data do file.write(JSON.generate(remote_data)) end end + +desc "Extract CODEOWNERS and output to _data/codeowners.json" +task :codeowners_data do + codeowners = [] + File.readlines("CODEOWNERS").each do |line| + next if line.start_with?("#") || line.strip.empty? + parts = line.split + next if parts.length < 2 + owners = parts[1..-1] + owners.each do |owner| + owner = owner.delete_prefix('@') + next if owner.include?('/') + codeowners << owner unless codeowners.include?(owner) + end + end + + codeowners.sort! + + File.open("#{source_dir}/_data/codeowners.json", "w") do |file| + file.write(JSON.generate(codeowners)) + end +end \ No newline at end of file diff --git a/_config.yml b/_config.yml index c4741d91c4b..0f27e05289a 100644 --- a/_config.yml +++ b/_config.yml @@ -108,8 +108,8 @@ social: # Home Assistant release details current_major_version: 2025 current_minor_version: 9 -current_patch_version: 0 -date_released: 2025-09-03 +current_patch_version: 4 +date_released: 2025-09-19 # Either # or the anchor link to latest release notes in the blog post. # Must be prefixed with a # and have double quotes around it. diff --git a/sass/homeassistant/_overrides.scss b/sass/homeassistant/_overrides.scss index 9acd804a142..8f0466ee948 100644 --- a/sass/homeassistant/_overrides.scss +++ b/sass/homeassistant/_overrides.scss @@ -328,6 +328,7 @@ dd { display: flex; align-items: center; font-weight: normal; + @media only screen and (max-width: $menu-collapse) { user-select: none; } @@ -612,11 +613,11 @@ a.material-card:hover { .links ul { list-style: none; margin: 0; -} + } .links li { display: inline; -} + } } .installation-survey { @@ -894,10 +895,19 @@ a.material-card:hover { // make it blink every 1.5 seconds, no smoothing animation: blink 1.5s infinite; animation-timing-function: steps(1); + @keyframes blink { - 0% { opacity: 1; } - 50% { opacity: 0.2; } - 100% { opacity: 1; } + 0% { + opacity: 1; + } + + 50% { + opacity: 0.2; + } + + 100% { + opacity: 1; + } } } @@ -1228,12 +1238,43 @@ article.listing { border-radius: 8px; box-shadow: rgba(0, 0, 0, 0.5) 0 0 1px; vertical-align: middle; + } + img, + table, + div.contain { &+p { margin-top: 1.5rem; } } + div.contain { + display: grid; + font-size: .9rem; + font-style: italic; + gap: 16px; + text-align: center; + + img { + + background-color: unset; + border-radius: 20px; + border: unset; + box-shadow: unset; + display: block; + filter: drop-shadow(0 6px 16px rgba(0, 0, 0, 0.1)); + margin: 0 auto; + max-width: 620px; + width: 100%; + } + + &.nb { + img { + border-radius: unset; + } + } + } + img.no-shadow { border: 0; box-shadow: none; @@ -1275,11 +1316,20 @@ article.listing { border-radius: 8px; border-width: 8px; text-align: center; + overflow: hidden; padding-bottom: 8px; font-size: 0.9rem; box-shadow: rgba(0, 0, 0, 0.5) 0 0 1px; + font-style: italic; border: 0; + lite-youtube{ + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + overflow: hidden; + margin: 0 auto 8px; + } + img { display: block; box-shadow: none; @@ -1308,10 +1358,10 @@ article.listing { text-decoration: underline; overflow-wrap: break-word; - &[rel*="external"]{ + &[rel*="external"] { position: relative; - &:after{ + &:after { content: "\00a0\00a0\00a0\00a0\00a0"; display: inline-block; } diff --git a/sass/homeassistant/pages/_getting_started.scss b/sass/homeassistant/pages/_getting_started.scss index 64c829a2be1..acfbe1b84e7 100644 --- a/sass/homeassistant/pages/_getting_started.scss +++ b/sass/homeassistant/pages/_getting_started.scss @@ -1,6 +1,10 @@ #getting_started { .installations { + &.second { + margin-top: 50px; + } + .label { background: #e8e6f0; border-radius: 4px; @@ -143,7 +147,7 @@ } iconify-icon.external-link { - padding-top: 4px; + display: none; } svg { @@ -285,4 +289,4 @@ } } } -} \ No newline at end of file +} diff --git a/sass/homeassistant/pages/community/_base.scss b/sass/homeassistant/pages/community/_base.scss new file mode 100644 index 00000000000..d76c155f5a7 --- /dev/null +++ b/sass/homeassistant/pages/community/_base.scss @@ -0,0 +1,132 @@ +.container { + display: flex; + margin: 0 auto; + max-width: calc(var(--container-max-width) + (var(--container-gutters) * 2)); + padding: 12px calc(var(--container-gutters) / 2); + width: 100%; + height: 100%; + + @include bp(desktop) { + padding: 12px var(--container-gutters); + } + + &-full { + margin: 0 auto; + padding: 0 calc(var(--container-gutters) / 2); + max-width: calc(var(--container-full-max-width) + (var(--container-gutters) * 2)); + width: 100%; + + @include bp(desktop) { + padding: 0 var(--container-gutters); + } + } +} + +footer{ + isolation: isolate; + position: relative; + &:before{ + content: ''; + position: absolute; + height: 500px; + left: 0; + right: 0; + bottom: 100%; + background: linear-gradient(180deg, #F5F6FA 0%, #FFFFFF 100%); + } +} + +html{ + scroll-padding-top: 92px; +} + +#landingpage { + background-color: #F5F6FA; + color: #002332; + + height: auto; + + .page-content { + overflow-x: clip; + padding-top: 68px; + } + + .content { + max-width: unset; + margin: 0; + } + + img { + box-shadow: unset; + vertical-align: unset; + border: unset; + } + + .spacer { + display: none; + } +} + +section { + padding: var(--section-spacing-y) 0; + position: relative; + z-index: 1; +} + +main#page-community { + h1, + .h1 { + @include h1; + } + + h2, + .h2 { + @include h2; + } + + h3, + .h3 { + @include h3; + text-transform: unset; + letter-spacing: unset; + } + + h4, + .h4 { + @include h4; + } + + h5, + .h5 { + @include h5; + } + + h6, + .h6 { + @include h6; + } + + .small { + @include small; + } + + .big { + @include big; + } + + p { + color: var(--typography-paragraph-color); + font-size: var(--typography-paragraph-font-size); + font-weight: var(--typography-paragraph-font-weight); + line-height: var(--typography-paragraph-line-height); + margin: 0; + + &:last-child { + margin-bottom: 0; + } + } + + figure { + margin: 0; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_buttons.scss b/sass/homeassistant/pages/community/_buttons.scss new file mode 100644 index 00000000000..9dfa1bdb225 --- /dev/null +++ b/sass/homeassistant/pages/community/_buttons.scss @@ -0,0 +1,107 @@ + .button { + // Reset - remove after global button refactor + border: unset; + color: initial; + height: unset; + line-height: initial; + margin: unset; + overflow: hidden; + + align-items: center; + background-color: #99DFFC; + border-radius: 40px; + display: inline-flex; + font-size: 10px; + font-weight: 600; + padding: 10px 24px; + transition: color 0.2s ease, background-color 0.2s ease; + + @include bp(desktop) { + font-size: 14px; + } + + &:hover { + box-shadow: unset; + background-color: var(--color-primary); + color: #ffffff; + } + + &:before { + content: unset; + } + + &:has(.icon) { + gap: 4px; + padding: 4px 14px 4px 4px; + + @include bp(desktop) { + gap: 10px; + padding: 8px 24px 8px 8px; + } + } + + &.secondary { + background-color: var(--color-secondary); + + &:hover { + background-color: var(--color-primary); + color: #ffffff; + } + } + + &.hollow-dark { + background-color: unset; + box-shadow: inset 0 0 0 1px #fff; + color: #ffffff; + + + &:hover { + background-color: #ffffff; + color: #002332; + + + } + } + } + + .buttons { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 12px; + + // If DSAP is enabled + &[data-dsap] { + + // Only apply if scrolling down into view + &:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { + // Only if scrolling down into the element + + .button { + transition-duration: 0s; + transition-delay: 0s; + opacity: 0; + transform: translateY(50px); + scale: 0.85; + } + } + + .button { + transform: translateY(0); + + @for $i from 1 through 10 { + &:nth-child(#{$i}) { + transition-property: transform, opacity, scale; + transition-duration: .5s; + transition-delay: #{0.1 + ($i * 0.05)}s; + transition-timing-function: cubic-bezier(0.2, 1, 0.5, 1); + + } + } + } + } + + @include bp(desktop) { + gap: 24px; + } + } \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_event-card.scss b/sass/homeassistant/pages/community/_event-card.scss new file mode 100644 index 00000000000..09eb6987cf1 --- /dev/null +++ b/sass/homeassistant/pages/community/_event-card.scss @@ -0,0 +1,21 @@ +.event-card{ + background-color: rgba(255,255,255,0.4); + padding: 12px; + border-radius: 12px; + border: 1px solid #ffffff; + + .button{ + margin-top: 20px; + } + + .event-title{ + @include h4; + } + + .event-meta{ + @include p; + color: #4F606E; + margin-top: 6px; + font-size: 12px; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_icon.scss b/sass/homeassistant/pages/community/_icon.scss new file mode 100644 index 00000000000..582a2b1343b --- /dev/null +++ b/sass/homeassistant/pages/community/_icon.scss @@ -0,0 +1,25 @@ +.icon{ + aspect-ratio: 1/1; + background-color: #ffffff; + border-radius: 50%; + color: #002332; + height: 100%; + padding: 4px; + display: grid; + place-items: center; + height: 24px; + width: 24px; + + &:has(use[href="#facebook"]){ + padding: 0; + svg{ + height: 100%; + width: 100%; + } + } + + svg{ + width: 100%; + height: 100%; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_mixins.scss b/sass/homeassistant/pages/community/_mixins.scss new file mode 100644 index 00000000000..cf71fb96520 --- /dev/null +++ b/sass/homeassistant/pages/community/_mixins.scss @@ -0,0 +1,84 @@ +@mixin bp($breakpoint) { + @if $breakpoint ==large-mobile { + @media (min-width: 500px) { + @content; + } + } + + @else if $breakpoint ==tablet { + @media (min-width: 768px) { + @content; + } + } + + @else if $breakpoint ==desktop { + @media (min-width: 1024px) { + @content; + } + } + + @else if $breakpoint ==large-desktop { + @media (min-width: 1280px) { + @content; + } + } + + // else if the breakpoint is a pixel value, use it as is + @else { + @media (min-width: $breakpoint) { + @content; + } + } +} + +@mixin h1 { + font-size: var(--typography-h1-font-size); + font-weight: var(--typography-h1-font-weight); + line-height: var(--typography-h1-line-height); + letter-spacing: -1px; +} +@mixin h2 { + font-size: var(--typography-h2-font-size); + font-weight: var(--typography-h2-font-weight); + line-height: var(--typography-h2-line-height); + letter-spacing: -1px; +} +@mixin h3 { + font-size: var(--typography-h3-font-size); + font-weight: var(--typography-h3-font-weight); + line-height: var(--typography-h3-line-height); +} +@mixin h4 { + font-size: var(--typography-h4-font-size); + font-weight: var(--typography-h4-font-weight); + line-height: var(--typography-h4-line-height); +} +@mixin h5 { + font-size: var(--typography-h5-font-size); + font-weight: var(--typography-h5-font-weight); + line-height: var(--typography-h5-line-height); +} +@mixin h6 { + font-size: var(--typography-h6-font-size); + font-weight: var(--typography-h6-font-weight); + line-height: var(--typography-h6-line-height); +} + +@mixin p { + font-size: var(--typography-paragraph-font-size); + font-weight: var(--typography-paragraph-font-weight); + line-height: var(--typography-paragraph-line-height); +} + +@mixin small{ + font-size: var(--typography-small-paragraph-font-size, var(--typography-paragraph-font-size)); + font-weight: var(--typography-small-paragraph-font-weight, var(--typography-paragraph-font-weight)); + line-height: var(--typography-small-paragraph-line-height, var(--typography-paragraph-line-height)); +} + +@mixin big { + font-size: var(--typography-big-font-size); + font-weight: var(--typography-big-font-weight); + line-height: var(--typography-big-line-height); + text-transform: uppercase; +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_photos.scss b/sass/homeassistant/pages/community/_photos.scss new file mode 100644 index 00000000000..4051722b6b3 --- /dev/null +++ b/sass/homeassistant/pages/community/_photos.scss @@ -0,0 +1,92 @@ +.photos { + display: grid; + isolation: isolate; + place-items: center; + position: relative; + + &[data-dsap]:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { // Only if scrolling down into the element + .photo { + opacity: 0; + left: 0; + top: 0; + right: 0; + transform: rotate(0) scale(0.8); + transition-duration: 0s; + transition-delay: 0s; + + &.large { + opacity: 1; + + } + } + } + + .photo { + background-color: #ffffff; + grid-area: 1/1; + display: flex; + flex-direction: column; + gap: 8px; + transition-property: transform, opacity, top, left, right; + transition-duration: .8s; + transition-delay: .25s; + transition-timing-function: cubic-bezier(0.2, 1, 0.5, 1); + + @for $i from 1 through 3 { + &:nth-child(#{$i}) { + transition-delay: #{0.25 + ($i * 0.05)}s; + } + } + + img { + aspect-ratio: 1/1; + width: 100%; + background-color: #f5f5f5; + } + + figcaption { + font-size: 16px; + text-align: center; + } + + &.small { + border-radius: 8px; + padding: 6px; + position: absolute; + right: -15%; + top: -10%; + width: 50%; + z-index: 1; + transform: rotate(9deg); + + img { + border-radius: 4px; + } + } + + &.medium { + border-radius: 12px; + left: -10%; + padding: 8px; + position: absolute; + top: -15%; + width: 70%; + z-index: 2; + transform: rotate(-15deg); + + img { + border-radius: 6px; + } + } + + &.large { + border-radius: 12px; + padding: 12px; + z-index: 3; + + img { + border-radius: 6px; + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_stats.scss b/sass/homeassistant/pages/community/_stats.scss new file mode 100644 index 00000000000..dc6ab93cd34 --- /dev/null +++ b/sass/homeassistant/pages/community/_stats.scss @@ -0,0 +1,26 @@ +.stats { + display: flex; + flex-wrap: wrap; + gap: 24px 40px; + + .stat { + display: flex; + flex-direction: column; + min-width: 100px; + + .stat-value { + @include h3; + + color: var(--color-secondary); + display: flex; + gap: 4px; + } + + .stat-label { + @include small; + + max-width: 140px; + text-wrap: balance; + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/_variables.scss b/sass/homeassistant/pages/community/_variables.scss new file mode 100644 index 00000000000..0d4acb003ff --- /dev/null +++ b/sass/homeassistant/pages/community/_variables.scss @@ -0,0 +1,57 @@ +:root { + --color-primary: #00AEF8; + --color-secondary: #16F3BE; + + // Containers and widths + --container-max-width: 1100px; + --container-full-max-width: 1400px; + --container-gutters: 24px; + + --section-spacing-y: 52px; + + // Typography + --typography-base-font: "Figtree", serif; + --typography-heading-line-height: 1.25; + + --typography-h1-font-size: 36px; + --typography-h1-font-weight: 600; + --typography-h1-line-height: 1; + + --typography-h2-font-size: 30px; + --typography-h2-font-weight: 600; + --typography-h2-line-height: 1.1; + + --typography-h3-font-size: 24px; + --typography-h3-font-weight: 700; + --typography-h3-line-height: var(--typography-heading-line-height); + + --typography-h4-font-size: 14px; + --typography-h4-font-weight: 700; + --typography-h4-line-height: 1.25; + + --typography-paragraph-color: #4F606E; + --typography-paragraph-font-size: 16px; + --typography-paragraph-font-weight: 400; + --typography-paragraph-line-height: 1.25; + + --typography-small-paragraph-font-size: 12px; + --typography-small-paragraph-line-height: 1.3; + + --typography-big-font-size: 46px; + --typography-big-font-weight: 700; + --typography-big-line-height: 1; +} + +@include bp(desktop) { + :root { + --section-spacing-y: 80px; + + --typography-h1-font-size: 66px; + --typography-h2-font-size: 48px; + --typography-h3-font-size: 32px; + --typography-h4-font-size: 20px; + --typography-paragraph-font-size: 24px; + --typography-small-paragraph-font-size: 16px; + --typography-big-font-size: 128px; + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_faq.scss b/sass/homeassistant/pages/community/components/_faq.scss new file mode 100644 index 00000000000..1e793b438ad --- /dev/null +++ b/sass/homeassistant/pages/community/components/_faq.scss @@ -0,0 +1,260 @@ +section#faq { + + .container{ + flex-direction: column; + + h2{ + margin: 0; + margin-bottom: 30px; + @include bp(desktop){ + margin-bottom: 60px; + } + } + } + + .accordion { + + .accordion-items { + display: flex; + flex-direction: column; + margin-top: 1px; + } + + .accordion-item { + --open: 0; + border-bottom: 1px solid #72787E; + display: flex; + flex-direction: column; + + // Checkbox-driven open state + input[type="checkbox"] { + display: none; + } + + input[type="checkbox"]:checked ~ .accordion-item-heading { + // Optionally style the heading when open + } + + input[type="checkbox"]:checked ~ .accordion-item-content-animation-wrapper { + grid-template-rows: 1fr; + transition: grid-template-rows 0.4s ease 0s; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + + .accordion-item-content-transform-wrapper { + opacity: 1; + transform: translateY(0); + transition: transform 0.4s ease, visibility 0s 0.4s ease, margin-top 0.4s ease, opacity 0.3s ease 0.425s; + visibility: visible; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more { + background-color: var(--color-primary) + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:before, + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:after { + transform: translate(-50%, -50%) scale(calc(64/28)); + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:hover:before, + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more:hover:after { + transform: translate(-50%, -50%) scale(calc(56/28)); + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more .plus { + transform: translate(-50%, -50%) rotate(90deg); + } + + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more .plus:before { + opacity: 0; + } + input[type="checkbox"]:checked ~ .accordion-item-heading .button-more .plus:after { + background-color: #ffffff; + } + + &-heading { + cursor: pointer; + margin-bottom: -1px; + transition: background-color 0.3s, color 0.3s; + user-select: none; + isolation: isolate; + + label{ + + display: flex; + justify-content: space-between; + padding: 20px 0; + z-index: 1; + + @include bp(desktop){ + padding: 40px 0; + } + } + + &-title { + font-weight: 400; + font-size: 20px; + color: #002332; + @include bp(desktop){ + font-size: 24px; + } + } + + &-icon { + display: grid; + flex-shrink: 0; + height: 32px; + place-items: center; + position: relative; + width: 32px; + } + + .button-more { + background-color: #ffffff; + border-radius: 50%; + cursor: pointer; + height: 24px; + position: relative; + transition: background-color 0.25s ease-out, box-shadow 0.25s ease-out; + width: 24px; + + .plus { + height: 8px; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%) rotate(0deg); + transition: transform .25s ease-out; + width: 8px; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + .plus:before, + .plus:after { + background-color: var(--color-primary); + content: ''; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + transition: opacity .25s ease-out, background-color .25s ease-out; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + .plus:before { + height: 2px; + width: 8px; + } + + .plus:after { + height: 8px; + width: 2px; + } + + &:before { + -webkit-backdrop-filter: blur(2px); + backdrop-filter: blur(2px); + background-color: rgba(255, 255, 255, .25); + border-radius: 50%; + content: ''; + height: 28px; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + transition: transform .25s ease-out; + width: 28px; + z-index: -1; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + &:after { + border-radius: 50%; + content: ''; + height: 28px; + left: 50%; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + width: 28px; + z-index: 1; + } + + &:hover:before, + &:hover:after { + transform: translate(-50%, -50%) scale(calc(34/28)); + } + + // .active state now handled by input:checked selectors above + } + } + + &-content { + gap: 20px; + grid-template-rows: 0fr; + justify-content: center; + padding: 0 0 20px 0; + transition: grid-template-rows 0.3s, transform, visibility 0.3s; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + + &, + p { + color: #4F606E; + font-size: 16px; + line-height: 1.5; + margin: 0; + } + + p:not(:last-child) { + margin-bottom: 1rem; + } + + &-animation { + min-height: 0; + } + + &-animation-wrapper { + display: grid; + grid-template-rows: 0fr; + overflow: hidden; + transition: grid-template-rows 0.4s ease; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + + &-transform-wrapper { + margin-top: 0; + opacity: 0.875; + transform: translateY(-100%); + transition: transform 0.4s ease, margin-top 0.4s ease, opacity 0.3s ease; + + @media (prefers-reduced-motion: reduce) { + transition: none; + } + } + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_global.scss b/sass/homeassistant/pages/community/components/_global.scss new file mode 100644 index 00000000000..46b4ef6fe68 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_global.scss @@ -0,0 +1,54 @@ +section#global { + padding-bottom: 0; + + .container { + align-items: center; + flex-direction: column; + gap: 0 40px; + + @include bp(desktop) { + flex-direction: row; + } + } + + .content { + display: flex; + flex-basis: 0; + flex-direction: column; + flex-grow: 1; + gap: 24px; + + @include bp(desktop) { + gap: 60px; + } + + &-inner { + display: flex; + flex-direction: column; + gap: 6px; + + @include bp(desktop) { + gap: 12px; + } + } + + h2 { + margin: 0; + } + + } + + .photos-wrapper { + max-width: 424px; + padding: 100px 0 0; + + @include bp(desktop) { + margin-left: 75px; + } + + .photos { + flex-basis: 0; + flex-grow: 1; + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_hero.scss b/sass/homeassistant/pages/community/components/_hero.scss new file mode 100644 index 00000000000..8d914870c3c --- /dev/null +++ b/sass/homeassistant/pages/community/components/_hero.scss @@ -0,0 +1,45 @@ +section#hero { + --section-spacing-y: 0; + + background-image: url('/images/community/hero-m.svg'); + background-position: center; + background-size: cover; + border-radius: 12px; + display: flex; + flex-direction: column; + justify-content: flex-end; + min-height: 600px; + + @include bp(tablet) { + background-image: url('/images/community/hero.svg'); + background-position: center; + border-radius: 24px; + } + + .container { + display: flex; + flex-direction: column; + justify-content: flex-end; + padding: 24px 12px; + + @include bp(tablet) { + padding: 164px 12px 66px 12px; + } + + .content { + align-items: flex-start; + display: flex; + flex-direction: column; + max-width: 670px; + + .event-card { + margin-top: 24px; + + @include bp(tablet) { + margin-top: 60px; + } + } + } + + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_join.scss b/sass/homeassistant/pages/community/components/_join.scss new file mode 100644 index 00000000000..35fe3221dc9 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_join.scss @@ -0,0 +1,106 @@ +section#join { + isolation: isolate; + + .container { + align-items: center; + flex-direction: column; + position: relative; + } + + h2 { + align-items: center; + display: flex; + flex-direction: column; + margin: 0 auto; + text-transform: unset; + + span:not(:first-child) { + margin-top: 8px; + + @include bp(desktop) { + margin-top: 24px; + } + } + } + + p { + //background-color: rgba(245, 246, 250, 0.6); + //backdrop-filter: blur(2px); + max-width: 650px; + text-align: center; + text-wrap: balance; + padding-top: 16px; + z-index: 1; + + @include bp(desktop) { + padding-top: 40px; + } + } + + .buttons { + margin-top: 52px; + z-index: 1; + + @include bp(desktop) { + margin-top: 60px; + } + } + + .avatars { + display: grid; + // 12 cols + grid-template-columns: repeat(6, 1fr); + position: absolute; + inset: 0; + + &[data-dsap]:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { // Reset after scroll up + .avatar{ + opacity: 0; + } + } + + @include bp(tablet) { + grid-template-columns: repeat(12, 1fr); + } + + + .avatar { + justify-self: center; + transition: opacity 0.25s ease-out; + + &.hide{ + img{ + opacity: 0; + } + } + + img { + height: 48px; + width: 48px; + border-radius: 50%; + transition: opacity 0.5s ease-out; + } + + + // hide every even avatar on desktop + + &:nth-child(odd) { + display: none; + @include bp(tablet) { + display: block; + } + } + + + $list: 21,31,76,0,35,70,100,95,50,6,30,26; + @for $i from 1 through 12 { + &:nth-child(#{$i}) { + $offset: nth($list, $i); + transform: translateY(calc(#{$offset} * 1%)); + opacity: 1; + transition-delay: #{0.2 + ($i * 0.05)}s; + } + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_meetups.scss b/sass/homeassistant/pages/community/components/_meetups.scss new file mode 100644 index 00000000000..d8fe54f5ceb --- /dev/null +++ b/sass/homeassistant/pages/community/components/_meetups.scss @@ -0,0 +1,126 @@ +section#meetups { + + background-color: #CCEFFE; + border-radius: 12px; + overflow: hidden; + margin-top: 24px; + + @include bp(tablet) { + border-radius: 24px; + } + + .container { + gap: 60px; + flex-direction: column; + + @include bp(tablet) { + flex-direction: row; + } + + .content { + display: flex; + flex-direction: column; + align-items: flex-start; + + h2 { + margin: 0; + margin-bottom: 20px; + + @include bp(tablet) { + margin-bottom: 40px; + } + } + + svg:has(use[href="#community"]) { + height: 40px; + width: 40px; + margin-bottom: 12px; + + @include bp(desktop) { + margin-bottom: 40px; + height: 80px; + width: 80px; + } + } + + .event-card { + margin-top: 20px; + + @include bp(tablet) { + margin-top: 40px; + } + } + } + + .guide { + background-color: rgba(246, 248, 251, 0.2); + border: 1px solid #ffffff; + border-radius: 12px; + padding: 40px 24px; + + h3 { + margin: 0; + text-wrap: balance; + margin-bottom: 12px; + } + + p { + color: #002332; + } + + .buttons { + justify-content: flex-start; + } + + .steps { + display: flex; + flex-direction: column; + gap: 8px; + margin: 40px 0; + + .step { + @include small; + padding-left: 32px; + line-height: 1.5; + color: #4F606E; + position: relative; + + &:before { + content: ''; + width: 15px; + height: 15px; + border-radius: 50%; + + box-shadow: inset 0 0 0 5px var(--color-primary); + left: 0; + top: 4px; + position: absolute; + } + + &:not(:last-child) { + padding-bottom: 28px; + + &:after { + content: ''; + width: 1px; + background-color: #4F606E; + left: 7px; + bottom: -4px; + top: 26px; + position: absolute; + } + } + } + } + } + } + + .content, + .guide { + @include bp(desktop) { + flex-grow: 1; + flex-basis: 50%; + width: 100%; + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_nav.scss b/sass/homeassistant/pages/community/components/_nav.scss new file mode 100644 index 00000000000..339f5c33cd5 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_nav.scss @@ -0,0 +1,36 @@ +section#nav { + --section-spacing-y: 20px; + @include bp(tablet) { + --section-spacing-y: 40px; + } + + .nav-pills{ + display: flex; + justify-content: center; + flex-wrap: wrap; + + gap: 12px; + + .nav-pill{ + background-color: #ffffff; + border-radius: 32px; + cursor: pointer; + transition: background-color 0.25s ease, color 0.25s ease; + font-size: 12px; + font-weight: 500; + padding: 6px 12px; + white-space: nowrap; + text-decoration: none; + color: #002332; + + &:hover{ + background-color: var(--color-primary); + color: #ffffff; + } + + @include bp(tablet) { + font-size: 14px; + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/components/_newsletter.scss b/sass/homeassistant/pages/community/components/_newsletter.scss new file mode 100644 index 00000000000..c4f2cea8e15 --- /dev/null +++ b/sass/homeassistant/pages/community/components/_newsletter.scss @@ -0,0 +1,157 @@ +section#newsletter { + --section-spacing-y: 0; + background-color: #002332; + border-radius: 12px; + overflow: hidden; + + .container { + gap: 0px 60px; + align-items: flex-end; + justify-content: center; + align-items: center; + flex-direction: column; + + @include bp(tablet) { + align-items: center; + flex-direction: row; + } + + @include bp(desktop) { + align-items: flex-end; + } + } + + + + h2 { + margin-top: 0; + text-wrap: balance; + } + + &, + p { + color: #ffffff; + } + + @include bp(tablet) { + border-radius: 24px; + } + + .content { + padding: 52px 0; + + @include bp(tablet) { + padding: 100px 0; + } + } + + .buttons { + justify-content: flex-start; + margin-top: 20px; + + @include bp(tablet) { + margin-top: 40px; + } + } + + .editions { + display: flex; + flex-direction: column; + flex-shrink: 0; + max-width: 570px; + align-items: center; + margin-bottom: -40px; + width: 100%; + order: 1; + + @include bp(tablet) { + order: -1; + flex-basis: 50%; + align-self: center; + } + @include bp(desktop) { + } + + @include bp(large-desktop) { + flex-basis: 570px; + align-self: flex-end; + margin-bottom: -64px; + + } + + &[data-dsap]:not([data-dsap-is="in"]):not([data-dsap-is="above"]) { + + // Only if scrolling down into the element + .edition { + transition-duration: 0s; + transition-delay: 0s; + + &:nth-child(1) { + transform: translateY(120px); + } + + &:nth-child(2) { + transform: translateY(40px); + } + } + } + + .edition { + aspect-ratio: 571/300; + width: 100%; + max-width: 100%; + position: relative; + border-radius: 6px; + overflow: hidden; + transition: transform 0.8s cubic-bezier(0.3, 1, 0.5, 1); + transition-delay: .25s; + + @include bp(tablet) { + border-radius: 12px; + } + + .label { + display: none; + } + + img { + width: 100%; + height: 100%; + object-fit: cover; + position: absolute; + border-radius: 0; + inset: 0; + } + + &:nth-child(1) { + max-width: 80%; + height: 45px; + transition-delay: .3s; + z-index: 1; + + @include bp(tablet) { + height: 70px; + } + } + + &:nth-child(2) { + max-width: 90%; + justify-self: center; + height: 50px; + transform: translateY(-20px); + z-index: 2; + + @include bp(tablet) { + height: 80px; + } + } + + &:nth-child(3) { + max-width: 100%; + justify-self: center; + z-index: 3; + transform: translateY(-40px); + } + } + } +} \ No newline at end of file diff --git a/sass/homeassistant/pages/community/index.scss b/sass/homeassistant/pages/community/index.scss new file mode 100644 index 00000000000..ddfff1905df --- /dev/null +++ b/sass/homeassistant/pages/community/index.scss @@ -0,0 +1,20 @@ +// Setup +@import "homeassistant/pages/community/mixins.scss"; +@import "homeassistant/pages/community/variables.scss"; + +// Base +@import "homeassistant/pages/community/base.scss"; +@import "homeassistant/pages/community/icon.scss"; +@import "homeassistant/pages/community/buttons.scss"; +@import "homeassistant/pages/community/event-card.scss"; +@import "homeassistant/pages/community/photos.scss"; +@import "homeassistant/pages/community/stats.scss"; + +// Components +@import "homeassistant/pages/community/components/nav.scss"; +@import "homeassistant/pages/community/components/hero.scss"; +@import "homeassistant/pages/community/components/global.scss"; +@import "homeassistant/pages/community/components/join.scss"; +@import "homeassistant/pages/community/components/newsletter.scss"; +@import "homeassistant/pages/community/components/meetups.scss"; +@import "homeassistant/pages/community/components/faq.scss"; diff --git a/source/_dashboards/area.markdown b/source/_dashboards/area.markdown index cada9ef23d7..093249306bf 100644 --- a/source/_dashboards/area.markdown +++ b/source/_dashboards/area.markdown @@ -104,7 +104,7 @@ type: area area: bedroom display_type: picture navigation_path: my_bedroom -sensor_classes: +sensor_classes: - temperature - humidity alert_classes: @@ -116,4 +116,4 @@ features: ## Available colors -You want to colorize the area card? Choose one of the following colors: `primary`, `accent`, `disabled`, `red`, `pink`, `purple`, `deep-purple`, `indigo`, `blue`, `light-blue`, `cyan`, `teal`, `green`, `light-green`, `lime`, `yellow`, `amber`, `orange`, `deep-orange`, `brown`, `grey`, `blue-grey`, `black`, and `white`. +The following colors are available to colorize the area card: `primary`, `accent`, `disabled`, `red`, `pink`, `purple`, `deep-purple`, `indigo`, `blue`, `light-blue`, `cyan`, `teal`, `green`, `light-green`, `lime`, `yellow`, `amber`, `orange`, `deep-orange`, `brown`, `grey`, `blue-grey`, `black`, `white`, or any hex color code (for example, `#93c47d`). diff --git a/source/_dashboards/tile.markdown b/source/_dashboards/tile.markdown index 7974ecaa559..d6e48b25cca 100644 --- a/source/_dashboards/tile.markdown +++ b/source/_dashboards/tile.markdown @@ -132,7 +132,7 @@ hide_state: true ```yaml type: tile entity: light.living_room -state_content: +state_content: - state - brightness - last-changed @@ -150,6 +150,6 @@ features: ## Available colors -You want to colorize the tile card? Choose one of the following colors: `primary`, `accent`, `disabled`, `red`, `pink`, `purple`, `deep-purple`, `indigo`, `blue`, `light-blue`, `cyan`, `teal`, `green`, `light-green`, `lime`, `yellow`, `amber`, `orange`, `deep-orange`, `brown`, `grey`, `blue-grey`, `black` and `white`. +The following colors are available to colorize the tile card: `primary`, `accent`, `disabled`, `red`, `pink`, `purple`, `deep-purple`, `indigo`, `blue`, `light-blue`, `cyan`, `teal`, `green`, `light-green`, `lime`, `yellow`, `amber`, `orange`, `deep-orange`, `brown`, `grey`, `blue-grey`, `black`, `white`, or any hex color code (for example, `#93c47d`). diff --git a/source/_data/community-faq.yml b/source/_data/community-faq.yml new file mode 100644 index 00000000000..ed442270f0b --- /dev/null +++ b/source/_data/community-faq.yml @@ -0,0 +1,11 @@ +items: + - question: Where do I find support? + answer: Support for Home Assistant software (and other Open Home Foundation projects) is done by community members who volunteer their time to help out fellow hobbyists. The most active communities for providing support are our community forums and the Discord server. Just make sure to follow the rules about where and how to post your support query. It is also possible to ask for support in the Facebook group and on Reddit. + - question: How can I contribute to the project? + answer:

No matter your experience, there are plenty of ways to get involved and contribute to Home Assistant! If you’ve got the dev skills (whether you're a beginner or expert), start here, which shows you how to craft a PR, and then check out our extensive Core documentation to help familiarize yourself with our architecture. There you will find instructions on how to join the Developers category in our Discord server, which allows you to chat directly with other developers.

If you're knowledgeable about how to use Home Assistant, don't be afraid to hop onto one (or more) of our community platforms to share this knowledge. This is a great way to contribute if you’re not a developer. Additionally, suppose you're a designer and are passionate about Home Assistant. In that case, we'd love for you to check out our Developers category in Discord (Follow the steps to join the development server, and choose I want to contribute design skills!).

If you’re not able to give your time, you can also financially support the foundation, which pays passionate people to work on Home Assistant full-time. Subscribing to Home Assistant Cloud or purchasing our officially licensed Home Assistant hardware supports the development of this project and many others. In the near future, we hope to relaunch our merch store where community members can purchase swag to support the foundation.

+ - question: Where can I find regional communities? + answer:

This is not an exhaustive list of regional communities, but the ones that we are aware of. Is yours missing? Let us know!

+ - question: Can community hosts be reimbursed for fees related to their meetups? + answer: Yes! Community is the foundation of Home Assistant, and we want to help make sure that meeting with other smart home enthusiasts is a stress-free experience. The Open Home Foundation will reimburse hosts for certain fees related to hosting a meetup. Check out our Expense Guidelines for Hosts for more information. + - question: I have a suggestion for this page! + answer: Excellent! Let Missy know by emailing community@openhomefoundation.org, and we'll put it under consideration. \ No newline at end of file diff --git a/source/_data/glossary.yml b/source/_data/glossary.yml index f60b457e083..d493ca42616 100644 --- a/source/_data/glossary.yml +++ b/source/_data/glossary.yml @@ -79,7 +79,7 @@ Home Assistant has built-in functionality to create files containing a copy of your configuration. This can be used to restore your Home Assistant as well as migrate to a new system. The backup feature is available for all - [installation types](/installation/#about-installation-methods). + [installation types](/installation/#about-installation-types). link: /common-tasks/general/#backups aliases: - backups @@ -307,23 +307,23 @@ Home Assistant Container is a standalone container-based installation of Home Assistant Core. Any [OCI](https://opencontainers.org/) compatible runtime can be used, but the documentation focus is on Docker. - link: /installation/#about-installation-methods + link: /installation/#about-installation-types - term: Home Assistant Core definition: >- Home Assistant Core is the Python program at the heart of Home Assistant. It is part of all installation types. It can be installed standalone (without Home Assistant Supervisor) as a container using Docker (this is typically referred to as the Home Assistant - Container installation method). For development, Core can also be run using a Virtual - Environment (previously referred as the Home Assistant Core installation method. - For production setup, the [Home Assistant Core installation method is deprecated](https://www.home-assistant.io/blog/2025/05/22/deprecating-core-and-supervised-installation-methods-and-32-bit-systems/). + Container installation type). For development, Core can also be run using a Virtual + Environment (previously referred as the Home Assistant Core installation type. + For production setup, the [Home Assistant Core installation type is deprecated](https://www.home-assistant.io/blog/2025/05/22/deprecating-core-and-supervised-installation-methods-and-32-bit-systems/). - term: Home Assistant Supervised definition: >- - The Home Assistant Supervised installation method is a full UI managed home automation ecosystem + The Home Assistant Supervised installation type is a full UI managed home automation ecosystem that runs the Home Assistant Core program, the Home Assistant Supervisor and add-ons. It comes pre-installed on Home Assistant OS, but can be installed standalone on Debian Linux systems. It leverages Docker, which is managed by the Home Assistant Supervisor. The - [Home Assistant Supervised installation method is deprecated](https://www.home-assistant.io/blog/2025/05/22/deprecating-core-and-supervised-installation-methods-and-32-bit-systems/). + [Home Assistant Supervised installation type is deprecated](https://www.home-assistant.io/blog/2025/05/22/deprecating-core-and-supervised-installation-methods-and-32-bit-systems/). - term: Home Assistant Supervisor definition: >- The Home Assistant Supervisor is a program that manages a Home Assistant @@ -337,7 +337,7 @@ includes Home Assistant Core, the Home Assistant Supervisor, and supports add-ons. Home Assistant Supervisor keeps it up to date, removing the need for you to manage an operating system. Home Assistant Operating System is - the recommended installation method for most users. + the recommended installation type for most users. - term: Host definition: >- A device that can communicate with other devices on a network. During setup diff --git a/source/_docs/automation/templating.markdown b/source/_docs/automation/templating.markdown index 0b6d054283e..95ab1ce678a 100644 --- a/source/_docs/automation/templating.markdown +++ b/source/_docs/automation/templating.markdown @@ -7,10 +7,10 @@ Automations support the advanced features of [templating](/docs/configuration/te Example of variables used in templates: -```jinja - {{ this.name }} is the name of the automation executing from this trigger - {{ trigger.platform }} is the type of trigger object, like `calendar` - ``` +{% raw %} +- `{{ this.name }}` is the name of the automation executing from this trigger +- `{{ trigger.platform }}` is the type of trigger object, like `calendar` +{% endraw %} ## Available state data diff --git a/source/_docs/automation/using_blueprints.markdown b/source/_docs/automation/using_blueprints.markdown index ce6834b1262..994ed35caee 100644 --- a/source/_docs/automation/using_blueprints.markdown +++ b/source/_docs/automation/using_blueprints.markdown @@ -86,7 +86,7 @@ If you do not want to [re-import the blueprint](/docs/automation/using_blueprint its {% term YAML %} content to keep it up to date: 1. Navigate to the blueprints directory (`blueprints/automation/`). - The location of this directory depends on the installation method. It's + The location of this directory depends on the installation type. It's similar to how you find [`configuration.yaml`](/docs/configuration/#editing-configurationyaml). 2. Next, you must find the blueprint to update. The path name of a blueprint consists of: - The username of the user that created it. The name depends on the source of the blueprint: diff --git a/source/_docs/blueprint/selectors.markdown b/source/_docs/blueprint/selectors.markdown index 691f7b5afc7..b459f2e1f96 100644 --- a/source/_docs/blueprint/selectors.markdown +++ b/source/_docs/blueprint/selectors.markdown @@ -1197,7 +1197,7 @@ When used without options, the selector will accept a free form object. object: ``` -When used with a `schema`, the selector will force the object to be in this format by displaying a form. +When used with `fields` specified, the selector will force the object to be in this format by displaying a form. ![Screenshot of an object selector](/images/blueprints/selector-object-schema.png) @@ -1220,7 +1220,7 @@ object: The output of this selector is a YAML object. -{% configuration qr_code %} +{% configuration object %} fields: description: > List of fields of the object. @@ -1231,6 +1231,11 @@ fields: description: The label of the field required: false type: string + required: + description: If set to true, the field must be present. + required: false + default: false + type: boolean selector: description: The selector to use for this field. It can be any available selector. required: true @@ -1256,7 +1261,7 @@ translation_key: required: false multiple: description: > - Allows selecting multiple options. If set to `true`, the resulting value of this selector will be a list instead of a single string value. This option is only used if `fields` option set. + Allows adding multiple objects. If set to `true`, the resulting value of this selector will be a list instead of a single YAML object. This option is only used if `fields` option set. type: boolean required: false default: false diff --git a/source/_docs/configuration.markdown b/source/_docs/configuration.markdown index b7e7d543460..2ab9ddbd0bb 100644 --- a/source/_docs/configuration.markdown +++ b/source/_docs/configuration.markdown @@ -27,7 +27,7 @@ Example of a configuration.yaml file, accessed using the File editor add-on on a ## Editing `configuration.yaml` -How you edit your `configuration.yaml` file depends on your editor preferences and the [installation method](/installation/#about-installation-methods) you used to set up Home Assistant. Follow these steps: +How you edit your `configuration.yaml` file depends on your editor preferences and the [installation type](/installation/#about-installation-types) you used to set up Home Assistant. Follow these steps: 1. [Set up file access](#to-set-up-access-to-the-files-and-prepare-an-editor). 2. [Locate the config directory](#to-find-the-configuration-directory). @@ -37,7 +37,7 @@ How you edit your `configuration.yaml` file depends on your editor preferences a ### To set up access to the files and prepare an editor Before you can edit a file, you need to know how to access files in Home Assistant and setup an editor. -File access depends on your [installation method](/installation/#about-installation-methods). If you use {% term "Home Assistant Operating System" %}, you can use editor add-ons, for example. If you use {% term "Home Assistant Container" %}, add-ons are not available. +File access depends on your [installation type](/installation/#about-installation-types). If you use {% term "Home Assistant Operating System" %}, you can use editor add-ons, for example. If you use {% term "Home Assistant Container" %}, add-ons are not available. To set up file access on the Home Assistant Operating System, follow these steps: @@ -70,7 +70,7 @@ If you have watched any videos about setting up Home Assistant using `configurat After changing configuration or automation files, you can check if the configuration is valid. A configuration check is also applied automatically when you reload the configuration or when you restart Home Assistant. -The method for running a configuration check depends on your [installation type](/installation/#about-installation-methods). Check the common tasks for your installation type: +The method for running a configuration check depends on your [installation type](/installation/#about-installation-types). Check the common tasks for your installation type: - [Configuration check on Operating System](/common-tasks/os/#configuration-check) - [Configuration check on Container](/common-tasks/container/#configuration-check) diff --git a/source/_docs/tools/hass.markdown b/source/_docs/tools/hass.markdown index d3517c577e3..26dcd7be8c3 100644 --- a/source/_docs/tools/hass.markdown +++ b/source/_docs/tools/hass.markdown @@ -5,7 +5,7 @@ description: "Description of hass." The command-line part of Home Assistant is `hass`. -This tool is only available to users of the Home Assistant Core installation method. It is started from the command line on the computer running Home Assistant Core (accessed perhaps via SSH). +This tool is only available to users of the Home Assistant Core installation type. It is started from the command line on the computer running Home Assistant Core (accessed perhaps via SSH). ```text $ hass -h diff --git a/source/_faq/ha-vs-hassio.markdown b/source/_faq/ha-vs-hassio.markdown index 1cd8f365421..ce150c9cba1 100644 --- a/source/_faq/ha-vs-hassio.markdown +++ b/source/_faq/ha-vs-hassio.markdown @@ -5,7 +5,7 @@ ha_category: Installation --- Home Assistant Core is a Python program, in simple words. It can be run on various operating systems and provide the ability to track, control and automate your devices. -When people talking about Home Assistant Core they usually refer to a standalone [installation method](/docs/installation/). +When people talking about Home Assistant Core they usually refer to a standalone [installation type](/docs/installation/). [Home Assistant](/hassio/) is a combination of Home Assistant Core and tools which allows one to run it easily on a Raspberry Pi and other platforms without setting up an operating system first. Home Assistant is an all-in one-solution and has a management user interface that can be used from the Home Assistant frontend. This interface is not present in a Home Assistant Core setup. diff --git a/source/_includes/custom/news.html b/source/_includes/custom/news.html index 47bf98b3cbc..3f92dd924e9 100644 --- a/source/_includes/custom/news.html +++ b/source/_includes/custom/news.html @@ -80,11 +80,11 @@ - - + " aria-label="Join the Home Assistant community"> diff --git a/source/_includes/installation/container.md b/source/_includes/installation/container.md index fff3c8d248f..35083187877 100644 --- a/source/_includes/installation/container.md +++ b/source/_includes/installation/container.md @@ -4,7 +4,7 @@ These below instructions are for an installation of {% term "Home Assistant Container" %} running in your own container environment, which you manage yourself. Any [OCI](https://opencontainers.org/) compatible runtime can be used, however this guide will focus on installing it with Docker. {% note %} -This installation method **does not have access to add-ons**. If you want to use add-ons, you need to use another installation method. The recommended method is {% term "Home Assistant Operating System" %}. Checkout the [overview table of installation types](https://www.home-assistant.io/installation/#about-installation-methods) to see the differences. +This installation type **does not have access to add-ons**. If you want to use add-ons, you need to use another installation type. The recommended type is {% term "Home Assistant Operating System" %}. Checkout the [overview table of installation types](https://www.home-assistant.io/installation/#about-installation-types) to see the differences. {% endnote %} {% important %} diff --git a/source/_includes/integrations/google_client_secret.md b/source/_includes/integrations/google_client_secret.md index 51e16721a67..b716b738478 100644 --- a/source/_includes/integrations/google_client_secret.md +++ b/source/_includes/integrations/google_client_secret.md @@ -43,12 +43,7 @@ This section explains how to generate a client ID and client secret on - For Application type, choose **Web Application** and give this client ID a name (like "Home Assistant Client"). - Add `https://my.home-assistant.io/redirect/oauth` to **Authorized redirect URIs** then select **Create**. > **Note**: This is not a placeholder. It is the URI that must be used. - - Click **Create**. -9. Find the client you just created. Under the Actions column, choose **Download OAuth client** (download icon), which will show you the **Client ID** and **Client Secret**. - - Make a note of these (for example, copy and paste them into a text editor), as you will need them shortly. +9. From the resulting dialog take a note of **Client ID** and **Client Secret** you **can not retrieve it again** after closing the dialog. - Once you have noted these strings, select **Close**. - Congratulations! You are now the keeper of a client secret. Guard it in your treasure box. In most cases, your new credentials will be active within a few minutes. However, Google states that activation may take up to five hours in some circumstances. - > If you need to find these credentials again at any point, then navigate to **APIs & Services** > **Credentials**, and you will see **Home Assistant Credentials** (or whatever you named them in the previous step) under **OAuth 2.0 Client IDs**. - > - > To view the **Client ID** and **Client Secret**, click the **Download OAuth client** (download icon) under the Actions column. {% enddetails %} diff --git a/source/_includes/site/footer.html b/source/_includes/site/footer.html index ed9c23e63ad..3867b1c48d3 100644 --- a/source/_includes/site/footer.html +++ b/source/_includes/site/footer.html @@ -31,6 +31,7 @@
  • Community Forum {% icon "tabler:external-link" %}
  • Creator Network {% icon "tabler:external-link" %}
  • Works With Home Assistant {% icon "tabler:external-link" %}
  • +
  • Our community
  • Reporting issues
  • System status

    diff --git a/source/_integrations/_integration_docs_template.markdown b/source/_integrations/_integration_docs_template.markdown index 6b49608f02d..7812f98c3f9 100644 --- a/source/_integrations/_integration_docs_template.markdown +++ b/source/_integrations/_integration_docs_template.markdown @@ -87,24 +87,22 @@ Timeframe: ## Supported functionality -### Entities - The **My integration** integration provides the following entities. -#### Buttons +### Buttons - **Start backflush** - **Description**: Starts the backflush process on your machine. You got 15 seconds to turn the paddle after activation. - **Available for machines**: all -#### Numbers +### Numbers - **Dose** - **Description**: Dosage (in ticks) for each key - **Available for machines**: GS3 AV, Linea Mini. - **Remarks**: GS3 has this multiple times, one for each physical key (1-4), and the entities are disabled by default. -#### Sensors +### Sensors - **Current coffee temperature** - **Description**: Current temperature of the coffee boiler. @@ -116,7 +114,7 @@ The **My integration** integration provides the following entities. - **Available for machines**: Linea Micra, GS3 AV, GS3 MP. - **Remarks**: - -#### Selects +### Selects - **Prebrew/-infusion mode** - **Description**: Whether to use prebrew, preinfusion, or neither. @@ -128,7 +126,7 @@ The **My integration** integration provides the following entities. - **Options**: 1, 2, 3 - **Available for machines**: Linea Micra -#### Updates +### Updates - **Gateway firmware** - **Description**: Firmware status of the gateway. @@ -174,11 +172,11 @@ The integration does not provide the ability to reboot, which can instead be don When trying to set up the integration, the form shows the message “This device can’t be reached”. -##### Description +#### Description This means the settings on the device are incorrect, since the device needs to be enabled for local communication. -##### Resolution +#### Resolution To resolve this issue, try the following steps: diff --git a/source/_integrations/alexa_devices.markdown b/source/_integrations/alexa_devices.markdown index 44a4b879aa3..73b49d18bfb 100644 --- a/source/_integrations/alexa_devices.markdown +++ b/source/_integrations/alexa_devices.markdown @@ -74,10 +74,24 @@ Available actions: `notify.send_message`, `alexa_devices.send_sound`, `alexa_dev Devices with appropriate functionality will have speak and announce notify entities created. These can be used as the target for the `notify.send_message` action. +| Data attribute | Optional | Description | +| -------------- | -------- | ----------------------------------------- | +| `message` | no | Text to be output (see below for advanced markup) | + {% tip %} When sending notifications to multiple devices, you may experience delays due to rate limiting by Amazon. You can avoid this by sending notifications to speaker groups created in Alexa. {% endtip %} +{% details "Advanced Message Markup" %} + +Amazon provide markup to control not only what is said but how it is said and to add additional option such as pausing and playing certain audio clips. Details of this are covered in [Amazon's documentation](https://developer.amazon.com/en-US/docs/alexa/custom-skills/speech-synthesis-markup-language-ssml-reference.html) where there are lots of examples (just pass everything between the `` and `` elements into the `message` parameter of the action). + +Audio files must meet certain criteria on size, bit and sample rates and must be served over HTTPS (see [documentation](https://developer.amazon.com/en-US/docs/alexa/custom-skills/speech-synthesis-markup-language-ssml-reference.html#audio) for full details). These restrictions make them fine for text and sound effects but you will not be able to play music this way. + +Amazon provide a set of [sounds you can use](https://developer.amazon.com/en-US/docs/alexa/custom-skills/ask-soundlibrary.html) which contains the markup you will need for that clip. + +{% enddetails %} + #### Action `alexa_devices.send_text_command` This action essentially allows you to control Alexa using text commands rather than speech. You should be able to request anything you would via speech using this action. @@ -89,12 +103,11 @@ This action essentially allows you to control Alexa using text commands rather t #### Action `alexa_devices.send_sound` -This action allows you to play one of the built-in Alexa sounds. The full list of sounds and their variants is available in [Amazon's documentation](https://developer.amazon.com/en-US/docs/alexa/custom-skills/ask-soundlibrary.html) +This action allows you to play one of the built-in Alexa sounds. The full list of sounds is available in [Amazon's documentation (needs authentication)](https://alexa.amazon.com/api/behaviors/entities?skillId=amzn1.ask.1p.sound) | Data attribute | Optional | Description | | -------------- | -------- | ----------------------------------------- | | `device_id` | no | Device on which you want to play sound | -| `sound_variant` | no | The variant you want to play (generally 1) | | `sound` | no | The name of the sound to play | ## Examples @@ -140,19 +153,37 @@ data: ```yaml action: alexa_devices.send_sound data: - sound_variant: 1 - sound: amzn_sfx_doorbell_chime + sound: amzn_sfx_doorbell_chime_01 device_id: 037d79c1af96c67ba57ebcae560fb18e ``` -### Play alternative doorbell sound +### Using advanced markup in a notification ```yaml -action: alexa_devices.send_sound +action: notify.send_message data: - sound_variant: 2 - sound: amzn_sfx_doorbell_chime - device_id: 037d79c1af96c67ba57ebcae560fb18e + message: > + Hello, lets have some examples. + This is me being mildly excited! + The farmer's dog was called bingo. + I can sing high and I can sing low +target: + entity_id: notify.study_dot_speak +``` + +```yaml +action: notify.send_message +data: + message: > + Stop! Hammer Time. Watch out +