feat(omnibox): add favorite indicator for history items
- commit
- 24d74a44d6034d29556444136fdb37ef257995ba
- author
- brice · · 2025-12-28 08:26 UTC
- parent
- e869777
- signature
- unsigned
4 files · +120 -19
M CHANGELOG.md +1 -0
| @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. | |||
| 5 | 5 | ## [Unreleased] | |
| 6 | 6 | ||
| 7 | 7 | ### Added | |
| 8 | + | - **Omnibox favorite indicator**: History items that are also bookmarked now display a yellowish left border and subtle background tint in the omnibox. Uses parallel async loading to avoid blocking browser startup. | |
| 8 | 9 | - **Mode indicator toaster**: Visual notification showing current modal mode (PANE MODE, TAB MODE, SESSION MODE, RESIZE MODE) at bottom-left corner with mode-specific colors. Configurable via `workspace.styling.mode_indicator_toaster_enabled` (default: true). | |
| 9 | 10 | - **Config migration system**: Detects missing config keys when new settings are added in updates and provides tools to add them. | |
| 10 | 11 | - `dumber config status`: Shows config file path and number of new settings available. | |
| @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. | |||||
| 5 | ## [Unreleased] | 5 | ## [Unreleased] | ||
| 6 | 6 | ||||
| 7 | ### Added | 7 | ### Added | ||
| 8 | + | - **Omnibox favorite indicator**: History items that are also bookmarked now display a yellowish left border and subtle background tint in the omnibox. Uses parallel async loading to avoid blocking browser startup. | |||
| 8 | - **Mode indicator toaster**: Visual notification showing current modal mode (PANE MODE, TAB MODE, SESSION MODE, RESIZE MODE) at bottom-left corner with mode-specific colors. Configurable via `workspace.styling.mode_indicator_toaster_enabled` (default: true). | 9 | - **Mode indicator toaster**: Visual notification showing current modal mode (PANE MODE, TAB MODE, SESSION MODE, RESIZE MODE) at bottom-left corner with mode-specific colors. Configurable via `workspace.styling.mode_indicator_toaster_enabled` (default: true). | ||
| 9 | - **Config migration system**: Detects missing config keys when new settings are added in updates and provides tools to add them. | 10 | - **Config migration system**: Detects missing config keys when new settings are added in updates and provides tools to add them. | ||
| 10 | - `dumber config status`: Shows config file path and number of new settings available. | 11 | - `dumber config status`: Shows config file path and number of new settings available. | ||
M internal/application/usecase/manage_favorites.go +19 -0
| @@ -196,6 +196,25 @@ func (uc *ManageFavoritesUseCase) IsFavorite(ctx context.Context, url string) (b | |||
| 196 | 196 | return fav != nil, nil | |
| 197 | 197 | } | |
| 198 | 198 | ||
| 199 | + | // GetAllURLs returns a set of all favorited URLs for efficient batch lookup. | |
| 200 | + | func (uc *ManageFavoritesUseCase) GetAllURLs(ctx context.Context) (map[string]struct{}, error) { | |
| 201 | + | log := logging.FromContext(ctx) | |
| 202 | + | log.Debug().Msg("getting all favorite URLs") | |
| 203 | + | ||
| 204 | + | favs, err := uc.favoriteRepo.GetAll(ctx) | |
| 205 | + | if err != nil { | |
| 206 | + | return nil, fmt.Errorf("failed to get favorites: %w", err) | |
| 207 | + | } | |
| 208 | + | ||
| 209 | + | urls := make(map[string]struct{}, len(favs)) | |
| 210 | + | for _, fav := range favs { | |
| 211 | + | urls[fav.URL] = struct{}{} | |
| 212 | + | } | |
| 213 | + | ||
| 214 | + | log.Debug().Int("count", len(urls)).Msg("retrieved favorite URLs") | |
| 215 | + | return urls, nil | |
| 216 | + | } | |
| 217 | + | ||
| 199 | 218 | // GetTree builds a complete hierarchical view of folders and favorites. | |
| 200 | 219 | func (uc *ManageFavoritesUseCase) GetTree(ctx context.Context) (*entity.FavoriteTree, error) { | |
| 201 | 220 | log := logging.FromContext(ctx) | |
| @@ -196,6 +196,25 @@ func (uc *ManageFavoritesUseCase) IsFavorite(ctx context.Context, url string) (b | |||||
| 196 | return fav != nil, nil | 196 | return fav != nil, nil | ||
| 197 | } | 197 | } | ||
| 198 | 198 | ||||
| 199 | + | // GetAllURLs returns a set of all favorited URLs for efficient batch lookup. | |||
| 200 | + | func (uc *ManageFavoritesUseCase) GetAllURLs(ctx context.Context) (map[string]struct{}, error) { | |||
| 201 | + | log := logging.FromContext(ctx) | |||
| 202 | + | log.Debug().Msg("getting all favorite URLs") | |||
| 203 | + | ||||
| 204 | + | favs, err := uc.favoriteRepo.GetAll(ctx) | |||
| 205 | + | if err != nil { | |||
| 206 | + | return nil, fmt.Errorf("failed to get favorites: %w", err) | |||
| 207 | + | } | |||
| 208 | + | ||||
| 209 | + | urls := make(map[string]struct{}, len(favs)) | |||
| 210 | + | for _, fav := range favs { | |||
| 211 | + | urls[fav.URL] = struct{}{} | |||
| 212 | + | } | |||
| 213 | + | ||||
| 214 | + | log.Debug().Int("count", len(urls)).Msg("retrieved favorite URLs") | |||
| 215 | + | return urls, nil | |||
| 216 | + | } | |||
| 217 | + | ||||
| 199 | // GetTree builds a complete hierarchical view of folders and favorites. | 218 | // GetTree builds a complete hierarchical view of folders and favorites. | ||
| 200 | func (uc *ManageFavoritesUseCase) GetTree(ctx context.Context) (*entity.FavoriteTree, error) { | 219 | func (uc *ManageFavoritesUseCase) GetTree(ctx context.Context) (*entity.FavoriteTree, error) { | ||
| 201 | log := logging.FromContext(ctx) | 220 | log := logging.FromContext(ctx) | ||
M internal/ui/component/omnibox.go +84 -19
| @@ -37,6 +37,7 @@ type Suggestion struct { | |||
| 37 | 37 | URL string | |
| 38 | 38 | Title string | |
| 39 | 39 | FaviconURL string | |
| 40 | + | IsFavorite bool // Indicates if this URL is also bookmarked as a favorite | |
| 40 | 41 | } | |
| 41 | 42 | ||
| 42 | 43 | // Favorite represents a bookmarked URL. | |
| @@ -596,21 +597,43 @@ func (o *Omnibox) performSearch() { | |||
| 596 | 597 | return | |
| 597 | 598 | } | |
| 598 | 599 | ||
| 599 | - | searchInput := usecase.SearchInput{ | |
| 600 | - | Query: query, | |
| 601 | - | Limit: OmniboxListDefaults.MaxResults, | |
| 600 | + | // Run history search and favorite URL fetch in parallel | |
| 601 | + | type searchResult struct { | |
| 602 | + | output *usecase.SearchOutput | |
| 603 | + | err error | |
| 602 | 604 | } | |
| 603 | - | output, err := o.historyUC.Search(ctx, searchInput) | |
| 604 | - | if err != nil { | |
| 605 | - | log.Error().Err(err).Msg("history search failed") | |
| 605 | + | searchCh := make(chan searchResult, 1) | |
| 606 | + | favCh := make(chan map[string]struct{}, 1) | |
| 607 | + | ||
| 608 | + | go func() { | |
| 609 | + | searchInput := usecase.SearchInput{ | |
| 610 | + | Query: query, | |
| 611 | + | Limit: OmniboxListDefaults.MaxResults, | |
| 612 | + | } | |
| 613 | + | output, err := o.historyUC.Search(ctx, searchInput) | |
| 614 | + | searchCh <- searchResult{output, err} | |
| 615 | + | }() | |
| 616 | + | ||
| 617 | + | go func() { | |
| 618 | + | favCh <- o.getFavoriteURLs(ctx) | |
| 619 | + | }() | |
| 620 | + | ||
| 621 | + | // Wait for both results | |
| 622 | + | sr := <-searchCh | |
| 623 | + | favoriteURLs := <-favCh | |
| 624 | + | ||
| 625 | + | if sr.err != nil { | |
| 626 | + | log.Error().Err(sr.err).Msg("history search failed") | |
| 606 | 627 | return | |
| 607 | 628 | } | |
| 608 | 629 | ||
| 609 | - | suggestions := make([]Suggestion, 0, len(output.Matches)) | |
| 610 | - | for _, r := range output.Matches { | |
| 630 | + | suggestions := make([]Suggestion, 0, len(sr.output.Matches)) | |
| 631 | + | for _, r := range sr.output.Matches { | |
| 632 | + | _, isFav := favoriteURLs[r.Entry.URL] | |
| 611 | 633 | suggestions = append(suggestions, Suggestion{ | |
| 612 | - | URL: r.Entry.URL, | |
| 613 | - | Title: r.Entry.Title, | |
| 634 | + | URL: r.Entry.URL, | |
| 635 | + | Title: r.Entry.Title, | |
| 636 | + | IsFavorite: isFav, | |
| 614 | 637 | }) | |
| 615 | 638 | } | |
| 616 | 639 | ||
| @@ -636,17 +659,40 @@ func (o *Omnibox) loadInitialHistory() { | |||
| 636 | 659 | return | |
| 637 | 660 | ||
| 638 | 661 | case "most_visited", "recent", "": | |
| 639 | - | // TODO: Implement GetMostVisited in use case if needed | |
| 640 | - | results, err := o.historyUC.GetRecent(ctx, OmniboxListDefaults.MaxResults, 0) | |
| 641 | - | if err != nil { | |
| 642 | - | log.Error().Err(err).Msg("failed to load recent history") | |
| 662 | + | // Run history fetch and favorite URL fetch in parallel | |
| 663 | + | type historyResult struct { | |
| 664 | + | results []*entity.HistoryEntry | |
| 665 | + | err error | |
| 666 | + | } | |
| 667 | + | historyCh := make(chan historyResult, 1) | |
| 668 | + | favCh := make(chan map[string]struct{}, 1) | |
| 669 | + | ||
| 670 | + | go func() { | |
| 671 | + | // TODO: Implement GetMostVisited in use case if needed | |
| 672 | + | results, err := o.historyUC.GetRecent(ctx, OmniboxListDefaults.MaxResults, 0) | |
| 673 | + | historyCh <- historyResult{results, err} | |
| 674 | + | }() | |
| 675 | + | ||
| 676 | + | go func() { | |
| 677 | + | favCh <- o.getFavoriteURLs(ctx) | |
| 678 | + | }() | |
| 679 | + | ||
| 680 | + | // Wait for both results | |
| 681 | + | hr := <-historyCh | |
| 682 | + | favoriteURLs := <-favCh | |
| 683 | + | ||
| 684 | + | if hr.err != nil { | |
| 685 | + | log.Error().Err(hr.err).Msg("failed to load recent history") | |
| 643 | 686 | return | |
| 644 | 687 | } | |
| 645 | - | suggestions = make([]Suggestion, 0, len(results)) | |
| 646 | - | for _, r := range results { | |
| 688 | + | ||
| 689 | + | suggestions = make([]Suggestion, 0, len(hr.results)) | |
| 690 | + | for _, r := range hr.results { | |
| 691 | + | _, isFav := favoriteURLs[r.URL] | |
| 647 | 692 | suggestions = append(suggestions, Suggestion{ | |
| 648 | - | URL: r.URL, | |
| 649 | - | Title: r.Title, | |
| 693 | + | URL: r.URL, | |
| 694 | + | Title: r.Title, | |
| 695 | + | IsFavorite: isFav, | |
| 650 | 696 | }) | |
| 651 | 697 | } | |
| 652 | 698 | } | |
| @@ -898,7 +944,11 @@ func (o *Omnibox) createRowWithFavicon(rawURL, title, fallbackIcon string, index | |||
| 898 | 944 | ||
| 899 | 945 | // createSuggestionRow creates a ListBoxRow for a suggestion. | |
| 900 | 946 | func (o *Omnibox) createSuggestionRow(s Suggestion, index int) *gtk.ListBoxRow { | |
| 901 | - | return o.createRowWithFavicon(s.URL, s.Title, "web-browser-symbolic", index) | |
| 947 | + | row := o.createRowWithFavicon(s.URL, s.Title, "web-browser-symbolic", index) | |
| 948 | + | if row != nil && s.IsFavorite { | |
| 949 | + | row.AddCssClass("omnibox-row-favorite") | |
| 950 | + | } | |
| 951 | + | return row | |
| 902 | 952 | } | |
| 903 | 953 | ||
| 904 | 954 | // createFavoriteRow creates a ListBoxRow for a favorite. | |
| @@ -1340,6 +1390,21 @@ func (o *Omnibox) idleAddUpdateSuggestions(suggestions []Suggestion) { | |||
| 1340 | 1390 | glib.IdleAdd(&cb, 0) | |
| 1341 | 1391 | } | |
| 1342 | 1392 | ||
| 1393 | + | // getFavoriteURLs returns a set of all favorited URLs for batch lookup. | |
| 1394 | + | // Returns empty map on error to avoid blocking history display. | |
| 1395 | + | func (o *Omnibox) getFavoriteURLs(ctx context.Context) map[string]struct{} { | |
| 1396 | + | if o.favoritesUC == nil { | |
| 1397 | + | return make(map[string]struct{}) | |
| 1398 | + | } | |
| 1399 | + | urls, err := o.favoritesUC.GetAllURLs(ctx) | |
| 1400 | + | if err != nil { | |
| 1401 | + | log := logging.FromContext(ctx) | |
| 1402 | + | log.Warn().Err(err).Msg("failed to load favorite URLs for indicator") | |
| 1403 | + | return make(map[string]struct{}) | |
| 1404 | + | } | |
| 1405 | + | return urls | |
| 1406 | + | } | |
| 1407 | + | ||
| 1343 | 1408 | // idleAddUpdateFavorites schedules updateFavorites on the GTK main thread. | |
| 1344 | 1409 | func (o *Omnibox) idleAddUpdateFavorites(favorites []Favorite) { | |
| 1345 | 1410 | var cb glib.SourceFunc = func(data uintptr) bool { | |
| @@ -37,6 +37,7 @@ type Suggestion struct { | |||||
| 37 | URL string | 37 | URL string | ||
| 38 | Title string | 38 | Title string | ||
| 39 | FaviconURL string | 39 | FaviconURL string | ||
| 40 | + | IsFavorite bool // Indicates if this URL is also bookmarked as a favorite | |||
| 40 | } | 41 | } | ||
| 41 | 42 | ||||
| 42 | // Favorite represents a bookmarked URL. | 43 | // Favorite represents a bookmarked URL. | ||
| @@ -596,21 +597,43 @@ func (o *Omnibox) performSearch() { | |||||
| 596 | return | 597 | return | ||
| 597 | } | 598 | } | ||
| 598 | 599 | ||||
| 599 | - | searchInput := usecase.SearchInput{ | 600 | + | // Run history search and favorite URL fetch in parallel |
| 600 | - | Query: query, | 601 | + | type searchResult struct { |
| 601 | - | Limit: OmniboxListDefaults.MaxResults, | 602 | + | output *usecase.SearchOutput |
| 603 | + | err error | |||
| 602 | } | 604 | } | ||
| 603 | - | output, err := o.historyUC.Search(ctx, searchInput) | 605 | + | searchCh := make(chan searchResult, 1) |
| 604 | - | if err != nil { | 606 | + | favCh := make(chan map[string]struct{}, 1) |
| 605 | - | log.Error().Err(err).Msg("history search failed") | 607 | + | |
| 608 | + | go func() { | |||
| 609 | + | searchInput := usecase.SearchInput{ | |||
| 610 | + | Query: query, | |||
| 611 | + | Limit: OmniboxListDefaults.MaxResults, | |||
| 612 | + | } | |||
| 613 | + | output, err := o.historyUC.Search(ctx, searchInput) | |||
| 614 | + | searchCh <- searchResult{output, err} | |||
| 615 | + | }() | |||
| 616 | + | ||||
| 617 | + | go func() { | |||
| 618 | + | favCh <- o.getFavoriteURLs(ctx) | |||
| 619 | + | }() | |||
| 620 | + | ||||
| 621 | + | // Wait for both results | |||
| 622 | + | sr := <-searchCh | |||
| 623 | + | favoriteURLs := <-favCh | |||
| 624 | + | ||||
| 625 | + | if sr.err != nil { | |||
| 626 | + | log.Error().Err(sr.err).Msg("history search failed") | |||
| 606 | return | 627 | return | ||
| 607 | } | 628 | } | ||
| 608 | 629 | ||||
| 609 | - | suggestions := make([]Suggestion, 0, len(output.Matches)) | 630 | + | suggestions := make([]Suggestion, 0, len(sr.output.Matches)) |
| 610 | - | for _, r := range output.Matches { | 631 | + | for _, r := range sr.output.Matches { |
| 632 | + | _, isFav := favoriteURLs[r.Entry.URL] | |||
| 611 | suggestions = append(suggestions, Suggestion{ | 633 | suggestions = append(suggestions, Suggestion{ | ||
| 612 | - | URL: r.Entry.URL, | 634 | + | URL: r.Entry.URL, |
| 613 | - | Title: r.Entry.Title, | 635 | + | Title: r.Entry.Title, |
| 636 | + | IsFavorite: isFav, | |||
| 614 | }) | 637 | }) | ||
| 615 | } | 638 | } | ||
| 616 | 639 | ||||
| @@ -636,17 +659,40 @@ func (o *Omnibox) loadInitialHistory() { | |||||
| 636 | return | 659 | return | ||
| 637 | 660 | ||||
| 638 | case "most_visited", "recent", "": | 661 | case "most_visited", "recent", "": | ||
| 639 | - | // TODO: Implement GetMostVisited in use case if needed | 662 | + | // Run history fetch and favorite URL fetch in parallel |
| 640 | - | results, err := o.historyUC.GetRecent(ctx, OmniboxListDefaults.MaxResults, 0) | 663 | + | type historyResult struct { |
| 641 | - | if err != nil { | 664 | + | results []*entity.HistoryEntry |
| 642 | - | log.Error().Err(err).Msg("failed to load recent history") | 665 | + | err error |
| 666 | + | } | |||
| 667 | + | historyCh := make(chan historyResult, 1) | |||
| 668 | + | favCh := make(chan map[string]struct{}, 1) | |||
| 669 | + | ||||
| 670 | + | go func() { | |||
| 671 | + | // TODO: Implement GetMostVisited in use case if needed | |||
| 672 | + | results, err := o.historyUC.GetRecent(ctx, OmniboxListDefaults.MaxResults, 0) | |||
| 673 | + | historyCh <- historyResult{results, err} | |||
| 674 | + | }() | |||
| 675 | + | ||||
| 676 | + | go func() { | |||
| 677 | + | favCh <- o.getFavoriteURLs(ctx) | |||
| 678 | + | }() | |||
| 679 | + | ||||
| 680 | + | // Wait for both results | |||
| 681 | + | hr := <-historyCh | |||
| 682 | + | favoriteURLs := <-favCh | |||
| 683 | + | ||||
| 684 | + | if hr.err != nil { | |||
| 685 | + | log.Error().Err(hr.err).Msg("failed to load recent history") | |||
| 643 | return | 686 | return | ||
| 644 | } | 687 | } | ||
| 645 | - | suggestions = make([]Suggestion, 0, len(results)) | 688 | + | |
| 646 | - | for _, r := range results { | 689 | + | suggestions = make([]Suggestion, 0, len(hr.results)) |
| 690 | + | for _, r := range hr.results { | |||
| 691 | + | _, isFav := favoriteURLs[r.URL] | |||
| 647 | suggestions = append(suggestions, Suggestion{ | 692 | suggestions = append(suggestions, Suggestion{ | ||
| 648 | - | URL: r.URL, | 693 | + | URL: r.URL, |
| 649 | - | Title: r.Title, | 694 | + | Title: r.Title, |
| 695 | + | IsFavorite: isFav, | |||
| 650 | }) | 696 | }) | ||
| 651 | } | 697 | } | ||
| 652 | } | 698 | } | ||
| @@ -898,7 +944,11 @@ func (o *Omnibox) createRowWithFavicon(rawURL, title, fallbackIcon string, index | |||||
| 898 | 944 | ||||
| 899 | // createSuggestionRow creates a ListBoxRow for a suggestion. | 945 | // createSuggestionRow creates a ListBoxRow for a suggestion. | ||
| 900 | func (o *Omnibox) createSuggestionRow(s Suggestion, index int) *gtk.ListBoxRow { | 946 | func (o *Omnibox) createSuggestionRow(s Suggestion, index int) *gtk.ListBoxRow { | ||
| 901 | - | return o.createRowWithFavicon(s.URL, s.Title, "web-browser-symbolic", index) | 947 | + | row := o.createRowWithFavicon(s.URL, s.Title, "web-browser-symbolic", index) |
| 948 | + | if row != nil && s.IsFavorite { | |||
| 949 | + | row.AddCssClass("omnibox-row-favorite") | |||
| 950 | + | } | |||
| 951 | + | return row | |||
| 902 | } | 952 | } | ||
| 903 | 953 | ||||
| 904 | // createFavoriteRow creates a ListBoxRow for a favorite. | 954 | // createFavoriteRow creates a ListBoxRow for a favorite. | ||
| @@ -1340,6 +1390,21 @@ func (o *Omnibox) idleAddUpdateSuggestions(suggestions []Suggestion) { | |||||
| 1340 | glib.IdleAdd(&cb, 0) | 1390 | glib.IdleAdd(&cb, 0) | ||
| 1341 | } | 1391 | } | ||
| 1342 | 1392 | ||||
| 1393 | + | // getFavoriteURLs returns a set of all favorited URLs for batch lookup. | |||
| 1394 | + | // Returns empty map on error to avoid blocking history display. | |||
| 1395 | + | func (o *Omnibox) getFavoriteURLs(ctx context.Context) map[string]struct{} { | |||
| 1396 | + | if o.favoritesUC == nil { | |||
| 1397 | + | return make(map[string]struct{}) | |||
| 1398 | + | } | |||
| 1399 | + | urls, err := o.favoritesUC.GetAllURLs(ctx) | |||
| 1400 | + | if err != nil { | |||
| 1401 | + | log := logging.FromContext(ctx) | |||
| 1402 | + | log.Warn().Err(err).Msg("failed to load favorite URLs for indicator") | |||
| 1403 | + | return make(map[string]struct{}) | |||
| 1404 | + | } | |||
| 1405 | + | return urls | |||
| 1406 | + | } | |||
| 1407 | + | ||||
| 1343 | // idleAddUpdateFavorites schedules updateFavorites on the GTK main thread. | 1408 | // idleAddUpdateFavorites schedules updateFavorites on the GTK main thread. | ||
| 1344 | func (o *Omnibox) idleAddUpdateFavorites(favorites []Favorite) { | 1409 | func (o *Omnibox) idleAddUpdateFavorites(favorites []Favorite) { | ||
| 1345 | var cb glib.SourceFunc = func(data uintptr) bool { | 1410 | var cb glib.SourceFunc = func(data uintptr) bool { | ||
M internal/ui/theme/css.go +16 -0
| @@ -299,6 +299,22 @@ entry.omnibox-entry > *:focus-visible { | |||
| 299 | 299 | border-left: 0.1875em solid var(--accent); | |
| 300 | 300 | } | |
| 301 | 301 | ||
| 302 | + | /* Favorite indicator in history mode - yellowish accent */ | |
| 303 | + | .omnibox-row.omnibox-row-favorite { | |
| 304 | + | background-color: alpha(var(--warning), 0.08); | |
| 305 | + | border-left: 0.1875em solid var(--warning); | |
| 306 | + | } | |
| 307 | + | ||
| 308 | + | .omnibox-row.omnibox-row-favorite:hover { | |
| 309 | + | background-color: alpha(var(--warning), 0.15); | |
| 310 | + | border-left: 0.1875em solid var(--warning); | |
| 311 | + | } | |
| 312 | + | ||
| 313 | + | .omnibox-row.omnibox-row-favorite:selected { | |
| 314 | + | background-color: alpha(var(--warning), 0.2); | |
| 315 | + | border-left: 0.1875em solid var(--warning); | |
| 316 | + | } | |
| 317 | + | ||
| 302 | 318 | /* Favicon in omnibox rows */ | |
| 303 | 319 | .omnibox-favicon { | |
| 304 | 320 | min-width: 1em; | |
| @@ -299,6 +299,22 @@ entry.omnibox-entry > *:focus-visible { | |||||
| 299 | border-left: 0.1875em solid var(--accent); | 299 | border-left: 0.1875em solid var(--accent); | ||
| 300 | } | 300 | } | ||
| 301 | 301 | ||||
| 302 | + | /* Favorite indicator in history mode - yellowish accent */ | |||
| 303 | + | .omnibox-row.omnibox-row-favorite { | |||
| 304 | + | background-color: alpha(var(--warning), 0.08); | |||
| 305 | + | border-left: 0.1875em solid var(--warning); | |||
| 306 | + | } | |||
| 307 | + | ||||
| 308 | + | .omnibox-row.omnibox-row-favorite:hover { | |||
| 309 | + | background-color: alpha(var(--warning), 0.15); | |||
| 310 | + | border-left: 0.1875em solid var(--warning); | |||
| 311 | + | } | |||
| 312 | + | ||||
| 313 | + | .omnibox-row.omnibox-row-favorite:selected { | |||
| 314 | + | background-color: alpha(var(--warning), 0.2); | |||
| 315 | + | border-left: 0.1875em solid var(--warning); | |||
| 316 | + | } | |||
| 317 | + | ||||
| 302 | /* Favicon in omnibox rows */ | 318 | /* Favicon in omnibox rows */ | ||
| 303 | .omnibox-favicon { | 319 | .omnibox-favicon { | ||
| 304 | min-width: 1em; | 320 | min-width: 1em; | ||