diff --git a/app/assets/stylesheets/android/utilities.css b/app/assets/stylesheets/android/utilities.css new file mode 100644 index 000000000..e0d03f570 --- /dev/null +++ b/app/assets/stylesheets/android/utilities.css @@ -0,0 +1,5 @@ +@layer android { + .hide-in-android-app { + display: none; + } +} diff --git a/app/assets/stylesheets/ios/utilities.css b/app/assets/stylesheets/ios/utilities.css new file mode 100644 index 000000000..0dfeada57 --- /dev/null +++ b/app/assets/stylesheets/ios/utilities.css @@ -0,0 +1,5 @@ +@layer ios { + .hide-in-ios-app { + display: none; + } +} diff --git a/app/assets/stylesheets/mobile_app/_global.css b/app/assets/stylesheets/mobile_app/_global.css new file mode 100644 index 000000000..5d0648df5 --- /dev/null +++ b/app/assets/stylesheets/mobile_app/_global.css @@ -0,0 +1,10 @@ +@layer mobile_app { + /* Use custom insets to account for floating navigation elements. + The mobile apps can inject their own inset value based on native elements on screen. */ + :root { + --custom-safe-inset-top: var(--injected-safe-inset-top, env(safe-area-inset-top, 0px)); + --custom-safe-inset-right: var(--injected-safe-inset-right, env(safe-area-inset-right, 0px)); + --custom-safe-inset-bottom: var(--injected-safe-inset-bottom, env(safe-area-inset-bottom, 0px)); + --custom-safe-inset-left: var(--injected-safe-inset-left, env(safe-area-inset-left, 0px)); + } +} diff --git a/app/assets/stylesheets/mobile_app/utilities.css b/app/assets/stylesheets/mobile_app/utilities.css new file mode 100644 index 000000000..85e9a9848 --- /dev/null +++ b/app/assets/stylesheets/mobile_app/utilities.css @@ -0,0 +1,9 @@ +@layer mobile_app { + .hide-in-mobile-app { + display: none; + } + + .show-in-mobile-app { + display: unset; + } +} diff --git a/app/assets/stylesheets/_global.css b/app/assets/stylesheets/web/_global.css similarity index 99% rename from app/assets/stylesheets/_global.css rename to app/assets/stylesheets/web/_global.css index dc928b40d..a88c2c14c 100644 --- a/app/assets/stylesheets/_global.css +++ b/app/assets/stylesheets/web/_global.css @@ -1,4 +1,4 @@ -@layer reset, base, components, modules, utilities; +@layer reset, base, components, modules, utilities, mobile_app, android, ios; :root { /* Spacing */ diff --git a/app/assets/stylesheets/animation.css b/app/assets/stylesheets/web/animation.css similarity index 100% rename from app/assets/stylesheets/animation.css rename to app/assets/stylesheets/web/animation.css diff --git a/app/assets/stylesheets/autoresize.css b/app/assets/stylesheets/web/autoresize.css similarity index 100% rename from app/assets/stylesheets/autoresize.css rename to app/assets/stylesheets/web/autoresize.css diff --git a/app/assets/stylesheets/avatars.css b/app/assets/stylesheets/web/avatars.css similarity index 100% rename from app/assets/stylesheets/avatars.css rename to app/assets/stylesheets/web/avatars.css diff --git a/app/assets/stylesheets/bar.css b/app/assets/stylesheets/web/bar.css similarity index 100% rename from app/assets/stylesheets/bar.css rename to app/assets/stylesheets/web/bar.css diff --git a/app/assets/stylesheets/base.css b/app/assets/stylesheets/web/base.css similarity index 100% rename from app/assets/stylesheets/base.css rename to app/assets/stylesheets/web/base.css diff --git a/app/assets/stylesheets/bubble.css b/app/assets/stylesheets/web/bubble.css similarity index 100% rename from app/assets/stylesheets/bubble.css rename to app/assets/stylesheets/web/bubble.css diff --git a/app/assets/stylesheets/buttons.css b/app/assets/stylesheets/web/buttons.css similarity index 100% rename from app/assets/stylesheets/buttons.css rename to app/assets/stylesheets/web/buttons.css diff --git a/app/assets/stylesheets/card-columns.css b/app/assets/stylesheets/web/card-columns.css similarity index 100% rename from app/assets/stylesheets/card-columns.css rename to app/assets/stylesheets/web/card-columns.css diff --git a/app/assets/stylesheets/card-perma.css b/app/assets/stylesheets/web/card-perma.css similarity index 100% rename from app/assets/stylesheets/card-perma.css rename to app/assets/stylesheets/web/card-perma.css diff --git a/app/assets/stylesheets/cards.css b/app/assets/stylesheets/web/cards.css similarity index 100% rename from app/assets/stylesheets/cards.css rename to app/assets/stylesheets/web/cards.css diff --git a/app/assets/stylesheets/circled-text.css b/app/assets/stylesheets/web/circled-text.css similarity index 100% rename from app/assets/stylesheets/circled-text.css rename to app/assets/stylesheets/web/circled-text.css diff --git a/app/assets/stylesheets/color-picker.css b/app/assets/stylesheets/web/color-picker.css similarity index 100% rename from app/assets/stylesheets/color-picker.css rename to app/assets/stylesheets/web/color-picker.css diff --git a/app/assets/stylesheets/comments.css b/app/assets/stylesheets/web/comments.css similarity index 100% rename from app/assets/stylesheets/comments.css rename to app/assets/stylesheets/web/comments.css diff --git a/app/assets/stylesheets/dialog.css b/app/assets/stylesheets/web/dialog.css similarity index 100% rename from app/assets/stylesheets/dialog.css rename to app/assets/stylesheets/web/dialog.css diff --git a/app/assets/stylesheets/dividers.css b/app/assets/stylesheets/web/dividers.css similarity index 100% rename from app/assets/stylesheets/dividers.css rename to app/assets/stylesheets/web/dividers.css diff --git a/app/assets/stylesheets/drag_and_drop.css b/app/assets/stylesheets/web/drag_and_drop.css similarity index 100% rename from app/assets/stylesheets/drag_and_drop.css rename to app/assets/stylesheets/web/drag_and_drop.css diff --git a/app/assets/stylesheets/events.css b/app/assets/stylesheets/web/events.css similarity index 99% rename from app/assets/stylesheets/events.css rename to app/assets/stylesheets/web/events.css index 1dbdf0997..c6bd0ff2a 100644 --- a/app/assets/stylesheets/events.css +++ b/app/assets/stylesheets/web/events.css @@ -221,6 +221,7 @@ background-color: var(--color-canvas); grid-row-start: 1; inset-block-start: calc(var(--block-space) * -1); + margin-inline: calc(var(--main-padding) * -1); margin-block-end: var(--events-gap); padding-block: calc(var(--events-gap) * 3) var(--events-gap); position: sticky; diff --git a/app/assets/stylesheets/filters.css b/app/assets/stylesheets/web/filters.css similarity index 100% rename from app/assets/stylesheets/filters.css rename to app/assets/stylesheets/web/filters.css diff --git a/app/assets/stylesheets/flash.css b/app/assets/stylesheets/web/flash.css similarity index 100% rename from app/assets/stylesheets/flash.css rename to app/assets/stylesheets/web/flash.css diff --git a/app/assets/stylesheets/golden-effect.css b/app/assets/stylesheets/web/golden-effect.css similarity index 100% rename from app/assets/stylesheets/golden-effect.css rename to app/assets/stylesheets/web/golden-effect.css diff --git a/app/assets/stylesheets/header.css b/app/assets/stylesheets/web/header.css similarity index 95% rename from app/assets/stylesheets/header.css rename to app/assets/stylesheets/web/header.css index 21553e358..c2471e522 100644 --- a/app/assets/stylesheets/header.css +++ b/app/assets/stylesheets/web/header.css @@ -39,6 +39,7 @@ .header__actions { display: flex; + align-items: center; font-size: var(--text-x-small); gap: var(--header-gap); inline-size: var(--header-actions-width); @@ -116,17 +117,15 @@ /* Optional class to stack header actions on small screens /* ------------------------------------------------------------------------ */ - /* .header--mobile-actions-stack { + .header--mobile-actions-stack { @media (max-width: 639px) { - grid-template-columns: 1fr 1fr; grid-template-areas: - "menu menu" - "actions-start actions-end" - "title title"; + "actions-start menu actions-end" + "title title title"; .header__title { margin-block-start: 0.25rem; } } - } */ + } } diff --git a/app/assets/stylesheets/web/icons.css b/app/assets/stylesheets/web/icons.css new file mode 100644 index 000000000..6d1697bf9 --- /dev/null +++ b/app/assets/stylesheets/web/icons.css @@ -0,0 +1,108 @@ +@layer components { + .icon { + -webkit-touch-callout: none; + background-color: currentColor; + block-size: var(--icon-size, 1em); + display: inline-block; + flex-shrink: 0; + inline-size: var(--icon-size, 1em); + mask-image: var(--svg); + mask-position: center; + mask-repeat: no-repeat; + mask-size: var(--icon-size, 1em); + pointer-events: none; + user-select: none; + } + + img.icon { + background: none; + } + + .icon--37signals { --svg: url("/37signals.svg"); } + .icon--add { --svg: url("/add.svg"); } + .icon--add--meta { --svg: url("/add--meta.svg"); } + .icon--arrow-left { --svg: url("/arrow-left.svg"); } + .icon--arrow-right { --svg: url("/arrow-right.svg"); } + .icon--arrow-up { --svg: url("/arrow-up.svg"); } + .icon--art { --svg: url("/art.svg"); } + .icon--assigned { --svg: url("/assigned.svg"); } + .icon--attachment { --svg: url("/attachment.svg"); } + .icon--bell-alert { --svg: url("/bell-alert.svg"); } + .icon--bell-off { --svg: url("/bell-off.svg"); } + .icon--bell { --svg: url("/bell.svg"); } + .icon--bolt { --svg: url("/bolt.svg"); } + .icon--bookmark-outline { --svg: url("/bookmark-outline.svg"); } + .icon--bookmark { --svg: url("/bookmark.svg"); } + .icon--boost { --svg: url("/boost.svg"); } + .icon--camera { --svg: url("/camera.svg"); } + .icon--caret-down { --svg: url("/caret-down.svg"); } + .icon--check { --svg: url("/check.svg"); } + .icon--check-circle { --svg: url("/check-circle.svg"); } + .icon--check-all { --svg: url("/check-all.svg"); } + .icon--clipboard { --svg: url("/clipboard.svg"); } + .icon--close { --svg: url("/close.svg"); } + .icon--close-circle { --svg: url("/close-circle.svg"); } + .icon--collapse { --svg: url("/collapse.svg"); } + .icon--board { --svg: url("/board.svg"); } + .icon--board-add { --svg: url("/board-add.svg"); } + .icon--column-left { --svg: url("/column-left.svg"); } + .icon--column-right { --svg: url("/column-right.svg"); } + .icon--comment { --svg: url("/comment.svg"); } + .icon--copy-paste { --svg: url("/copy-paste.svg"); } + .icon--crown { --svg: url("/crown.svg"); } + .icon--email { --svg: url("/email.svg"); } + .icon--everyone { --svg: url("/everyone.svg"); } + .icon--expand { --svg: url("/expand.svg"); } + .icon--gear { --svg: url("/gear.svg"); } + .icon--grid { --svg: url("/grid.svg"); } + .icon--filter { --svg: url("/filter.svg"); } + .icon--fizzy { --svg: url("/fizzy.svg"); } + .icon--globe { --svg: url("/globe.svg"); } + .icon--golden-ticket { --svg: url("/golden-ticket.svg"); } + .icon--home { --svg: url("/home.svg"); } + .icon--install { --svg: url("/install.svg"); } + .icon--install { --svg: url("/install.svg"); } + .icon--install-edge { --svg: url("/install-edge.svg"); } + .icon--lifebuoy { --svg: url("/lifebuoy.svg"); } + .icon--lock { --svg: url("/lock.svg"); } + .icon--logout { --svg: url("/logout.svg"); } + .icon--marker { --svg: url("/marker.svg"); } + .icon--maximize { --svg: url("/maximize.svg"); } + .icon--menu { --svg: url("/menu.svg"); } + .icon--menu-dots-horizontal { --svg: url("/menu-dots-horizontal.svg"); } + .icon--menu-dots-vertical { --svg: url("/menu-dots-vertical.svg"); } + .icon--minus { --svg: url("/minus.svg"); } + .icon--move { --svg: url("/move.svg"); } + .icon--notification-bell-access-only { --svg: url("/bell.svg"); } + .icon--notification-bell-watching { --svg: url("/bell-off.svg"); } + .icon--notification-bell-reverse-access-only { --svg: url("/bell-off.svg"); } + .icon--notification-bell-reverse-watching { --svg: url("/bell.svg"); } + .icon--password { --svg: url("/password.svg"); } + .icon--pencil { --svg: url("/pencil.svg"); } + .icon--person { --svg: url("/person.svg"); } + .icon--person-add { --svg: url("/person-add.svg"); } + .icon--picture-add { --svg: url("/picture-add.svg"); } + .icon--picture-double { --svg: url("/picture-double.svg"); } + .icon--picture-remove { --svg: url("/picture-remove.svg"); } + .icon--picture-zoom { --svg: url("/picture-zoom.svg"); } + .icon--pinned { --svg: url("/pinned.svg"); } + .icon--qr-code { --svg: url("/qr-code.svg"); } + .icon--reaction { --svg: url("/reaction.svg"); } + .icon--refresh { --svg: url("/refresh.svg"); } + .icon--refresh--meta { --svg: url("/refresh--meta.svg"); } + .icon--remove { --svg: url("/remove.svg"); } + .icon--rename { --svg: url("/rename.svg"); } + .icon--search { --svg: url("/search.svg"); } + .icon--settings { --svg: url("/settings.svg"); } + .icon--share { --svg: url("/share.svg"); } + .icon--sliders { --svg: url("/sliders.svg"); } + .icon--switch { --svg: url("/switch.svg"); } + .icon--tag { --svg: url("/tag.svg"); } + .icon--tag-outline { --svg: url("/tag-outline.svg"); } + .icon--thumb-up { --svg: url("/thumb-up.svg"); } + .icon--trash { --svg: url("/trash.svg"); } + .icon--unpinned { --svg: url("/unpinned.svg"); } + .icon--unseen { --svg: url("/unseen.svg"); } + .icon--world { --svg: url("/world.svg"); } + .icon--youtube { --svg: url("/youtube.svg"); } +} diff --git a/app/assets/stylesheets/inputs.css b/app/assets/stylesheets/web/inputs.css similarity index 100% rename from app/assets/stylesheets/inputs.css rename to app/assets/stylesheets/web/inputs.css diff --git a/app/assets/stylesheets/knobs.css b/app/assets/stylesheets/web/knobs.css similarity index 100% rename from app/assets/stylesheets/knobs.css rename to app/assets/stylesheets/web/knobs.css diff --git a/app/assets/stylesheets/layout.css b/app/assets/stylesheets/web/layout.css similarity index 100% rename from app/assets/stylesheets/layout.css rename to app/assets/stylesheets/web/layout.css diff --git a/app/assets/stylesheets/lexxy.css b/app/assets/stylesheets/web/lexxy.css similarity index 100% rename from app/assets/stylesheets/lexxy.css rename to app/assets/stylesheets/web/lexxy.css diff --git a/app/assets/stylesheets/lightbox.css b/app/assets/stylesheets/web/lightbox.css similarity index 100% rename from app/assets/stylesheets/lightbox.css rename to app/assets/stylesheets/web/lightbox.css diff --git a/app/assets/stylesheets/markdown.css b/app/assets/stylesheets/web/markdown.css similarity index 91% rename from app/assets/stylesheets/markdown.css rename to app/assets/stylesheets/web/markdown.css index f6aef0e39..fe26141c2 100644 --- a/app/assets/stylesheets/markdown.css +++ b/app/assets/stylesheets/web/markdown.css @@ -3,7 +3,7 @@ --opacity: 0.5; --size: 0.8em; - background: url(link.svg) no-repeat center bottom 0.2em; + background: url("/link.svg") no-repeat center bottom 0.2em; background-size: var(--size); block-size: 1em; color: var(--color-link); diff --git a/app/assets/stylesheets/nav.css b/app/assets/stylesheets/web/nav.css similarity index 100% rename from app/assets/stylesheets/nav.css rename to app/assets/stylesheets/web/nav.css diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/web/notifications.css similarity index 100% rename from app/assets/stylesheets/notifications.css rename to app/assets/stylesheets/web/notifications.css diff --git a/app/assets/stylesheets/pagination.css b/app/assets/stylesheets/web/pagination.css similarity index 100% rename from app/assets/stylesheets/pagination.css rename to app/assets/stylesheets/web/pagination.css diff --git a/app/assets/stylesheets/panels.css b/app/assets/stylesheets/web/panels.css similarity index 100% rename from app/assets/stylesheets/panels.css rename to app/assets/stylesheets/web/panels.css diff --git a/app/assets/stylesheets/popup.css b/app/assets/stylesheets/web/popup.css similarity index 100% rename from app/assets/stylesheets/popup.css rename to app/assets/stylesheets/web/popup.css diff --git a/app/assets/stylesheets/print.css b/app/assets/stylesheets/web/print.css similarity index 100% rename from app/assets/stylesheets/print.css rename to app/assets/stylesheets/web/print.css diff --git a/app/assets/stylesheets/profile-layout.css b/app/assets/stylesheets/web/profile-layout.css similarity index 100% rename from app/assets/stylesheets/profile-layout.css rename to app/assets/stylesheets/web/profile-layout.css diff --git a/app/assets/stylesheets/pwa.css b/app/assets/stylesheets/web/pwa.css similarity index 100% rename from app/assets/stylesheets/pwa.css rename to app/assets/stylesheets/web/pwa.css diff --git a/app/assets/stylesheets/qr-codes.css b/app/assets/stylesheets/web/qr-codes.css similarity index 100% rename from app/assets/stylesheets/qr-codes.css rename to app/assets/stylesheets/web/qr-codes.css diff --git a/app/assets/stylesheets/reactions.css b/app/assets/stylesheets/web/reactions.css similarity index 100% rename from app/assets/stylesheets/reactions.css rename to app/assets/stylesheets/web/reactions.css diff --git a/app/assets/stylesheets/reset.css b/app/assets/stylesheets/web/reset.css similarity index 100% rename from app/assets/stylesheets/reset.css rename to app/assets/stylesheets/web/reset.css diff --git a/app/assets/stylesheets/rich-text-content.css b/app/assets/stylesheets/web/rich-text-content.css similarity index 100% rename from app/assets/stylesheets/rich-text-content.css rename to app/assets/stylesheets/web/rich-text-content.css diff --git a/app/assets/stylesheets/search.css b/app/assets/stylesheets/web/search.css similarity index 100% rename from app/assets/stylesheets/search.css rename to app/assets/stylesheets/web/search.css diff --git a/app/assets/stylesheets/separators.css b/app/assets/stylesheets/web/separators.css similarity index 100% rename from app/assets/stylesheets/separators.css rename to app/assets/stylesheets/web/separators.css diff --git a/app/assets/stylesheets/settings.css b/app/assets/stylesheets/web/settings.css similarity index 100% rename from app/assets/stylesheets/settings.css rename to app/assets/stylesheets/web/settings.css diff --git a/app/assets/stylesheets/spinners.css b/app/assets/stylesheets/web/spinners.css similarity index 100% rename from app/assets/stylesheets/spinners.css rename to app/assets/stylesheets/web/spinners.css diff --git a/app/assets/stylesheets/steps.css b/app/assets/stylesheets/web/steps.css similarity index 100% rename from app/assets/stylesheets/steps.css rename to app/assets/stylesheets/web/steps.css diff --git a/app/assets/stylesheets/syntax.css b/app/assets/stylesheets/web/syntax.css similarity index 100% rename from app/assets/stylesheets/syntax.css rename to app/assets/stylesheets/web/syntax.css diff --git a/app/assets/stylesheets/tags.css b/app/assets/stylesheets/web/tags.css similarity index 100% rename from app/assets/stylesheets/tags.css rename to app/assets/stylesheets/web/tags.css diff --git a/app/assets/stylesheets/toggles.css b/app/assets/stylesheets/web/toggles.css similarity index 100% rename from app/assets/stylesheets/toggles.css rename to app/assets/stylesheets/web/toggles.css diff --git a/app/assets/stylesheets/tooltips.css b/app/assets/stylesheets/web/tooltips.css similarity index 100% rename from app/assets/stylesheets/tooltips.css rename to app/assets/stylesheets/web/tooltips.css diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/web/trays.css similarity index 100% rename from app/assets/stylesheets/trays.css rename to app/assets/stylesheets/web/trays.css diff --git a/app/assets/stylesheets/user.css b/app/assets/stylesheets/web/user.css similarity index 100% rename from app/assets/stylesheets/user.css rename to app/assets/stylesheets/web/user.css diff --git a/app/assets/stylesheets/utilities.css b/app/assets/stylesheets/web/utilities.css similarity index 99% rename from app/assets/stylesheets/utilities.css rename to app/assets/stylesheets/web/utilities.css index 0f487e1f9..9add37264 100644 --- a/app/assets/stylesheets/utilities.css +++ b/app/assets/stylesheets/web/utilities.css @@ -252,6 +252,10 @@ } } + .show-in-mobile-app { + display: none; + } + .hide-scrollbar { -ms-overflow-style: none; /* Edge */ scrollbar-width: none; /* FF */ diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b3657c76e..9733a7eec 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,4 +1,8 @@ module ApplicationHelper + def stylesheet_link_tags + stylesheet_link_tag *platform.stylesheet_paths, "data-turbo-track": "reload" + end + def page_title_tag account_name = if Current.account && Current.session&.identity&.users&.many? Current.account&.name diff --git a/app/models/application_platform.rb b/app/models/application_platform.rb index 500f4adc6..c484bf335 100644 --- a/app/models/application_platform.rb +++ b/app/models/application_platform.rb @@ -1,4 +1,6 @@ class ApplicationPlatform < PlatformAgent + SCOPED_STYLESHEET_PATHS = {} + def ios? match? /iPhone|iPad/ end @@ -39,6 +41,18 @@ class ApplicationPlatform < PlatformAgent operating_system == "Windows" end + def ios_app? + match? /Fizzy iOS/ + end + + def android_app? + match? /Fizzy Android/ + end + + def mobile_app? + ios_app? || android_app? + end + def operating_system case user_agent.platform when /Android/ then "Android" @@ -51,4 +65,31 @@ class ApplicationPlatform < PlatformAgent os =~ /Linux/ ? "Linux" : os end end + + def stylesheet_paths + scoped_stylesheet_paths("web") + + (mobile_app? ? scoped_stylesheet_paths("mobile_app") : []) + + scoped_stylesheet_paths(stylesheet_asset_name) + end + + private + def stylesheet_asset_name + case + when android_app? then "android" + when ios_app? then "ios" + else "desktop" + end + end + + def scoped_stylesheet_paths(scope = css_asset_name) + # Allow new stylesheets to be added in dev/test without restarting server + SCOPED_STYLESHEET_PATHS.clear if Rails.env.development? + + SCOPED_STYLESHEET_PATHS[scope] ||= + Rails.root.join("app/assets/stylesheets").then do |stylesheet_root| + stylesheet_root.glob("#{scope}/**/*.css").collect do |path| + path.to_s.remove(stylesheet_root.to_s + "/", ".css") + end + end + end end diff --git a/app/views/layouts/shared/_head.html.erb b/app/views/layouts/shared/_head.html.erb index 9ef153df2..0c8dbdd73 100644 --- a/app/views/layouts/shared/_head.html.erb +++ b/app/views/layouts/shared/_head.html.erb @@ -16,7 +16,7 @@ <% turbo_refreshes_with method: :morph, scroll: :preserve %> <%= render "layouts/theme_preference" %> - <%= stylesheet_link_tag :app, "data-turbo-track": "reload" %> + <%= stylesheet_link_tags %> <%= javascript_importmap_tags %> <%= tenanted_action_cable_meta_tag %>